summaryrefslogtreecommitdiffstats
path: root/packages
diff options
context:
space:
mode:
Diffstat (limited to 'packages')
-rw-r--r--packages/DocumentsUI/AndroidManifest.xml23
-rw-r--r--packages/DocumentsUI/res/layout/fragment_directory.xml8
-rw-r--r--packages/DocumentsUI/res/menu/mode_directory.xml10
-rw-r--r--packages/DocumentsUI/res/values/strings.xml9
-rw-r--r--packages/DocumentsUI/res/xml/document_provider.xml19
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java4
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java290
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java92
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DocumentChangedReceiver.java38
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java206
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java80
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java4
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java5
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java4
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/RootsCache.java99
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java116
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java3
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/SectionedListAdapter.java8
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/TestActivity.java22
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/ThumbnailCache.java (renamed from packages/SystemUI/res/values-sw600dp-port/refs.xml)30
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/UriDerivativeLoader.java37
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/model/Document.java31
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/model/Root.java6
-rw-r--r--packages/ExternalStorageProvider/AndroidManifest.xml15
-rw-r--r--packages/ExternalStorageProvider/src/com/android/externalstorage/CloudTestDocumentsProvider.java253
-rw-r--r--packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java133
-rw-r--r--packages/Keyguard/AndroidManifest.xml3
-rw-r--r--packages/Keyguard/src/com/android/keyguard/HotwordServiceClient.java208
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardSelectorView.java126
-rw-r--r--packages/Keyguard/src/com/google/android/search/service/IHotwordService.aidl35
-rw-r--r--packages/Keyguard/src/com/google/android/search/service/IHotwordServiceCallback.aidl34
-rw-r--r--packages/PrintSpooler/AndroidManifest.xml9
-rw-r--r--packages/PrintSpooler/res/drawable-hdpi/ic_menu_add.pngbin0 -> 667 bytes
-rw-r--r--packages/PrintSpooler/res/drawable-mdpi/ic_menu_add.pngbin0 -> 596 bytes
-rw-r--r--packages/PrintSpooler/res/drawable-xhdpi/ic_menu_add.pngbin0 -> 761 bytes
-rw-r--r--packages/PrintSpooler/res/layout/print_job_config_activity_container.xml5
-rw-r--r--packages/PrintSpooler/res/layout/select_printer_activity.xml29
-rw-r--r--packages/PrintSpooler/res/layout/spinner_dropdown_item.xml2
-rw-r--r--packages/PrintSpooler/res/menu/select_printer_activity.xml37
-rw-r--r--packages/PrintSpooler/res/values/strings.xml26
-rw-r--r--packages/PrintSpooler/res/values/themes.xml8
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/FusedPrintersProvider.java575
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java993
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/PrintSpooler.java979
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java1258
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/SelectPrinterActivity.java41
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/SelectPrinterFragment.java401
-rw-r--r--packages/SystemUI/ic_sysbar_internal.psdbin360448 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-nodpi/lightning.pngbin0 -> 2896 bytes
-rw-r--r--packages/SystemUI/res/layout/quick_settings_tile_battery.xml10
-rw-r--r--packages/SystemUI/res/layout/signal_cluster_view.xml3
-rw-r--r--packages/SystemUI/res/layout/status_bar.xml10
-rw-r--r--packages/SystemUI/res/values-af/strings.xml2
-rw-r--r--packages/SystemUI/res/values-am/strings.xml4
-rw-r--r--packages/SystemUI/res/values-ar/strings.xml2
-rw-r--r--packages/SystemUI/res/values-az/strings.xml204
-rw-r--r--packages/SystemUI/res/values-be/strings.xml4
-rw-r--r--packages/SystemUI/res/values-bg/strings.xml5
-rw-r--r--packages/SystemUI/res/values-ca/strings.xml5
-rw-r--r--packages/SystemUI/res/values-cs/strings.xml2
-rw-r--r--packages/SystemUI/res/values-da/strings.xml5
-rw-r--r--packages/SystemUI/res/values-de/strings.xml5
-rw-r--r--packages/SystemUI/res/values-el/strings.xml2
-rw-r--r--packages/SystemUI/res/values-en-rGB/strings.xml2
-rw-r--r--packages/SystemUI/res/values-en-rIN/strings.xml204
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings.xml5
-rw-r--r--packages/SystemUI/res/values-es/strings.xml2
-rw-r--r--packages/SystemUI/res/values-et/strings.xml2
-rw-r--r--packages/SystemUI/res/values-fa/strings.xml2
-rw-r--r--packages/SystemUI/res/values-fi/strings.xml2
-rw-r--r--packages/SystemUI/res/values-fr-rCA/strings.xml206
-rw-r--r--packages/SystemUI/res/values-fr/strings.xml5
-rw-r--r--packages/SystemUI/res/values-hi/strings.xml2
-rw-r--r--packages/SystemUI/res/values-hr/strings.xml2
-rw-r--r--packages/SystemUI/res/values-hu/strings.xml2
-rw-r--r--packages/SystemUI/res/values-hy/strings.xml204
-rw-r--r--packages/SystemUI/res/values-in/strings.xml5
-rw-r--r--packages/SystemUI/res/values-it/strings.xml2
-rw-r--r--packages/SystemUI/res/values-iw/strings.xml5
-rw-r--r--packages/SystemUI/res/values-ja/strings.xml5
-rw-r--r--packages/SystemUI/res/values-ka/strings.xml204
-rw-r--r--packages/SystemUI/res/values-km/strings.xml204
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml5
-rw-r--r--packages/SystemUI/res/values-lo/strings.xml204
-rw-r--r--packages/SystemUI/res/values-lt/strings.xml5
-rw-r--r--packages/SystemUI/res/values-lv/strings.xml5
-rw-r--r--packages/SystemUI/res/values-mn/strings.xml204
-rw-r--r--packages/SystemUI/res/values-ms/strings.xml2
-rw-r--r--packages/SystemUI/res/values-nb/strings.xml5
-rw-r--r--packages/SystemUI/res/values-ne/strings.xml204
-rw-r--r--packages/SystemUI/res/values-nl/strings.xml2
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml5
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings.xml5
-rw-r--r--packages/SystemUI/res/values-pt/strings.xml5
-rw-r--r--packages/SystemUI/res/values-rm/strings.xml4
-rw-r--r--packages/SystemUI/res/values-ro/strings.xml5
-rw-r--r--packages/SystemUI/res/values-ru/strings.xml5
-rw-r--r--packages/SystemUI/res/values-si/strings.xml204
-rw-r--r--packages/SystemUI/res/values-sk/strings.xml5
-rw-r--r--packages/SystemUI/res/values-sl/strings.xml5
-rw-r--r--packages/SystemUI/res/values-sr/strings.xml2
-rw-r--r--packages/SystemUI/res/values-sv/strings.xml5
-rw-r--r--packages/SystemUI/res/values-sw/strings.xml2
-rw-r--r--packages/SystemUI/res/values-th/strings.xml2
-rw-r--r--packages/SystemUI/res/values-tl/strings.xml2
-rw-r--r--packages/SystemUI/res/values-tr/strings.xml5
-rw-r--r--packages/SystemUI/res/values-uk/strings.xml5
-rw-r--r--packages/SystemUI/res/values-vi/strings.xml5
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings.xml5
-rw-r--r--packages/SystemUI/res/values-zh-rHK/strings.xml206
-rw-r--r--packages/SystemUI/res/values-zh-rTW/strings.xml2
-rw-r--r--packages/SystemUI/res/values-zu/strings.xml2
-rw-r--r--packages/SystemUI/res/values/arrays.xml12
-rw-r--r--packages/SystemUI/res/values/colors.xml6
-rw-r--r--packages/SystemUI/res/values/strings.xml7
-rwxr-xr-xpackages/SystemUI/src/com/android/systemui/BatteryMeterView.java302
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java108
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java86
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java59
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java129
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java41
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/Prefs.java2
-rw-r--r--packages/services/PacProcessor/Android.mk27
-rw-r--r--packages/services/PacProcessor/AndroidManifest.xml16
-rw-r--r--packages/services/PacProcessor/IProxyService.cpp97
-rw-r--r--packages/services/PacProcessor/IProxyService.h59
-rw-r--r--packages/services/PacProcessor/ProxyService.cpp96
-rw-r--r--packages/services/PacProcessor/ProxyService.h33
-rw-r--r--packages/services/PacProcessor/com/android/net/IProxyService.aidl (renamed from packages/SystemUI/res/values-land/refs.xml)21
-rw-r--r--packages/services/PacProcessor/jni/Android.mk41
-rw-r--r--packages/services/PacProcessor/jni/com_android_pacprocessor_PacNative.cpp148
-rw-r--r--packages/services/PacProcessor/jni/jni_init.cpp38
-rw-r--r--packages/services/PacProcessor/main_pacserver.cpp43
-rw-r--r--packages/services/PacProcessor/res/values/strings.xml6
-rw-r--r--packages/services/PacProcessor/src/com/android/pacprocessor/PacNative.java86
-rw-r--r--packages/services/PacProcessor/src/com/android/pacprocessor/PacService.java101
-rw-r--r--packages/services/Proxy/AndroidManifest.xml1
-rw-r--r--packages/services/Proxy/com/android/net/IProxyService.aidl16
-rw-r--r--packages/services/Proxy/src/com/android/proxyhandler/ProxyService.java10
-rw-r--r--packages/services/Proxy/src/com/android/proxyhandler/ProxyServiceReceiver.java13
146 files changed, 7974 insertions, 2481 deletions
diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml
index 27f93c0..d79f5c6 100644
--- a/packages/DocumentsUI/AndroidManifest.xml
+++ b/packages/DocumentsUI/AndroidManifest.xml
@@ -4,6 +4,7 @@
<uses-permission android:name="android.permission.MANAGE_DOCUMENTS" />
<application
+ android:name=".DocumentsApplication"
android:label="@string/app_label"
android:supportsRtl="true">
@@ -17,13 +18,27 @@
<intent-filter android:priority="100">
<action android:name="android.intent.action.OPEN_DOCUMENT" />
<category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.OPENABLE" />
<data android:mimeType="*/*" />
</intent-filter>
<intent-filter android:priority="100">
<action android:name="android.intent.action.CREATE_DOCUMENT" />
<category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.OPENABLE" />
<data android:mimeType="*/*" />
</intent-filter>
+ <intent-filter android:priority="100">
+ <action android:name="android.intent.action.GET_CONTENT" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.OPENABLE" />
+ <data android:mimeType="*/*" />
+ </intent-filter>
+ <!-- data expected to point at existing root to manage -->
+ <intent-filter>
+ <action android:name="android.intent.action.MANAGE_DOCUMENT" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <data android:mimeType="vnd.android.cursor.item/root" />
+ </intent-filter>
</activity>
<activity
@@ -37,6 +52,14 @@
android:authorities="com.android.documentsui.recents"
android:exported="false" />
+ <receiver android:name=".DocumentChangedReceiver">
+ <intent-filter>
+ <action android:name="android.provider.action.DOCUMENT_CHANGED" />
+ <data android:mimeType="vnd.android.cursor.dir/root" />
+ <data android:mimeType="vnd.android.cursor.item/root" />
+ </intent-filter>
+ </receiver>
+
<!-- TODO: remove when we have real clients -->
<activity android:name=".TestActivity" android:enabled="false">
<intent-filter>
diff --git a/packages/DocumentsUI/res/layout/fragment_directory.xml b/packages/DocumentsUI/res/layout/fragment_directory.xml
index 8dbd1de..67c5954 100644
--- a/packages/DocumentsUI/res/layout/fragment_directory.xml
+++ b/packages/DocumentsUI/res/layout/fragment_directory.xml
@@ -42,4 +42,12 @@
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:visibility="gone" />
+ <Button
+ android:id="@+id/more"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom"
+ android:text="@string/more"
+ android:visibility="gone" />
+
</FrameLayout>
diff --git a/packages/DocumentsUI/res/menu/mode_directory.xml b/packages/DocumentsUI/res/menu/mode_directory.xml
index 6b6d7e9..624e024 100644
--- a/packages/DocumentsUI/res/menu/mode_directory.xml
+++ b/packages/DocumentsUI/res/menu/mode_directory.xml
@@ -19,4 +19,14 @@
android:id="@+id/menu_open"
android:title="@string/menu_open"
android:showAsAction="always" />
+ <item
+ android:id="@+id/menu_share"
+ android:icon="@android:drawable/ic_menu_share"
+ android:title="@string/menu_share"
+ android:showAsAction="always" />
+ <item
+ android:id="@+id/menu_delete"
+ android:icon="@android:drawable/ic_menu_delete"
+ android:title="@string/menu_delete"
+ android:showAsAction="always" />
</menu>
diff --git a/packages/DocumentsUI/res/values/strings.xml b/packages/DocumentsUI/res/values/strings.xml
index 84f89b4..928ba85 100644
--- a/packages/DocumentsUI/res/values/strings.xml
+++ b/packages/DocumentsUI/res/values/strings.xml
@@ -29,6 +29,8 @@
<string name="menu_open">Open</string>
<string name="menu_save">Save</string>
+ <string name="menu_share">Share</string>
+ <string name="menu_delete">Delete</string>
<string name="mode_selected_count"><xliff:g id="count" example="3">%1$d</xliff:g> selected</string>
@@ -47,6 +49,7 @@
<string name="root_type_service">Services</string>
<string name="root_type_shortcut">Shortcuts</string>
<string name="root_type_device">Devices</string>
+ <string name="root_type_apps">More apps</string>
<string name="pref_advanced_devices">Display advanced devices</string>
<string name="pref_file_size">Display file size</string>
@@ -54,4 +57,10 @@
<string name="empty">No items</string>
+ <string name="toast_no_application">Can\'t open file</string>
+ <string name="toast_failed_delete">Unable to delete some documents</string>
+
+ <string name="more">More</string>
+ <string name="loading">Loading\u2026</string>
+
</resources>
diff --git a/packages/DocumentsUI/res/xml/document_provider.xml b/packages/DocumentsUI/res/xml/document_provider.xml
new file mode 100644
index 0000000..77891cb
--- /dev/null
+++ b/packages/DocumentsUI/res/xml/document_provider.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<documents-provider xmlns:android="http://schemas.android.com/apk/res/android"
+ android:customRoots="true">
+</documents-provider>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
index 313774b..575947f 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
@@ -27,8 +27,8 @@ import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.net.Uri;
import android.os.Bundle;
-import android.provider.DocumentsContract;
import android.provider.DocumentsContract.DocumentColumns;
+import android.provider.DocumentsContract.Documents;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
@@ -69,7 +69,7 @@ public class CreateDirectoryFragment extends DialogFragment {
final String displayName = text1.getText().toString();
final ContentValues values = new ContentValues();
- values.put(DocumentColumns.MIME_TYPE, DocumentsContract.MIME_TYPE_DIRECTORY);
+ values.put(DocumentColumns.MIME_TYPE, Documents.MIME_TYPE_DIR);
values.put(DocumentColumns.DISPLAY_NAME, displayName);
final DocumentsActivity activity = (DocumentsActivity) getActivity();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
index 5a6060a..dd9aee5 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
@@ -16,17 +16,33 @@
package com.android.documentsui;
+import static com.android.documentsui.DocumentsActivity.TAG;
+import static com.android.documentsui.DocumentsActivity.DisplayState.ACTION_MANAGE;
+import static com.android.documentsui.DocumentsActivity.DisplayState.MODE_GRID;
+import static com.android.documentsui.DocumentsActivity.DisplayState.MODE_LIST;
+import static com.android.documentsui.DocumentsActivity.DisplayState.SORT_ORDER_DATE;
+import static com.android.documentsui.DocumentsActivity.DisplayState.SORT_ORDER_NAME;
+import static com.android.documentsui.DocumentsActivity.DisplayState.SORT_ORDER_SIZE;
+
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.app.LoaderManager.LoaderCallbacks;
+import android.content.ContentResolver;
import android.content.Context;
+import android.content.Intent;
import android.content.Loader;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.Point;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.DocumentsContract;
import android.text.format.DateUtils;
import android.text.format.Formatter;
+import android.text.format.Time;
+import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.ActionMode;
import android.view.LayoutInflater;
@@ -39,10 +55,12 @@ import android.widget.AbsListView.MultiChoiceModeListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
+import android.widget.Button;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
+import android.widget.Toast;
import com.android.documentsui.DocumentsActivity.DisplayState;
import com.android.documentsui.model.Document;
@@ -50,7 +68,6 @@ import com.android.documentsui.model.Root;
import com.android.internal.util.Predicate;
import com.google.android.collect.Lists;
-import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
@@ -64,6 +81,7 @@ public class DirectoryFragment extends Fragment {
private View mEmptyView;
private ListView mListView;
private GridView mGridView;
+ private Button mMoreView;
private AbsListView mCurrentView;
@@ -75,8 +93,10 @@ public class DirectoryFragment extends Fragment {
private int mType = TYPE_NORMAL;
+ private Point mThumbSize;
+
private DocumentsAdapter mAdapter;
- private LoaderCallbacks<List<Document>> mCallbacks;
+ private LoaderCallbacks<DirectoryResult> mCallbacks;
private static final String EXTRA_TYPE = "type";
private static final String EXTRA_URI = "uri";
@@ -133,18 +153,20 @@ public class DirectoryFragment extends Fragment {
mGridView.setOnItemClickListener(mItemListener);
mGridView.setMultiChoiceModeListener(mMultiListener);
+ mMoreView = (Button) view.findViewById(R.id.more);
+
mAdapter = new DocumentsAdapter();
final Uri uri = getArguments().getParcelable(EXTRA_URI);
mType = getArguments().getInt(EXTRA_TYPE);
- mCallbacks = new LoaderCallbacks<List<Document>>() {
+ mCallbacks = new LoaderCallbacks<DirectoryResult>() {
@Override
- public Loader<List<Document>> onCreateLoader(int id, Bundle args) {
+ public Loader<DirectoryResult> onCreateLoader(int id, Bundle args) {
final DisplayState state = getDisplayState(DirectoryFragment.this);
mFilter = new MimePredicate(state.acceptMimes);
- final Uri contentsUri;
+ Uri contentsUri;
if (mType == TYPE_NORMAL) {
contentsUri = DocumentsContract.buildContentsUri(uri);
} else if (mType == TYPE_RECENT_OPEN) {
@@ -153,12 +175,16 @@ public class DirectoryFragment extends Fragment {
contentsUri = uri;
}
+ if (state.localOnly) {
+ contentsUri = DocumentsContract.setLocalOnly(contentsUri);
+ }
+
final Comparator<Document> sortOrder;
- if (state.sortOrder == DisplayState.SORT_ORDER_DATE || mType == TYPE_RECENT_OPEN) {
+ if (state.sortOrder == SORT_ORDER_DATE || mType == TYPE_RECENT_OPEN) {
sortOrder = new Document.DateComparator();
- } else if (state.sortOrder == DisplayState.SORT_ORDER_NAME) {
+ } else if (state.sortOrder == SORT_ORDER_NAME) {
sortOrder = new Document.NameComparator();
- } else if (state.sortOrder == DisplayState.SORT_ORDER_SIZE) {
+ } else if (state.sortOrder == SORT_ORDER_SIZE) {
sortOrder = new Document.SizeComparator();
} else {
throw new IllegalArgumentException("Unknown sort order " + state.sortOrder);
@@ -168,12 +194,34 @@ public class DirectoryFragment extends Fragment {
}
@Override
- public void onLoadFinished(Loader<List<Document>> loader, List<Document> data) {
- mAdapter.swapDocuments(data);
+ public void onLoadFinished(Loader<DirectoryResult> loader, DirectoryResult result) {
+ mAdapter.swapDocuments(result.contents);
+
+ final Cursor cursor = result.cursor;
+ if (cursor != null && cursor.getExtras()
+ .getBoolean(DocumentsContract.EXTRA_HAS_MORE, false)) {
+ mMoreView.setText(R.string.more);
+ mMoreView.setVisibility(View.VISIBLE);
+ mMoreView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mMoreView.setText(R.string.loading);
+ final Bundle bundle = new Bundle();
+ bundle.putBoolean(DocumentsContract.EXTRA_REQUEST_MORE, true);
+ try {
+ cursor.respond(bundle);
+ } catch (Exception e) {
+ Log.w(TAG, "Failed to respond: " + e);
+ }
+ }
+ });
+ } else {
+ mMoreView.setVisibility(View.GONE);
+ }
}
@Override
- public void onLoaderReset(Loader<List<Document>> loader) {
+ public void onLoaderReset(Loader<DirectoryResult> loader) {
mAdapter.swapDocuments(null);
}
};
@@ -186,10 +234,6 @@ public class DirectoryFragment extends Fragment {
@Override
public void onStart() {
super.onStart();
-
- final Context context = getActivity();
- getDisplayState(this).showSize = SettingsActivity.getDisplayFileSize(context);
-
getLoaderManager().restartLoader(mLoaderId, getArguments(), mCallbacks);
}
@@ -207,8 +251,8 @@ public class DirectoryFragment extends Fragment {
mListView.smoothScrollToPosition(0);
mGridView.smoothScrollToPosition(0);
- mListView.setVisibility(state.mode == DisplayState.MODE_LIST ? View.VISIBLE : View.GONE);
- mGridView.setVisibility(state.mode == DisplayState.MODE_GRID ? View.VISIBLE : View.GONE);
+ mListView.setVisibility(state.mode == MODE_LIST ? View.VISIBLE : View.GONE);
+ mGridView.setVisibility(state.mode == MODE_GRID ? View.VISIBLE : View.GONE);
final int choiceMode;
if (state.allowMultiple) {
@@ -217,7 +261,9 @@ public class DirectoryFragment extends Fragment {
choiceMode = ListView.CHOICE_MODE_NONE;
}
- if (state.mode == DisplayState.MODE_GRID) {
+ final int thumbSize;
+ if (state.mode == MODE_GRID) {
+ thumbSize = getResources().getDimensionPixelSize(R.dimen.grid_width);
mListView.setAdapter(null);
mListView.setChoiceMode(ListView.CHOICE_MODE_NONE);
mGridView.setAdapter(mAdapter);
@@ -225,7 +271,8 @@ public class DirectoryFragment extends Fragment {
mGridView.setNumColumns(GridView.AUTO_FIT);
mGridView.setChoiceMode(choiceMode);
mCurrentView = mGridView;
- } else if (state.mode == DisplayState.MODE_LIST) {
+ } else if (state.mode == MODE_LIST) {
+ thumbSize = getResources().getDimensionPixelSize(android.R.dimen.app_icon_size);
mGridView.setAdapter(null);
mGridView.setChoiceMode(ListView.CHOICE_MODE_NONE);
mListView.setAdapter(mAdapter);
@@ -234,13 +281,17 @@ public class DirectoryFragment extends Fragment {
} else {
throw new IllegalStateException();
}
+
+ mThumbSize = new Point(thumbSize, thumbSize);
}
private OnItemClickListener mItemListener = new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final Document doc = mAdapter.getItem(position);
- ((DocumentsActivity) getActivity()).onDocumentPicked(doc);
+ if (mFilter.apply(doc)) {
+ ((DocumentsActivity) getActivity()).onDocumentPicked(doc);
+ }
}
};
@@ -253,26 +304,45 @@ public class DirectoryFragment extends Fragment {
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+ final DisplayState state = getDisplayState(DirectoryFragment.this);
+
+ final MenuItem open = menu.findItem(R.id.menu_open);
+ final MenuItem share = menu.findItem(R.id.menu_share);
+ final MenuItem delete = menu.findItem(R.id.menu_delete);
+
+ final boolean manageMode = state.action == ACTION_MANAGE;
+ open.setVisible(!manageMode);
+ share.setVisible(manageMode);
+ delete.setVisible(manageMode);
+
return true;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
- if (item.getItemId() == R.id.menu_open) {
- final Uri uri = getArguments().getParcelable(EXTRA_URI);
- final SparseBooleanArray checked = mCurrentView.getCheckedItemPositions();
- final ArrayList<Document> docs = Lists.newArrayList();
-
- final int size = checked.size();
- for (int i = 0; i < size; i++) {
- if (checked.valueAt(i)) {
- final Document doc = mAdapter.getItem(checked.keyAt(i));
- docs.add(doc);
- }
+ final SparseBooleanArray checked = mCurrentView.getCheckedItemPositions();
+ final ArrayList<Document> docs = Lists.newArrayList();
+ final int size = checked.size();
+ for (int i = 0; i < size; i++) {
+ if (checked.valueAt(i)) {
+ final Document doc = mAdapter.getItem(checked.keyAt(i));
+ docs.add(doc);
}
+ }
- ((DocumentsActivity) getActivity()).onDocumentsPicked(docs);
+ final int id = item.getItemId();
+ if (id == R.id.menu_open) {
+ DocumentsActivity.get(DirectoryFragment.this).onDocumentsPicked(docs);
return true;
+
+ } else if (id == R.id.menu_share) {
+ onShareDocuments(docs);
+ return true;
+
+ } else if (id == R.id.menu_delete) {
+ onDeleteDocuments(docs);
+ return true;
+
} else {
return false;
}
@@ -299,6 +369,58 @@ public class DirectoryFragment extends Fragment {
}
};
+ private void onShareDocuments(List<Document> docs) {
+ final ArrayList<Uri> uris = Lists.newArrayList();
+ for (Document doc : docs) {
+ uris.add(doc.uri);
+ }
+
+ final Intent intent;
+ if (uris.size() > 1) {
+ intent = new Intent(Intent.ACTION_SEND_MULTIPLE);
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ intent.addCategory(Intent.CATEGORY_DEFAULT);
+ // TODO: find common mimetype
+ intent.setType("*/*");
+ intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
+ } else {
+ intent = new Intent(Intent.ACTION_SEND);
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ intent.addCategory(Intent.CATEGORY_DEFAULT);
+ intent.setData(uris.get(0));
+ }
+
+ startActivity(intent);
+ }
+
+ private void onDeleteDocuments(List<Document> docs) {
+ final Context context = getActivity();
+ final ContentResolver resolver = context.getContentResolver();
+
+ boolean hadTrouble = false;
+ for (Document doc : docs) {
+ if (!doc.isDeleteSupported()) {
+ Log.w(TAG, "Skipping " + doc);
+ hadTrouble = true;
+ continue;
+ }
+
+ try {
+ if (resolver.delete(doc.uri, null, null) != 1) {
+ Log.w(TAG, "Failed to delete " + doc);
+ hadTrouble = true;
+ }
+ } catch (Exception e) {
+ Log.w(TAG, "Failed to delete " + doc + ": " + e);
+ hadTrouble = true;
+ }
+ }
+
+ if (hadTrouble) {
+ Toast.makeText(context, R.string.toast_failed_delete, Toast.LENGTH_SHORT).show();
+ }
+ }
+
private static DisplayState getDisplayState(Fragment fragment) {
return ((DocumentsActivity) fragment.getActivity()).getDisplayState();
}
@@ -312,7 +434,7 @@ public class DirectoryFragment extends Fragment {
public void swapDocuments(List<Document> documents) {
mDocuments = documents;
- if (documents != null && documents.isEmpty()) {
+ if (mDocuments != null && mDocuments.isEmpty()) {
mEmptyView.setVisibility(View.VISIBLE);
} else {
mEmptyView.setVisibility(View.GONE);
@@ -326,11 +448,15 @@ public class DirectoryFragment extends Fragment {
final Context context = parent.getContext();
final DisplayState state = getDisplayState(DirectoryFragment.this);
+ final RootsCache roots = DocumentsApplication.getRootsCache(context);
+ final ThumbnailCache thumbs = DocumentsApplication.getThumbnailsCache(
+ context, mThumbSize);
+
if (convertView == null) {
final LayoutInflater inflater = LayoutInflater.from(context);
- if (state.mode == DisplayState.MODE_LIST) {
+ if (state.mode == MODE_LIST) {
convertView = inflater.inflate(R.layout.item_doc_list, parent, false);
- } else if (state.mode == DisplayState.MODE_GRID) {
+ } else if (state.mode == MODE_GRID) {
convertView = inflater.inflate(R.layout.item_doc_grid, parent, false);
} else {
throw new IllegalStateException();
@@ -347,11 +473,23 @@ public class DirectoryFragment extends Fragment {
final TextView date = (TextView) convertView.findViewById(R.id.date);
final TextView size = (TextView) convertView.findViewById(R.id.size);
+ final ThumbnailAsyncTask oldTask = (ThumbnailAsyncTask) icon.getTag();
+ if (oldTask != null) {
+ oldTask.cancel(false);
+ }
+
if (doc.isThumbnailSupported()) {
- // TODO: load thumbnails async
- icon.setImageURI(doc.uri);
+ final Bitmap cachedResult = thumbs.get(doc.uri);
+ if (cachedResult != null) {
+ icon.setImageBitmap(cachedResult);
+ } else {
+ final ThumbnailAsyncTask task = new ThumbnailAsyncTask(icon, mThumbSize);
+ icon.setImageBitmap(null);
+ icon.setTag(task);
+ task.execute(doc.uri);
+ }
} else {
- icon.setImageDrawable(RootsCache.resolveDocumentIcon(
+ icon.setImageDrawable(roots.resolveDocumentIcon(
context, doc.uri.getAuthority(), doc.mimeType));
}
@@ -366,7 +504,7 @@ public class DirectoryFragment extends Fragment {
summary.setVisibility(View.INVISIBLE);
}
} else if (mType == TYPE_RECENT_OPEN) {
- final Root root = RootsCache.findRoot(context, doc);
+ final Root root = roots.findRoot(doc);
icon1.setVisibility(View.VISIBLE);
icon1.setImageDrawable(root.icon);
summary.setText(root.getDirectoryString());
@@ -378,14 +516,15 @@ public class DirectoryFragment extends Fragment {
(summary.getVisibility() == View.VISIBLE) ? View.VISIBLE : View.GONE);
}
- // TODO: omit year from format
- date.setText(DateUtils.formatSameDayTime(
- doc.lastModified, System.currentTimeMillis(), DateFormat.SHORT,
- DateFormat.SHORT));
+ if (doc.lastModified == -1) {
+ date.setText(null);
+ } else {
+ date.setText(formatTime(context, doc.lastModified));
+ }
if (state.showSize) {
size.setVisibility(View.VISIBLE);
- if (doc.isDirectory()) {
+ if (doc.isDirectory() || doc.size == -1) {
size.setText(null);
} else {
size.setText(Formatter.formatFileSize(context, doc.size));
@@ -411,16 +550,69 @@ public class DirectoryFragment extends Fragment {
public long getItemId(int position) {
return getItem(position).uri.hashCode();
}
+ }
+
+ private static class ThumbnailAsyncTask extends AsyncTask<Uri, Void, Bitmap> {
+ private final ImageView mTarget;
+ private final Point mThumbSize;
+
+ public ThumbnailAsyncTask(ImageView target, Point thumbSize) {
+ mTarget = target;
+ mThumbSize = thumbSize;
+ }
@Override
- public boolean areAllItemsEnabled() {
- return false;
+ protected void onPreExecute() {
+ mTarget.setTag(this);
}
@Override
- public boolean isEnabled(int position) {
- final Document doc = getItem(position);
- return mFilter.apply(doc);
+ protected Bitmap doInBackground(Uri... params) {
+ final Context context = mTarget.getContext();
+ final Uri uri = params[0];
+
+ Bitmap result = null;
+ try {
+ result = DocumentsContract.getThumbnail(
+ context.getContentResolver(), uri, mThumbSize);
+ if (result != null) {
+ final ThumbnailCache thumbs = DocumentsApplication.getThumbnailsCache(
+ context, mThumbSize);
+ thumbs.put(uri, result);
+ }
+ } catch (Exception e) {
+ Log.w(TAG, "Failed to load thumbnail: " + e);
+ }
+ return result;
+ }
+
+ @Override
+ protected void onPostExecute(Bitmap result) {
+ if (mTarget.getTag() == this) {
+ mTarget.setImageBitmap(result);
+ mTarget.setTag(null);
+ }
+ }
+ }
+
+ private static String formatTime(Context context, long when) {
+ // TODO: DateUtils should make this easier
+ Time then = new Time();
+ then.set(when);
+ Time now = new Time();
+ now.setToNow();
+
+ int flags = DateUtils.FORMAT_NO_NOON | DateUtils.FORMAT_NO_MIDNIGHT
+ | DateUtils.FORMAT_ABBREV_ALL;
+
+ if (then.year != now.year) {
+ flags |= DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_SHOW_DATE;
+ } else if (then.yearDay != now.yearDay) {
+ flags |= DateUtils.FORMAT_SHOW_DATE;
+ } else {
+ flags |= DateUtils.FORMAT_SHOW_TIME;
}
+
+ return DateUtils.formatDateTime(context, when, flags);
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
index 94c2b61..14d6fd5 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
@@ -26,6 +26,7 @@ import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.CancellationSignal;
+import android.provider.DocumentsContract.DocumentColumns;
import android.util.Log;
import com.android.documentsui.model.Document;
@@ -35,12 +36,22 @@ import com.google.android.collect.Lists;
import libcore.io.IoUtils;
import java.io.FileNotFoundException;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
-public class DirectoryLoader extends UriDerivativeLoader<List<Document>> {
+class DirectoryResult implements AutoCloseable {
+ Cursor cursor;
+ List<Document> contents = Lists.newArrayList();
+ Exception e;
+
+ @Override
+ public void close() throws Exception {
+ IoUtils.closeQuietly(cursor);
+ }
+}
+
+public class DirectoryLoader extends UriDerivativeLoader<Uri, DirectoryResult> {
private final int mType;
private Predicate<Document> mFilter;
@@ -55,43 +66,60 @@ public class DirectoryLoader extends UriDerivativeLoader<List<Document>> {
}
@Override
- public List<Document> loadInBackground(Uri uri, CancellationSignal signal) {
- final ArrayList<Document> result = Lists.newArrayList();
+ public DirectoryResult loadInBackground(Uri uri, CancellationSignal signal) {
+ final DirectoryResult result = new DirectoryResult();
+ try {
+ loadInBackgroundInternal(result, uri, signal);
+ } catch (Exception e) {
+ result.e = e;
+ }
+ return result;
+ }
- // TODO: send selection and sorting hints to backend
+ private void loadInBackgroundInternal(
+ DirectoryResult result, Uri uri, CancellationSignal signal) {
final ContentResolver resolver = getContext().getContentResolver();
- final Cursor cursor = resolver.query(uri, null, null, null, null, signal);
- try {
- while (cursor != null && cursor.moveToNext()) {
- Document doc = null;
- switch (mType) {
- case TYPE_NORMAL:
- case TYPE_SEARCH:
- doc = Document.fromDirectoryCursor(uri, cursor);
- break;
- case TYPE_RECENT_OPEN:
- try {
- doc = Document.fromRecentOpenCursor(resolver, cursor);
- } catch (FileNotFoundException e) {
- Log.w(TAG, "Failed to find recent: " + e);
- }
- break;
- default:
- throw new IllegalArgumentException("Unknown type");
- }
-
- if (doc != null && (mFilter == null || mFilter.apply(doc))) {
- result.add(doc);
- }
+ final Cursor cursor = resolver.query(uri, null, null, null, getQuerySortOrder(), signal);
+ result.cursor = cursor;
+ result.cursor.registerContentObserver(mObserver);
+
+ while (cursor.moveToNext()) {
+ Document doc = null;
+ switch (mType) {
+ case TYPE_NORMAL:
+ case TYPE_SEARCH:
+ doc = Document.fromDirectoryCursor(uri, cursor);
+ break;
+ case TYPE_RECENT_OPEN:
+ try {
+ doc = Document.fromRecentOpenCursor(resolver, cursor);
+ } catch (FileNotFoundException e) {
+ Log.w(TAG, "Failed to find recent: " + e);
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown type");
+ }
+
+ if (doc != null && (mFilter == null || mFilter.apply(doc))) {
+ result.contents.add(doc);
}
- } finally {
- IoUtils.closeQuietly(cursor);
}
if (mSortOrder != null) {
- Collections.sort(result, mSortOrder);
+ Collections.sort(result.contents, mSortOrder);
}
+ }
- return result;
+ private String getQuerySortOrder() {
+ if (mSortOrder instanceof Document.DateComparator) {
+ return DocumentColumns.LAST_MODIFIED + " DESC";
+ } else if (mSortOrder instanceof Document.NameComparator) {
+ return DocumentColumns.DISPLAY_NAME + " ASC";
+ } else if (mSortOrder instanceof Document.SizeComparator) {
+ return DocumentColumns.SIZE + " DESC";
+ } else {
+ return null;
+ }
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentChangedReceiver.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentChangedReceiver.java
new file mode 100644
index 0000000..72afd9e
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentChangedReceiver.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui;
+
+import static com.android.documentsui.DocumentsActivity.TAG;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+import com.android.documentsui.model.Root;
+
+/**
+ * Handles {@link Root} changes which invalidate cached data.
+ */
+public class DocumentChangedReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.d(TAG, "Regenerating roots cache");
+ DocumentsApplication.getRootsCache(context).update();
+ // TODO: invalidate cached data in recents provider
+ }
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index a536acb..091737d 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -16,19 +16,31 @@
package com.android.documentsui;
+import static com.android.documentsui.DocumentsActivity.DisplayState.ACTION_CREATE;
+import static com.android.documentsui.DocumentsActivity.DisplayState.ACTION_GET_CONTENT;
+import static com.android.documentsui.DocumentsActivity.DisplayState.ACTION_MANAGE;
+import static com.android.documentsui.DocumentsActivity.DisplayState.ACTION_OPEN;
+import static com.android.documentsui.DocumentsActivity.DisplayState.MODE_GRID;
+import static com.android.documentsui.DocumentsActivity.DisplayState.MODE_LIST;
+import static com.android.documentsui.DocumentsActivity.DisplayState.SORT_ORDER_DATE;
+
import android.app.ActionBar;
import android.app.ActionBar.OnNavigationListener;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
+import android.content.ActivityNotFoundException;
import android.content.ClipData;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Intent;
+import android.content.pm.ResolveInfo;
import android.database.Cursor;
import android.graphics.drawable.ColorDrawable;
import android.net.Uri;
import android.os.Bundle;
+import android.provider.DocumentsContract;
import android.provider.DocumentsContract.DocumentColumns;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.view.GravityCompat;
@@ -58,9 +70,6 @@ import java.util.List;
public class DocumentsActivity extends Activity {
public static final String TAG = "Documents";
- public static final int ACTION_OPEN = 1;
- public static final int ACTION_CREATE = 2;
-
private int mAction;
private SearchView mSearchView;
@@ -71,6 +80,8 @@ public class DocumentsActivity extends Activity {
private final DisplayState mDisplayState = new DisplayState();
+ private RootsCache mRoots;
+
/** Current user navigation stack; empty implies recents. */
private DocumentStack mStack = new DocumentStack();
/** Currently active search, overriding any stack. */
@@ -80,28 +91,38 @@ public class DocumentsActivity extends Activity {
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
+ mRoots = DocumentsApplication.getRootsCache(this);
+
final Intent intent = getIntent();
final String action = intent.getAction();
if (Intent.ACTION_OPEN_DOCUMENT.equals(action)) {
mAction = ACTION_OPEN;
- mDisplayState.allowMultiple = intent.getBooleanExtra(
- Intent.EXTRA_ALLOW_MULTIPLE, false);
} else if (Intent.ACTION_CREATE_DOCUMENT.equals(action)) {
mAction = ACTION_CREATE;
- mDisplayState.allowMultiple = false;
+ } else if (Intent.ACTION_GET_CONTENT.equals(action)) {
+ mAction = ACTION_GET_CONTENT;
+ } else if (Intent.ACTION_MANAGE_DOCUMENT.equals(action)) {
+ mAction = ACTION_MANAGE;
}
- if (intent.hasExtra(Intent.EXTRA_MIME_TYPES)) {
+ // TODO: unify action in single place
+ mDisplayState.action = mAction;
+
+ if (mAction == ACTION_OPEN || mAction == ACTION_GET_CONTENT) {
+ mDisplayState.allowMultiple = intent.getBooleanExtra(
+ Intent.EXTRA_ALLOW_MULTIPLE, false);
+ }
+
+ if (mAction == ACTION_MANAGE) {
+ mDisplayState.acceptMimes = new String[] { "*/*" };
+ mDisplayState.allowMultiple = true;
+ } else if (intent.hasExtra(Intent.EXTRA_MIME_TYPES)) {
mDisplayState.acceptMimes = intent.getStringArrayExtra(Intent.EXTRA_MIME_TYPES);
} else {
mDisplayState.acceptMimes = new String[] { intent.getType() };
}
- if (MimePredicate.mimeMatches("image/*", mDisplayState.acceptMimes)) {
- mDisplayState.mode = DisplayState.MODE_GRID;
- } else {
- mDisplayState.mode = DisplayState.MODE_LIST;
- }
+ mDisplayState.localOnly = intent.getBooleanExtra(Intent.EXTRA_LOCAL_ONLY, false);
setResult(Activity.RESULT_CANCELED);
setContentView(R.layout.activity);
@@ -112,7 +133,18 @@ public class DocumentsActivity extends Activity {
SaveFragment.show(getFragmentManager(), mimeType, title);
}
- RootsFragment.show(getFragmentManager());
+ if (mAction == ACTION_GET_CONTENT) {
+ final Intent moreApps = new Intent(getIntent());
+ moreApps.setComponent(null);
+ moreApps.setPackage(null);
+ RootsFragment.show(getFragmentManager(), moreApps);
+ } else if (mAction == ACTION_OPEN || mAction == ACTION_CREATE) {
+ RootsFragment.show(getFragmentManager(), null);
+ }
+
+ if (mAction == ACTION_MANAGE) {
+ mDisplayState.sortOrder = SORT_ORDER_DATE;
+ }
mRootsContainer = findViewById(R.id.container_roots);
@@ -124,26 +156,54 @@ public class DocumentsActivity extends Activity {
mDrawerLayout.setDrawerListener(mDrawerListener);
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
- mDrawerLayout.openDrawer(mRootsContainer);
+ if (mAction == ACTION_MANAGE) {
+ mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
- // Restore last stack for calling package
- // TODO: move into async loader
- final String packageName = getCallingPackage();
- final Cursor cursor = getContentResolver()
- .query(RecentsProvider.buildResume(packageName), null, null, null, null);
- try {
- if (cursor.moveToFirst()) {
- final String raw = cursor.getString(
- cursor.getColumnIndex(RecentsProvider.COL_PATH));
- mStack = DocumentStack.deserialize(getContentResolver(), raw);
+ final Uri rootUri = intent.getData();
+ final String authority = rootUri.getAuthority();
+ final String rootId = DocumentsContract.getRootId(rootUri);
+
+ final Root root = mRoots.findRoot(authority, rootId);
+ if (root != null) {
+ onRootPicked(root, true);
+ } else {
+ Log.w(TAG, "Failed to find root: " + rootUri);
+ finish();
}
- } catch (FileNotFoundException e) {
- Log.w(TAG, "Failed to resume", e);
- } finally {
- cursor.close();
+
+ } else {
+ mDrawerLayout.openDrawer(mRootsContainer);
+
+ // Restore last stack for calling package
+ // TODO: move into async loader
+ final String packageName = getCallingPackage();
+ final Cursor cursor = getContentResolver()
+ .query(RecentsProvider.buildResume(packageName), null, null, null, null);
+ try {
+ if (cursor.moveToFirst()) {
+ final String raw = cursor.getString(
+ cursor.getColumnIndex(RecentsProvider.COL_PATH));
+ mStack = DocumentStack.deserialize(getContentResolver(), raw);
+ }
+ } catch (FileNotFoundException e) {
+ Log.w(TAG, "Failed to resume", e);
+ } finally {
+ cursor.close();
+ }
+
+ onCurrentDirectoryChanged();
}
+ }
- onCurrentDirectoryChanged();
+ @Override
+ public void onStart() {
+ super.onStart();
+
+ if (mAction == ACTION_MANAGE) {
+ mDisplayState.showSize = true;
+ } else {
+ mDisplayState.showSize = SettingsActivity.getDisplayFileSize(this);
+ }
}
private DrawerListener mDrawerListener = new DrawerListener() {
@@ -180,18 +240,20 @@ public class DocumentsActivity extends Activity {
final ActionBar actionBar = getActionBar();
actionBar.setDisplayShowHomeEnabled(true);
- actionBar.setDisplayHomeAsUpEnabled(true);
if (mDrawerLayout.isDrawerOpen(mRootsContainer)) {
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
actionBar.setIcon(new ColorDrawable());
- if (mAction == ACTION_OPEN) {
+ if (mAction == ACTION_OPEN || mAction == ACTION_GET_CONTENT) {
actionBar.setTitle(R.string.title_open);
} else if (mAction == ACTION_CREATE) {
actionBar.setTitle(R.string.title_save);
}
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ mDrawerToggle.setDrawerIndicatorEnabled(true);
+
} else {
final Root root = getCurrentRoot();
actionBar.setIcon(root != null ? root.icon : null);
@@ -207,8 +269,13 @@ public class DocumentsActivity extends Activity {
}
if (mStack.size() > 1) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ mDrawerToggle.setDrawerIndicatorEnabled(false);
+ } else if (mAction == ACTION_MANAGE) {
+ actionBar.setDisplayHomeAsUpEnabled(false);
mDrawerToggle.setDrawerIndicatorEnabled(false);
} else {
+ actionBar.setDisplayHomeAsUpEnabled(true);
mDrawerToggle.setDrawerIndicatorEnabled(true);
}
}
@@ -259,9 +326,10 @@ public class DocumentsActivity extends Activity {
final MenuItem search = menu.findItem(R.id.menu_search);
final MenuItem grid = menu.findItem(R.id.menu_grid);
final MenuItem list = menu.findItem(R.id.menu_list);
+ final MenuItem settings = menu.findItem(R.id.menu_settings);
- grid.setVisible(mDisplayState.mode != DisplayState.MODE_GRID);
- list.setVisible(mDisplayState.mode != DisplayState.MODE_LIST);
+ grid.setVisible(mDisplayState.mode != MODE_GRID);
+ list.setVisible(mDisplayState.mode != MODE_LIST);
final boolean searchVisible;
if (mAction == ACTION_CREATE) {
@@ -283,6 +351,8 @@ public class DocumentsActivity extends Activity {
// TODO: close any search in-progress when hiding
search.setVisible(searchVisible);
+ settings.setVisible(mAction != ACTION_MANAGE);
+
return true;
}
@@ -302,12 +372,14 @@ public class DocumentsActivity extends Activity {
} else if (id == R.id.menu_search) {
return false;
} else if (id == R.id.menu_grid) {
- mDisplayState.mode = DisplayState.MODE_GRID;
+ // TODO: persist explicit user mode for cwd
+ mDisplayState.mode = MODE_GRID;
updateDisplayState();
invalidateOptionsMenu();
return true;
} else if (id == R.id.menu_list) {
- mDisplayState.mode = DisplayState.MODE_LIST;
+ // TODO: persist explicit user mode for cwd
+ mDisplayState.mode = MODE_LIST;
updateDisplayState();
invalidateOptionsMenu();
return true;
@@ -408,9 +480,9 @@ public class DocumentsActivity extends Activity {
public Root getCurrentRoot() {
final Document cwd = getCurrentDirectory();
if (cwd != null) {
- return RootsCache.findRoot(this, cwd);
+ return mRoots.findRoot(cwd);
} else {
- return RootsCache.getRecentsRoot(this);
+ return mRoots.getRecentsRoot();
}
}
@@ -484,27 +556,55 @@ public class DocumentsActivity extends Activity {
}
}
+ public void onAppPicked(ResolveInfo info) {
+ final Intent intent = new Intent(getIntent());
+ intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
+ intent.setComponent(new ComponentName(
+ info.activityInfo.applicationInfo.packageName, info.activityInfo.name));
+ startActivity(intent);
+ finish();
+ }
+
public void onDocumentPicked(Document doc) {
final FragmentManager fm = getFragmentManager();
if (doc.isDirectory()) {
+ // TODO: query display mode user preference for this dir
+ if (doc.isGridPreferred()) {
+ mDisplayState.mode = MODE_GRID;
+ } else {
+ mDisplayState.mode = MODE_LIST;
+ }
mStack.push(doc);
onCurrentDirectoryChanged();
- } else if (mAction == ACTION_OPEN) {
+ } else if (mAction == ACTION_OPEN || mAction == ACTION_GET_CONTENT) {
// Explicit file picked, return
onFinished(doc.uri);
} else if (mAction == ACTION_CREATE) {
// Replace selected file
SaveFragment.get(fm).setReplaceTarget(doc);
+ } else if (mAction == ACTION_MANAGE) {
+ // Open the document
+ // TODO: trampoline activity for launching downloaded APKs
+ final Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ intent.setData(doc.uri);
+ try {
+ startActivity(intent);
+ } catch (ActivityNotFoundException ex) {
+ Toast.makeText(this, R.string.toast_no_application, Toast.LENGTH_SHORT).show();
+ }
}
}
public void onDocumentsPicked(List<Document> docs) {
- final int size = docs.size();
- final Uri[] uris = new Uri[size];
- for (int i = 0; i < size; i++) {
- uris[i] = docs.get(i).uri;
+ if (mAction == ACTION_OPEN || mAction == ACTION_GET_CONTENT) {
+ final int size = docs.size();
+ final Uri[] uris = new Uri[size];
+ for (int i = 0; i < size; i++) {
+ uris[i] = docs.get(i).uri;
+ }
+ onFinished(uris);
}
- onFinished(uris);
}
public void onSaveRequested(Document replaceTarget) {
@@ -538,7 +638,7 @@ public class DocumentsActivity extends Activity {
values.put(RecentsProvider.COL_PATH, rawStack);
resolver.insert(RecentsProvider.buildRecentCreate(), values);
- } else if (mAction == ACTION_OPEN) {
+ } else if (mAction == ACTION_OPEN || mAction == ACTION_GET_CONTENT) {
// Remember opened items
for (Uri uri : uris) {
values.clear();
@@ -565,21 +665,31 @@ public class DocumentsActivity extends Activity {
intent.setClipData(clipData);
}
- // TODO: omit WRITE and PERSIST for GET_CONTENT
- intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
- | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
- | Intent.FLAG_PERSIST_GRANT_URI_PERMISSION);
+ if (mAction == ACTION_GET_CONTENT) {
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ } else {
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+ | Intent.FLAG_PERSIST_GRANT_URI_PERMISSION);
+ }
setResult(Activity.RESULT_OK, intent);
finish();
}
public static class DisplayState {
+ public int action;
public int mode = MODE_LIST;
public String[] acceptMimes;
public int sortOrder = SORT_ORDER_NAME;
public boolean allowMultiple = false;
public boolean showSize = false;
+ public boolean localOnly = false;
+
+ public static final int ACTION_OPEN = 1;
+ public static final int ACTION_CREATE = 2;
+ public static final int ACTION_GET_CONTENT = 3;
+ public static final int ACTION_MANAGE = 4;
public static final int MODE_LIST = 0;
public static final int MODE_GRID = 1;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java
new file mode 100644
index 0000000..0a6cbc0
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui;
+
+import android.app.ActivityManager;
+import android.app.Application;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.graphics.Point;
+
+public class DocumentsApplication extends Application {
+ private RootsCache mRoots;
+ private Point mThumbnailsSize;
+ private ThumbnailCache mThumbnails;
+
+ public static RootsCache getRootsCache(Context context) {
+ return ((DocumentsApplication) context.getApplicationContext()).mRoots;
+ }
+
+ public static ThumbnailCache getThumbnailsCache(Context context, Point size) {
+ final DocumentsApplication app = (DocumentsApplication) context.getApplicationContext();
+ final ThumbnailCache thumbnails = app.mThumbnails;
+ if (!size.equals(app.mThumbnailsSize)) {
+ thumbnails.evictAll();
+ app.mThumbnailsSize = size;
+ }
+ return thumbnails;
+ }
+
+ @Override
+ public void onCreate() {
+ final ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
+ final int memoryClassBytes = am.getMemoryClass() * 1024 * 1024;
+
+ mRoots = new RootsCache(this);
+ mThumbnails = new ThumbnailCache(memoryClassBytes / 4);
+
+ final IntentFilter packageFilter = new IntentFilter();
+ packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
+ packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+ packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ packageFilter.addDataScheme("package");
+ registerReceiver(mPackageReceiver, packageFilter);
+ }
+
+ @Override
+ public void onTrimMemory(int level) {
+ super.onTrimMemory(level);
+
+ if (level >= TRIM_MEMORY_MODERATE) {
+ mThumbnails.evictAll();
+ } else if (level >= TRIM_MEMORY_BACKGROUND) {
+ mThumbnails.trimToSize(mThumbnails.size() / 2);
+ }
+ }
+
+ private BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ // TODO: narrow changed/removed to only packages that have backends
+ mRoots.update();
+ }
+ };
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java b/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java
index f945c6a0..a9929de 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java
@@ -49,7 +49,9 @@ public class MimePredicate implements Predicate<Document> {
}
public static boolean mimeMatches(String filter, String test) {
- if (filter.equals(test)) {
+ if (test == null) {
+ return false;
+ } else if (filter.equals(test)) {
return true;
} else if ("*/*".equals(filter)) {
return true;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
index 5cdc915..5466dbf 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
@@ -124,7 +124,7 @@ public class RecentsCreateFragment extends Fragment {
}
};
- public static class RecentsCreateLoader extends UriDerivativeLoader<List<DocumentStack>> {
+ public static class RecentsCreateLoader extends UriDerivativeLoader<Uri, List<DocumentStack>> {
public RecentsCreateLoader(Context context) {
super(context, RecentsProvider.buildRecentCreate());
}
@@ -169,6 +169,7 @@ public class RecentsCreateFragment extends Fragment {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final Context context = parent.getContext();
+ final RootsCache roots = DocumentsApplication.getRootsCache(context);
if (convertView == null) {
final LayoutInflater inflater = LayoutInflater.from(context);
@@ -180,7 +181,7 @@ public class RecentsCreateFragment extends Fragment {
final View summaryList = convertView.findViewById(R.id.summary_list);
final DocumentStack stack = getItem(position);
- final Root root = RootsCache.findRoot(context, stack.peek());
+ final Root root = roots.findRoot(stack.peek());
icon.setImageDrawable(root != null ? root.icon : null);
final StringBuilder builder = new StringBuilder();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java b/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java
index 5268c1d..dbcb039 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java
@@ -129,11 +129,11 @@ public class RecentsProvider extends ContentProvider {
switch (sMatcher.match(uri)) {
case URI_RECENT_OPEN: {
return db.query(TABLE_RECENT_OPEN, projection,
- buildWhereYounger(DateUtils.WEEK_IN_MILLIS), null, null, null, sortOrder);
+ buildWhereYounger(DateUtils.WEEK_IN_MILLIS), null, null, null, null);
}
case URI_RECENT_CREATE: {
return db.query(TABLE_RECENT_CREATE, projection,
- buildWhereYounger(DateUtils.WEEK_IN_MILLIS), null, null, null, sortOrder);
+ buildWhereYounger(DateUtils.WEEK_IN_MILLIS), null, null, null, null);
}
case URI_RESUME: {
final String packageName = uri.getPathSegments().get(1);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
index b26db3b..c3b498e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
@@ -27,6 +27,7 @@ import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.provider.DocumentsContract;
+import android.provider.DocumentsContract.Documents;
import android.util.Log;
import android.util.Pair;
@@ -49,106 +50,110 @@ import java.util.List;
public class RootsCache {
// TODO: cache roots in local provider to avoid spinning up backends
+ // TODO: root updates should trigger UI refresh
- private static boolean sCached = false;
+ private final Context mContext;
/** Map from authority to cached info */
- private static HashMap<String, DocumentsProviderInfo> sProviders = Maps.newHashMap();
+ private HashMap<String, DocumentsProviderInfo> mProviders = Maps.newHashMap();
/** Map from (authority+rootId) to cached info */
- private static HashMap<Pair<String, String>, Root> sRoots = Maps.newHashMap();
+ private HashMap<Pair<String, String>, Root> mRoots = Maps.newHashMap();
- public static ArrayList<Root> sRootsList = Lists.newArrayList();
+ public ArrayList<Root> mRootsList = Lists.newArrayList();
- private static Root sRecentsRoot;
+ private Root mRecentsRoot;
+
+ public RootsCache(Context context) {
+ mContext = context;
+ update();
+ }
/**
* Gather roots from all known storage providers.
*/
- private static void ensureCache(Context context) {
- if (sCached) return;
- sCached = true;
-
- sProviders.clear();
- sRoots.clear();
- sRootsList.clear();
+ @GuardedBy("ActivityThread")
+ public void update() {
+ mProviders.clear();
+ mRoots.clear();
+ mRootsList.clear();
{
// Create special root for recents
- final Root root = Root.buildRecents(context);
- sRootsList.add(root);
- sRecentsRoot = root;
+ final Root root = Root.buildRecents(mContext);
+ mRootsList.add(root);
+ mRecentsRoot = root;
}
// Query for other storage backends
- final PackageManager pm = context.getPackageManager();
+ final PackageManager pm = mContext.getPackageManager();
final List<ProviderInfo> providers = pm.queryContentProviders(
null, -1, PackageManager.GET_META_DATA);
for (ProviderInfo providerInfo : providers) {
if (providerInfo.metaData != null && providerInfo.metaData.containsKey(
DocumentsContract.META_DATA_DOCUMENT_PROVIDER)) {
final DocumentsProviderInfo info = DocumentsProviderInfo.parseInfo(
- context, providerInfo);
+ mContext, providerInfo);
if (info == null) {
Log.w(TAG, "Missing info for " + providerInfo);
continue;
}
- sProviders.put(info.providerInfo.authority, info);
+ mProviders.put(info.providerInfo.authority, info);
- // TODO: remove deprecated customRoots flag
- // TODO: populate roots on background thread, and cache results
- final Uri uri = DocumentsContract.buildRootsUri(providerInfo.authority);
- final Cursor cursor = context.getContentResolver()
- .query(uri, null, null, null, null);
try {
- while (cursor.moveToNext()) {
- final Root root = Root.fromCursor(context, info, cursor);
- sRoots.put(Pair.create(info.providerInfo.authority, root.rootId), root);
- sRootsList.add(root);
+ // TODO: remove deprecated customRoots flag
+ // TODO: populate roots on background thread, and cache results
+ final Uri uri = DocumentsContract.buildRootsUri(providerInfo.authority);
+ final Cursor cursor = mContext.getContentResolver()
+ .query(uri, null, null, null, null);
+ try {
+ while (cursor.moveToNext()) {
+ final Root root = Root.fromCursor(mContext, info, cursor);
+ mRoots.put(Pair.create(info.providerInfo.authority, root.rootId), root);
+ mRootsList.add(root);
+ }
+ } finally {
+ cursor.close();
}
- } finally {
- cursor.close();
+ } catch (Exception e) {
+ Log.w(TAG, "Failed to load some roots from " + info.providerInfo.authority
+ + ": " + e);
}
}
}
}
@GuardedBy("ActivityThread")
- public static DocumentsProviderInfo findProvider(Context context, String authority) {
- ensureCache(context);
- return sProviders.get(authority);
+ public DocumentsProviderInfo findProvider(String authority) {
+ return mProviders.get(authority);
}
@GuardedBy("ActivityThread")
- public static Root findRoot(Context context, String authority, String rootId) {
- ensureCache(context);
- return sRoots.get(Pair.create(authority, rootId));
+ public Root findRoot(String authority, String rootId) {
+ return mRoots.get(Pair.create(authority, rootId));
}
@GuardedBy("ActivityThread")
- public static Root findRoot(Context context, Document doc) {
+ public Root findRoot(Document doc) {
final String authority = doc.uri.getAuthority();
final String rootId = DocumentsContract.getRootId(doc.uri);
- return findRoot(context, authority, rootId);
+ return findRoot(authority, rootId);
}
@GuardedBy("ActivityThread")
- public static Root getRecentsRoot(Context context) {
- ensureCache(context);
- return sRecentsRoot;
+ public Root getRecentsRoot() {
+ return mRecentsRoot;
}
@GuardedBy("ActivityThread")
- public static Collection<Root> getRoots(Context context) {
- ensureCache(context);
- return sRootsList;
+ public Collection<Root> getRoots() {
+ return mRootsList;
}
@GuardedBy("ActivityThread")
- public static Drawable resolveDocumentIcon(Context context, String authority, String mimeType) {
+ public Drawable resolveDocumentIcon(Context context, String authority, String mimeType) {
// Custom icons take precedence
- ensureCache(context);
- final DocumentsProviderInfo info = sProviders.get(authority);
+ final DocumentsProviderInfo info = mProviders.get(authority);
if (info != null) {
for (Icon icon : info.customIcons) {
if (MimePredicate.mimeMatches(icon.mimeType, mimeType)) {
@@ -157,7 +162,7 @@ public class RootsCache {
}
}
- if (DocumentsContract.MIME_TYPE_DIRECTORY.equals(mimeType)) {
+ if (Documents.MIME_TYPE_DIR.equals(mimeType)) {
return context.getResources().getDrawable(R.drawable.ic_dir);
} else {
final PackageManager pm = context.getPackageManager();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
index 427ad42..8a48e2a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
@@ -22,8 +22,11 @@ import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
import android.os.Bundle;
-import android.provider.DocumentsContract;
+import android.provider.DocumentsContract.Roots;
import android.text.format.Formatter;
import android.util.Log;
import android.view.LayoutInflater;
@@ -41,6 +44,7 @@ import com.android.documentsui.model.Root;
import com.android.documentsui.model.Root.RootComparator;
import java.util.Collection;
+import java.util.List;
/**
* Display list of known storage backend roots.
@@ -50,8 +54,14 @@ public class RootsFragment extends Fragment {
private ListView mList;
private SectionedRootsAdapter mAdapter;
- public static void show(FragmentManager fm) {
+ private static final String EXTRA_INCLUDE_APPS = "includeApps";
+
+ public static void show(FragmentManager fm, Intent includeApps) {
+ final Bundle args = new Bundle();
+ args.putParcelable(EXTRA_INCLUDE_APPS, includeApps);
+
final RootsFragment fragment = new RootsFragment();
+ fragment.setArguments(args);
final FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.container_roots, fragment);
@@ -66,14 +76,15 @@ public class RootsFragment extends Fragment {
public View onCreateView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final Context context = inflater.getContext();
+ final RootsCache roots = DocumentsApplication.getRootsCache(context);
final View view = inflater.inflate(R.layout.fragment_roots, container, false);
mList = (ListView) view.findViewById(android.R.id.list);
-
- mAdapter = new SectionedRootsAdapter(context, RootsCache.getRoots(context));
- mList.setAdapter(mAdapter);
mList.setOnItemClickListener(mItemListener);
+ final Intent includeApps = getArguments().getParcelable(EXTRA_INCLUDE_APPS);
+ mAdapter = new SectionedRootsAdapter(context, roots.getRoots(), includeApps);
+
return view;
}
@@ -82,18 +93,26 @@ public class RootsFragment extends Fragment {
super.onStart();
final Context context = getActivity();
- mAdapter.setShowAdvanced(SettingsActivity.getDisplayAdvancedDevices(context));
+ mAdapter.updateVisible(SettingsActivity.getDisplayAdvancedDevices(context));
+ mList.setAdapter(mAdapter);
}
private OnItemClickListener mItemListener = new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- final Root root = (Root) mAdapter.getItem(position);
- ((DocumentsActivity) getActivity()).onRootPicked(root, true);
+ final DocumentsActivity activity = DocumentsActivity.get(RootsFragment.this);
+ final Object item = mAdapter.getItem(position);
+ if (item instanceof Root) {
+ activity.onRootPicked((Root) item, true);
+ } else if (item instanceof ResolveInfo) {
+ activity.onAppPicked((ResolveInfo) item);
+ } else {
+ throw new IllegalStateException("Unknown root: " + item);
+ }
}
};
- public static class RootsAdapter extends ArrayAdapter<Root> implements SectionAdapter {
+ private static class RootsAdapter extends ArrayAdapter<Root> implements SectionAdapter {
private int mHeaderId;
public RootsAdapter(Context context, int headerId) {
@@ -119,8 +138,8 @@ public class RootsFragment extends Fragment {
// Device summary is always available space
final String summaryText;
- if ((root.rootType == DocumentsContract.ROOT_TYPE_DEVICE
- || root.rootType == DocumentsContract.ROOT_TYPE_DEVICE_ADVANCED)
+ if ((root.rootType == Roots.ROOT_TYPE_DEVICE
+ || root.rootType == Roots.ROOT_TYPE_DEVICE_ADVANCED)
&& root.availableBytes >= 0) {
summaryText = context.getString(R.string.root_available_bytes,
Formatter.formatFileSize(context, root.availableBytes));
@@ -148,37 +167,94 @@ public class RootsFragment extends Fragment {
}
}
- public static class SectionedRootsAdapter extends SectionedListAdapter {
+ private static class AppsAdapter extends ArrayAdapter<ResolveInfo> implements SectionAdapter {
+ public AppsAdapter(Context context) {
+ super(context, 0);
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ final Context context = parent.getContext();
+ final PackageManager pm = context.getPackageManager();
+ if (convertView == null) {
+ convertView = LayoutInflater.from(context)
+ .inflate(R.layout.item_root, parent, false);
+ }
+
+ final ImageView icon = (ImageView) convertView.findViewById(android.R.id.icon);
+ final TextView title = (TextView) convertView.findViewById(android.R.id.title);
+ final TextView summary = (TextView) convertView.findViewById(android.R.id.summary);
+
+ final ResolveInfo info = getItem(position);
+ icon.setImageDrawable(info.loadIcon(pm));
+ title.setText(info.loadLabel(pm));
+
+ // TODO: match existing summary behavior from disambig dialog
+ summary.setVisibility(View.GONE);
+
+ return convertView;
+ }
+
+ @Override
+ public View getHeaderView(View convertView, ViewGroup parent) {
+ if (convertView == null) {
+ convertView = LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.item_root_header, parent, false);
+ }
+
+ final TextView title = (TextView) convertView.findViewById(android.R.id.title);
+ title.setText(R.string.root_type_apps);
+
+ return convertView;
+ }
+ }
+
+ private static class SectionedRootsAdapter extends SectionedListAdapter {
private final RootsAdapter mServices;
private final RootsAdapter mShortcuts;
private final RootsAdapter mDevices;
private final RootsAdapter mDevicesAdvanced;
+ private final AppsAdapter mApps;
- public SectionedRootsAdapter(Context context, Collection<Root> roots) {
+ public SectionedRootsAdapter(Context context, Collection<Root> roots, Intent includeApps) {
mServices = new RootsAdapter(context, R.string.root_type_service);
mShortcuts = new RootsAdapter(context, R.string.root_type_shortcut);
mDevices = new RootsAdapter(context, R.string.root_type_device);
mDevicesAdvanced = new RootsAdapter(context, R.string.root_type_device);
+ mApps = new AppsAdapter(context);
for (Root root : roots) {
Log.d(TAG, "Found rootType=" + root.rootType);
switch (root.rootType) {
- case DocumentsContract.ROOT_TYPE_SERVICE:
+ case Roots.ROOT_TYPE_SERVICE:
mServices.add(root);
break;
- case DocumentsContract.ROOT_TYPE_SHORTCUT:
+ case Roots.ROOT_TYPE_SHORTCUT:
mShortcuts.add(root);
break;
- case DocumentsContract.ROOT_TYPE_DEVICE:
+ case Roots.ROOT_TYPE_DEVICE:
mDevices.add(root);
mDevicesAdvanced.add(root);
break;
- case DocumentsContract.ROOT_TYPE_DEVICE_ADVANCED:
+ case Roots.ROOT_TYPE_DEVICE_ADVANCED:
mDevicesAdvanced.add(root);
break;
}
}
+ if (includeApps != null) {
+ final PackageManager pm = context.getPackageManager();
+ final List<ResolveInfo> infos = pm.queryIntentActivities(
+ includeApps, PackageManager.MATCH_DEFAULT_ONLY);
+
+ // Omit ourselves from the list
+ for (ResolveInfo info : infos) {
+ if (!context.getPackageName().equals(info.activityInfo.packageName)) {
+ mApps.add(info);
+ }
+ }
+ }
+
final RootComparator comp = new RootComparator();
mServices.sort(comp);
mShortcuts.sort(comp);
@@ -186,7 +262,7 @@ public class RootsFragment extends Fragment {
mDevicesAdvanced.sort(comp);
}
- public void setShowAdvanced(boolean showAdvanced) {
+ public void updateVisible(boolean showAdvanced) {
clearSections();
if (mServices.getCount() > 0) {
addSection(mServices);
@@ -199,6 +275,10 @@ public class RootsFragment extends Fragment {
if (devices.getCount() > 0) {
addSection(devices);
}
+
+ if (mApps.getCount() > 0) {
+ addSection(mApps);
+ }
}
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java b/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java
index 69010dd..8eb81b8 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/SaveFragment.java
@@ -68,11 +68,12 @@ public class SaveFragment extends Fragment {
public View onCreateView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final Context context = inflater.getContext();
+ final RootsCache roots = DocumentsApplication.getRootsCache(context);
final View view = inflater.inflate(R.layout.fragment_save, container, false);
final ImageView icon = (ImageView) view.findViewById(android.R.id.icon);
- icon.setImageDrawable(RootsCache.resolveDocumentIcon(
+ icon.setImageDrawable(roots.resolveDocumentIcon(
context, null, getArguments().getString(EXTRA_MIME_TYPE)));
mDisplayName = (EditText) view.findViewById(android.R.id.title);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/SectionedListAdapter.java b/packages/DocumentsUI/src/com/android/documentsui/SectionedListAdapter.java
index aacce65..088e3fa 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/SectionedListAdapter.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/SectionedListAdapter.java
@@ -18,6 +18,7 @@ package com.android.documentsui;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListAdapter;
@@ -41,6 +42,11 @@ public class SectionedListAdapter extends BaseAdapter {
notifyDataSetChanged();
}
+ /**
+ * After mutating sections, you <em>must</em>
+ * {@link AdapterView#setAdapter(android.widget.Adapter)} to correctly
+ * recount view types.
+ */
public void addSection(SectionAdapter adapter) {
mSections.add(adapter);
notifyDataSetChanged();
@@ -117,7 +123,7 @@ public class SectionedListAdapter extends BaseAdapter {
if (position == 0) {
return false;
} else if (position < sectionSize) {
- return section.isEnabled(position);
+ return section.isEnabled(position - 1);
}
// Otherwise jump into next section
diff --git a/packages/DocumentsUI/src/com/android/documentsui/TestActivity.java b/packages/DocumentsUI/src/com/android/documentsui/TestActivity.java
index a086a43..f6548e8 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/TestActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/TestActivity.java
@@ -60,6 +60,7 @@ public class TestActivity extends Activity {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
if (multiple.isChecked()) {
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
@@ -75,6 +76,7 @@ public class TestActivity extends Activity {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
if (multiple.isChecked()) {
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
@@ -90,6 +92,7 @@ public class TestActivity extends Activity {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[] {
"text/plain", "application/msword" });
@@ -107,6 +110,7 @@ public class TestActivity extends Activity {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TITLE, "foobar.txt");
startActivityForResult(intent, 42);
@@ -114,6 +118,22 @@ public class TestActivity extends Activity {
});
view.addView(button);
+ button = new Button(context);
+ button.setText("GET_CONTENT */*");
+ button.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setType("*/*");
+ if (multiple.isChecked()) {
+ intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
+ }
+ startActivityForResult(Intent.createChooser(intent, "Kittens!"), 42);
+ }
+ });
+ view.addView(button);
+
mResult = new TextView(context);
view.addView(mResult);
@@ -131,7 +151,7 @@ public class TestActivity extends Activity {
is = getContentResolver().openInputStream(uri);
final int length = Streams.readFullyNoClose(is).length;
Log.d(TAG, "read length=" + length);
- } catch (IOException e) {
+ } catch (Exception e) {
Log.w(TAG, "Failed to read " + uri, e);
} finally {
IoUtils.closeQuietly(is);
diff --git a/packages/SystemUI/res/values-sw600dp-port/refs.xml b/packages/DocumentsUI/src/com/android/documentsui/ThumbnailCache.java
index 62fb77d..ad7cbf6 100644
--- a/packages/SystemUI/res/values-sw600dp-port/refs.xml
+++ b/packages/DocumentsUI/src/com/android/documentsui/ThumbnailCache.java
@@ -1,20 +1,32 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- * Copyright (c) 2013, The Android Open Source Project
+/*
+ * Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
-*/
--->
-<resources>
- <item type="string" name="hiding_navigation_confirmation_message">@string/hiding_navigation_confirmation_message_long</item>
-</resources>
+ */
+
+package com.android.documentsui;
+
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.util.LruCache;
+
+public class ThumbnailCache extends LruCache<Uri, Bitmap> {
+ public ThumbnailCache(int maxSizeBytes) {
+ super(maxSizeBytes);
+ }
+
+ @Override
+ protected int sizeOf(Uri key, Bitmap value) {
+ return value.getByteCount();
+ }
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/UriDerivativeLoader.java b/packages/DocumentsUI/src/com/android/documentsui/UriDerivativeLoader.java
index 1b88af4..1a5bb0c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/UriDerivativeLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/UriDerivativeLoader.java
@@ -19,7 +19,6 @@ package com.android.documentsui;
import android.content.AsyncTaskLoader;
import android.content.Context;
import android.database.ContentObserver;
-import android.net.Uri;
import android.os.CancellationSignal;
import android.os.OperationCanceledException;
@@ -28,17 +27,16 @@ import android.os.OperationCanceledException;
* changes while started, manages {@link CancellationSignal}, and caches
* returned results.
*/
-public abstract class UriDerivativeLoader<T> extends AsyncTaskLoader<T> {
- private final ForceLoadContentObserver mObserver;
- private boolean mObserving;
+public abstract class UriDerivativeLoader<P, R> extends AsyncTaskLoader<R> {
+ final ForceLoadContentObserver mObserver;
- private final Uri mUri;
+ private final P mParam;
- private T mResult;
+ private R mResult;
private CancellationSignal mCancellationSignal;
@Override
- public final T loadInBackground() {
+ public final R loadInBackground() {
synchronized (this) {
if (isLoadInBackgroundCanceled()) {
throw new OperationCanceledException();
@@ -46,7 +44,7 @@ public abstract class UriDerivativeLoader<T> extends AsyncTaskLoader<T> {
mCancellationSignal = new CancellationSignal();
}
try {
- return loadInBackground(mUri, mCancellationSignal);
+ return loadInBackground(mParam, mCancellationSignal);
} finally {
synchronized (this) {
mCancellationSignal = null;
@@ -54,7 +52,7 @@ public abstract class UriDerivativeLoader<T> extends AsyncTaskLoader<T> {
}
}
- public abstract T loadInBackground(Uri uri, CancellationSignal signal);
+ public abstract R loadInBackground(P param, CancellationSignal signal);
@Override
public void cancelLoadInBackground() {
@@ -68,12 +66,12 @@ public abstract class UriDerivativeLoader<T> extends AsyncTaskLoader<T> {
}
@Override
- public void deliverResult(T result) {
+ public void deliverResult(R result) {
if (isReset()) {
closeQuietly(result);
return;
}
- T oldResult = mResult;
+ R oldResult = mResult;
mResult = result;
if (isStarted()) {
@@ -85,18 +83,14 @@ public abstract class UriDerivativeLoader<T> extends AsyncTaskLoader<T> {
}
}
- public UriDerivativeLoader(Context context, Uri uri) {
+ public UriDerivativeLoader(Context context, P param) {
super(context);
mObserver = new ForceLoadContentObserver();
- mUri = uri;
+ mParam = param;
}
@Override
protected void onStartLoading() {
- if (!mObserving) {
- getContext().getContentResolver().registerContentObserver(mUri, false, mObserver);
- mObserving = true;
- }
if (mResult != null) {
deliverResult(mResult);
}
@@ -111,7 +105,7 @@ public abstract class UriDerivativeLoader<T> extends AsyncTaskLoader<T> {
}
@Override
- public void onCanceled(T result) {
+ public void onCanceled(R result) {
closeQuietly(result);
}
@@ -125,13 +119,10 @@ public abstract class UriDerivativeLoader<T> extends AsyncTaskLoader<T> {
closeQuietly(mResult);
mResult = null;
- if (mObserving) {
- getContext().getContentResolver().unregisterContentObserver(mObserver);
- mObserving = false;
- }
+ getContext().getContentResolver().unregisterContentObserver(mObserver);
}
- private void closeQuietly(T result) {
+ private void closeQuietly(R result) {
if (result instanceof AutoCloseable) {
try {
((AutoCloseable) result).close();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/Document.java b/packages/DocumentsUI/src/com/android/documentsui/model/Document.java
index 95922b4..c0f21cb 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/Document.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/Document.java
@@ -21,6 +21,7 @@ import android.database.Cursor;
import android.net.Uri;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.DocumentColumns;
+import android.provider.DocumentsContract.Documents;
import com.android.documentsui.RecentsProvider;
@@ -87,7 +88,7 @@ public class Document {
final String mimeType = getCursorString(cursor, DocumentColumns.MIME_TYPE);
final String displayName = getCursorString(cursor, DocumentColumns.DISPLAY_NAME);
final int flags = getCursorInt(cursor, DocumentColumns.FLAGS)
- & DocumentsContract.FLAG_SUPPORTS_THUMBNAIL;
+ & Documents.FLAG_SUPPORTS_THUMBNAIL;
final String summary = getCursorString(cursor, DocumentColumns.SUMMARY);
final long size = getCursorLong(cursor, DocumentColumns.SIZE);
@@ -127,19 +128,27 @@ public class Document {
}
public boolean isCreateSupported() {
- return (flags & DocumentsContract.FLAG_SUPPORTS_CREATE) != 0;
+ return (flags & Documents.FLAG_SUPPORTS_CREATE) != 0;
}
public boolean isSearchSupported() {
- return (flags & DocumentsContract.FLAG_SUPPORTS_SEARCH) != 0;
+ return (flags & Documents.FLAG_SUPPORTS_SEARCH) != 0;
}
public boolean isThumbnailSupported() {
- return (flags & DocumentsContract.FLAG_SUPPORTS_THUMBNAIL) != 0;
+ return (flags & Documents.FLAG_SUPPORTS_THUMBNAIL) != 0;
}
public boolean isDirectory() {
- return DocumentsContract.MIME_TYPE_DIRECTORY.equals(mimeType);
+ return Documents.MIME_TYPE_DIR.equals(mimeType);
+ }
+
+ public boolean isGridPreferred() {
+ return (flags & Documents.FLAG_PREFERS_GRID) != 0;
+ }
+
+ public boolean isDeleteSupported() {
+ return (flags & Documents.FLAG_SUPPORTS_DELETE) != 0;
}
private static String getCursorString(Cursor cursor, String columnName) {
@@ -147,9 +156,19 @@ public class Document {
return (index != -1) ? cursor.getString(index) : null;
}
+ /**
+ * Missing or null values are returned as -1.
+ */
private static long getCursorLong(Cursor cursor, String columnName) {
final int index = cursor.getColumnIndex(columnName);
- return (index != -1) ? cursor.getLong(index) : 0;
+ if (index == -1) return -1;
+ final String value = cursor.getString(index);
+ if (value == null) return -1;
+ try {
+ return Long.parseLong(value);
+ } catch (NumberFormatException e) {
+ return -1;
+ }
}
private static int getCursorInt(Cursor cursor, String columnName) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/Root.java b/packages/DocumentsUI/src/com/android/documentsui/model/Root.java
index 0880731..23d16df 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/Root.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/Root.java
@@ -24,7 +24,9 @@ import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.provider.DocumentsContract;
+import android.provider.DocumentsContract.Documents;
import android.provider.DocumentsContract.RootColumns;
+import android.provider.DocumentsContract.Roots;
import com.android.documentsui.R;
@@ -47,7 +49,7 @@ public class Root {
final PackageManager pm = context.getPackageManager();
final Root root = new Root();
root.rootId = null;
- root.rootType = DocumentsContract.ROOT_TYPE_SHORTCUT;
+ root.rootType = Roots.ROOT_TYPE_SHORTCUT;
root.uri = null;
root.icon = context.getResources().getDrawable(R.drawable.ic_dir);
root.title = context.getString(R.string.root_recent);
@@ -65,7 +67,7 @@ public class Root {
root.rootId = cursor.getString(cursor.getColumnIndex(RootColumns.ROOT_ID));
root.rootType = cursor.getInt(cursor.getColumnIndex(RootColumns.ROOT_TYPE));
root.uri = DocumentsContract.buildDocumentUri(
- info.providerInfo.authority, root.rootId, DocumentsContract.ROOT_DOC_ID);
+ info.providerInfo.authority, root.rootId, Documents.DOC_ID_ROOT);
root.icon = info.providerInfo.loadIcon(pm);
root.title = info.providerInfo.loadLabel(pm).toString();
root.availableBytes = cursor.getLong(cursor.getColumnIndex(RootColumns.AVAILABLE_BYTES));
diff --git a/packages/ExternalStorageProvider/AndroidManifest.xml b/packages/ExternalStorageProvider/AndroidManifest.xml
index afdb6bb..8bd2a6d 100644
--- a/packages/ExternalStorageProvider/AndroidManifest.xml
+++ b/packages/ExternalStorageProvider/AndroidManifest.xml
@@ -7,7 +7,7 @@
<application android:label="@string/app_label">
<provider
android:name=".ExternalStorageProvider"
- android:authorities="com.android.externalstorage"
+ android:authorities="com.android.externalstorage.documents"
android:grantUriPermissions="true"
android:exported="true"
android:permission="android.permission.MANAGE_DOCUMENTS">
@@ -15,5 +15,18 @@
android:name="android.content.DOCUMENT_PROVIDER"
android:resource="@xml/document_provider" />
</provider>
+
+ <!-- TODO: remove when we have real providers -->
+ <provider
+ android:name=".CloudTestDocumentsProvider"
+ android:authorities="com.android.externalstorage.cloudtest"
+ android:grantUriPermissions="true"
+ android:exported="true"
+ android:enabled="false"
+ android:permission="android.permission.MANAGE_DOCUMENTS">
+ <meta-data
+ android:name="android.content.DOCUMENT_PROVIDER"
+ android:resource="@xml/document_provider" />
+ </provider>
</application>
</manifest>
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/CloudTestDocumentsProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/CloudTestDocumentsProvider.java
new file mode 100644
index 0000000..119d92e
--- /dev/null
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/CloudTestDocumentsProvider.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.externalstorage;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.UriMatcher;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.database.MatrixCursor.RowBuilder;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.ParcelFileDescriptor;
+import android.os.SystemClock;
+import android.provider.DocumentsContract;
+import android.provider.DocumentsContract.DocumentColumns;
+import android.provider.DocumentsContract.Documents;
+import android.provider.DocumentsContract.RootColumns;
+import android.provider.DocumentsContract.Roots;
+import android.util.Log;
+
+import com.google.android.collect.Lists;
+
+import libcore.io.IoUtils;
+
+import java.io.FileNotFoundException;
+import java.util.List;
+
+public class CloudTestDocumentsProvider extends ContentProvider {
+ private static final String TAG = "CloudTest";
+
+ private static final String AUTHORITY = "com.android.externalstorage.cloudtest";
+
+ private static final UriMatcher sMatcher = new UriMatcher(UriMatcher.NO_MATCH);
+
+ private static final int URI_ROOTS = 1;
+ private static final int URI_ROOTS_ID = 2;
+ private static final int URI_DOCS_ID = 3;
+ private static final int URI_DOCS_ID_CONTENTS = 4;
+ private static final int URI_DOCS_ID_SEARCH = 5;
+
+ static {
+ sMatcher.addURI(AUTHORITY, "roots", URI_ROOTS);
+ sMatcher.addURI(AUTHORITY, "roots/*", URI_ROOTS_ID);
+ sMatcher.addURI(AUTHORITY, "roots/*/docs/*", URI_DOCS_ID);
+ sMatcher.addURI(AUTHORITY, "roots/*/docs/*/contents", URI_DOCS_ID_CONTENTS);
+ sMatcher.addURI(AUTHORITY, "roots/*/docs/*/search", URI_DOCS_ID_SEARCH);
+ }
+
+ private static final String[] ALL_ROOTS_COLUMNS = new String[] {
+ RootColumns.ROOT_ID, RootColumns.ROOT_TYPE, RootColumns.ICON, RootColumns.TITLE,
+ RootColumns.SUMMARY, RootColumns.AVAILABLE_BYTES
+ };
+
+ private static final String[] ALL_DOCUMENTS_COLUMNS = new String[] {
+ DocumentColumns.DOC_ID, DocumentColumns.DISPLAY_NAME, DocumentColumns.SIZE,
+ DocumentColumns.MIME_TYPE, DocumentColumns.LAST_MODIFIED, DocumentColumns.FLAGS
+ };
+
+ private List<String> mKnownDocs = Lists.newArrayList("meow.png", "kittens.pdf");
+
+ private int mPage;
+
+ @Override
+ public boolean onCreate() {
+ return true;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ switch (sMatcher.match(uri)) {
+ case URI_ROOTS: {
+ final MatrixCursor result = new MatrixCursor(
+ projection != null ? projection : ALL_ROOTS_COLUMNS);
+ includeDefaultRoot(result);
+ return result;
+ }
+ case URI_ROOTS_ID: {
+ final MatrixCursor result = new MatrixCursor(
+ projection != null ? projection : ALL_ROOTS_COLUMNS);
+ includeDefaultRoot(result);
+ return result;
+ }
+ case URI_DOCS_ID: {
+ final String docId = DocumentsContract.getDocId(uri);
+ final MatrixCursor result = new MatrixCursor(
+ projection != null ? projection : ALL_DOCUMENTS_COLUMNS);
+ includeDoc(result, docId);
+ return result;
+ }
+ case URI_DOCS_ID_CONTENTS: {
+ final CloudCursor result = new CloudCursor(
+ projection != null ? projection : ALL_DOCUMENTS_COLUMNS, uri);
+ for (String docId : mKnownDocs) {
+ includeDoc(result, docId);
+ }
+ if (mPage < 3) {
+ result.setHasMore();
+ }
+ result.setNotificationUri(getContext().getContentResolver(), uri);
+ return result;
+ }
+ default: {
+ throw new UnsupportedOperationException("Unsupported Uri " + uri);
+ }
+ }
+ }
+
+ private void includeDefaultRoot(MatrixCursor result) {
+ final RowBuilder row = result.newRow();
+ row.offer(RootColumns.ROOT_ID, "testroot");
+ row.offer(RootColumns.ROOT_TYPE, Roots.ROOT_TYPE_SERVICE);
+ row.offer(RootColumns.TITLE, "_TestTitle");
+ row.offer(RootColumns.SUMMARY, "_TestSummary");
+ }
+
+ private void includeDoc(MatrixCursor result, String docId) {
+ int flags = 0;
+
+ final String mimeType;
+ if (Documents.DOC_ID_ROOT.equals(docId)) {
+ mimeType = Documents.MIME_TYPE_DIR;
+ } else {
+ mimeType = "application/octet-stream";
+ }
+
+ final RowBuilder row = result.newRow();
+ row.offer(DocumentColumns.DOC_ID, docId);
+ row.offer(DocumentColumns.DISPLAY_NAME, docId);
+ row.offer(DocumentColumns.MIME_TYPE, mimeType);
+ row.offer(DocumentColumns.LAST_MODIFIED, System.currentTimeMillis());
+ row.offer(DocumentColumns.FLAGS, flags);
+ }
+
+ private class CloudCursor extends MatrixCursor {
+ private final Uri mUri;
+ private Bundle mExtras = new Bundle();
+
+ public CloudCursor(String[] columnNames, Uri uri) {
+ super(columnNames);
+ mUri = uri;
+ }
+
+ public void setHasMore() {
+ mExtras.putBoolean(DocumentsContract.EXTRA_HAS_MORE, true);
+ }
+
+ @Override
+ public Bundle getExtras() {
+ Log.d(TAG, "getExtras() " + mExtras);
+ return mExtras;
+ }
+
+ @Override
+ public Bundle respond(Bundle extras) {
+ extras.size();
+ Log.d(TAG, "respond() " + extras);
+ if (extras.getBoolean(DocumentsContract.EXTRA_REQUEST_MORE, false)) {
+ new CloudTask().execute(mUri);
+ }
+ return Bundle.EMPTY;
+ }
+ }
+
+ private class CloudTask extends AsyncTask<Uri, Void, Void> {
+ @Override
+ protected Void doInBackground(Uri... uris) {
+ final Uri uri = uris[0];
+
+ SystemClock.sleep(1000);
+
+ // Grab some files from the cloud
+ for (int i = 0; i < 5; i++) {
+ mKnownDocs.add("cloud-page" + mPage + "-file" + i);
+ }
+ mPage++;
+
+ Log.d(TAG, "Loaded more; notifying " + uri);
+ getContext().getContentResolver().notifyChange(uri, null, false);
+ return null;
+ }
+ }
+
+ private interface TypeQuery {
+ final String[] PROJECTION = {
+ DocumentColumns.MIME_TYPE };
+
+ final int MIME_TYPE = 0;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ switch (sMatcher.match(uri)) {
+ case URI_ROOTS: {
+ return Roots.MIME_TYPE_DIR;
+ }
+ case URI_ROOTS_ID: {
+ return Roots.MIME_TYPE_ITEM;
+ }
+ case URI_DOCS_ID: {
+ final Cursor cursor = query(uri, TypeQuery.PROJECTION, null, null, null);
+ try {
+ if (cursor.moveToFirst()) {
+ return cursor.getString(TypeQuery.MIME_TYPE);
+ } else {
+ return null;
+ }
+ } finally {
+ IoUtils.closeQuietly(cursor);
+ }
+ }
+ default: {
+ throw new UnsupportedOperationException("Unsupported Uri " + uri);
+ }
+ }
+ }
+
+ @Override
+ public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+ throw new UnsupportedOperationException("Unsupported Uri " + uri);
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ throw new UnsupportedOperationException("Unsupported Uri " + uri);
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ throw new UnsupportedOperationException("Unsupported Uri " + uri);
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ throw new UnsupportedOperationException("Unsupported Uri " + uri);
+ }
+}
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 5c12484..b4bf563 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -22,13 +22,15 @@ import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.MatrixCursor;
+import android.database.MatrixCursor.RowBuilder;
import android.net.Uri;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
-import android.provider.BaseColumns;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.DocumentColumns;
+import android.provider.DocumentsContract.Documents;
import android.provider.DocumentsContract.RootColumns;
+import android.provider.DocumentsContract.Roots;
import android.util.Log;
import android.webkit.MimeTypeMap;
@@ -43,7 +45,7 @@ import java.util.LinkedList;
public class ExternalStorageProvider extends ContentProvider {
private static final String TAG = "ExternalStorage";
- private static final String AUTHORITY = "com.android.externalstorage";
+ private static final String AUTHORITY = "com.android.externalstorage.documents";
// TODO: support multiple storage devices
@@ -55,6 +57,14 @@ public class ExternalStorageProvider extends ContentProvider {
private static final int URI_DOCS_ID_CONTENTS = 4;
private static final int URI_DOCS_ID_SEARCH = 5;
+ static {
+ sMatcher.addURI(AUTHORITY, "roots", URI_ROOTS);
+ sMatcher.addURI(AUTHORITY, "roots/*", URI_ROOTS_ID);
+ sMatcher.addURI(AUTHORITY, "roots/*/docs/*", URI_DOCS_ID);
+ sMatcher.addURI(AUTHORITY, "roots/*/docs/*/contents", URI_DOCS_ID_CONTENTS);
+ sMatcher.addURI(AUTHORITY, "roots/*/docs/*/search", URI_DOCS_ID_SEARCH);
+ }
+
private HashMap<String, Root> mRoots = Maps.newHashMap();
private static class Root {
@@ -66,20 +76,22 @@ public class ExternalStorageProvider extends ContentProvider {
public File path;
}
- static {
- sMatcher.addURI(AUTHORITY, "roots", URI_ROOTS);
- sMatcher.addURI(AUTHORITY, "roots/*", URI_ROOTS_ID);
- sMatcher.addURI(AUTHORITY, "roots/*/docs/*", URI_DOCS_ID);
- sMatcher.addURI(AUTHORITY, "roots/*/docs/*/contents", URI_DOCS_ID_CONTENTS);
- sMatcher.addURI(AUTHORITY, "roots/*/docs/*/search", URI_DOCS_ID_SEARCH);
- }
+ private static final String[] ALL_ROOTS_COLUMNS = new String[] {
+ RootColumns.ROOT_ID, RootColumns.ROOT_TYPE, RootColumns.ICON, RootColumns.TITLE,
+ RootColumns.SUMMARY, RootColumns.AVAILABLE_BYTES
+ };
+
+ private static final String[] ALL_DOCUMENTS_COLUMNS = new String[] {
+ DocumentColumns.DOC_ID, DocumentColumns.DISPLAY_NAME, DocumentColumns.SIZE,
+ DocumentColumns.MIME_TYPE, DocumentColumns.LAST_MODIFIED, DocumentColumns.FLAGS
+ };
@Override
public boolean onCreate() {
mRoots.clear();
final Root root = new Root();
- root.rootType = DocumentsContract.ROOT_TYPE_DEVICE_ADVANCED;
+ root.rootType = Roots.ROOT_TYPE_DEVICE_ADVANCED;
root.name = "primary";
root.title = getContext().getString(R.string.root_internal_storage);
root.path = Environment.getExternalStorageDirectory();
@@ -91,64 +103,59 @@ public class ExternalStorageProvider extends ContentProvider {
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
-
- // TODO: support custom projections
- final String[] rootsProjection = new String[] {
- BaseColumns._ID, RootColumns.ROOT_ID, RootColumns.ROOT_TYPE, RootColumns.ICON,
- RootColumns.TITLE, RootColumns.SUMMARY, RootColumns.AVAILABLE_BYTES };
- final String[] docsProjection = new String[] {
- BaseColumns._ID, DocumentColumns.DISPLAY_NAME, DocumentColumns.SIZE,
- DocumentColumns.DOC_ID, DocumentColumns.MIME_TYPE, DocumentColumns.LAST_MODIFIED,
- DocumentColumns.FLAGS };
-
switch (sMatcher.match(uri)) {
case URI_ROOTS: {
- final MatrixCursor cursor = new MatrixCursor(rootsProjection);
+ final MatrixCursor result = new MatrixCursor(
+ projection != null ? projection : ALL_ROOTS_COLUMNS);
for (Root root : mRoots.values()) {
- includeRoot(cursor, root);
+ includeRoot(result, root);
}
- return cursor;
+ return result;
}
case URI_ROOTS_ID: {
final Root root = mRoots.get(DocumentsContract.getRootId(uri));
- final MatrixCursor cursor = new MatrixCursor(rootsProjection);
- includeRoot(cursor, root);
- return cursor;
+ final MatrixCursor result = new MatrixCursor(
+ projection != null ? projection : ALL_ROOTS_COLUMNS);
+ includeRoot(result, root);
+ return result;
}
case URI_DOCS_ID: {
final Root root = mRoots.get(DocumentsContract.getRootId(uri));
final String docId = DocumentsContract.getDocId(uri);
- final MatrixCursor cursor = new MatrixCursor(docsProjection);
+ final MatrixCursor result = new MatrixCursor(
+ projection != null ? projection : ALL_DOCUMENTS_COLUMNS);
final File file = docIdToFile(root, docId);
- includeFile(cursor, root, file);
- return cursor;
+ includeFile(result, root, file);
+ return result;
}
case URI_DOCS_ID_CONTENTS: {
final Root root = mRoots.get(DocumentsContract.getRootId(uri));
final String docId = DocumentsContract.getDocId(uri);
- final MatrixCursor cursor = new MatrixCursor(docsProjection);
+ final MatrixCursor result = new MatrixCursor(
+ projection != null ? projection : ALL_DOCUMENTS_COLUMNS);
final File parent = docIdToFile(root, docId);
for (File file : parent.listFiles()) {
- includeFile(cursor, root, file);
+ includeFile(result, root, file);
}
- return cursor;
+ return result;
}
case URI_DOCS_ID_SEARCH: {
final Root root = mRoots.get(DocumentsContract.getRootId(uri));
final String docId = DocumentsContract.getDocId(uri);
final String query = DocumentsContract.getSearchQuery(uri).toLowerCase();
- final MatrixCursor cursor = new MatrixCursor(docsProjection);
+ final MatrixCursor result = new MatrixCursor(
+ projection != null ? projection : ALL_DOCUMENTS_COLUMNS);
final File parent = docIdToFile(root, docId);
final LinkedList<File> pending = new LinkedList<File>();
pending.add(parent);
- while (!pending.isEmpty() && cursor.getCount() < 20) {
+ while (!pending.isEmpty() && result.getCount() < 20) {
final File file = pending.removeFirst();
if (file.isDirectory()) {
for (File child : file.listFiles()) {
@@ -156,12 +163,12 @@ public class ExternalStorageProvider extends ContentProvider {
}
} else {
if (file.getName().toLowerCase().contains(query)) {
- includeFile(cursor, root, file);
+ includeFile(result, root, file);
}
}
}
- return cursor;
+ return result;
}
default: {
throw new UnsupportedOperationException("Unsupported Uri " + uri);
@@ -173,7 +180,7 @@ public class ExternalStorageProvider extends ContentProvider {
String rootPath = root.path.getAbsolutePath();
final String path = file.getAbsolutePath();
if (path.equals(rootPath)) {
- return DocumentsContract.ROOT_DOC_ID;
+ return Documents.DOC_ID_ROOT;
}
if (!rootPath.endsWith("/")) {
@@ -187,55 +194,69 @@ public class ExternalStorageProvider extends ContentProvider {
}
private File docIdToFile(Root root, String docId) {
- if (DocumentsContract.ROOT_DOC_ID.equals(docId)) {
+ if (Documents.DOC_ID_ROOT.equals(docId)) {
return root.path;
} else {
return new File(root.path, docId);
}
}
- private void includeRoot(MatrixCursor cursor, Root root) {
- cursor.addRow(new Object[] {
- root.name.hashCode(), root.name, root.rootType, root.icon, root.title, root.summary,
- root.path.getFreeSpace() });
+ private void includeRoot(MatrixCursor result, Root root) {
+ final RowBuilder row = result.newRow();
+ row.offer(RootColumns.ROOT_ID, root.name);
+ row.offer(RootColumns.ROOT_TYPE, root.rootType);
+ row.offer(RootColumns.ICON, root.icon);
+ row.offer(RootColumns.TITLE, root.title);
+ row.offer(RootColumns.SUMMARY, root.summary);
+ row.offer(RootColumns.AVAILABLE_BYTES, root.path.getFreeSpace());
}
- private void includeFile(MatrixCursor cursor, Root root, File file) {
+ private void includeFile(MatrixCursor result, Root root, File file) {
int flags = 0;
if (file.isDirectory()) {
- flags |= DocumentsContract.FLAG_SUPPORTS_SEARCH;
+ flags |= Documents.FLAG_SUPPORTS_SEARCH;
}
if (file.isDirectory() && file.canWrite()) {
- flags |= DocumentsContract.FLAG_SUPPORTS_CREATE;
+ flags |= Documents.FLAG_SUPPORTS_CREATE;
}
if (file.canWrite()) {
- flags |= DocumentsContract.FLAG_SUPPORTS_RENAME;
- flags |= DocumentsContract.FLAG_SUPPORTS_DELETE;
+ flags |= Documents.FLAG_SUPPORTS_WRITE;
+ flags |= Documents.FLAG_SUPPORTS_RENAME;
+ flags |= Documents.FLAG_SUPPORTS_DELETE;
}
final String mimeType = getTypeForFile(file);
if (mimeType.startsWith("image/")) {
- flags |= DocumentsContract.FLAG_SUPPORTS_THUMBNAIL;
+ flags |= Documents.FLAG_SUPPORTS_THUMBNAIL;
}
final String docId = fileToDocId(root, file);
- final long id = docId.hashCode();
-
final String displayName;
- if (DocumentsContract.ROOT_DOC_ID.equals(docId)) {
+ if (Documents.DOC_ID_ROOT.equals(docId)) {
displayName = root.title;
} else {
displayName = file.getName();
}
- cursor.addRow(new Object[] {
- id, displayName, file.length(), docId, mimeType, file.lastModified(), flags });
+ final RowBuilder row = result.newRow();
+ row.offer(DocumentColumns.DOC_ID, docId);
+ row.offer(DocumentColumns.DISPLAY_NAME, displayName);
+ row.offer(DocumentColumns.SIZE, file.length());
+ row.offer(DocumentColumns.MIME_TYPE, mimeType);
+ row.offer(DocumentColumns.LAST_MODIFIED, file.lastModified());
+ row.offer(DocumentColumns.FLAGS, flags);
}
@Override
public String getType(Uri uri) {
switch (sMatcher.match(uri)) {
+ case URI_ROOTS: {
+ return Roots.MIME_TYPE_DIR;
+ }
+ case URI_ROOTS_ID: {
+ return Roots.MIME_TYPE_ITEM;
+ }
case URI_DOCS_ID: {
final Root root = mRoots.get(DocumentsContract.getRootId(uri));
final String docId = DocumentsContract.getDocId(uri);
@@ -249,7 +270,7 @@ public class ExternalStorageProvider extends ContentProvider {
private String getTypeForFile(File file) {
if (file.isDirectory()) {
- return DocumentsContract.MIME_TYPE_DIRECTORY;
+ return Documents.MIME_TYPE_DIR;
} else {
return getTypeForName(file.getName());
}
@@ -299,7 +320,7 @@ public class ExternalStorageProvider extends ContentProvider {
values.getAsString(DocumentColumns.DISPLAY_NAME), mimeType);
final File file = new File(parent, name);
- if (DocumentsContract.MIME_TYPE_DIRECTORY.equals(mimeType)) {
+ if (Documents.MIME_TYPE_DIR.equals(mimeType)) {
if (!file.mkdir()) {
return null;
}
@@ -359,7 +380,7 @@ public class ExternalStorageProvider extends ContentProvider {
}
private String validateDisplayName(String displayName, String mimeType) {
- if (DocumentsContract.MIME_TYPE_DIRECTORY.equals(mimeType)) {
+ if (Documents.MIME_TYPE_DIR.equals(mimeType)) {
return displayName;
} else {
// Try appending meaningful extension if needed
diff --git a/packages/Keyguard/AndroidManifest.xml b/packages/Keyguard/AndroidManifest.xml
index 7d77c48..f3106da 100644
--- a/packages/Keyguard/AndroidManifest.xml
+++ b/packages/Keyguard/AndroidManifest.xml
@@ -38,6 +38,9 @@
<uses-permission android:name="android.permission.BIND_DEVICE_ADMIN" />
<uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />
+ <!-- Permission for the Hotword detector service -->
+ <uses-permission android:name="com.google.android.googlequicksearchbox.SEARCH_API" />
+
<application android:label="@string/app_name"
android:process="com.android.systemui"
android:persistent="true" >
diff --git a/packages/Keyguard/src/com/android/keyguard/HotwordServiceClient.java b/packages/Keyguard/src/com/android/keyguard/HotwordServiceClient.java
new file mode 100644
index 0000000..94733d4
--- /dev/null
+++ b/packages/Keyguard/src/com/android/keyguard/HotwordServiceClient.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.keyguard;
+
+import android.app.SearchManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.Log;
+
+import com.google.android.search.service.IHotwordService;
+import com.google.android.search.service.IHotwordServiceCallback;
+
+/**
+ * Utility class with its callbacks to simplify usage of {@link IHotwordService}.
+ *
+ * The client is meant to be used for a single hotword detection in a session.
+ * start() -> stop(); client is asked to stop & disconnect from the service.
+ * start() -> onHotwordDetected(); client disconnects from the service automatically.
+ */
+public class HotwordServiceClient implements Handler.Callback {
+ private static final String TAG = "HotwordServiceClient";
+ private static final boolean DBG = true;
+ private static final String ACTION_HOTWORD =
+ "com.google.android.search.service.IHotwordService";
+
+ private static final int MSG_SERVICE_CONNECTED = 0;
+ private static final int MSG_SERVICE_DISCONNECTED = 1;
+ private static final int MSG_HOTWORD_STARTED = 2;
+ private static final int MSG_HOTWORD_STOPPED = 3;
+ private static final int MSG_HOTWORD_DETECTED = 4;
+
+ private final Context mContext;
+ private final Callback mClientCallback;
+ private final Handler mHandler;
+
+ private IHotwordService mService;
+
+ public HotwordServiceClient(Context context, Callback callback) {
+ mContext = context;
+ mClientCallback = callback;
+ mHandler = new Handler(this);
+ }
+
+ public interface Callback {
+ void onServiceConnected();
+ void onServiceDisconnected();
+ void onHotwordDetectionStarted();
+ void onHotwordDetectionStopped();
+ void onHotwordDetected(String action);
+ }
+
+ /**
+ * Binds to the {@link IHotwordService} and starts hotword detection
+ * when the service is connected.
+ *
+ * @return false if the service can't be bound to.
+ */
+ public synchronized boolean start() {
+ if (mService != null) {
+ if (DBG) Log.d(TAG, "Multiple call to start(), service was already bound");
+ return true;
+ } else {
+ // TODO: The hotword service is currently hosted within the search app
+ // so the component handling the assist intent should handle hotwording
+ // as well.
+ final Intent intent =
+ ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
+ .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
+ if (intent == null) {
+ return false;
+ }
+
+ Intent hotwordIntent = new Intent(ACTION_HOTWORD);
+ hotwordIntent.fillIn(intent, Intent.FILL_IN_PACKAGE);
+ return mContext.bindService(
+ hotwordIntent,
+ mConnection,
+ Context.BIND_AUTO_CREATE);
+ }
+ }
+
+ /**
+ * Unbinds from the the {@link IHotwordService}.
+ */
+ public synchronized void stop() {
+ if (mService != null) {
+ mContext.unbindService(mConnection);
+ mService = null;
+ }
+ }
+
+ @Override
+ public boolean handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_SERVICE_CONNECTED:
+ handleServiceConnected();
+ break;
+ case MSG_SERVICE_DISCONNECTED:
+ handleServiceDisconnected();
+ break;
+ case MSG_HOTWORD_STARTED:
+ handleHotwordDetectionStarted();
+ break;
+ case MSG_HOTWORD_STOPPED:
+ handleHotwordDetectionStopped();
+ break;
+ case MSG_HOTWORD_DETECTED:
+ handleHotwordDetected((String) msg.obj);
+ break;
+ default:
+ if (DBG) Log.e(TAG, "Unhandled message");
+ return false;
+ }
+ return true;
+ }
+
+ private void handleServiceConnected() {
+ if (DBG) Log.d(TAG, "handleServiceConnected()");
+ if (mClientCallback != null) mClientCallback.onServiceConnected();
+ try {
+ mService.requestHotwordDetection(mServiceCallback);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Exception while registering callback", e);
+ mHandler.sendEmptyMessage(MSG_SERVICE_DISCONNECTED);
+ }
+ }
+
+ private void handleServiceDisconnected() {
+ if (DBG) Log.d(TAG, "handleServiceDisconnected()");
+ mService = null;
+ if (mClientCallback != null) mClientCallback.onServiceDisconnected();
+ }
+
+ private void handleHotwordDetectionStarted() {
+ if (DBG) Log.d(TAG, "handleHotwordDetectionStarted()");
+ if (mClientCallback != null) mClientCallback.onHotwordDetectionStarted();
+ }
+
+ private void handleHotwordDetectionStopped() {
+ if (DBG) Log.d(TAG, "handleHotwordDetectionStopped()");
+ if (mClientCallback != null) mClientCallback.onHotwordDetectionStopped();
+ }
+
+ void handleHotwordDetected(final String action) {
+ if (DBG) Log.d(TAG, "handleHotwordDetected()");
+ if (mClientCallback != null) mClientCallback.onHotwordDetected(action);
+ stop();
+ }
+
+ /**
+ * Implements service connection methods.
+ */
+ private ServiceConnection mConnection = new ServiceConnection() {
+ /**
+ * Called when the service connects after calling bind().
+ */
+ public void onServiceConnected(ComponentName className, IBinder iservice) {
+ mService = IHotwordService.Stub.asInterface(iservice);
+ mHandler.sendEmptyMessage(MSG_SERVICE_CONNECTED);
+ }
+
+ /**
+ * Called if the service unexpectedly disconnects. This indicates an error.
+ */
+ public void onServiceDisconnected(ComponentName className) {
+ mService = null;
+ mHandler.sendEmptyMessage(MSG_SERVICE_DISCONNECTED);
+ }
+ };
+
+ /**
+ * Implements the AIDL IHotwordServiceCallback interface.
+ */
+ private final IHotwordServiceCallback mServiceCallback = new IHotwordServiceCallback.Stub() {
+
+ public void onHotwordDetectionStarted() {
+ mHandler.sendEmptyMessage(MSG_HOTWORD_STARTED);
+ }
+
+ public void onHotwordDetectionStopped() {
+ mHandler.sendEmptyMessage(MSG_HOTWORD_STOPPED);
+ }
+
+ public void onHotwordDetected(String action) {
+ mHandler.obtainMessage(MSG_HOTWORD_DETECTED, action).sendToTarget();
+ }
+ };
+}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSelectorView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSelectorView.java
index 4d891be..1c658e3 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSelectorView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSelectorView.java
@@ -22,8 +22,11 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.os.PowerManager;
import android.os.UserHandle;
import android.provider.Settings;
+import android.telephony.TelephonyManager;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Slog;
@@ -34,12 +37,15 @@ import com.android.internal.telephony.IccCardConstants.State;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.multiwaveview.GlowPadView;
import com.android.internal.widget.multiwaveview.GlowPadView.OnTriggerListener;
+import com.android.keyguard.KeyguardHostView.OnDismissAction;
public class KeyguardSelectorView extends LinearLayout implements KeyguardSecurityView {
private static final boolean DEBUG = KeyguardHostView.DEBUG;
private static final String TAG = "SecuritySelectorView";
private static final String ASSIST_ICON_METADATA_NAME =
"com.android.systemui.action_assist_icon";
+ // Flag to enable/disable hotword detection on lock screen.
+ private static final boolean FLAG_HOTWORD = true;
private KeyguardSecurityCallback mCallback;
private GlowPadView mGlowPadView;
@@ -51,11 +57,15 @@ public class KeyguardSelectorView extends LinearLayout implements KeyguardSecuri
private LockPatternUtils mLockPatternUtils;
private SecurityMessageDisplay mSecurityMessageDisplay;
private Drawable mBouncerFrame;
+ private HotwordServiceClient mHotwordClient;
OnTriggerListener mOnTriggerListener = new OnTriggerListener() {
public void onTrigger(View v, int target) {
final int resId = mGlowPadView.getResourceIdForTarget(target);
+ if (FLAG_HOTWORD) {
+ maybeStopHotwordDetector();
+ }
switch (resId) {
case R.drawable.ic_action_assist_generic:
Intent assistIntent =
@@ -103,7 +113,7 @@ public class KeyguardSelectorView extends LinearLayout implements KeyguardSecuri
};
- KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
+ KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() {
@Override
public void onDevicePolicyManagerStateChanged() {
@@ -114,6 +124,24 @@ public class KeyguardSelectorView extends LinearLayout implements KeyguardSecuri
public void onSimStateChanged(State simState) {
updateTargets();
}
+
+ @Override
+ public void onPhoneStateChanged(int phoneState) {
+ if (FLAG_HOTWORD) {
+ // We need to stop the hotwording when a phone call comes in
+ // TODO(sansid): This is not really needed if onPause triggers
+ // when we navigate away from the keyguard
+ if (phoneState == TelephonyManager.CALL_STATE_RINGING) {
+ if (DEBUG) Log.d(TAG, "Stopping due to CALL_STATE_RINGING");
+ maybeStopHotwordDetector();
+ }
+ }
+ }
+
+ @Override
+ public void onUserSwitching(int userId) {
+ maybeStopHotwordDetector();
+ }
};
private final KeyguardActivityLauncher mActivityLauncher = new KeyguardActivityLauncher() {
@@ -152,6 +180,9 @@ public class KeyguardSelectorView extends LinearLayout implements KeyguardSecuri
mSecurityMessageDisplay = new KeyguardMessageArea.Helper(this);
View bouncerFrameView = findViewById(R.id.keyguard_selector_view_frame);
mBouncerFrame = bouncerFrameView.getBackground();
+ if (FLAG_HOTWORD) {
+ mHotwordClient = new HotwordServiceClient(getContext(), mHotwordCallback);
+ }
}
public void setCarrierArea(View carrierArea) {
@@ -254,12 +285,22 @@ public class KeyguardSelectorView extends LinearLayout implements KeyguardSecuri
@Override
public void onPause() {
- KeyguardUpdateMonitor.getInstance(getContext()).removeCallback(mInfoCallback);
+ KeyguardUpdateMonitor.getInstance(getContext()).removeCallback(mUpdateCallback);
}
@Override
public void onResume(int reason) {
- KeyguardUpdateMonitor.getInstance(getContext()).registerCallback(mInfoCallback);
+ KeyguardUpdateMonitor.getInstance(getContext()).registerCallback(mUpdateCallback);
+ // TODO: Figure out if there's a better way to do it.
+ // Right now we don't get onPause at all, and onResume gets called
+ // multiple times (even when the screen is turned off with VIEW_REVEALED)
+ if (reason == SCREEN_ON) {
+ if (!KeyguardUpdateMonitor.getInstance(getContext()).isSwitchingUser()) {
+ maybeStartHotwordDetector();
+ }
+ } else {
+ maybeStopHotwordDetector();
+ }
}
@Override
@@ -280,4 +321,83 @@ public class KeyguardSelectorView extends LinearLayout implements KeyguardSecuri
KeyguardSecurityViewHelper.
hideBouncer(mSecurityMessageDisplay, mFadeView, mBouncerFrame, duration);
}
+
+ /**
+ * Start the hotword detector if:
+ * <li> HOTWORDING_ENABLED is true and
+ * <li> HotwordUnlock is initialized and
+ * <li> TelephonyManager is in CALL_STATE_IDLE
+ *
+ * If this method is called when the screen is off,
+ * it attempts to stop hotwording if it's running.
+ */
+ private void maybeStartHotwordDetector() {
+ if (FLAG_HOTWORD) {
+ if (DEBUG) Log.d(TAG, "maybeStartHotwordDetector()");
+ // Don't start it if the screen is off or not showing
+ PowerManager powerManager = (PowerManager) getContext().getSystemService(
+ Context.POWER_SERVICE);
+ if (!powerManager.isScreenOn()) {
+ if (DEBUG) Log.d(TAG, "screen was off, not starting");
+ return;
+ }
+
+ KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(getContext());
+ if (monitor.getPhoneState() != TelephonyManager.CALL_STATE_IDLE) {
+ if (DEBUG) Log.d(TAG, "Call underway, not starting");
+ return;
+ }
+ if (!mHotwordClient.start()) {
+ Log.w(TAG, "Failed to start the hotword detector");
+ }
+ }
+ }
+
+ /**
+ * Stop hotword detector if HOTWORDING_ENABLED is true.
+ */
+ private void maybeStopHotwordDetector() {
+ if (FLAG_HOTWORD) {
+ if (DEBUG) Log.d(TAG, "maybeStopHotwordDetector()");
+ mHotwordClient.stop();
+ }
+ }
+
+ private final HotwordServiceClient.Callback mHotwordCallback =
+ new HotwordServiceClient.Callback() {
+ private static final String TAG = "HotwordServiceClient.Callback";
+
+ @Override
+ public void onServiceConnected() {
+ if (DEBUG) Log.d(TAG, "onServiceConnected()");
+ }
+
+ @Override
+ public void onServiceDisconnected() {
+ if (DEBUG) Log.d(TAG, "onServiceDisconnected()");
+ }
+
+ @Override
+ public void onHotwordDetectionStarted() {
+ if (DEBUG) Log.d(TAG, "onHotwordDetectionStarted()");
+ // TODO: Change the usage of SecurityMessageDisplay to a better visual indication.
+ mSecurityMessageDisplay.setMessage("\"Ok Google...\"", true);
+ }
+
+ @Override
+ public void onHotwordDetectionStopped() {
+ if (DEBUG) Log.d(TAG, "onHotwordDetectionStopped()");
+ // TODO: Change the usage of SecurityMessageDisplay to a better visual indication.
+ }
+
+ @Override
+ public void onHotwordDetected(String action) {
+ if (DEBUG) Log.d(TAG, "onHotwordDetected(" + action + ")");
+ if (action != null) {
+ Intent intent = new Intent(action);
+ mActivityLauncher.launchActivity(intent, true, true, null, null);
+ }
+ mCallback.userActivity(0);
+ }
+ };
}
diff --git a/packages/Keyguard/src/com/google/android/search/service/IHotwordService.aidl b/packages/Keyguard/src/com/google/android/search/service/IHotwordService.aidl
new file mode 100644
index 0000000..e053d7d
--- /dev/null
+++ b/packages/Keyguard/src/com/google/android/search/service/IHotwordService.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.search.service;
+
+import com.google.android.search.service.IHotwordServiceCallback;
+
+/**
+ * Interface exposing hotword detector as a service.
+ */
+oneway interface IHotwordService {
+
+ /**
+ * Indicates a desire to start hotword detection.
+ * It's best-effort and the client should rely on
+ * the callbacks to figure out if hotwording was actually
+ * started or not.
+ *
+ * @param a callback to notify of hotword events.
+ */
+ void requestHotwordDetection(in IHotwordServiceCallback callback);
+}
diff --git a/packages/Keyguard/src/com/google/android/search/service/IHotwordServiceCallback.aidl b/packages/Keyguard/src/com/google/android/search/service/IHotwordServiceCallback.aidl
new file mode 100644
index 0000000..7b3765f
--- /dev/null
+++ b/packages/Keyguard/src/com/google/android/search/service/IHotwordServiceCallback.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.search.service;
+
+/**
+ * Interface implemented by users of Hotword service to get callbacks
+ * for hotword events.
+ */
+oneway interface IHotwordServiceCallback {
+
+ /** Hotword detection start/stop callbacks */
+ void onHotwordDetectionStarted();
+ void onHotwordDetectionStopped();
+
+ /**
+ * Called back when hotword is detected.
+ * The action tells the client what action to take, post hotword-detection.
+ */
+ void onHotwordDetected(in String action);
+}
diff --git a/packages/PrintSpooler/AndroidManifest.xml b/packages/PrintSpooler/AndroidManifest.xml
index 74fd7a8..1f10af8 100644
--- a/packages/PrintSpooler/AndroidManifest.xml
+++ b/packages/PrintSpooler/AndroidManifest.xml
@@ -18,7 +18,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.printspooler"
- android:sharedUserId="android.uid.printspooler"
+ android:sharedUserId="android.uid.system"
android:versionName="1"
android:versionCode="1"
coreApp="true">
@@ -50,6 +50,13 @@
android:theme="@style/PrintJobConfigActivityTheme">
</activity>
+ <activity
+ android:name=".SelectPrinterActivity"
+ android:label="@string/all_printers_label"
+ android:theme="@style/SelectPrinterActivityTheme"
+ android:exported="false">
+ </activity>
+
<receiver
android:name=".NotificationController$NotificationBroadcastReceiver"
android:exported="false" >
diff --git a/packages/PrintSpooler/res/drawable-hdpi/ic_menu_add.png b/packages/PrintSpooler/res/drawable-hdpi/ic_menu_add.png
new file mode 100644
index 0000000..4b68f52
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable-hdpi/ic_menu_add.png
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-mdpi/ic_menu_add.png b/packages/PrintSpooler/res/drawable-mdpi/ic_menu_add.png
new file mode 100644
index 0000000..15ffadd
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable-mdpi/ic_menu_add.png
Binary files differ
diff --git a/packages/PrintSpooler/res/drawable-xhdpi/ic_menu_add.png b/packages/PrintSpooler/res/drawable-xhdpi/ic_menu_add.png
new file mode 100644
index 0000000..420510e
--- /dev/null
+++ b/packages/PrintSpooler/res/drawable-xhdpi/ic_menu_add.png
Binary files differ
diff --git a/packages/PrintSpooler/res/layout/print_job_config_activity_container.xml b/packages/PrintSpooler/res/layout/print_job_config_activity_container.xml
index a0c111b..7817094 100644
--- a/packages/PrintSpooler/res/layout/print_job_config_activity_container.xml
+++ b/packages/PrintSpooler/res/layout/print_job_config_activity_container.xml
@@ -20,9 +20,4 @@
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@color/container_background">
-
- <include
- layout="@layout/print_job_config_activity_content_editing">
- </include>
-
</FrameLayout>
diff --git a/packages/PrintSpooler/res/layout/select_printer_activity.xml b/packages/PrintSpooler/res/layout/select_printer_activity.xml
new file mode 100644
index 0000000..f4e1853
--- /dev/null
+++ b/packages/PrintSpooler/res/layout/select_printer_activity.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <fragment
+ android:name="com.android.printspooler.SelectPrinterFragment"
+ android:id="@+id/select_printer_fragment"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+ </fragment>
+
+</FrameLayout> \ No newline at end of file
diff --git a/packages/PrintSpooler/res/layout/spinner_dropdown_item.xml b/packages/PrintSpooler/res/layout/spinner_dropdown_item.xml
index 002cc14..d14c064 100644
--- a/packages/PrintSpooler/res/layout/spinner_dropdown_item.xml
+++ b/packages/PrintSpooler/res/layout/spinner_dropdown_item.xml
@@ -15,7 +15,7 @@
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
+ android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingStart="8dip"
android:paddingEnd="8dip"
diff --git a/packages/PrintSpooler/res/menu/select_printer_activity.xml b/packages/PrintSpooler/res/menu/select_printer_activity.xml
new file mode 100644
index 0000000..28fbd35
--- /dev/null
+++ b/packages/PrintSpooler/res/menu/select_printer_activity.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <item
+ android:id="@+id/action_search"
+ android:title="@string/search"
+ android:icon="@*android:drawable/ic_menu_search_holo_light"
+ android:actionViewClass="android.widget.SearchView"
+ android:showAsAction="ifRoom"
+ android:alphabeticShortcut="f"
+ android:imeOptions="actionSearch">
+ </item>
+
+ <item
+ android:id="@+id/action_add_printer"
+ android:title="@null"
+ android:icon="@drawable/ic_menu_add"
+ android:showAsAction="ifRoom"
+ android:alphabeticShortcut="a">
+ </item>
+
+</menu>
diff --git a/packages/PrintSpooler/res/values/strings.xml b/packages/PrintSpooler/res/values/strings.xml
index 2086f58..41fc516 100644
--- a/packages/PrintSpooler/res/values/strings.xml
+++ b/packages/PrintSpooler/res/values/strings.xml
@@ -58,6 +58,32 @@
<!-- Title for the temporary dialog show while an app is generating a print job. [CHAR LIMIT=30] -->
<string name="generating_print_job">Generating print job</string>
+ <!-- Title for the save as PDF option in the printer list. [CHAR LIMIT=30] -->
+ <string name="save_as_pdf">Save as PDF</string>
+
+ <!-- Title for the open all printers UI option in the printer list. [CHAR LIMIT=30] -->
+ <string name="all_printers">All printers\.\.\.</string>
+
+ <!-- Title for the searching for printers option in the printer list
+ (only option if not printers are available). [CHAR LIMIT=40] -->
+ <string name="searching_for_printers">Searching for printers\.\.\.</string>
+
+ <!-- Select printer activity -->
+
+ <!-- Title for the share action bar menu item. [CHAR LIMIT=20] -->
+ <string name="search">Search</string>
+
+ <!-- Title for the select printer activity. [CHAR LIMIT=30] -->
+ <string name="all_printers_label">All printers</string>
+
+ <!-- Add printer dialog -->
+
+ <!-- Title for the alert dialog for selecting a print service. [CHAR LIMIT=50] -->
+ <string name="choose_print_service">Choose print service</string>
+
+ <!-- Title for the button to search the play store for print services. [CHAR LIMIT=50] -->
+ <string name="search_play_store">Search in play store</string>
+
<!-- Notifications -->
<!-- Template for the notificaiton label for a printing print job. [CHAR LIMIT=25] -->
diff --git a/packages/PrintSpooler/res/values/themes.xml b/packages/PrintSpooler/res/values/themes.xml
index ab16c65..831b0ec 100644
--- a/packages/PrintSpooler/res/values/themes.xml
+++ b/packages/PrintSpooler/res/values/themes.xml
@@ -24,4 +24,12 @@
<item name="android:colorBackgroundCacheHint">@android:color/transparent</item>
</style>
+ <style name="SelectPrinterActivityTheme" parent="@android:style/Theme.Holo.Light">
+ <item name="android:actionBarStyle">@style/SelectPrinterActivityActionBarStyle</item>
+ </style>
+
+ <style name="SelectPrinterActivityActionBarStyle" parent="@android:style/Widget.Holo.ActionBar">
+ <item name="android:displayOptions">showTitle</item>
+ </style>
+
</resources>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/FusedPrintersProvider.java b/packages/PrintSpooler/src/com/android/printspooler/FusedPrintersProvider.java
new file mode 100644
index 0000000..6bad5b3
--- /dev/null
+++ b/packages/PrintSpooler/src/com/android/printspooler/FusedPrintersProvider.java
@@ -0,0 +1,575 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.printspooler;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Loader;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.print.PrinterId;
+import android.print.PrinterInfo;
+import android.util.ArrayMap;
+import android.util.AtomicFile;
+import android.util.Log;
+import android.util.Slog;
+import android.util.Xml;
+
+import com.android.internal.util.FastXmlSerializer;
+import com.android.printspooler.PrintSpoolerService.PrinterDiscoverySession;
+
+import libcore.io.IoUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This class is responsible for loading printers by doing discovery
+ * and merging the discovered printers with the previously used ones.
+ */
+public class FusedPrintersProvider extends Loader<List<PrinterInfo>> {
+ private static final String LOG_TAG = "FusedPrintersProvider";
+
+ private static final boolean DEBUG = true && Build.IS_DEBUGGABLE;
+
+ private static final double WEIGHT_DECAY_COEFFICIENT = 0.95f;
+
+ private static final int MAX_HISTORY_LENGTH = 50;
+
+ private static final int MAX_HISTORICAL_PRINTER_COUNT = 4;
+
+ private final Map<PrinterId, PrinterInfo> mPrinters =
+ new LinkedHashMap<PrinterId, PrinterInfo>();
+
+ private final PersistenceManager mPersistenceManager;
+
+ private PrinterDiscoverySession mDiscoverySession;
+
+ private List<PrinterInfo> mFavoritePrinters;
+
+ public FusedPrintersProvider(Context context) {
+ super(context);
+ mPersistenceManager = new PersistenceManager(context);
+ }
+
+ public void addHistoricalPrinter(PrinterInfo printer) {
+ mPersistenceManager.addPrinterAndWritePrinterHistory(printer);
+ }
+
+ public List<PrinterInfo> getPrinters() {
+ return new ArrayList<PrinterInfo>(mPrinters.values());
+ }
+
+ @Override
+ public void deliverResult(List<PrinterInfo> printers) {
+ if (isStarted()) {
+ super.deliverResult(printers);
+ }
+ }
+
+ @Override
+ protected void onStartLoading() {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "onStartLoading()");
+ }
+ // The contract is that if we already have a valid,
+ // result the we have to deliver it immediately.
+ if (!mPrinters.isEmpty()) {
+ deliverResult(new ArrayList<PrinterInfo>(mPrinters.values()));
+ }
+ // If the data has changed since the last load
+ // or is not available, start a load.
+ if (takeContentChanged() || mPrinters.isEmpty()) {
+ onForceLoad();
+ }
+ }
+
+ @Override
+ protected void onStopLoading() {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "onStopLoading()");
+ }
+ onCancelLoad();
+ }
+
+ @Override
+ protected void onForceLoad() {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "onForceLoad()");
+ }
+ onCancelLoad();
+ loadInternal();
+ }
+
+ private void loadInternal() {
+ if (mDiscoverySession == null) {
+ mDiscoverySession = new MyPrinterDiscoverySession();
+ mPersistenceManager.readPrinterHistory();
+ }
+ if (mPersistenceManager.isReadHistoryCompleted()
+ && !mDiscoverySession.isStarted()) {
+ final int favoriteCount = Math.min(MAX_HISTORICAL_PRINTER_COUNT,
+ mFavoritePrinters.size());
+ List<PrinterId> printerIds = new ArrayList<PrinterId>(favoriteCount);
+ for (int i = 0; i < favoriteCount; i++) {
+ printerIds.add(mFavoritePrinters.get(i).getId());
+ }
+ mDiscoverySession.startPrinterDisovery(printerIds);
+ }
+ }
+
+ @Override
+ protected boolean onCancelLoad() {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "onCancelLoad()");
+ }
+ return cancelInternal();
+ }
+
+ private boolean cancelInternal() {
+ if (mDiscoverySession != null && mDiscoverySession.isStarted()) {
+ mDiscoverySession.stopPrinterDiscovery();
+ return true;
+ } else if (mPersistenceManager.isReadHistoryInProgress()) {
+ return mPersistenceManager.stopReadPrinterHistory();
+ }
+ return false;
+ }
+
+ @Override
+ protected void onReset() {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "onReset()");
+ }
+ onStopLoading();
+ mPrinters.clear();
+ if (mDiscoverySession != null) {
+ mDiscoverySession.destroy();
+ mDiscoverySession = null;
+ }
+ }
+
+ @Override
+ protected void onAbandon() {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "onAbandon()");
+ }
+ onStopLoading();
+ }
+
+ public void refreshPrinter(PrinterId printerId) {
+ if (isStarted() && mDiscoverySession != null && mDiscoverySession.isStarted()) {
+ mDiscoverySession.requestPrinterUpdated(printerId);
+ }
+ }
+
+ private final class MyPrinterDiscoverySession extends PrinterDiscoverySession {
+
+ @Override
+ public void onPrintersAdded(List<PrinterInfo> printers) {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "MyPrinterDiscoverySession#onPrintersAdded()");
+ }
+ boolean printersAdded = false;
+ final int addedPrinterCount = printers.size();
+ for (int i = 0; i < addedPrinterCount; i++) {
+ PrinterInfo printer = printers.get(i);
+ if (!mPrinters.containsKey(printer.getId())) {
+ mPrinters.put(printer.getId(), printer);
+ printersAdded = true;
+ }
+ }
+ if (printersAdded) {
+ deliverResult(new ArrayList<PrinterInfo>(mPrinters.values()));
+ }
+ }
+
+ @Override
+ public void onPrintersRemoved(List<PrinterId> printerIds) {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "MyPrinterDiscoverySession#onPrintersRemoved()");
+ }
+ boolean removedPrinters = false;
+ final int removedPrinterCount = printerIds.size();
+ for (int i = 0; i < removedPrinterCount; i++) {
+ PrinterId removedPrinterId = printerIds.get(i);
+ if (mPrinters.remove(removedPrinterId) != null) {
+ removedPrinters = true;
+ }
+ }
+ if (removedPrinters) {
+ deliverResult(new ArrayList<PrinterInfo>(mPrinters.values()));
+ }
+ }
+
+ @Override
+ public void onPrintersUpdated(List<PrinterInfo> printers) {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "MyPrinterDiscoverySession#onPrintersUpdated()");
+ }
+ boolean updatedPrinters = false;
+ final int updatedPrinterCount = printers.size();
+ for (int i = 0; i < updatedPrinterCount; i++) {
+ PrinterInfo updatedPrinter = printers.get(i);
+ if (mPrinters.containsKey(updatedPrinter.getId())) {
+ mPrinters.put(updatedPrinter.getId(), updatedPrinter);
+ updatedPrinters = true;
+ }
+ }
+ if (updatedPrinters) {
+ deliverResult(new ArrayList<PrinterInfo>(mPrinters.values()));
+ }
+ }
+ }
+
+ private final class PersistenceManager {
+ private static final String PERSIST_FILE_NAME = "printer_history.xml";
+
+ private static final String TAG_PRINTERS = "printers";
+
+ private static final String TAG_PRINTER = "printer";
+ private static final String TAG_PRINTER_ID = "printerId";
+
+ private static final String ATTR_LOCAL_ID = "localId";
+ private static final String ATTR_SERVICE_NAME = "serviceName";
+
+ private static final String ATTR_NAME = "name";
+ private static final String ATTR_DESCRIPTION = "description";
+ private static final String ATTR_STATUS = "status";
+
+ private final AtomicFile mStatePersistFile;
+
+ private List<PrinterInfo> mHistoricalPrinters;
+
+ private boolean mReadHistoryCompleted;
+ private boolean mReadHistoryInProgress;
+
+ private final AsyncTask<Void, Void, List<PrinterInfo>> mReadTask =
+ new AsyncTask<Void, Void, List<PrinterInfo>>() {
+ @Override
+ protected List<PrinterInfo> doInBackground(Void... args) {
+ return doReadPrinterHistory();
+ }
+
+ @Override
+ protected void onPostExecute(List<PrinterInfo> printers) {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "read history completed");
+ }
+
+ mHistoricalPrinters = printers;
+
+ // Compute the favorite printers.
+ mFavoritePrinters = computeFavoritePrinters(printers);
+
+ // We want the first few favorite printers on top of the list.
+ final int favoriteCount = Math.min(mFavoritePrinters.size(),
+ MAX_HISTORICAL_PRINTER_COUNT);
+ for (int i = 0; i < favoriteCount; i++) {
+ PrinterInfo favoritePrinter = mFavoritePrinters.get(i);
+ mPrinters.put(favoritePrinter.getId(), favoritePrinter);
+ }
+
+ mReadHistoryInProgress = false;
+ mReadHistoryCompleted = true;
+
+ loadInternal();
+ }
+
+ private List<PrinterInfo> doReadPrinterHistory() {
+ FileInputStream in = null;
+ try {
+ in = mStatePersistFile.openRead();
+ } catch (FileNotFoundException fnfe) {
+ Log.i(LOG_TAG, "No existing printer history.");
+ return new ArrayList<PrinterInfo>();
+ }
+ try {
+ List<PrinterInfo> printers = new ArrayList<PrinterInfo>();
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(in, null);
+ parseState(parser, printers);
+ return printers;
+ } catch (IllegalStateException ise) {
+ Slog.w(LOG_TAG, "Failed parsing ", ise);
+ } catch (NullPointerException npe) {
+ Slog.w(LOG_TAG, "Failed parsing ", npe);
+ } catch (NumberFormatException nfe) {
+ Slog.w(LOG_TAG, "Failed parsing ", nfe);
+ } catch (XmlPullParserException xppe) {
+ Slog.w(LOG_TAG, "Failed parsing ", xppe);
+ } catch (IOException ioe) {
+ Slog.w(LOG_TAG, "Failed parsing ", ioe);
+ } catch (IndexOutOfBoundsException iobe) {
+ Slog.w(LOG_TAG, "Failed parsing ", iobe);
+ } finally {
+ IoUtils.closeQuietly(in);
+ }
+
+ return Collections.emptyList();
+ }
+
+ private void parseState(XmlPullParser parser, List<PrinterInfo> outPrinters)
+ throws IOException, XmlPullParserException {
+ parser.next();
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.START_TAG, TAG_PRINTERS);
+ parser.next();
+
+ while (parsePrinter(parser, outPrinters)) {
+ // Be nice and respond to cancellation
+ if (isCancelled()) {
+ return;
+ }
+ parser.next();
+ }
+
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.END_TAG, TAG_PRINTERS);
+ }
+
+ private boolean parsePrinter(XmlPullParser parser, List<PrinterInfo> outPrinters)
+ throws IOException, XmlPullParserException {
+ skipEmptyTextTags(parser);
+ if (!accept(parser, XmlPullParser.START_TAG, TAG_PRINTER)) {
+ return false;
+ }
+
+ String name = parser.getAttributeValue(null, ATTR_NAME);
+ String description = parser.getAttributeValue(null, ATTR_DESCRIPTION);
+ final int status = Integer.parseInt(parser.getAttributeValue(null, ATTR_STATUS));
+
+ parser.next();
+
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.START_TAG, TAG_PRINTER_ID);
+ String localId = parser.getAttributeValue(null, ATTR_LOCAL_ID);
+ ComponentName service = ComponentName.unflattenFromString(parser.getAttributeValue(
+ null, ATTR_SERVICE_NAME));
+ PrinterId printerId = new PrinterId(service, localId);
+ parser.next();
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.END_TAG, TAG_PRINTER_ID);
+ parser.next();
+
+ PrinterInfo.Builder builder = new PrinterInfo.Builder(printerId, name, status);
+ builder.setDescription(description);
+ PrinterInfo printer = builder.create();
+
+ outPrinters.add(printer);
+
+ if (DEBUG) {
+ Log.i(LOG_TAG, "[RESTORED] " + printer);
+ }
+
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.END_TAG, TAG_PRINTER);
+
+ return true;
+ }
+
+ private void expect(XmlPullParser parser, int type, String tag)
+ throws IOException, XmlPullParserException {
+ if (!accept(parser, type, tag)) {
+ throw new XmlPullParserException("Exepected event: " + type
+ + " and tag: " + tag + " but got event: " + parser.getEventType()
+ + " and tag:" + parser.getName());
+ }
+ }
+
+ private void skipEmptyTextTags(XmlPullParser parser)
+ throws IOException, XmlPullParserException {
+ while (accept(parser, XmlPullParser.TEXT, null)
+ && "\n".equals(parser.getText())) {
+ parser.next();
+ }
+ }
+
+ private boolean accept(XmlPullParser parser, int type, String tag)
+ throws IOException, XmlPullParserException {
+ if (parser.getEventType() != type) {
+ return false;
+ }
+ if (tag != null) {
+ if (!tag.equals(parser.getName())) {
+ return false;
+ }
+ } else if (parser.getName() != null) {
+ return false;
+ }
+ return true;
+ }
+ };
+
+ private final AsyncTask<List<PrinterInfo>, Void, Void> mWriteTask =
+ new AsyncTask<List<PrinterInfo>, Void, Void>() {
+ @Override
+ protected Void doInBackground(List<PrinterInfo>... printers) {
+ doWritePrinterHistory(printers[0]);
+ return null;
+ }
+
+ private void doWritePrinterHistory(List<PrinterInfo> printers) {
+ FileOutputStream out = null;
+ try {
+ out = mStatePersistFile.startWrite();
+
+ XmlSerializer serializer = new FastXmlSerializer();
+ serializer.setOutput(out, "utf-8");
+ serializer.startDocument(null, true);
+ serializer.startTag(null, TAG_PRINTERS);
+
+ final int printerCount = printers.size();
+ for (int i = 0; i < printerCount; i++) {
+ PrinterInfo printer = printers.get(i);
+
+ serializer.startTag(null, TAG_PRINTER);
+
+ serializer.attribute(null, ATTR_NAME, printer.getName());
+ serializer.attribute(null, ATTR_STATUS, String.valueOf(
+ printer.getStatus()));
+ String description = printer.getDescription();
+ if (description != null) {
+ serializer.attribute(null, ATTR_DESCRIPTION, description);
+ }
+
+ PrinterId printerId = printer.getId();
+ serializer.startTag(null, TAG_PRINTER_ID);
+ serializer.attribute(null, ATTR_LOCAL_ID, printerId.getLocalId());
+ serializer.attribute(null, ATTR_SERVICE_NAME, printerId.getServiceName()
+ .flattenToString());
+ serializer.endTag(null, TAG_PRINTER_ID);
+
+ serializer.endTag(null, TAG_PRINTER);
+
+ if (DEBUG) {
+ Log.i(LOG_TAG, "[PERSISTED] " + printer);
+ }
+ }
+
+ serializer.endTag(null, TAG_PRINTERS);
+ serializer.endDocument();
+ mStatePersistFile.finishWrite(out);
+
+ if (DEBUG) {
+ Log.i(LOG_TAG, "[PERSIST END]");
+ }
+ } catch (IOException ioe) {
+ Slog.w(LOG_TAG, "Failed to write printer history, restoring backup.", ioe);
+ mStatePersistFile.failWrite(out);
+ } finally {
+ IoUtils.closeQuietly(out);
+ }
+ }
+ };
+
+ private PersistenceManager(Context context) {
+ mStatePersistFile = new AtomicFile(new File(context.getFilesDir(),
+ PERSIST_FILE_NAME));
+ }
+
+ public boolean isReadHistoryInProgress() {
+ return mReadHistoryInProgress;
+ }
+
+ public boolean isReadHistoryCompleted() {
+ return mReadHistoryCompleted;
+ }
+
+ public boolean stopReadPrinterHistory() {
+ return mReadTask.cancel(true);
+ }
+
+ public void readPrinterHistory() {
+ if (DEBUG) {
+ Log.i(LOG_TAG, "read history started");
+ }
+ mReadHistoryInProgress = true;
+ mReadTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void addPrinterAndWritePrinterHistory(PrinterInfo printer) {
+ if (mHistoricalPrinters.size() >= MAX_HISTORY_LENGTH) {
+ mHistoricalPrinters.remove(0);
+ }
+ mHistoricalPrinters.add(printer);
+ mWriteTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, mHistoricalPrinters);
+ }
+
+ private List<PrinterInfo> computeFavoritePrinters(List<PrinterInfo> printers) {
+ Map<PrinterId, PrinterRecord> recordMap =
+ new ArrayMap<PrinterId, PrinterRecord>();
+
+ // Recompute the weights.
+ float currentWeight = 1.0f;
+ final int printerCount = printers.size();
+ for (int i = printerCount - 1; i >= 0; i--) {
+ PrinterInfo printer = printers.get(i);
+ // Aggregate weight for the same printer
+ PrinterRecord record = recordMap.get(printer.getId());
+ if (record == null) {
+ record = new PrinterRecord(printer);
+ recordMap.put(printer.getId(), record);
+ }
+ record.weight += currentWeight;
+ currentWeight *= WEIGHT_DECAY_COEFFICIENT;
+ }
+
+ // Soft the favorite printers.
+ List<PrinterRecord> favoriteRecords = new ArrayList<PrinterRecord>(
+ recordMap.values());
+ Collections.sort(favoriteRecords);
+
+ // Write the favorites to the output.
+ final int favoriteCount = favoriteRecords.size();
+ List<PrinterInfo> favoritePrinters = new ArrayList<PrinterInfo>(favoriteCount);
+ for (int i = 0; i < favoriteCount; i++) {
+ PrinterInfo printer = favoriteRecords.get(i).printer;
+ favoritePrinters.add(printer);
+ }
+
+ return favoritePrinters;
+ }
+
+ private final class PrinterRecord implements Comparable<PrinterRecord> {
+ public final PrinterInfo printer;
+ public float weight;
+
+ public PrinterRecord(PrinterInfo printer) {
+ this.printer = printer;
+ }
+
+ @Override
+ public int compareTo(PrinterRecord another) {
+ return Float.floatToIntBits(another.weight) - Float.floatToIntBits(weight);
+ }
+ }
+ }
+}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
index 9160b7d..d3dd8c9 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
@@ -18,12 +18,17 @@ package com.android.printspooler;
import android.app.Activity;
import android.app.Dialog;
+import android.app.LoaderManager;
import android.content.Context;
+import android.content.Intent;
+import android.content.Loader;
import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.database.DataSetObserver;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
@@ -34,15 +39,15 @@ import android.os.Message;
import android.os.RemoteException;
import android.print.ILayoutResultCallback;
import android.print.IPrintDocumentAdapter;
-import android.print.IPrinterDiscoverySessionController;
-import android.print.IPrinterDiscoverySessionObserver;
import android.print.IWriteResultCallback;
import android.print.PageRange;
import android.print.PrintAttributes;
import android.print.PrintAttributes.MediaSize;
+import android.print.PrintAttributes.Resolution;
import android.print.PrintDocumentAdapter;
import android.print.PrintDocumentInfo;
import android.print.PrintJobInfo;
+import android.print.PrintManager;
import android.print.PrinterCapabilitiesInfo;
import android.print.PrinterId;
import android.print.PrinterInfo;
@@ -64,15 +69,23 @@ import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
+import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
+import libcore.io.IoUtils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
@@ -94,15 +107,32 @@ public class PrintJobConfigActivity extends Activity {
public static final String EXTRA_PRINT_ATTRIBUTES = "printAttributes";
public static final String EXTRA_PRINT_JOB_ID = "printJobId";
- private static final int CONTROLLER_STATE_INITIALIZED = 1;
- private static final int CONTROLLER_STATE_STARTED = 2;
- private static final int CONTROLLER_STATE_LAYOUT_STARTED = 3;
- private static final int CONTROLLER_STATE_LAYOUT_COMPLETED = 4;
- private static final int CONTROLLER_STATE_WRITE_STARTED = 5;
- private static final int CONTROLLER_STATE_WRITE_COMPLETED = 6;
- private static final int CONTROLLER_STATE_FINISHED = 7;
- private static final int CONTROLLER_STATE_FAILED = 8;
- private static final int CONTROLLER_STATE_CANCELLED = 9;
+ public static final String INTENT_EXTRA_PRINTER_ID = "INTENT_EXTRA_PRINTER_ID";
+
+ private static final int LOADER_ID_PRINTERS_LOADER = 1;
+
+ private static final int DEST_ADAPTER_MIN_ITEM_COUNT = 2;
+ private static final int DEST_ADAPTER_MAX_ITEM_COUNT = 9;
+
+ private static final int DEST_ADAPTER_POSITION_SEARCHING_FOR_PRINTERS = 0;
+ private static final int DEST_ADAPTER_POSITION_SAVE_AS_PDF = 1;
+
+ private static final int DEST_ADAPTER_ITEM_ID_SAVE_AS_PDF = Integer.MAX_VALUE;
+ private static final int DEST_ADAPTER_ITEM_ID_ALL_PRINTERS = Integer.MAX_VALUE - 1;
+ private static final int DEST_ADAPTER_ITEM_ID_SEARCHING_FOR_PRINTERS = Integer.MAX_VALUE - 2;
+
+ private static final int ACTIVITY_REQUEST_CREATE_FILE = 1;
+ private static final int ACTIVITY_REQUEST_SELECT_PRINTER = 2;
+
+ private static final int CONTROLLER_STATE_FINISHED = 1;
+ private static final int CONTROLLER_STATE_FAILED = 2;
+ private static final int CONTROLLER_STATE_CANCELLED = 3;
+ private static final int CONTROLLER_STATE_INITIALIZED = 4;
+ private static final int CONTROLLER_STATE_STARTED = 5;
+ private static final int CONTROLLER_STATE_LAYOUT_STARTED = 6;
+ private static final int CONTROLLER_STATE_LAYOUT_COMPLETED = 7;
+ private static final int CONTROLLER_STATE_WRITE_STARTED = 8;
+ private static final int CONTROLLER_STATE_WRITE_COMPLETED = 9;
private static final int EDITOR_STATE_INITIALIZED = 1;
private static final int EDITOR_STATE_CONFIRMED_PRINT = 2;
@@ -110,6 +140,7 @@ public class PrintJobConfigActivity extends Activity {
private static final int EDITOR_STATE_CANCELLED = 4;
private static final int MIN_COPIES = 1;
+ private static final String MIN_COPIES_STRING = String.valueOf(MIN_COPIES);
private static final Pattern PATTERN_DIGITS = Pattern.compile("\\d");
@@ -132,11 +163,9 @@ public class PrintJobConfigActivity extends Activity {
}
};
- private PrintSpooler mSpooler;
private Editor mEditor;
private Document mDocument;
private PrintController mController;
- private PrinterDiscoverySessionObserver mPrinterDiscoverySessionObserver;
private int mPrintJobId;
@@ -147,9 +176,6 @@ public class PrintJobConfigActivity extends Activity {
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
- setContentView(R.layout.print_job_config_activity_container);
-
- getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
Bundle extras = getIntent().getExtras();
@@ -168,12 +194,17 @@ public class PrintJobConfigActivity extends Activity {
mCurrPrintAttributes.copyFrom(attributes);
}
- mSpooler = PrintSpooler.peekInstance();
+ setContentView(R.layout.print_job_config_activity_container);
+
+ // TODO: This should be on the style
+ getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
+
+
mEditor = new Editor();
mDocument = new Document();
mController = new PrintController(new RemotePrintDocumentAdapter(
IPrintDocumentAdapter.Stub.asInterface(mIPrintDocumentAdapter),
- mSpooler.generateFileForPrintJob(mPrintJobId)));
+ PrintSpoolerService.peekInstance().generateFileForPrintJob(mPrintJobId)));
try {
mIPrintDocumentAdapter.linkToDeath(mDeathRecipient, 0);
@@ -184,9 +215,6 @@ public class PrintJobConfigActivity extends Activity {
mController.initialize();
mEditor.initialize();
- mPrinterDiscoverySessionObserver = new PrinterDiscoverySessionObserver(mEditor,
- getMainLooper());
- mSpooler.createPrinterDiscoverySession(mPrinterDiscoverySessionObserver);
}
@Override
@@ -194,17 +222,14 @@ public class PrintJobConfigActivity extends Activity {
// We can safely do the work in here since at this point
// the system is bound to our (spooler) process which
// guarantees that this process will not be killed.
- mPrinterDiscoverySessionObserver.close();
- mPrinterDiscoverySessionObserver.destroy();
- mPrinterDiscoverySessionObserver = null;
if (mController.hasStarted()) {
mController.finish();
}
if (mEditor.isPrintConfirmed() && mController.isFinished()) {
- mSpooler.setPrintJobState(mPrintJobId,
+ PrintSpoolerService.peekInstance().setPrintJobState(mPrintJobId,
PrintJobInfo.STATE_QUEUED, null);
} else {
- mSpooler.setPrintJobState(mPrintJobId,
+ PrintSpoolerService.peekInstance().setPrintJobState(mPrintJobId,
PrintJobInfo.STATE_CANCELED, null);
}
mIPrintDocumentAdapter.unlinkToDeath(mDeathRecipient, 0);
@@ -315,12 +340,13 @@ public class PrintJobConfigActivity extends Activity {
public void update() {
if (!printAttributesChanged()) {
- // If the attributes changes, then we do not do a layout but may
+ // If the attributes changed, then we do not do a layout but may
// have to ask the app to write some pages. Hence, pretend layout
// completed and nothing changed, so we handle writing as usual.
handleOnLayoutFinished(mDocument.info, false, mRequestCounter.get());
} else {
- mSpooler.setPrintJobAttributesNoPersistence(mPrintJobId, mCurrPrintAttributes);
+ PrintSpoolerService.peekInstance().setPrintJobAttributesNoPersistence(
+ mPrintJobId, mCurrPrintAttributes);
mMetadata.putBoolean(PrintDocumentAdapter.METADATA_KEY_PRINT_PREVIEW,
!mEditor.isPrintConfirmed());
@@ -353,15 +379,14 @@ public class PrintJobConfigActivity extends Activity {
}
mControllerState = CONTROLLER_STATE_LAYOUT_COMPLETED;
+ mEditor.updateUi();
- // If the info changed, we update the document and the print job,
- // and update the UI since the the page range selection may have
- // become invalid.
+ // If the info changed, we update the document and the print job.
final boolean infoChanged = !info.equals(mDocument.info);
if (infoChanged) {
mDocument.info = info;
- mSpooler.setPrintJobPrintDocumentInfoNoPersistence(mPrintJobId, info);
- mEditor.updateUi();
+ PrintSpoolerService.peekInstance().setPrintJobPrintDocumentInfoNoPersistence(
+ mPrintJobId, info);
}
// If the document info or the layout changed, then
@@ -447,11 +472,13 @@ public class PrintJobConfigActivity extends Activity {
if (Arrays.equals(mDocument.pages, mRequestedPages)) {
// We got a document with exactly the pages we wanted. Hence,
// the printer has to print all pages in the data.
- mSpooler.setPrintJobPagesNoPersistence(mPrintJobId, ALL_PAGES_ARRAY);
+ PrintSpoolerService.peekInstance().setPrintJobPagesNoPersistence(mPrintJobId,
+ ALL_PAGES_ARRAY);
} else if (Arrays.equals(mDocument.pages, ALL_PAGES_ARRAY)) {
// We requested specific pages but got all of them. Hence,
// the printer has to print only the requested pages.
- mSpooler.setPrintJobPagesNoPersistence(mPrintJobId, mRequestedPages);
+ PrintSpoolerService.peekInstance().setPrintJobPagesNoPersistence(mPrintJobId,
+ mRequestedPages);
} else if (PageRangeUtils.contains(mDocument.pages, mRequestedPages)) {
// We requested specific pages and got more but not all pages.
// Hence, we have to offset appropriately the printed pages to
@@ -460,14 +487,16 @@ public class PrintJobConfigActivity extends Activity {
final int offset = mDocument.pages[0].getStart() - pages[0].getStart();
PageRange[] offsetPages = Arrays.copyOf(mDocument.pages, mDocument.pages.length);
PageRangeUtils.offsetStart(offsetPages, offset);
- mSpooler.setPrintJobPagesNoPersistence(mPrintJobId, offsetPages);
+ PrintSpoolerService.peekInstance().setPrintJobPagesNoPersistence(mPrintJobId,
+ offsetPages);
} else if (Arrays.equals(mRequestedPages, ALL_PAGES_ARRAY)
&& mDocument.pages.length == 1 && mDocument.pages[0].getStart() == 0
&& mDocument.pages[0].getEnd() == mDocument.info.getPageCount() - 1) {
// We requested all pages via the special constant and got all
// of them as an explicit enumeration. Hence, the printer has
// to print only the requested pages.
- mSpooler.setPrintJobPagesNoPersistence(mPrintJobId, mDocument.pages);
+ PrintSpoolerService.peekInstance().setPrintJobPagesNoPersistence(mPrintJobId,
+ mDocument.pages);
} else {
// We did not get the pages we requested, then the application
// misbehaves, so we fail quickly.
@@ -478,7 +507,16 @@ public class PrintJobConfigActivity extends Activity {
}
if (mEditor.isDone()) {
- PrintJobConfigActivity.this.finish();
+ if (mEditor.isPrintingToPdf()) {
+ PrintJobInfo printJob = PrintSpoolerService.peekInstance()
+ .getPrintJobInfo(mPrintJobId, PrintManager.APP_ID_ANY);
+ Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
+ intent.setType("application/pdf");
+ intent.putExtra(Intent.EXTRA_TITLE, printJob.getLabel());
+ startActivityForResult(intent, ACTIVITY_REQUEST_CREATE_FILE);
+ } else {
+ PrintJobConfigActivity.this.finish();
+ }
}
}
@@ -585,33 +623,111 @@ public class PrintJobConfigActivity extends Activity {
}
}
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ switch (requestCode) {
+ case ACTIVITY_REQUEST_CREATE_FILE: {
+ if (data != null) {
+ Uri uri = data.getData();
+ writePrintJobDataAndFinish(uri);
+ } else {
+ mEditor.showUi(Editor.UI_EDITING_PRINT_JOB,
+ new Runnable() {
+ @Override
+ public void run() {
+ mEditor.initialize();
+ mEditor.bindUi();
+ mEditor.updateUi();
+ }
+ });
+ }
+ } break;
+
+ case ACTIVITY_REQUEST_SELECT_PRINTER: {
+ if (resultCode == RESULT_OK) {
+ PrinterId printerId = (PrinterId) data.getParcelableExtra(
+ INTENT_EXTRA_PRINTER_ID);
+ // TODO: Make sure the selected printer is in the shown list.
+ mEditor.selectPrinter(printerId);
+ }
+ } break;
+ }
+ }
+
+ private void writePrintJobDataAndFinish(final Uri uri) {
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ InputStream in = null;
+ OutputStream out = null;
+ try {
+ PrintJobInfo printJob = PrintSpoolerService.peekInstance()
+ .getPrintJobInfo(mPrintJobId, PrintManager.APP_ID_ANY);
+ if (printJob == null) {
+ return null;
+ }
+ File file = PrintSpoolerService.peekInstance()
+ .generateFileForPrintJob(mPrintJobId);
+ in = new FileInputStream(file);
+ out = getContentResolver().openOutputStream(uri);
+ final byte[] buffer = new byte[8192];
+ while (true) {
+ final int readByteCount = in.read(buffer);
+ if (readByteCount < 0) {
+ break;
+ }
+ out.write(buffer, 0, readByteCount);
+ }
+ } catch (FileNotFoundException fnfe) {
+ Log.e(LOG_TAG, "Error writing print job data!", fnfe);
+ } catch (IOException ioe) {
+ Log.e(LOG_TAG, "Error writing print job data!", ioe);
+ } finally {
+ IoUtils.closeQuietly(in);
+ IoUtils.closeQuietly(out);
+ }
+ return null;
+ }
+
+ @Override
+ public void onPostExecute(Void result) {
+ mEditor.cancel();
+ PrintJobConfigActivity.this.finish();
+ }
+ }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
+ }
+
private final class Editor {
- private final EditText mCopiesEditText;
+ private static final int UI_NONE = 0;
+ private static final int UI_EDITING_PRINT_JOB = 1;
+ private static final int UI_GENERATING_PRINT_JOB = 2;
+
+ private EditText mCopiesEditText;
- private final TextView mRangeTitle;
- private final EditText mRangeEditText;
+ private TextView mRangeTitle;
+ private EditText mRangeEditText;
- private final Spinner mDestinationSpinner;
- private final ArrayAdapter<SpinnerItem<PrinterInfo>> mDestinationSpinnerAdapter;
+ private Spinner mDestinationSpinner;
+ private final DestinationAdapter mDestinationSpinnerAdapter;
- private final Spinner mMediaSizeSpinner;
+ private Spinner mMediaSizeSpinner;
private final ArrayAdapter<SpinnerItem<MediaSize>> mMediaSizeSpinnerAdapter;
- private final Spinner mColorModeSpinner;
+ private Spinner mColorModeSpinner;
private final ArrayAdapter<SpinnerItem<Integer>> mColorModeSpinnerAdapter;
- private final Spinner mOrientationSpinner;
+ private Spinner mOrientationSpinner;
private final ArrayAdapter<SpinnerItem<Integer>> mOrientationSpinnerAdapter;
- private final Spinner mRangeOptionsSpinner;
+ private Spinner mRangeOptionsSpinner;
private final ArrayAdapter<SpinnerItem<Integer>> mRangeOptionsSpinnerAdapter;
private final SimpleStringSplitter mStringCommaSplitter =
new SimpleStringSplitter(',');
- private final View mContentContainer;
+ private View mContentContainer;
- private final Button mPrintButton;
+ private Button mPrintButton;
private final OnItemSelectedListener mOnItemSelectedListener =
new AdapterView.OnItemSelectedListener() {
@@ -622,16 +738,32 @@ public class PrintJobConfigActivity extends Activity {
mIgnoreNextDestinationChange = false;
return;
}
+ if (id == DEST_ADAPTER_ITEM_ID_ALL_PRINTERS) {
+ mIgnoreNextDestinationChange = true;
+ mDestinationSpinner.setSelection(0);
+ Intent intent = new Intent(PrintJobConfigActivity.this,
+ SelectPrinterActivity.class);
+ startActivityForResult(intent, ACTIVITY_REQUEST_SELECT_PRINTER);
+ return;
+ }
+ mWaitingForPrinterCapabilities = false;
mCurrPrintAttributes.clear();
- SpinnerItem<PrinterInfo> dstItem = mDestinationSpinnerAdapter.getItem(position);
- if (dstItem != null) {
- PrinterInfo printer = dstItem.value;
- mSpooler.setPrintJobPrinterNoPersistence(mPrintJobId, printer);
+ PrinterInfo printer = (PrinterInfo) mDestinationSpinnerAdapter
+ .getItem(position);
+ if (printer != null) {
+ PrintSpoolerService.peekInstance().setPrintJobPrinterNoPersistence(
+ mPrintJobId, printer);
PrinterCapabilitiesInfo capabilities = printer.getCapabilities();
if (capabilities == null) {
List<PrinterId> printerIds = new ArrayList<PrinterId>();
printerIds.add(printer.getId());
- mPrinterDiscoverySessionObserver.requestPrinterUpdate(printer.getId());
+ FusedPrintersProvider printersLoader = (FusedPrintersProvider)
+ (Loader<?>) getLoaderManager().getLoader(
+ LOADER_ID_PRINTERS_LOADER);
+ if (printersLoader != null) {
+ printersLoader.refreshPrinter(printer.getId());
+ }
+ mWaitingForPrinterCapabilities = true;
//TODO: We need a timeout for the update.
} else {
capabilities.getDefaults(mCurrPrintAttributes);
@@ -643,6 +775,31 @@ public class PrintJobConfigActivity extends Activity {
}
}
}
+
+ // The printer changed so we want to start with a clean slate
+ // for the print options and let them be populated from the
+ // printer capabilities and use the printer defaults.
+ if (!mMediaSizeSpinnerAdapter.isEmpty()) {
+ mIgnoreNextMediaSizeChange = true;
+ mMediaSizeSpinnerAdapter.clear();
+ }
+ if (!mColorModeSpinnerAdapter.isEmpty()) {
+ mIgnoreNextColorModeChange = true;
+ mColorModeSpinnerAdapter.clear();
+ }
+ if (!mOrientationSpinnerAdapter.isEmpty()) {
+ mIgnoreNextOrientationChange = true;
+ mOrientationSpinnerAdapter.clear();
+ }
+ if (mRangeOptionsSpinner.getSelectedItemPosition() != 0) {
+ mIgnoreNextRangeOptionChange = true;
+ mRangeOptionsSpinner.setSelection(0);
+ }
+ if (!TextUtils.isEmpty(mCopiesEditText.getText())) {
+ mIgnoreNextCopiesChange = true;
+ mCopiesEditText.setText(MIN_COPIES_STRING);
+ }
+
updateUi();
} else if (spinner == mMediaSizeSpinner) {
if (mIgnoreNextMediaSizeChange) {
@@ -728,7 +885,8 @@ public class PrintJobConfigActivity extends Activity {
}
mCopiesEditText.setError(null);
- mSpooler.setPrintJobCopiesNoPersistence(mPrintJobId, copies);
+ PrintSpoolerService.peekInstance().setPrintJobCopiesNoPersistence(
+ mPrintJobId, copies);
updateUi();
if (hadErrors && !hasErrors() && printAttributesChanged()) {
@@ -805,54 +963,64 @@ public class PrintJobConfigActivity extends Activity {
private boolean mIgnoreNextCopiesChange;
private boolean mIgnoreNextRangeChange;
- public Editor() {
- // Content container
- mContentContainer = findViewById(R.id.content_container);
+ private boolean mWaitingForPrinterCapabilities;
- // Copies
- mCopiesEditText = (EditText) findViewById(R.id.copies_edittext);
- mCopiesEditText.setText(String.valueOf(MIN_COPIES));
- mSpooler.setPrintJobCopiesNoPersistence(mPrintJobId, MIN_COPIES);
- mCopiesEditText.addTextChangedListener(mCopiesTextWatcher);
- mCopiesEditText.selectAll();
+ private int mCurrentUi = UI_NONE;
+ public Editor() {
// Destination.
- mDestinationSpinner = (Spinner) findViewById(R.id.destination_spinner);
mDestinationSpinnerAdapter = new DestinationAdapter();
- mDestinationSpinner.setAdapter(mDestinationSpinnerAdapter);
- mDestinationSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
+ mDestinationSpinnerAdapter.registerDataSetObserver(new DataSetObserver() {
+ @Override
+ public void onChanged() {
+ final int selectedPosition = mDestinationSpinner.getSelectedItemPosition();
+ if (mDestinationSpinnerAdapter.getCount() > 0) {
+ // Make sure we select the first printer if we have data.
+ if (selectedPosition == AdapterView.INVALID_POSITION) {
+ mDestinationSpinner.setSelection(0);
+ }
+ } else {
+ // Make sure we select no printer if we have no data.
+ mDestinationSpinner.setSelection(AdapterView.INVALID_POSITION);
+ }
+
+ // Maybe we did not have capabilities when the current printer was
+ // selected, but now the selected printer has capabilities. Generate
+ // a fake selection so the code in the selection change handling takes
+ // care of updating everything. This way the logic is in one place.
+ if (mWaitingForPrinterCapabilities) {
+ mWaitingForPrinterCapabilities = false;
+ PrinterInfo printer = (PrinterInfo) mDestinationSpinner.getSelectedItem();
+ if (printer != null && printer.getCapabilities() != null) {
+ mOnItemSelectedListener.onItemSelected(mDestinationSpinner, null,
+ selectedPosition, selectedPosition);
+ }
+ }
+ updateUi();
+ }
+
+ @Override
+ public void onInvalidated() {
+ updateUi();
+ }
+ });
// Media size.
- mMediaSizeSpinner = (Spinner) findViewById(R.id.paper_size_spinner);
mMediaSizeSpinnerAdapter = new ArrayAdapter<SpinnerItem<MediaSize>>(
PrintJobConfigActivity.this,
R.layout.spinner_dropdown_item, R.id.title);
- mMediaSizeSpinner.setAdapter(mMediaSizeSpinnerAdapter);
- mMediaSizeSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
// Color mode.
- mColorModeSpinner = (Spinner) findViewById(R.id.color_spinner);
mColorModeSpinnerAdapter = new ArrayAdapter<SpinnerItem<Integer>>(
PrintJobConfigActivity.this,
R.layout.spinner_dropdown_item, R.id.title);
- mColorModeSpinner.setAdapter(mColorModeSpinnerAdapter);
- mColorModeSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
// Orientation
- mOrientationSpinner = (Spinner) findViewById(R.id.orientation_spinner);
mOrientationSpinnerAdapter = new ArrayAdapter<SpinnerItem<Integer>>(
PrintJobConfigActivity.this,
R.layout.spinner_dropdown_item, R.id.title);
- mOrientationSpinner.setAdapter(mOrientationSpinnerAdapter);
- mOrientationSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
-
- // Range
- mRangeTitle = (TextView) findViewById(R.id.page_range_title);
- mRangeEditText = (EditText) findViewById(R.id.page_range_edittext);
- mRangeEditText.addTextChangedListener(mRangeTextWatcher);
// Range options
- mRangeOptionsSpinner = (Spinner) findViewById(R.id.range_options_spinner);
mRangeOptionsSpinnerAdapter = new ArrayAdapter<SpinnerItem<Integer>>(
PrintJobConfigActivity.this,
R.layout.spinner_dropdown_item, R.id.title);
@@ -865,25 +1033,26 @@ public class PrintJobConfigActivity extends Activity {
mRangeOptionsSpinnerAdapter.add(new SpinnerItem<Integer>(
rangeOptionsValues[i], rangeOptionsLabels[i]));
}
- mRangeOptionsSpinner.setAdapter(mRangeOptionsSpinnerAdapter);
- if (mRangeOptionsSpinner.getSelectedItemPosition() != 0) {
- mIgnoreNextRangeOptionChange = true;
- mRangeOptionsSpinner.setSelection(0);
- }
- // Print button
- mPrintButton = (Button) findViewById(R.id.print_button);
- mPrintButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- mEditor.confirmPrint();
- updateUi();
- mController.update();
- showGeneratingPrintJobUi();
+ showUi(UI_EDITING_PRINT_JOB, null);
+ bindUi();
+ updateUi();
+ }
+
+ public void selectPrinter(PrinterId printerId) {
+ final int printerCount = mDestinationSpinnerAdapter.getCount();
+ for (int i = 0; i < printerCount; i++) {
+ PrinterInfo printer = (PrinterInfo) mDestinationSpinnerAdapter.getItem(i);
+ if (printer.getId().equals(printerId)) {
+ mDestinationSpinner.setSelection(i);
+ return;
}
- });
+ }
+ }
- updateUi();
+ public boolean isPrintingToPdf() {
+ return mDestinationSpinner.getSelectedItem()
+ == mDestinationSpinnerAdapter.mFakePdfPrinter;
}
public boolean shouldCloseOnTouch(MotionEvent event) {
@@ -913,19 +1082,104 @@ public class PrintJobConfigActivity extends Activity {
}
public boolean isShwoingGeneratingPrintJobUi() {
- return (findViewById(R.id.content_generating) != null);
+ return (mCurrentUi == UI_GENERATING_PRINT_JOB);
}
- private void showGeneratingPrintJobUi() {
- // Find everything we will shuffle around.
- final ViewGroup contentContainer = (ViewGroup) findViewById(R.id.content_container);
- final View contentEditing = contentContainer.findViewById(R.id.content_editing);
- final View contentGenerating = getLayoutInflater().inflate(
- R.layout.print_job_config_activity_content_generating,
- contentContainer, false);
+ public void showUi(int ui, final Runnable postSwitchCallback) {
+ if (ui == UI_NONE) {
+ throw new IllegalStateException("cannot remove the ui");
+ }
+
+ if (mCurrentUi == ui) {
+ return;
+ }
+
+ switch (mCurrentUi) {
+ case UI_NONE: {
+ switch (ui) {
+ case UI_EDITING_PRINT_JOB: {
+ doUiSwitch(R.layout.print_job_config_activity_content_editing);
+ registerPrintButtonClickListener();
+ if (postSwitchCallback != null) {
+ postSwitchCallback.run();
+ }
+ } break;
- // Wire the cancel action.
- Button cancelButton = (Button) contentGenerating.findViewById(R.id.cancel_button);
+ case UI_GENERATING_PRINT_JOB: {
+ doUiSwitch(R.layout.print_job_config_activity_content_generating);
+ registerCancelButtonClickListener();
+ if (postSwitchCallback != null) {
+ postSwitchCallback.run();
+ }
+ } break;
+ }
+ } break;
+
+ case UI_EDITING_PRINT_JOB: {
+ switch (ui) {
+ case UI_GENERATING_PRINT_JOB: {
+ animateUiSwitch(R.layout.print_job_config_activity_content_generating,
+ new Runnable() {
+ @Override
+ public void run() {
+ registerCancelButtonClickListener();
+ if (postSwitchCallback != null) {
+ postSwitchCallback.run();
+ }
+ }
+ });
+ } break;
+ }
+ } break;
+
+ case UI_GENERATING_PRINT_JOB: {
+ switch (ui) {
+ case UI_EDITING_PRINT_JOB: {
+ animateUiSwitch(R.layout.print_job_config_activity_content_editing,
+ new Runnable() {
+ @Override
+ public void run() {
+ registerPrintButtonClickListener();
+ if (postSwitchCallback != null) {
+ postSwitchCallback.run();
+ }
+ }
+ });
+ } break;
+ }
+ } break;
+ }
+
+ mCurrentUi = ui;
+ }
+
+ private void registerPrintButtonClickListener() {
+ Button printButton = (Button) findViewById(R.id.print_button);
+ printButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ PrinterInfo printer = (PrinterInfo) mDestinationSpinner.getSelectedItem();
+ if (printer != null) {
+ mEditor.confirmPrint();
+ mController.update();
+ if (!printer.equals(mDestinationSpinnerAdapter.mFakePdfPrinter)) {
+ FusedPrintersProvider printersLoader = (FusedPrintersProvider)
+ (Loader<?>) getLoaderManager().getLoader(
+ LOADER_ID_PRINTERS_LOADER);
+ if (printersLoader != null) {
+ printersLoader.addHistoricalPrinter(printer);
+ }
+ }
+ } else {
+ mEditor.cancel();
+ PrintJobConfigActivity.this.finish();
+ }
+ }
+ });
+ }
+
+ private void registerCancelButtonClickListener() {
+ Button cancelButton = (Button) findViewById(R.id.cancel_button);
cancelButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
@@ -935,24 +1189,38 @@ public class PrintJobConfigActivity extends Activity {
mEditor.cancel();
}
});
+ }
+
+ private void doUiSwitch(int showLayoutId) {
+ ViewGroup contentContainer = (ViewGroup) findViewById(R.id.content_container);
+ contentContainer.removeAllViews();
+ getLayoutInflater().inflate(showLayoutId, contentContainer, true);
+ }
+
+ private void animateUiSwitch(int showLayoutId, final Runnable postAnimateCommand) {
+ // Find everything we will shuffle around.
+ final ViewGroup contentContainer = (ViewGroup) findViewById(R.id.content_container);
+ final View hidingView = contentContainer.getChildAt(0);
+ final View showingView = getLayoutInflater().inflate(showLayoutId,
+ null, false);
// First animation - fade out the old content.
- contentEditing.animate().alpha(0.0f).withLayer().withEndAction(new Runnable() {
+ hidingView.animate().alpha(0.0f).withLayer().withEndAction(new Runnable() {
@Override
public void run() {
- contentEditing.setVisibility(View.INVISIBLE);
+ hidingView.setVisibility(View.INVISIBLE);
// Prepare the new content with correct size and alpha.
- contentGenerating.setMinimumWidth(contentContainer.getWidth());
- contentGenerating.setAlpha(0.0f);
+ showingView.setMinimumWidth(contentContainer.getWidth());
+ showingView.setAlpha(0.0f);
- // Compute how to much shrink the container to fit around the new content.
+ // Compute how to much shrink /stretch the content.
final int widthSpec = MeasureSpec.makeMeasureSpec(
- contentContainer.getWidth(), MeasureSpec.AT_MOST);
+ contentContainer.getWidth(), MeasureSpec.UNSPECIFIED);
final int heightSpec = MeasureSpec.makeMeasureSpec(
- contentContainer.getHeight(), MeasureSpec.AT_MOST);
- contentGenerating.measure(widthSpec, heightSpec);
- final float scaleY = (float) contentGenerating.getMeasuredHeight()
+ contentContainer.getHeight(), MeasureSpec.UNSPECIFIED);
+ showingView.measure(widthSpec, heightSpec);
+ final float scaleY = (float) showingView.getMeasuredHeight()
/ (float) contentContainer.getHeight();
// Second animation - resize the container.
@@ -963,10 +1231,16 @@ public class PrintJobConfigActivity extends Activity {
// Swap the old and the new content.
contentContainer.removeAllViews();
contentContainer.setScaleY(1.0f);
- contentContainer.addView(contentGenerating);
+ contentContainer.addView(showingView);
// Third animation - show the new content.
- contentGenerating.animate().withLayer().alpha(1.0f);
+ showingView.animate().withLayer().alpha(1.0f).withEndAction(
+ new Runnable() {
+ @Override
+ public void run() {
+ postAnimateCommand.run();
+ }
+ });
}
});
}
@@ -975,10 +1249,6 @@ public class PrintJobConfigActivity extends Activity {
public void initialize() {
mEditorState = EDITOR_STATE_INITIALIZED;
- if (mDestinationSpinner.getSelectedItemPosition() != AdapterView.INVALID_POSITION) {
- mIgnoreNextDestinationChange = true;
- mDestinationSpinner.setSelection(AdapterView.INVALID_POSITION);
- }
}
public boolean isCancelled() {
@@ -1001,6 +1271,7 @@ public class PrintJobConfigActivity extends Activity {
public void confirmPrint() {
mEditorState = EDITOR_STATE_CONFIRMED_PRINT;
+ showUi(UI_GENERATING_PRINT_JOB, null);
}
public boolean isPreviewConfirmed() {
@@ -1046,7 +1317,79 @@ public class PrintJobConfigActivity extends Activity {
return ALL_PAGES_ARRAY;
}
+ private void bindUi() {
+ if (mCurrentUi != UI_EDITING_PRINT_JOB) {
+ return;
+ }
+
+ // Content container
+ mContentContainer = findViewById(R.id.content_container);
+
+ // Copies
+ mCopiesEditText = (EditText) findViewById(R.id.copies_edittext);
+ mCopiesEditText.setText(MIN_COPIES_STRING);
+ mCopiesEditText.addTextChangedListener(mCopiesTextWatcher);
+ mCopiesEditText.selectAll();
+ if (!TextUtils.equals(mCopiesEditText.getText(), MIN_COPIES_STRING)) {
+ mIgnoreNextCopiesChange = true;
+ }
+ PrintSpoolerService.peekInstance().setPrintJobCopiesNoPersistence(
+ mPrintJobId, MIN_COPIES);
+
+ // Destination.
+ mDestinationSpinner = (Spinner) findViewById(R.id.destination_spinner);
+ mDestinationSpinner.setAdapter(mDestinationSpinnerAdapter);
+ mDestinationSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
+ if (mDestinationSpinnerAdapter.getCount() > 0) {
+ mIgnoreNextDestinationChange = true;
+ }
+
+ // Media size.
+ mMediaSizeSpinner = (Spinner) findViewById(R.id.paper_size_spinner);
+ mMediaSizeSpinner.setAdapter(mMediaSizeSpinnerAdapter);
+ mMediaSizeSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
+ if (mMediaSizeSpinnerAdapter.getCount() > 0) {
+ mIgnoreNextMediaSizeChange = true;
+ }
+
+ // Color mode.
+ mColorModeSpinner = (Spinner) findViewById(R.id.color_spinner);
+ mColorModeSpinner.setAdapter(mColorModeSpinnerAdapter);
+ mColorModeSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
+ if (mColorModeSpinnerAdapter.getCount() > 0) {
+ mIgnoreNextColorModeChange = true;
+ }
+
+ // Orientation
+ mOrientationSpinner = (Spinner) findViewById(R.id.orientation_spinner);
+ mOrientationSpinner.setAdapter(mOrientationSpinnerAdapter);
+ mOrientationSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
+ if (mOrientationSpinnerAdapter.getCount() > 0) {
+ mIgnoreNextOrientationChange = true;
+ }
+
+ // Range
+ mRangeTitle = (TextView) findViewById(R.id.page_range_title);
+ mRangeEditText = (EditText) findViewById(R.id.page_range_edittext);
+ mRangeEditText.addTextChangedListener(mRangeTextWatcher);
+
+ // Range options
+ mRangeOptionsSpinner = (Spinner) findViewById(R.id.range_options_spinner);
+ mRangeOptionsSpinner.setAdapter(mRangeOptionsSpinnerAdapter);
+ mRangeOptionsSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
+ if (mRangeOptionsSpinnerAdapter.getCount() > 0) {
+ mIgnoreNextRangeOptionChange = true;
+ }
+
+ // Print button
+ mPrintButton = (Button) findViewById(R.id.print_button);
+ registerPrintButtonClickListener();
+ }
+
public void updateUi() {
+ if (mCurrentUi != UI_EDITING_PRINT_JOB) {
+ return;
+ }
if (isPrintConfirmed() || isPreviewConfirmed() || isCancelled()) {
mDestinationSpinner.setEnabled(false);
mCopiesEditText.setEnabled(false);
@@ -1061,14 +1404,20 @@ public class PrintJobConfigActivity extends Activity {
return;
}
+ // If a printer with capabilities is selected, then we enabled all options.
+ boolean allOptionsEnabled = false;
final int selectedIndex = mDestinationSpinner.getSelectedItemPosition();
+ if (selectedIndex >= 0) {
+ Object item = mDestinationSpinnerAdapter.getItem(selectedIndex);
+ if (item instanceof PrinterInfo) {
+ PrinterInfo printer = (PrinterInfo) item;
+ if (printer.getCapabilities() != null) {
+ allOptionsEnabled = true;
+ }
+ }
+ }
- if (selectedIndex < 0 || mDestinationSpinnerAdapter.getItem(
- selectedIndex).value.getCapabilities() == null) {
-
- // Destination
- mDestinationSpinner.setEnabled(false);
-
+ if (!allOptionsEnabled) {
String minCopiesString = String.valueOf(MIN_COPIES);
if (!TextUtils.equals(mCopiesEditText.getText(), minCopiesString)) {
mIgnoreNextCopiesChange = true;
@@ -1121,17 +1470,10 @@ public class PrintJobConfigActivity extends Activity {
mPrintButton.setEnabled(false);
} else {
PrintAttributes defaultAttributes = mTempPrintAttributes;
- PrinterInfo printer = mDestinationSpinnerAdapter.getItem(selectedIndex).value;
+ PrinterInfo printer = (PrinterInfo) mDestinationSpinner.getSelectedItem();
PrinterCapabilitiesInfo capabilities = printer.getCapabilities();
printer.getCapabilities().getDefaults(defaultAttributes);
- // Destination
- if (mDestinationSpinnerAdapter.getCount() > 1) {
- mDestinationSpinner.setEnabled(true);
- } else {
- mDestinationSpinner.setEnabled(false);
- }
-
// Copies
mCopiesEditText.setEnabled(true);
@@ -1159,9 +1501,6 @@ public class PrintJobConfigActivity extends Activity {
if (mediaSizeCount <= 0) {
mMediaSizeSpinner.setEnabled(false);
mMediaSizeSpinner.setSelection(AdapterView.INVALID_POSITION);
- } else if (mediaSizeCount == 1) {
- mMediaSizeSpinner.setEnabled(false);
- mMediaSizeSpinner.setSelection(0);
} else {
mMediaSizeSpinner.setEnabled(true);
final int selectedMediaSizeIndex = Math.max(mediaSizes.indexOf(
@@ -1172,6 +1511,7 @@ public class PrintJobConfigActivity extends Activity {
}
}
}
+ mMediaSizeSpinner.setEnabled(true);
// Color mode.
final int colorModes = capabilities.getColorModes();
@@ -1210,9 +1550,6 @@ public class PrintJobConfigActivity extends Activity {
if (colorModeCount <= 0) {
mColorModeSpinner.setEnabled(false);
mColorModeSpinner.setSelection(AdapterView.INVALID_POSITION);
- } else if (colorModeCount == 1) {
- mColorModeSpinner.setEnabled(false);
- mColorModeSpinner.setSelection(0);
} else {
mColorModeSpinner.setEnabled(true);
final int selectedColorModeIndex = Integer.numberOfTrailingZeros(
@@ -1223,6 +1560,7 @@ public class PrintJobConfigActivity extends Activity {
}
}
}
+ mColorModeSpinner.setEnabled(true);
// Orientation.
final int orientations = capabilities.getOrientations();
@@ -1262,9 +1600,6 @@ public class PrintJobConfigActivity extends Activity {
if (orientationCount <= 0) {
mOrientationSpinner.setEnabled(false);
mOrientationSpinner.setSelection(AdapterView.INVALID_POSITION);
- } else if (orientationCount == 1) {
- mOrientationSpinner.setEnabled(false);
- mOrientationSpinner.setSelection(0);
} else {
mOrientationSpinner.setEnabled(true);
final int selectedOrientationIndex = Integer.numberOfTrailingZeros(
@@ -1276,20 +1611,25 @@ public class PrintJobConfigActivity extends Activity {
}
}
}
+ mOrientationSpinner.setEnabled(true);
// Range options
PrintDocumentInfo info = mDocument.info;
if (info != null && (info.getPageCount() > 1
|| info.getPageCount() == PrintDocumentInfo.PAGE_COUNT_UNKNOWN)) {
mRangeOptionsSpinner.setEnabled(true);
- if (mRangeOptionsSpinner.getSelectedItemPosition() > 0
- && !mRangeEditText.isEnabled()) {
- mRangeEditText.setEnabled(true);
- mRangeEditText.setVisibility(View.VISIBLE);
- mRangeEditText.requestFocus();
- InputMethodManager imm = (InputMethodManager)
- getSystemService(INPUT_METHOD_SERVICE);
- imm.showSoftInput(mRangeEditText, 0);
+ if (mRangeOptionsSpinner.getSelectedItemPosition() > 0) {
+ if (!mRangeEditText.isEnabled()) {
+ mRangeEditText.setEnabled(true);
+ mRangeEditText.setVisibility(View.VISIBLE);
+ mRangeEditText.requestFocus();
+ InputMethodManager imm = (InputMethodManager)
+ getSystemService(INPUT_METHOD_SERVICE);
+ imm.showSoftInput(mRangeEditText, 0);
+ }
+ } else {
+ mRangeEditText.setEnabled(false);
+ mRangeEditText.setVisibility(View.INVISIBLE);
}
final int pageCount = mDocument.info.getPageCount();
mRangeTitle.setText(getString(R.string.label_pages,
@@ -1307,6 +1647,7 @@ public class PrintJobConfigActivity extends Activity {
mRangeEditText.setEnabled(false);
mRangeEditText.setVisibility(View.INVISIBLE);
}
+ mRangeOptionsSpinner.setEnabled(true);
// Print/Print preview
if ((mRangeOptionsSpinner.getSelectedItemPosition() == 1
@@ -1333,99 +1674,7 @@ public class PrintJobConfigActivity extends Activity {
mCopiesEditText.selectAll();
mCopiesEditText.requestFocus();
}
- }
- }
-
- public void addPrinters(List<PrinterInfo> addedPrinters) {
- final int addedPrinterCount = addedPrinters.size();
- for (int i = 0; i < addedPrinterCount; i++) {
- PrinterInfo addedPrinter = addedPrinters.get(i);
- boolean duplicate = false;
- final int existingPrinterCount = mDestinationSpinnerAdapter.getCount();
- for (int j = 0; j < existingPrinterCount; j++) {
- PrinterInfo existingPrinter = mDestinationSpinnerAdapter.getItem(j).value;
- if (addedPrinter.getId().equals(existingPrinter.getId())) {
- duplicate = true;
- break;
- }
- }
- if (!duplicate) {
- mDestinationSpinnerAdapter.add(new SpinnerItem<PrinterInfo>(
- addedPrinter, addedPrinter.getName()));
- } else {
- Log.w(LOG_TAG, "Skipping a duplicate printer: " + addedPrinter);
- }
- }
-
- if (mDestinationSpinner.getSelectedItemPosition() == AdapterView.INVALID_POSITION
- && mDestinationSpinnerAdapter.getCount() > 0) {
- mDestinationSpinner.setSelection(0);
- }
-
- mEditor.updateUi();
- }
-
- public void removePrinters(List<PrinterId> pritnerIds) {
- final int printerIdCount = pritnerIds.size();
- for (int i = 0; i < printerIdCount; i++) {
- PrinterId removedPrinterId = pritnerIds.get(i);
- boolean removed = false;
- final int existingPrinterCount = mDestinationSpinnerAdapter.getCount();
- for (int j = 0; j < existingPrinterCount; j++) {
- PrinterInfo existingPrinter = mDestinationSpinnerAdapter.getItem(j).value;
- if (removedPrinterId.equals(existingPrinter.getId())) {
- mDestinationSpinnerAdapter.remove(mDestinationSpinnerAdapter.getItem(j));
- removed = true;
- break;
- }
- }
- if (!removed) {
- Log.w(LOG_TAG, "Ignoring not added printer with id: " + removedPrinterId);
- }
- }
-
- if (mDestinationSpinner.getSelectedItemPosition() != AdapterView.INVALID_POSITION
- && mDestinationSpinnerAdapter.getCount() == 0) {
- mDestinationSpinner.setSelection(AdapterView.INVALID_POSITION);
- }
- }
-
- @SuppressWarnings("unchecked")
- public void updatePrinters(List<PrinterInfo> pritners) {
- SpinnerItem<PrinterInfo> selectedItem =
- (SpinnerItem<PrinterInfo>) mDestinationSpinner.getSelectedItem();
- PrinterId selectedPrinterId = (selectedItem != null)
- ? selectedItem.value.getId() : null;
-
- boolean updated = false;
-
- final int printerCount = pritners.size();
- for (int i = 0; i < printerCount; i++) {
- PrinterInfo updatedPrinter = pritners.get(i);
- final int existingPrinterCount = mDestinationSpinnerAdapter.getCount();
- for (int j = 0; j < existingPrinterCount; j++) {
- PrinterInfo existingPrinter = mDestinationSpinnerAdapter.getItem(j).value;
- if (updatedPrinter.getId().equals(existingPrinter.getId())) {
- existingPrinter.copyFrom(updatedPrinter);
- updated = true;
- if (selectedPrinterId != null
- && selectedPrinterId.equals(updatedPrinter.getId())) {
- // The selected printer was updated. We simulate a fake
- // selection to reuse the normal printer change handling.
- mOnItemSelectedListener.onItemSelected(mDestinationSpinner,
- mDestinationSpinner.getSelectedView(),
- mDestinationSpinner.getSelectedItemPosition(),
- mDestinationSpinner.getSelectedItemId());
- // TODO: This will reset the UI to the defaults for the
- // printer. We may need to revisit this.
-
- }
- break;
- }
- }
- }
- if (updated) {
- mDestinationSpinnerAdapter.notifyDataSetChanged();
+ mCopiesEditText.setEnabled(true);
}
}
@@ -1455,10 +1704,52 @@ public class PrintJobConfigActivity extends Activity {
}
}
- private final class DestinationAdapter extends ArrayAdapter<SpinnerItem<PrinterInfo>> {
+ private final class DestinationAdapter extends BaseAdapter
+ implements LoaderManager.LoaderCallbacks<List<PrinterInfo>>{
+ private final List<PrinterInfo> mPrinters = new ArrayList<PrinterInfo>();
+
+ public final PrinterInfo mFakePdfPrinter;
public DestinationAdapter() {
- super( PrintJobConfigActivity.this, R.layout.spinner_dropdown_item);
+ getLoaderManager().initLoader(LOADER_ID_PRINTERS_LOADER, null, this);
+ mFakePdfPrinter = createFakePdfPrinter();
+ }
+
+ @Override
+ public int getCount() {
+ return Math.max(Math.min(mPrinters.size(), DEST_ADAPTER_MAX_ITEM_COUNT),
+ DEST_ADAPTER_MIN_ITEM_COUNT);
+ }
+
+ @Override
+ public Object getItem(int position) {
+ if (position == DEST_ADAPTER_POSITION_SAVE_AS_PDF) {
+ return mFakePdfPrinter;
+ }
+ if (!mPrinters.isEmpty()) {
+ if (position < DEST_ADAPTER_POSITION_SAVE_AS_PDF) {
+ return mPrinters.get(position);
+ } else if (position > DEST_ADAPTER_POSITION_SAVE_AS_PDF
+ && position < getCount() - 1) {
+ return mPrinters.get(position - 1);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public long getItemId(int position) {
+ if (position == DEST_ADAPTER_POSITION_SAVE_AS_PDF) {
+ return DEST_ADAPTER_ITEM_ID_SAVE_AS_PDF;
+ }
+ if (mPrinters.isEmpty()) {
+ if (position == DEST_ADAPTER_POSITION_SEARCHING_FOR_PRINTERS) {
+ return DEST_ADAPTER_ITEM_ID_SEARCHING_FOR_PRINTERS;
+ }
+ } else if (position == getCount() - 1) {
+ return DEST_ADAPTER_ITEM_ID_ALL_PRINTERS;
+ }
+ return position;
}
@Override
@@ -1474,149 +1765,91 @@ public class PrintJobConfigActivity extends Activity {
R.layout.spinner_dropdown_item, parent, false);
}
- PrinterInfo printerInfo = getItem(position).value;
- TextView title = (TextView) convertView.findViewById(R.id.title);
- title.setText(printerInfo.getName());
-
- try {
- TextView subtitle = (TextView)
- convertView.findViewById(R.id.subtitle);
- PackageManager pm = getPackageManager();
- PackageInfo packageInfo = pm.getPackageInfo(
- printerInfo.getId().getServiceName().getPackageName(), 0);
- subtitle.setText(packageInfo.applicationInfo.loadLabel(pm));
- subtitle.setVisibility(View.VISIBLE);
- } catch (NameNotFoundException nnfe) {
- /* ignore */
- }
-
- return convertView;
- }
- }
- }
-
- private static final class PrinterDiscoverySessionObserver
- extends IPrinterDiscoverySessionObserver.Stub {
- private static final int MSG_SET_CONTROLLER = 1;
- private static final int MSG_ON_PRINTERS_ADDED = 2;
- private static final int MSG_ON_PRINTERS_REMOVED = 3;
- private static final int MSG_ON_PRINTERS_UPDATED = 4;
-
- private Handler mHandler;
- private Editor mEditor;
- private IPrinterDiscoverySessionController mController;
-
- @SuppressWarnings("unchecked")
- public PrinterDiscoverySessionObserver(Editor editor, Looper looper) {
- mEditor = editor;
- mHandler = new Handler(looper, null, true) {
- @Override
- public void handleMessage(Message message) {
- switch (message.what) {
- case MSG_SET_CONTROLLER: {
- mController = (IPrinterDiscoverySessionController) message.obj;
- // TODO: This should be cleaned up
- List<PrinterId> printerIds = Collections.emptyList();
- try {
- mController.open(printerIds);
- } catch (RemoteException e) {
- Log.e(LOG_TAG, "Error starting printer discovery");
- }
- } break;
-
- case MSG_ON_PRINTERS_ADDED: {
- List<PrinterInfo> printers = (List<PrinterInfo>) message.obj;
- mEditor.addPrinters(printers);
- } break;
-
- case MSG_ON_PRINTERS_REMOVED: {
- List<PrinterId> printerIds = (List<PrinterId>) message.obj;
- mEditor.removePrinters(printerIds);
- } break;
+ CharSequence title = null;
+ CharSequence subtitle = null;
- case MSG_ON_PRINTERS_UPDATED: {
- List<PrinterInfo> printers = (List<PrinterInfo>) message.obj;
- mEditor.updatePrinters(printers);
- } break;
+ if (mPrinters.isEmpty()
+ && position == DEST_ADAPTER_POSITION_SEARCHING_FOR_PRINTERS) {
+ title = getString(R.string.searching_for_printers);
+ } else {
+ if (position == DEST_ADAPTER_POSITION_SAVE_AS_PDF) {
+ PrinterInfo printer = (PrinterInfo) getItem(position);
+ title = printer.getName();
+ } else if (position == getCount() - 1) {
+ title = getString(R.string.all_printers);
+ } else {
+ PrinterInfo printer = (PrinterInfo) getItem(position);
+ title = printer.getName();
+ try {
+ PackageInfo packageInfo = getPackageManager().getPackageInfo(
+ printer.getId().getServiceName().getPackageName(), 0);
+ subtitle = packageInfo.applicationInfo.loadLabel(getPackageManager());
+ } catch (NameNotFoundException nnfe) {
+ /* ignore */
+ }
}
}
- };
- }
- public void open(List<PrinterId> priorityList) {
- if (mController != null) {
- try {
- mController.open(priorityList);
- } catch (RemoteException re) {
- Log.e(LOG_TAG, "Error closing printer discovery session", re);
- }
- }
- }
-
- public void close() {
- if (mController != null) {
- try {
- mController.close();
- } catch (RemoteException re) {
- Log.e(LOG_TAG, "Error closing printer discovery session", re);
- }
- }
- }
+ TextView titleView = (TextView) convertView.findViewById(R.id.title);
+ titleView.setText(title);
- public void requestPrinterUpdate(PrinterId printerId) {
- if (mController != null) {
- try {
- mController.requestPrinterUpdate(printerId);
- } catch (RemoteException re) {
- Log.e(LOG_TAG, "Error requestin printer update", re);
- }
- }
- }
-
- @Override
- public void setController(IPrinterDiscoverySessionController controller) {
- synchronized (this) {
- if (mHandler != null) {
- mHandler.obtainMessage(MSG_SET_CONTROLLER, controller)
- .sendToTarget();
+ TextView subtitleView = (TextView) convertView.findViewById(R.id.subtitle);
+ if (!TextUtils.isEmpty(subtitle)) {
+ subtitleView.setText(subtitle);
+ subtitleView.setVisibility(View.VISIBLE);
+ } else {
+ subtitleView.setText(null);
+ subtitleView.setVisibility(View.GONE);
}
- }
- }
- @Override
- public void onPrintersAdded(List<PrinterInfo> printers) {
- synchronized (this) {
- if (mHandler != null) {
- mHandler.obtainMessage(MSG_ON_PRINTERS_ADDED, printers)
- .sendToTarget();
- }
+ return convertView;
}
- }
- @Override
- public void onPrintersRemoved(List<PrinterId> printers) {
- synchronized (this) {
- if (mHandler != null) {
- mHandler.obtainMessage(MSG_ON_PRINTERS_REMOVED, printers)
- .sendToTarget();
+ @Override
+ public Loader<List<PrinterInfo>> onCreateLoader(int id, Bundle args) {
+ if (id == LOADER_ID_PRINTERS_LOADER) {
+ return new FusedPrintersProvider(PrintJobConfigActivity.this);
}
+ return null;
}
- }
- @Override
- public void onPrintersUpdated(List<PrinterInfo> printers) {
- synchronized (this) {
- if (mHandler != null) {
- mHandler.obtainMessage(MSG_ON_PRINTERS_UPDATED, printers)
- .sendToTarget();
- }
+ @Override
+ public void onLoadFinished(Loader<List<PrinterInfo>> loader,
+ List<PrinterInfo> printers) {
+ mPrinters.clear();
+ mPrinters.addAll(printers);
+ notifyDataSetChanged();
}
- }
- public void destroy() {
- synchronized (this) {
- mHandler = null;
- mEditor = null;
+ @Override
+ public void onLoaderReset(Loader<List<PrinterInfo>> loader) {
+ mPrinters.clear();
+ notifyDataSetInvalidated();
+ }
+
+ private PrinterInfo createFakePdfPrinter() {
+ PrinterId printerId = new PrinterId(getComponentName(), "PDF printer");
+
+ PrinterCapabilitiesInfo capabilities =
+ new PrinterCapabilitiesInfo.Builder(printerId)
+ .addMediaSize(MediaSize.createMediaSize(getPackageManager(),
+ MediaSize.ISO_A4), true)
+ .addMediaSize(MediaSize.createMediaSize(getPackageManager(),
+ MediaSize.NA_LETTER), false)
+ .addResolution(new Resolution("PDF resolution", "PDF resolution",
+ 300, 300), true)
+ .setColorModes(PrintAttributes.COLOR_MODE_COLOR
+ | PrintAttributes.COLOR_MODE_MONOCHROME,
+ PrintAttributes.COLOR_MODE_COLOR)
+ .setOrientations(PrintAttributes.ORIENTATION_PORTRAIT
+ | PrintAttributes.ORIENTATION_LANDSCAPE,
+ PrintAttributes.ORIENTATION_PORTRAIT)
+ .create();
+
+ return new PrinterInfo.Builder(printerId, getString(R.string.save_as_pdf),
+ PrinterInfo.STATUS_READY)
+ .setCapabilities(capabilities)
+ .create();
}
}
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintSpooler.java b/packages/PrintSpooler/src/com/android/printspooler/PrintSpooler.java
deleted file mode 100644
index 1b8b81a..0000000
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintSpooler.java
+++ /dev/null
@@ -1,979 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.printspooler;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.os.AsyncTask;
-import android.os.ParcelFileDescriptor;
-import android.print.IPrintClient;
-import android.print.IPrinterDiscoverySessionObserver;
-import android.print.PageRange;
-import android.print.PrintAttributes;
-import android.print.PrintAttributes.Margins;
-import android.print.PrintAttributes.MediaSize;
-import android.print.PrintAttributes.Resolution;
-import android.print.PrintAttributes.Tray;
-import android.print.PrintDocumentInfo;
-import android.print.PrintJobInfo;
-import android.print.PrintManager;
-import android.print.PrinterId;
-import android.print.PrinterInfo;
-import android.util.AtomicFile;
-import android.util.Log;
-import android.util.Slog;
-import android.util.Xml;
-
-import com.android.internal.util.FastXmlSerializer;
-
-import libcore.io.IoUtils;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-public class PrintSpooler {
-
- private static final String LOG_TAG = "PrintSpooler";
-
- private static final boolean DEBUG_PRINT_JOB_LIFECYCLE = true;
-
- private static final boolean DEBUG_PERSISTENCE = true;
-
- private static final boolean PERSISTNECE_MANAGER_ENABLED = true;
-
- private static final String PRINT_FILE_EXTENSION = "pdf";
-
- private static int sPrintJobIdCounter;
-
- private static final Object sLock = new Object();
-
- private static PrintSpooler sInstance;
-
- private final Object mLock = new Object();
-
- private final List<PrintJobInfo> mPrintJobs = new ArrayList<PrintJobInfo>();
-
- private final PersistenceManager mPersistanceManager;
-
- private final NotificationController mNotificationController;
-
- private final PrintSpoolerService mService;
-
- public static void destroyInstance() {
- synchronized (sLock) {
- sInstance = null;
- }
- }
-
- public static void createInstance(PrintSpoolerService service) {
- synchronized (sLock) {
- sInstance = new PrintSpooler(service);
- }
- }
-
- public static PrintSpooler peekInstance() {
- synchronized (sLock) {
- return sInstance;
- }
- }
-
- private PrintSpooler(PrintSpoolerService service) {
- mService = service;
- mPersistanceManager = new PersistenceManager(service);
- mNotificationController = new NotificationController(service);
- synchronized (mLock) {
- mPersistanceManager.readStateLocked();
- handleReadPrintJobsLocked();
- }
- }
-
- public List<PrintJobInfo> getPrintJobInfos(ComponentName componentName,
- int state, int appId) {
- List<PrintJobInfo> foundPrintJobs = null;
- synchronized (mLock) {
- final int printJobCount = mPrintJobs.size();
- for (int i = 0; i < printJobCount; i++) {
- PrintJobInfo printJob = mPrintJobs.get(i);
- PrinterId printerId = printJob.getPrinterId();
- final boolean sameComponent = (componentName == null
- || (printerId != null
- && componentName.equals(printerId.getServiceName())));
- final boolean sameAppId = appId == PrintManager.APP_ID_ANY
- || printJob.getAppId() == appId;
- final boolean sameState = (state == printJob.getState())
- || (state == PrintJobInfo.STATE_ANY)
- || (state == PrintJobInfo.STATE_ANY_VISIBLE_TO_CLIENTS
- && printJob.getState() > PrintJobInfo.STATE_CREATED);
- if (sameComponent && sameAppId && sameState) {
- if (foundPrintJobs == null) {
- foundPrintJobs = new ArrayList<PrintJobInfo>();
- }
- foundPrintJobs.add(printJob);
- }
- }
- }
- return foundPrintJobs;
- }
-
- public PrintJobInfo getPrintJobInfo(int printJobId, int appId) {
- synchronized (mLock) {
- final int printJobCount = mPrintJobs.size();
- for (int i = 0; i < printJobCount; i++) {
- PrintJobInfo printJob = mPrintJobs.get(i);
- if (printJob.getId() == printJobId
- && (appId == PrintManager.APP_ID_ANY
- || appId == printJob.getAppId())) {
- return printJob;
- }
- }
- return null;
- }
- }
-
- public PrintJobInfo createPrintJob(CharSequence label, IPrintClient client,
- PrintAttributes attributes, int appId) {
- synchronized (mLock) {
- final int printJobId = generatePrintJobIdLocked();
- PrintJobInfo printJob = new PrintJobInfo();
- printJob.setId(printJobId);
- printJob.setAppId(appId);
- printJob.setLabel(label);
- printJob.setAttributes(attributes);
- printJob.setState(PrintJobInfo.STATE_CREATED);
-
- addPrintJobLocked(printJob);
-
- return printJob;
- }
- }
-
- private void handleReadPrintJobsLocked() {
- final int printJobCount = mPrintJobs.size();
- for (int i = 0; i < printJobCount; i++) {
- PrintJobInfo printJob = mPrintJobs.get(i);
-
- // Update the notification.
- mNotificationController.onPrintJobStateChanged(printJob);
-
- switch (printJob.getState()) {
- case PrintJobInfo.STATE_QUEUED:
- case PrintJobInfo.STATE_STARTED: {
- // We have a print job that was queued or started in the past
- // but the device battery died or a crash occurred. In this case
- // we assume the print job failed and let the user decide whether
- // to restart the job or just
- setPrintJobState(printJob.getId(), PrintJobInfo.STATE_FAILED,
- mService.getString(R.string.no_connection_to_printer));
- } break;
- }
- }
- }
-
- public void checkAllPrintJobsHandled() {
- synchronized (mLock) {
- if (!hasActivePrintJobsLocked()) {
- notifyOnAllPrintJobsHandled();
- }
- }
- }
-
- public void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer) {
- mService.createPrinterDiscoverySession(observer);
- }
-
- private int generatePrintJobIdLocked() {
- int printJobId = sPrintJobIdCounter++;
- while (isDuplicatePrintJobId(printJobId)) {
- printJobId = sPrintJobIdCounter++;
- }
- return printJobId;
- }
-
- private boolean isDuplicatePrintJobId(int printJobId) {
- final int printJobCount = mPrintJobs.size();
- for (int j = 0; j < printJobCount; j++) {
- PrintJobInfo printJob = mPrintJobs.get(j);
- if (printJob.getId() == printJobId) {
- return true;
- }
- }
- return false;
- }
-
- public void writePrintJobData(final ParcelFileDescriptor fd, final int printJobId) {
- final PrintJobInfo printJob;
- synchronized (mLock) {
- printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
- }
- new AsyncTask<Void, Void, Void>() {
- @Override
- protected Void doInBackground(Void... params) {
- FileInputStream in = null;
- FileOutputStream out = null;
- try {
- if (printJob != null) {
- File file = generateFileForPrintJob(printJobId);
- in = new FileInputStream(file);
- out = new FileOutputStream(fd.getFileDescriptor());
- }
- final byte[] buffer = new byte[8192];
- while (true) {
- final int readByteCount = in.read(buffer);
- if (readByteCount < 0) {
- return null;
- }
- out.write(buffer, 0, readByteCount);
- }
- } catch (FileNotFoundException fnfe) {
- Log.e(LOG_TAG, "Error writing print job data!", fnfe);
- } catch (IOException ioe) {
- Log.e(LOG_TAG, "Error writing print job data!", ioe);
- } finally {
- IoUtils.closeQuietly(in);
- IoUtils.closeQuietly(out);
- IoUtils.closeQuietly(fd);
- }
- Log.i(LOG_TAG, "[END WRITE]");
- return null;
- }
- }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
- }
-
- public File generateFileForPrintJob(int printJobId) {
- return new File(mService.getFilesDir(), "print_job_"
- + printJobId + "." + PRINT_FILE_EXTENSION);
- }
-
- private void addPrintJobLocked(PrintJobInfo printJob) {
- mPrintJobs.add(printJob);
- if (DEBUG_PRINT_JOB_LIFECYCLE) {
- Slog.i(LOG_TAG, "[ADD] " + printJob);
- }
- }
-
- private void removePrintJobLocked(PrintJobInfo printJob) {
- if (mPrintJobs.remove(printJob)) {
- generateFileForPrintJob(printJob.getId()).delete();
- if (DEBUG_PRINT_JOB_LIFECYCLE) {
- Slog.i(LOG_TAG, "[REMOVE] " + printJob);
- }
- }
- }
-
- public boolean setPrintJobState(int printJobId, int state, CharSequence error) {
- boolean success = false;
-
- synchronized (mLock) {
- PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
- if (printJob != null) {
- success = true;
-
- printJob.setState(state);
- printJob.setFailureReason(error);
- mNotificationController.onPrintJobStateChanged(printJob);
-
- if (DEBUG_PRINT_JOB_LIFECYCLE) {
- Slog.i(LOG_TAG, "[STATE CHANGED] " + printJob);
- }
-
- switch (state) {
- case PrintJobInfo.STATE_COMPLETED:
- case PrintJobInfo.STATE_CANCELED:
- removePrintJobLocked(printJob);
- // $fall-through$
- case PrintJobInfo.STATE_FAILED: {
- PrinterId printerId = printJob.getPrinterId();
- if (printerId != null) {
- ComponentName service = printerId.getServiceName();
- if (!hasActivePrintJobsForServiceLocked(service)) {
- mService.onAllPrintJobsForServiceHandled(service);
- }
- }
- } break;
-
- case PrintJobInfo.STATE_QUEUED: {
- mService.onPrintJobQueued(new PrintJobInfo(printJob));
- } break;
- }
-
- if (shouldPersistPrintJob(printJob)) {
- mPersistanceManager.writeStateLocked();
- }
-
- if (!hasActivePrintJobsLocked()) {
- notifyOnAllPrintJobsHandled();
- }
- }
- }
-
- return success;
- }
-
- public boolean hasActivePrintJobsLocked() {
- final int printJobCount = mPrintJobs.size();
- for (int i = 0; i < printJobCount; i++) {
- PrintJobInfo printJob = mPrintJobs.get(i);
- if (isActiveState(printJob.getState())) {
- return true;
- }
- }
- return false;
- }
-
- public boolean hasActivePrintJobsForServiceLocked(ComponentName service) {
- final int printJobCount = mPrintJobs.size();
- for (int i = 0; i < printJobCount; i++) {
- PrintJobInfo printJob = mPrintJobs.get(i);
- if (isActiveState(printJob.getState())
- && printJob.getPrinterId().getServiceName().equals(service)) {
- return true;
- }
- }
- return false;
- }
-
- private static boolean isActiveState(int printJobState) {
- return printJobState == PrintJobInfo.STATE_CREATED
- || printJobState == PrintJobInfo.STATE_QUEUED
- || printJobState == PrintJobInfo.STATE_STARTED;
- }
-
- public boolean setPrintJobTag(int printJobId, String tag) {
- synchronized (mLock) {
- PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
- if (printJob != null) {
- String printJobTag = printJob.getTag();
- if (printJobTag == null) {
- if (tag == null) {
- return false;
- }
- } else if (printJobTag.equals(tag)) {
- return false;
- }
- printJob.setTag(tag);
- if (shouldPersistPrintJob(printJob)) {
- mPersistanceManager.writeStateLocked();
- }
- return true;
- }
- }
- return false;
- }
-
- public void setPrintJobCopiesNoPersistence(int printJobId, int copies) {
- synchronized (mLock) {
- PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
- if (printJob != null) {
- printJob.setCopies(copies);
- }
- }
- }
-
- public void setPrintJobPrintDocumentInfoNoPersistence(int printJobId, PrintDocumentInfo info) {
- synchronized (mLock) {
- PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
- if (printJob != null) {
- printJob.setDocumentInfo(info);
- }
- }
- }
-
- public void setPrintJobAttributesNoPersistence(int printJobId, PrintAttributes attributes) {
- synchronized (mLock) {
- PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
- if (printJob != null) {
- printJob.setAttributes(attributes);
- }
- }
- }
-
- public void setPrintJobPrinterNoPersistence(int printJobId, PrinterInfo printer) {
- synchronized (mLock) {
- PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
- if (printJob != null) {
- printJob.setPrinterId(printer.getId());
- printJob.setPrinterName(printer.getName());
- }
- }
- }
-
- public void setPrintJobPagesNoPersistence(int printJobId, PageRange[] pages) {
- synchronized (mLock) {
- PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
- if (printJob != null) {
- printJob.setPages(pages);
- }
- }
- }
-
- private boolean shouldPersistPrintJob(PrintJobInfo printJob) {
- return printJob.getState() >= PrintJobInfo.STATE_QUEUED;
- }
-
- private void notifyOnAllPrintJobsHandled() {
- // This has to run on the tread that is persisting the current state
- // since this call may result in the system unbinding from the spooler
- // and as a result the spooler process may get killed before the write
- // completes.
- new AsyncTask<Void, Void, Void>() {
- @Override
- protected Void doInBackground(Void... params) {
- mService.onAllPrintJobsHandled();
- return null;
- }
- }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
- }
-
- private final class PersistenceManager {
- private static final String PERSIST_FILE_NAME = "print_spooler_state.xml";
-
- private static final String TAG_SPOOLER = "spooler";
- private static final String TAG_JOB = "job";
-
- private static final String TAG_PRINTER_ID = "printerId";
- private static final String TAG_PAGE_RANGE = "pageRange";
- private static final String TAG_ATTRIBUTES = "attributes";
- private static final String TAG_DOCUMENT_INFO = "documentInfo";
-
- private static final String ATTR_ID = "id";
- private static final String ATTR_LABEL = "label";
- private static final String ATTR_STATE = "state";
- private static final String ATTR_APP_ID = "appId";
- private static final String ATTR_USER_ID = "userId";
- private static final String ATTR_TAG = "tag";
- private static final String ATTR_COPIES = "copies";
-
- private static final String TAG_MEDIA_SIZE = "mediaSize";
- private static final String TAG_RESOLUTION = "resolution";
- private static final String TAG_MARGINS = "margins";
- private static final String TAG_INPUT_TRAY = "inputTray";
- private static final String TAG_OUTPUT_TRAY = "outputTray";
-
- private static final String ATTR_DUPLEX_MODE = "duplexMode";
- private static final String ATTR_COLOR_MODE = "colorMode";
- private static final String ATTR_FITTING_MODE = "fittingMode";
- private static final String ATTR_ORIENTATION = "orientation";
-
- private static final String ATTR_PRINTER_NAME = "printerName";
- private static final String ATTR_SERVICE_NAME = "serviceName";
-
- private static final String ATTR_WIDTH_MILS = "widthMils";
- private static final String ATTR_HEIGHT_MILS = "heightMils";
-
- private static final String ATTR_HORIZONTAL_DPI = "horizontalDip";
- private static final String ATTR_VERTICAL_DPI = "verticalDpi";
-
- private static final String ATTR_LEFT_MILS = "leftMils";
- private static final String ATTR_TOP_MILS = "topMils";
- private static final String ATTR_RIGHT_MILS = "rightMils";
- private static final String ATTR_BOTTOM_MILS = "bottomMils";
-
- private static final String ATTR_START = "start";
- private static final String ATTR_END = "end";
-
- private static final String ATTR_NAME = "name";
- private static final String ATTR_PAGE_COUNT = "pageCount";
- private static final String ATTR_CONTENT_TYPE = "contentType";
-
- private final AtomicFile mStatePersistFile;
-
- private boolean mWriteStateScheduled;
-
- private PersistenceManager(Context context) {
- mStatePersistFile = new AtomicFile(new File(context.getFilesDir(),
- PERSIST_FILE_NAME));
- }
-
- public void writeStateLocked() {
- if (!PERSISTNECE_MANAGER_ENABLED) {
- return;
- }
- if (mWriteStateScheduled) {
- return;
- }
- mWriteStateScheduled = true;
- new AsyncTask<Void, Void, Void>() {
- @Override
- protected Void doInBackground(Void... params) {
- synchronized (mLock) {
- mWriteStateScheduled = false;
- doWriteStateLocked();
- }
- return null;
- }
- }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
- }
-
- private void doWriteStateLocked() {
- if (DEBUG_PERSISTENCE) {
- Log.i(LOG_TAG, "[PERSIST START]");
- }
- FileOutputStream out = null;
- try {
- out = mStatePersistFile.startWrite();
-
- XmlSerializer serializer = new FastXmlSerializer();
- serializer.setOutput(out, "utf-8");
- serializer.startDocument(null, true);
- serializer.startTag(null, TAG_SPOOLER);
-
- List<PrintJobInfo> printJobs = mPrintJobs;
-
- final int printJobCount = printJobs.size();
- for (int j = 0; j < printJobCount; j++) {
- PrintJobInfo printJob = printJobs.get(j);
-
- final int state = printJob.getState();
- if (state < PrintJobInfo.STATE_QUEUED
- || state > PrintJobInfo.STATE_CANCELED) {
- continue;
- }
-
- serializer.startTag(null, TAG_JOB);
-
- serializer.attribute(null, ATTR_ID, String.valueOf(printJob.getId()));
- serializer.attribute(null, ATTR_LABEL, printJob.getLabel().toString());
- serializer.attribute(null, ATTR_STATE, String.valueOf(printJob.getState()));
- serializer.attribute(null, ATTR_APP_ID, String.valueOf(printJob.getAppId()));
- serializer.attribute(null, ATTR_USER_ID, String.valueOf(printJob.getUserId()));
- String tag = printJob.getTag();
- if (tag != null) {
- serializer.attribute(null, ATTR_TAG, tag);
- }
- serializer.attribute(null, ATTR_COPIES, String.valueOf(printJob.getCopies()));
-
- PrinterId printerId = printJob.getPrinterId();
- if (printerId != null) {
- serializer.startTag(null, TAG_PRINTER_ID);
- serializer.attribute(null, ATTR_PRINTER_NAME, printerId.getLocalId());
- serializer.attribute(null, ATTR_SERVICE_NAME, printerId.getServiceName()
- .flattenToString());
- serializer.endTag(null, TAG_PRINTER_ID);
- }
-
- PageRange[] pages = printJob.getPages();
- if (pages != null) {
- for (int i = 0; i < pages.length; i++) {
- serializer.startTag(null, TAG_PAGE_RANGE);
- serializer.attribute(null, ATTR_START, String.valueOf(
- pages[i].getStart()));
- serializer.attribute(null, ATTR_END, String.valueOf(
- pages[i].getEnd()));
- serializer.endTag(null, TAG_PAGE_RANGE);
- }
- }
-
- PrintAttributes attributes = printJob.getAttributes();
- if (attributes != null) {
- serializer.startTag(null, TAG_ATTRIBUTES);
-
- final int duplexMode = attributes.getDuplexMode();
- serializer.attribute(null, ATTR_DUPLEX_MODE,
- String.valueOf(duplexMode));
-
- final int colorMode = attributes.getColorMode();
- serializer.attribute(null, ATTR_COLOR_MODE,
- String.valueOf(colorMode));
-
- final int fittingMode = attributes.getFittingMode();
- serializer.attribute(null, ATTR_FITTING_MODE,
- String.valueOf(fittingMode));
-
- final int orientation = attributes.getOrientation();
- serializer.attribute(null, ATTR_ORIENTATION,
- String.valueOf(orientation));
-
- MediaSize mediaSize = attributes.getMediaSize();
- if (mediaSize != null) {
- serializer.startTag(null, TAG_MEDIA_SIZE);
- serializer.attribute(null, ATTR_ID, mediaSize.getId());
- serializer.attribute(null, ATTR_LABEL, mediaSize.getLabel()
- .toString());
- serializer.attribute(null, ATTR_WIDTH_MILS, String.valueOf(
- mediaSize.getWidthMils()));
- serializer.attribute(null, ATTR_HEIGHT_MILS,String.valueOf(
- mediaSize.getHeightMils()));
- serializer.endTag(null, TAG_MEDIA_SIZE);
- }
-
- Resolution resolution = attributes.getResolution();
- if (resolution != null) {
- serializer.startTag(null, TAG_RESOLUTION);
- serializer.attribute(null, ATTR_ID, resolution.getId());
- serializer.attribute(null, ATTR_LABEL, resolution.getLabel()
- .toString());
- serializer.attribute(null, ATTR_HORIZONTAL_DPI, String.valueOf(
- resolution.getHorizontalDpi()));
- serializer.attribute(null, ATTR_VERTICAL_DPI, String.valueOf(
- resolution.getVerticalDpi()));
- serializer.endTag(null, TAG_RESOLUTION);
- }
-
- Margins margins = attributes.getMargins();
- if (margins != null) {
- serializer.startTag(null, TAG_MARGINS);
- serializer.attribute(null, ATTR_LEFT_MILS, String.valueOf(
- margins.getLeftMils()));
- serializer.attribute(null, ATTR_TOP_MILS, String.valueOf(
- margins.getTopMils()));
- serializer.attribute(null, ATTR_RIGHT_MILS, String.valueOf(
- margins.getRightMils()));
- serializer.attribute(null, ATTR_BOTTOM_MILS, String.valueOf(
- margins.getBottomMils()));
- serializer.endTag(null, TAG_MARGINS);
- }
-
- Tray inputTray = attributes.getInputTray();
- if (inputTray != null) {
- serializer.startTag(null, TAG_INPUT_TRAY);
- serializer.attribute(null, ATTR_ID, inputTray.getId());
- serializer.attribute(null, ATTR_LABEL, inputTray.getLabel()
- .toString());
- serializer.endTag(null, TAG_INPUT_TRAY);
- }
-
- Tray outputTray = attributes.getOutputTray();
- if (outputTray != null) {
- serializer.startTag(null, TAG_OUTPUT_TRAY);
- serializer.attribute(null, ATTR_ID, outputTray.getId());
- serializer.attribute(null, ATTR_LABEL, outputTray.getLabel()
- .toString());
- serializer.endTag(null, TAG_OUTPUT_TRAY);
- }
-
- serializer.endTag(null, TAG_ATTRIBUTES);
- }
-
- PrintDocumentInfo documentInfo = printJob.getDocumentInfo();
- if (documentInfo != null) {
- serializer.startTag(null, TAG_DOCUMENT_INFO);
- serializer.attribute(null, ATTR_NAME, documentInfo.getName());
- serializer.attribute(null, ATTR_CONTENT_TYPE, String.valueOf(
- documentInfo.getContentType()));
- serializer.attribute(null, ATTR_PAGE_COUNT, String.valueOf(
- documentInfo.getPageCount()));
- serializer.endTag(null, TAG_DOCUMENT_INFO);
- }
-
- serializer.endTag(null, TAG_JOB);
-
- if (DEBUG_PERSISTENCE) {
- Log.i(LOG_TAG, "[PERSISTED] " + printJob);
- }
- }
-
- serializer.endTag(null, TAG_SPOOLER);
- serializer.endDocument();
- mStatePersistFile.finishWrite(out);
- if (DEBUG_PERSISTENCE) {
- Log.i(LOG_TAG, "[PERSIST END]");
- }
- } catch (IOException e) {
- Slog.w(LOG_TAG, "Failed to write state, restoring backup.", e);
- mStatePersistFile.failWrite(out);
- } finally {
- if (out != null) {
- try {
- out.close();
- } catch (IOException ioe) {
- /* ignore */
- }
- }
- }
- }
-
- public void readStateLocked() {
- if (!PERSISTNECE_MANAGER_ENABLED) {
- return;
- }
- FileInputStream in = null;
- try {
- in = mStatePersistFile.openRead();
- } catch (FileNotFoundException e) {
- Log.i(LOG_TAG, "No existing print spooler state.");
- return;
- }
- try {
- XmlPullParser parser = Xml.newPullParser();
- parser.setInput(in, null);
- parseState(parser);
- } catch (IllegalStateException ise) {
- Slog.w(LOG_TAG, "Failed parsing ", ise);
- } catch (NullPointerException npe) {
- Slog.w(LOG_TAG, "Failed parsing ", npe);
- } catch (NumberFormatException nfe) {
- Slog.w(LOG_TAG, "Failed parsing ", nfe);
- } catch (XmlPullParserException xppe) {
- Slog.w(LOG_TAG, "Failed parsing ", xppe);
- } catch (IOException ioe) {
- Slog.w(LOG_TAG, "Failed parsing ", ioe);
- } catch (IndexOutOfBoundsException iobe) {
- Slog.w(LOG_TAG, "Failed parsing ", iobe);
- } finally {
- try {
- in.close();
- } catch (IOException ioe) {
- /* ignore */
- }
- }
- }
-
- private void parseState(XmlPullParser parser)
- throws IOException, XmlPullParserException {
- parser.next();
- skipEmptyTextTags(parser);
- expect(parser, XmlPullParser.START_TAG, TAG_SPOOLER);
- parser.next();
-
- while (parsePrintJob(parser)) {
- parser.next();
- }
-
- skipEmptyTextTags(parser);
- expect(parser, XmlPullParser.END_TAG, TAG_SPOOLER);
- }
-
- private boolean parsePrintJob(XmlPullParser parser)
- throws IOException, XmlPullParserException {
- skipEmptyTextTags(parser);
- if (!accept(parser, XmlPullParser.START_TAG, TAG_JOB)) {
- return false;
- }
-
- PrintJobInfo printJob = new PrintJobInfo();
-
- final int printJobId = Integer.parseInt(parser.getAttributeValue(null, ATTR_ID));
- printJob.setId(printJobId);
- String label = parser.getAttributeValue(null, ATTR_LABEL);
- printJob.setLabel(label);
- final int state = Integer.parseInt(parser.getAttributeValue(null, ATTR_STATE));
- printJob.setState(state);
- final int appId = Integer.parseInt(parser.getAttributeValue(null, ATTR_APP_ID));
- printJob.setAppId(appId);
- final int userId = Integer.parseInt(parser.getAttributeValue(null, ATTR_USER_ID));
- printJob.setUserId(userId);
- String tag = parser.getAttributeValue(null, ATTR_TAG);
- printJob.setTag(tag);
- String copies = parser.getAttributeValue(null, ATTR_COPIES);
- printJob.setCopies(Integer.parseInt(copies));
-
- parser.next();
-
- skipEmptyTextTags(parser);
- if (accept(parser, XmlPullParser.START_TAG, TAG_PRINTER_ID)) {
- String localId = parser.getAttributeValue(null, ATTR_PRINTER_NAME);
- ComponentName service = ComponentName.unflattenFromString(parser.getAttributeValue(
- null, ATTR_SERVICE_NAME));
- printJob.setPrinterId(new PrinterId(service, localId));
- parser.next();
- skipEmptyTextTags(parser);
- expect(parser, XmlPullParser.END_TAG, TAG_PRINTER_ID);
- parser.next();
- }
-
- skipEmptyTextTags(parser);
- List<PageRange> pageRanges = null;
- while (accept(parser, XmlPullParser.START_TAG, TAG_PAGE_RANGE)) {
- final int start = Integer.parseInt(parser.getAttributeValue(null, ATTR_START));
- final int end = Integer.parseInt(parser.getAttributeValue(null, ATTR_END));
- PageRange pageRange = new PageRange(start, end);
- if (pageRanges == null) {
- pageRanges = new ArrayList<PageRange>();
- }
- pageRanges.add(pageRange);
- parser.next();
- skipEmptyTextTags(parser);
- expect(parser, XmlPullParser.END_TAG, TAG_PAGE_RANGE);
- parser.next();
- }
- if (pageRanges != null) {
- PageRange[] pageRangesArray = new PageRange[pageRanges.size()];
- pageRanges.toArray(pageRangesArray);
- printJob.setPages(pageRangesArray);
- }
-
- skipEmptyTextTags(parser);
- if (accept(parser, XmlPullParser.START_TAG, TAG_ATTRIBUTES)) {
-
- PrintAttributes.Builder builder = new PrintAttributes.Builder();
-
- String duplexMode = parser.getAttributeValue(null, ATTR_DUPLEX_MODE);
- builder.setDuplexMode(Integer.parseInt(duplexMode));
-
- String colorMode = parser.getAttributeValue(null, ATTR_COLOR_MODE);
- builder.setColorMode(Integer.parseInt(colorMode));
-
- String fittingMode = parser.getAttributeValue(null, ATTR_FITTING_MODE);
- builder.setFittingMode(Integer.parseInt(fittingMode));
-
- String orientation = parser.getAttributeValue(null, ATTR_ORIENTATION);
- builder.setOrientation(Integer.parseInt(orientation));
-
- parser.next();
-
- skipEmptyTextTags(parser);
- if (accept(parser, XmlPullParser.START_TAG, TAG_MEDIA_SIZE)) {
- String id = parser.getAttributeValue(null, ATTR_ID);
- label = parser.getAttributeValue(null, ATTR_LABEL);
- final int widthMils = Integer.parseInt(parser.getAttributeValue(null,
- ATTR_WIDTH_MILS));
- final int heightMils = Integer.parseInt(parser.getAttributeValue(null,
- ATTR_HEIGHT_MILS));
- MediaSize mediaSize = new MediaSize(id, label, widthMils, heightMils);
- builder.setMediaSize(mediaSize);
- parser.next();
- skipEmptyTextTags(parser);
- expect(parser, XmlPullParser.END_TAG, TAG_MEDIA_SIZE);
- parser.next();
- }
-
- skipEmptyTextTags(parser);
- if (accept(parser, XmlPullParser.START_TAG, TAG_RESOLUTION)) {
- String id = parser.getAttributeValue(null, ATTR_ID);
- label = parser.getAttributeValue(null, ATTR_LABEL);
- final int horizontalDpi = Integer.parseInt(parser.getAttributeValue(null,
- ATTR_HORIZONTAL_DPI));
- final int verticalDpi = Integer.parseInt(parser.getAttributeValue(null,
- ATTR_VERTICAL_DPI));
- Resolution resolution = new Resolution(id, label, horizontalDpi, verticalDpi);
- builder.setResolution(resolution);
- parser.next();
- skipEmptyTextTags(parser);
- expect(parser, XmlPullParser.END_TAG, TAG_RESOLUTION);
- parser.next();
- }
-
- skipEmptyTextTags(parser);
- if (accept(parser, XmlPullParser.START_TAG, TAG_MARGINS)) {
- final int leftMils = Integer.parseInt(parser.getAttributeValue(null,
- ATTR_LEFT_MILS));
- final int topMils = Integer.parseInt(parser.getAttributeValue(null,
- ATTR_TOP_MILS));
- final int rightMils = Integer.parseInt(parser.getAttributeValue(null,
- ATTR_RIGHT_MILS));
- final int bottomMils = Integer.parseInt(parser.getAttributeValue(null,
- ATTR_BOTTOM_MILS));
- Margins margins = new Margins(leftMils, topMils, rightMils, bottomMils);
- builder.setMargins(margins);
- parser.next();
- skipEmptyTextTags(parser);
- expect(parser, XmlPullParser.END_TAG, TAG_MARGINS);
- parser.next();
- }
-
- skipEmptyTextTags(parser);
- if (accept(parser, XmlPullParser.START_TAG, TAG_INPUT_TRAY)) {
- String id = parser.getAttributeValue(null, ATTR_ID);
- label = parser.getAttributeValue(null, ATTR_LABEL);
- Tray tray = new Tray(id, label);
- builder.setInputTray(tray);
- parser.next();
- skipEmptyTextTags(parser);
- expect(parser, XmlPullParser.END_TAG, TAG_INPUT_TRAY);
- parser.next();
- }
-
- skipEmptyTextTags(parser);
- if (accept(parser, XmlPullParser.START_TAG, TAG_OUTPUT_TRAY)) {
- String id = parser.getAttributeValue(null, ATTR_ID);
- label = parser.getAttributeValue(null, ATTR_LABEL);
- Tray tray = new Tray(id, label);
- builder.setOutputTray(tray);
- parser.next();
- skipEmptyTextTags(parser);
- expect(parser, XmlPullParser.END_TAG, TAG_OUTPUT_TRAY);
- parser.next();
- }
-
- printJob.setAttributes(builder.create());
-
- skipEmptyTextTags(parser);
- expect(parser, XmlPullParser.END_TAG, TAG_ATTRIBUTES);
- parser.next();
- }
-
- skipEmptyTextTags(parser);
- if (accept(parser, XmlPullParser.START_TAG, TAG_DOCUMENT_INFO)) {
- String name = parser.getAttributeValue(null, ATTR_NAME);
- final int pageCount = Integer.parseInt(parser.getAttributeValue(null,
- ATTR_PAGE_COUNT));
- final int contentType = Integer.parseInt(parser.getAttributeValue(null,
- ATTR_CONTENT_TYPE));
- PrintDocumentInfo info = new PrintDocumentInfo.Builder(name)
- .setPageCount(pageCount)
- .setContentType(contentType).create();
- printJob.setDocumentInfo(info);
- parser.next();
- skipEmptyTextTags(parser);
- expect(parser, XmlPullParser.END_TAG, TAG_DOCUMENT_INFO);
- parser.next();
- }
-
- mPrintJobs.add(printJob);
-
- if (DEBUG_PERSISTENCE) {
- Log.i(LOG_TAG, "[RESTORED] " + printJob);
- }
-
- skipEmptyTextTags(parser);
- expect(parser, XmlPullParser.END_TAG, TAG_JOB);
-
- return true;
- }
-
- private void expect(XmlPullParser parser, int type, String tag)
- throws IOException, XmlPullParserException {
- if (!accept(parser, type, tag)) {
- throw new XmlPullParserException("Exepected event: " + type
- + " and tag: " + tag + " but got event: " + parser.getEventType()
- + " and tag:" + parser.getName());
- }
- }
-
- private void skipEmptyTextTags(XmlPullParser parser)
- throws IOException, XmlPullParserException {
- while (accept(parser, XmlPullParser.TEXT, null)
- && "\n".equals(parser.getText())) {
- parser.next();
- }
- }
-
- private boolean accept(XmlPullParser parser, int type, String tag)
- throws IOException, XmlPullParserException {
- if (parser.getEventType() != type) {
- return false;
- }
- if (tag != null) {
- if (!tag.equals(parser.getName())) {
- return false;
- }
- } else if (parser.getName() != null) {
- return false;
- }
- return true;
- }
- }
-}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java b/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
index 4fab4f8..fda64c9 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
@@ -21,9 +21,8 @@ import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentSender;
-import android.os.Handler;
+import android.os.AsyncTask;
import android.os.IBinder;
-import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
@@ -32,14 +31,38 @@ import android.print.IPrintDocumentAdapter;
import android.print.IPrintSpooler;
import android.print.IPrintSpoolerCallbacks;
import android.print.IPrintSpoolerClient;
-import android.print.IPrinterDiscoverySessionObserver;
+import android.print.PageRange;
import android.print.PrintAttributes;
+import android.print.PrintAttributes.Margins;
+import android.print.PrintAttributes.MediaSize;
+import android.print.PrintAttributes.Resolution;
+import android.print.PrintAttributes.Tray;
+import android.print.PrintDocumentInfo;
import android.print.PrintJobInfo;
+import android.print.PrintManager;
+import android.print.PrinterId;
+import android.print.PrinterInfo;
+import android.util.AtomicFile;
import android.util.Log;
import android.util.Slog;
+import android.util.Xml;
+import com.android.internal.os.HandlerCaller;
import com.android.internal.os.SomeArgs;
+import com.android.internal.util.FastXmlSerializer;
+import libcore.io.IoUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -48,22 +71,65 @@ import java.util.List;
*/
public final class PrintSpoolerService extends Service {
+ private static final String LOG_TAG = "PrintSpoolerService";
+
+ private static final boolean DEBUG_PRINT_JOB_LIFECYCLE = true;
+
+ private static final boolean DEBUG_PERSISTENCE = true;
+
+ private static final boolean PERSISTNECE_MANAGER_ENABLED = true;
+
private static final long CHECK_ALL_PRINTJOBS_HANDLED_DELAY = 5000;
- private static final String LOG_TAG = "PrintSpoolerService";
+ private static final String PRINT_FILE_EXTENSION = "pdf";
+
+ private static final Object sLock = new Object();
+
+ private final Object mLock = new Object();
+
+ private final List<PrintJobInfo> mPrintJobs = new ArrayList<PrintJobInfo>();
+
+ private static PrintSpoolerService sInstance;
+
+ private static int sPrintJobIdCounter;
private Intent mStartPrintJobConfigActivityIntent;
private IPrintSpoolerClient mClient;
- private Handler mHandler;
+ private HandlerCaller mHandlerCaller;
+
+ private PersistenceManager mPersistanceManager;
+
+ private NotificationController mNotificationController;
+
+ private PrinterDiscoverySession mDiscoverySession;
+
+ public static PrintSpoolerService peekInstance() {
+ synchronized (sLock) {
+ return sInstance;
+ }
+ }
@Override
public void onCreate() {
super.onCreate();
mStartPrintJobConfigActivityIntent = new Intent(PrintSpoolerService.this,
PrintJobConfigActivity.class);
- mHandler = new MyHandler(getMainLooper());
+ mHandlerCaller = new HandlerCaller(this, getMainLooper(),
+ new HandlerCallerCallback(), false);
+
+ mPersistanceManager = new PersistenceManager();
+ mNotificationController = new NotificationController(PrintSpoolerService.this);
+
+ synchronized (mLock) {
+ mPersistanceManager.readStateLocked();
+ handleReadPrintJobsLocked();
+ }
+
+ synchronized (sLock) {
+ sInstance = this;
+ }
}
@Override
@@ -72,10 +138,10 @@ public final class PrintSpoolerService extends Service {
@Override
public void getPrintJobInfos(IPrintSpoolerCallbacks callback,
ComponentName componentName, int state, int appId, int sequence)
- throws RemoteException {
+ throws RemoteException {
List<PrintJobInfo> printJobs = null;
try {
- printJobs = PrintSpooler.peekInstance().getPrintJobInfos(
+ printJobs = PrintSpoolerService.this.getPrintJobInfos(
componentName, state, appId);
} finally {
callback.onGetPrintJobInfosResult(printJobs, sequence);
@@ -87,7 +153,7 @@ public final class PrintSpoolerService extends Service {
int appId, int sequence) throws RemoteException {
PrintJobInfo printJob = null;
try {
- printJob = PrintSpooler.peekInstance().getPrintJobInfo(printJobId, appId);
+ printJob = PrintSpoolerService.this.getPrintJobInfo(printJobId, appId);
} finally {
callback.onGetPrintJobInfoResult(printJob, sequence);
}
@@ -98,11 +164,11 @@ public final class PrintSpoolerService extends Service {
public void createPrintJob(String printJobName, IPrintClient client,
IPrintDocumentAdapter printAdapter, PrintAttributes attributes,
IPrintSpoolerCallbacks callback, int appId, int sequence)
- throws RemoteException {
+ throws RemoteException {
PrintJobInfo printJob = null;
try {
- printJob = PrintSpooler.peekInstance().createPrintJob(printJobName, client,
- attributes, appId);
+ printJob = PrintSpoolerService.this.createPrintJob(
+ printJobName, client, attributes, appId);
if (printJob != null) {
Intent intent = mStartPrintJobConfigActivityIntent;
intent.putExtra(PrintJobConfigActivity.EXTRA_PRINT_DOCUMENT_ADAPTER,
@@ -113,13 +179,12 @@ public final class PrintSpoolerService extends Service {
IntentSender sender = PendingIntent.getActivity(
PrintSpoolerService.this, 0, intent, PendingIntent.FLAG_ONE_SHOT
- | PendingIntent.FLAG_CANCEL_CURRENT).getIntentSender();
+ | PendingIntent.FLAG_CANCEL_CURRENT).getIntentSender();
- SomeArgs args = SomeArgs.obtain();
- args.arg1 = client;
- args.arg2 = sender;
- mHandler.obtainMessage(MyHandler.MSG_START_PRINT_JOB_CONFIG_ACTIVITY,
- args).sendToTarget();
+ Message message = mHandlerCaller.obtainMessageOO(
+ HandlerCallerCallback.MSG_START_PRINT_JOB_CONFIG_ACTIVITY,
+ client, sender);
+ mHandlerCaller.executeOrSendMessage(message);
}
} finally {
callback.onCreatePrintJobResult(printJob, sequence);
@@ -127,11 +192,11 @@ public final class PrintSpoolerService extends Service {
}
@Override
- public void setPrintJobState(int printJobId, int state, CharSequence error,
+ public void setPrintJobState(int printJobId, int state, String error,
IPrintSpoolerCallbacks callback, int sequece) throws RemoteException {
boolean success = false;
try {
- success = PrintSpooler.peekInstance().setPrintJobState(
+ success = PrintSpoolerService.this.setPrintJobState(
printJobId, state, error);
} finally {
callback.onSetPrintJobStateResult(success, sequece);
@@ -143,7 +208,7 @@ public final class PrintSpoolerService extends Service {
IPrintSpoolerCallbacks callback, int sequece) throws RemoteException {
boolean success = false;
try {
- success = PrintSpooler.peekInstance().setPrintJobTag(printJobId, tag);
+ success = PrintSpoolerService.this.setPrintJobTag(printJobId, tag);
} finally {
callback.onSetPrintJobTagResult(success, sequece);
}
@@ -151,60 +216,191 @@ public final class PrintSpoolerService extends Service {
@Override
public void writePrintJobData(ParcelFileDescriptor fd, int printJobId) {
- PrintSpooler.peekInstance().writePrintJobData(fd, printJobId);
+ PrintSpoolerService.this.writePrintJobData(fd, printJobId);
}
@Override
public void setClient(IPrintSpoolerClient client) {
- mHandler.obtainMessage(MyHandler.MSG_SET_CLIENT, client).sendToTarget();
+ Message message = mHandlerCaller.obtainMessageO(
+ HandlerCallerCallback.MSG_SET_CLIENT, client);
+ mHandlerCaller.executeOrSendMessage(message);
+ }
+
+ @Override
+ public void onPrintersAdded(List<PrinterInfo> printers) {
+ Message message = mHandlerCaller.obtainMessageO(
+ HandlerCallerCallback.MSG_ON_PRINTERS_ADDED, printers);
+ mHandlerCaller.executeOrSendMessage(message);
+ }
+
+ @Override
+ public void onPrintersRemoved(List<PrinterId> printerIds) {
+ Message message = mHandlerCaller.obtainMessageO(
+ HandlerCallerCallback.MSG_ON_PRINTERS_REMOVED, printerIds);
+ mHandlerCaller.executeOrSendMessage(message);
+ }
+
+ @Override
+ public void onPrintersUpdated(List<PrinterInfo> printers) {
+ Message message = mHandlerCaller.obtainMessageO(
+ HandlerCallerCallback.MSG_ON_PRINTERS_UPDATED, printers);
+ mHandlerCaller.executeOrSendMessage(message);
}
};
}
- public void onPrintJobQueued(PrintJobInfo printJob) {
- mHandler.obtainMessage(MyHandler.MSG_ON_PRINT_JOB_QUEUED,
- printJob).sendToTarget();
+ public void createPrinterDiscoverySession() {
+ Message message = mHandlerCaller.obtainMessage(
+ HandlerCallerCallback.MSG_CREATE_PRINTER_DISCOVERY_SESSION);
+ mHandlerCaller.executeOrSendMessage(message);
}
- public void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer) {
- mHandler.obtainMessage(MyHandler.MSG_CREATE_PRINTER_DISCOVERY_SESSION,
- observer).sendToTarget();
+ public void destroyPrinterDiscoverySession() {
+ Message message = mHandlerCaller.obtainMessage(
+ HandlerCallerCallback.MSG_DESTROY_PRINTER_DISCOVERY_SESSION);
+ mHandlerCaller.executeOrSendMessage(message);
}
- public void onAllPrintJobsForServiceHandled(ComponentName service) {
- mHandler.obtainMessage(MyHandler.MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED,
- service).sendToTarget();
+ public void startPrinterDiscovery(List<PrinterId> priorityList) {
+ Message message = mHandlerCaller.obtainMessageO(
+ HandlerCallerCallback.MSG_START_PRINTER_DISCOVERY, priorityList);
+ mHandlerCaller.executeOrSendMessage(message);
}
- public void onAllPrintJobsHandled() {
- mHandler.sendEmptyMessage(MyHandler.MSG_ON_ALL_PRINT_JOBS_HANDLED);
+ public void stopPrinterDiscovery() {
+ Message message = mHandlerCaller.obtainMessage(
+ HandlerCallerCallback.MSG_STOP_PRINTER_DISCOVERY);
+ mHandlerCaller.executeOrSendMessage(message);
}
- private final class MyHandler extends Handler {
- public static final int MSG_SET_CLIENT = 1;
- public static final int MSG_START_PRINT_JOB_CONFIG_ACTIVITY = 2;
- public static final int MSG_CREATE_PRINTER_DISCOVERY_SESSION = 3;
- public static final int MSG_ON_PRINT_JOB_QUEUED = 5;
- public static final int MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED = 6;
- public static final int MSG_ON_ALL_PRINT_JOBS_HANDLED = 7;
- public static final int MSG_CHECK_ALL_PRINTJOBS_HANDLED = 9;
+ public void requestPrinterUpdate(PrinterId pritnerId) {
+ Message message = mHandlerCaller.obtainMessageO(
+ HandlerCallerCallback.MSG_REQUEST_PRINTER_UPDATE, pritnerId);
+ mHandlerCaller.executeOrSendMessage(message);
+ }
- public MyHandler(Looper looper) {
- super(looper, null, false);
- }
+
+ private void sendOnPrintJobQueued(PrintJobInfo printJob) {
+ Message message = mHandlerCaller.obtainMessageO(
+ HandlerCallerCallback.MSG_ON_PRINT_JOB_QUEUED, printJob);
+ mHandlerCaller.executeOrSendMessage(message);
+ }
+
+ private void sendOnAllPrintJobsForServiceHandled(ComponentName service) {
+ Message message = mHandlerCaller.obtainMessageO(
+ HandlerCallerCallback.MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED, service);
+ mHandlerCaller.executeOrSendMessage(message);
+ }
+
+ private void sendOnAllPrintJobsHandled() {
+ Message message = mHandlerCaller.obtainMessage(
+ HandlerCallerCallback.MSG_ON_ALL_PRINT_JOBS_HANDLED);
+ mHandlerCaller.executeOrSendMessage(message);
+ }
+
+ private final class HandlerCallerCallback implements HandlerCaller.Callback {
+ public static final int MSG_CREATE_PRINTER_DISCOVERY_SESSION = 1;
+ public static final int MSG_DESTROY_PRINTER_DISCOVERY_SESSION = 2;
+ public static final int MSG_START_PRINTER_DISCOVERY = 3;
+ public static final int MSG_STOP_PRINTER_DISCOVERY = 4;
+ public static final int MSG_REQUEST_PRINTER_UPDATE = 5;
+
+ public static final int MSG_ON_PRINTERS_ADDED = 6;
+ public static final int MSG_ON_PRINTERS_REMOVED = 7;
+ public static final int MSG_ON_PRINTERS_UPDATED = 8;
+
+ public static final int MSG_SET_CLIENT = 9;
+ public static final int MSG_START_PRINT_JOB_CONFIG_ACTIVITY = 10;
+ public static final int MSG_ON_PRINT_JOB_QUEUED = 11;
+ public static final int MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED = 12;
+ public static final int MSG_ON_ALL_PRINT_JOBS_HANDLED = 13;
+ public static final int MSG_CHECK_ALL_PRINTJOBS_HANDLED = 14;
@Override
- public void handleMessage(Message message) {
+ @SuppressWarnings("unchecked")
+ public void executeMessage(Message message) {
switch (message.what) {
+ case MSG_CREATE_PRINTER_DISCOVERY_SESSION: {
+ final IPrintSpoolerClient client;
+ synchronized (mLock) {
+ client = mClient;
+ }
+ if (client != null) {
+ try {
+ client.createPrinterDiscoverySession();
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error creating printer discovery session.", re);
+ }
+ }
+ } break;
+
+ case MSG_DESTROY_PRINTER_DISCOVERY_SESSION: {
+ final IPrintSpoolerClient client;
+ synchronized (mLock) {
+ client = mClient;
+ }
+ if (client != null) {
+ try {
+ client.destroyPrinterDiscoverySession();
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error destroying printer discovery session.", re);
+ }
+ }
+ } break;
+
+ case MSG_START_PRINTER_DISCOVERY: {
+ final IPrintSpoolerClient client;
+ synchronized (mLock) {
+ client = mClient;
+ }
+ if (client != null) {
+ List<PrinterId> priorityList = (ArrayList<PrinterId>) message.obj;
+ try {
+ client.startPrinterDiscovery(priorityList);
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error starting printer discovery.", re);
+ }
+ }
+ } break;
+
+ case MSG_STOP_PRINTER_DISCOVERY: {
+ final IPrintSpoolerClient client;
+ synchronized (mLock) {
+ client = mClient;
+ }
+ if (client != null) {
+ try {
+ client.stopPrinterDiscovery();
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error stopping printer discovery.", re);
+ }
+ }
+ } break;
+
+ case MSG_REQUEST_PRINTER_UPDATE: {
+ final IPrintSpoolerClient client;
+ synchronized (mLock) {
+ client = mClient;
+ }
+ if (client != null) {
+ PrinterId printerId = (PrinterId) message.obj;
+ try {
+ client.requestPrinterUpdate(printerId);
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error requesing printer update.", re);
+ }
+ }
+ } break;
+
case MSG_SET_CLIENT: {
- mClient = (IPrintSpoolerClient) message.obj;
- if (mClient != null) {
- PrintSpooler.createInstance(PrintSpoolerService.this);
- mHandler.sendEmptyMessageDelayed(
- MyHandler.MSG_CHECK_ALL_PRINTJOBS_HANDLED,
- CHECK_ALL_PRINTJOBS_HANDLED_DELAY);
- } else {
- PrintSpooler.destroyInstance();
+ synchronized (mLock) {
+ mClient = (IPrintSpoolerClient) message.obj;
+ if (mClient != null) {
+ Message msg = mHandlerCaller.obtainMessage(
+ HandlerCallerCallback.MSG_CHECK_ALL_PRINTJOBS_HANDLED);
+ mHandlerCaller.sendMessageDelayed(msg,
+ CHECK_ALL_PRINTJOBS_HANDLED_DELAY);
+ }
}
} break;
@@ -220,18 +416,6 @@ public final class PrintSpoolerService extends Service {
}
} break;
- case MSG_CREATE_PRINTER_DISCOVERY_SESSION: {
- IPrinterDiscoverySessionObserver observer =
- (IPrinterDiscoverySessionObserver) message.obj;
- if (mClient != null) {
- try {
- mClient.createPrinterDiscoverySession(observer);
- } catch (RemoteException re) {
- Log.e(LOG_TAG, "Error creating printer discovery session.", re);
- }
- }
- } break;
-
case MSG_ON_PRINT_JOB_QUEUED: {
PrintJobInfo printJob = (PrintJobInfo) message.obj;
if (mClient != null) {
@@ -266,12 +450,948 @@ public final class PrintSpoolerService extends Service {
} break;
case MSG_CHECK_ALL_PRINTJOBS_HANDLED: {
- PrintSpooler spooler = PrintSpooler.peekInstance();
- if (spooler != null) {
- spooler.checkAllPrintJobsHandled();
+ checkAllPrintJobsHandled();
+ } break;
+
+ case MSG_ON_PRINTERS_ADDED: {
+ final PrinterDiscoverySession session;
+ synchronized (mLock) {
+ session = mDiscoverySession;
+ }
+ if (session != null) {
+ List<PrinterInfo> printers = (ArrayList<PrinterInfo>) message.obj;
+ session.onPrintersAdded(printers);
+ }
+ } break;
+
+ case MSG_ON_PRINTERS_REMOVED: {
+ final PrinterDiscoverySession session;
+ synchronized (mLock) {
+ session = mDiscoverySession;
+ }
+ if (session != null) {
+ List<PrinterId> printerIds = (ArrayList<PrinterId>) message.obj;
+ session.onPrintersRemoved(printerIds);
+ }
+ } break;
+
+ case MSG_ON_PRINTERS_UPDATED: {
+ final PrinterDiscoverySession session;
+ synchronized (mLock) {
+ session = mDiscoverySession;
+ }
+ if (session != null) {
+ List<PrinterInfo> printers = (ArrayList<PrinterInfo>) message.obj;
+ session.onPrintersUpdated(printers);
}
} break;
}
}
}
+
+ public List<PrintJobInfo> getPrintJobInfos(ComponentName componentName,
+ int state, int appId) {
+ List<PrintJobInfo> foundPrintJobs = null;
+ synchronized (mLock) {
+ final int printJobCount = mPrintJobs.size();
+ for (int i = 0; i < printJobCount; i++) {
+ PrintJobInfo printJob = mPrintJobs.get(i);
+ PrinterId printerId = printJob.getPrinterId();
+ final boolean sameComponent = (componentName == null
+ || (printerId != null
+ && componentName.equals(printerId.getServiceName())));
+ final boolean sameAppId = appId == PrintManager.APP_ID_ANY
+ || printJob.getAppId() == appId;
+ final boolean sameState = (state == printJob.getState())
+ || (state == PrintJobInfo.STATE_ANY)
+ || (state == PrintJobInfo.STATE_ANY_VISIBLE_TO_CLIENTS
+ && printJob.getState() > PrintJobInfo.STATE_CREATED);
+ if (sameComponent && sameAppId && sameState) {
+ if (foundPrintJobs == null) {
+ foundPrintJobs = new ArrayList<PrintJobInfo>();
+ }
+ foundPrintJobs.add(printJob);
+ }
+ }
+ }
+ return foundPrintJobs;
+ }
+
+ public PrintJobInfo getPrintJobInfo(int printJobId, int appId) {
+ synchronized (mLock) {
+ final int printJobCount = mPrintJobs.size();
+ for (int i = 0; i < printJobCount; i++) {
+ PrintJobInfo printJob = mPrintJobs.get(i);
+ if (printJob.getId() == printJobId
+ && (appId == PrintManager.APP_ID_ANY
+ || appId == printJob.getAppId())) {
+ return printJob;
+ }
+ }
+ return null;
+ }
+ }
+
+ public PrintJobInfo createPrintJob(String label, IPrintClient client,
+ PrintAttributes attributes, int appId) {
+ synchronized (mLock) {
+ final int printJobId = generatePrintJobIdLocked();
+ PrintJobInfo printJob = new PrintJobInfo();
+ printJob.setId(printJobId);
+ printJob.setAppId(appId);
+ printJob.setLabel(label);
+ printJob.setAttributes(attributes);
+ printJob.setState(PrintJobInfo.STATE_CREATED);
+
+ addPrintJobLocked(printJob);
+
+ return printJob;
+ }
+ }
+
+ private void handleReadPrintJobsLocked() {
+ final int printJobCount = mPrintJobs.size();
+ for (int i = 0; i < printJobCount; i++) {
+ PrintJobInfo printJob = mPrintJobs.get(i);
+
+ // Update the notification.
+ mNotificationController.onPrintJobStateChanged(printJob);
+
+ switch (printJob.getState()) {
+ case PrintJobInfo.STATE_QUEUED:
+ case PrintJobInfo.STATE_STARTED: {
+ // We have a print job that was queued or started in the
+ // past
+ // but the device battery died or a crash occurred. In this
+ // case
+ // we assume the print job failed and let the user decide
+ // whether
+ // to restart the job or just
+ setPrintJobState(printJob.getId(), PrintJobInfo.STATE_FAILED,
+ getString(R.string.no_connection_to_printer));
+ }
+ break;
+ }
+ }
+ }
+
+ public void checkAllPrintJobsHandled() {
+ synchronized (mLock) {
+ if (!hasActivePrintJobsLocked()) {
+ notifyOnAllPrintJobsHandled();
+ }
+ }
+ }
+
+ private void setPrinterDiscoverySessionClient(PrinterDiscoverySession session) {
+ synchronized (mLock) {
+ mDiscoverySession = session;
+ }
+ }
+
+ private int generatePrintJobIdLocked() {
+ int printJobId = sPrintJobIdCounter++;
+ while (isDuplicatePrintJobId(printJobId)) {
+ printJobId = sPrintJobIdCounter++;
+ }
+ return printJobId;
+ }
+
+ private boolean isDuplicatePrintJobId(int printJobId) {
+ final int printJobCount = mPrintJobs.size();
+ for (int j = 0; j < printJobCount; j++) {
+ PrintJobInfo printJob = mPrintJobs.get(j);
+ if (printJob.getId() == printJobId) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void writePrintJobData(final ParcelFileDescriptor fd, final int printJobId) {
+ final PrintJobInfo printJob;
+ synchronized (mLock) {
+ printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
+ }
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ FileInputStream in = null;
+ FileOutputStream out = null;
+ try {
+ if (printJob != null) {
+ File file = generateFileForPrintJob(printJobId);
+ in = new FileInputStream(file);
+ out = new FileOutputStream(fd.getFileDescriptor());
+ }
+ final byte[] buffer = new byte[8192];
+ while (true) {
+ final int readByteCount = in.read(buffer);
+ if (readByteCount < 0) {
+ return null;
+ }
+ out.write(buffer, 0, readByteCount);
+ }
+ } catch (FileNotFoundException fnfe) {
+ Log.e(LOG_TAG, "Error writing print job data!", fnfe);
+ } catch (IOException ioe) {
+ Log.e(LOG_TAG, "Error writing print job data!", ioe);
+ } finally {
+ IoUtils.closeQuietly(in);
+ IoUtils.closeQuietly(out);
+ IoUtils.closeQuietly(fd);
+ }
+ Log.i(LOG_TAG, "[END WRITE]");
+ return null;
+ }
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
+ }
+
+ public File generateFileForPrintJob(int printJobId) {
+ return new File(getFilesDir(), "print_job_"
+ + printJobId + "." + PRINT_FILE_EXTENSION);
+ }
+
+ private void addPrintJobLocked(PrintJobInfo printJob) {
+ mPrintJobs.add(printJob);
+ if (DEBUG_PRINT_JOB_LIFECYCLE) {
+ Slog.i(LOG_TAG, "[ADD] " + printJob);
+ }
+ }
+
+ private void removePrintJobLocked(PrintJobInfo printJob) {
+ if (mPrintJobs.remove(printJob)) {
+ generateFileForPrintJob(printJob.getId()).delete();
+ if (DEBUG_PRINT_JOB_LIFECYCLE) {
+ Slog.i(LOG_TAG, "[REMOVE] " + printJob);
+ }
+ }
+ }
+
+ public boolean setPrintJobState(int printJobId, int state, String error) {
+ boolean success = false;
+
+ synchronized (mLock) {
+ PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
+ if (printJob != null) {
+ success = true;
+
+ printJob.setState(state);
+ printJob.setFailureReason(error);
+ mNotificationController.onPrintJobStateChanged(printJob);
+
+ if (DEBUG_PRINT_JOB_LIFECYCLE) {
+ Slog.i(LOG_TAG, "[STATE CHANGED] " + printJob);
+ }
+
+ switch (state) {
+ case PrintJobInfo.STATE_COMPLETED:
+ case PrintJobInfo.STATE_CANCELED:
+ removePrintJobLocked(printJob);
+ // $fall-through$
+
+ case PrintJobInfo.STATE_FAILED: {
+ PrinterId printerId = printJob.getPrinterId();
+ if (printerId != null) {
+ ComponentName service = printerId.getServiceName();
+ if (!hasActivePrintJobsForServiceLocked(service)) {
+ sendOnAllPrintJobsForServiceHandled(service);
+ }
+ }
+ } break;
+
+ case PrintJobInfo.STATE_QUEUED: {
+ sendOnPrintJobQueued(new PrintJobInfo(printJob));
+ } break;
+ }
+
+ if (shouldPersistPrintJob(printJob)) {
+ mPersistanceManager.writeStateLocked();
+ }
+
+ if (!hasActivePrintJobsLocked()) {
+ notifyOnAllPrintJobsHandled();
+ }
+ }
+ }
+
+ return success;
+ }
+
+ public boolean hasActivePrintJobsLocked() {
+ final int printJobCount = mPrintJobs.size();
+ for (int i = 0; i < printJobCount; i++) {
+ PrintJobInfo printJob = mPrintJobs.get(i);
+ if (isActiveState(printJob.getState())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean hasActivePrintJobsForServiceLocked(ComponentName service) {
+ final int printJobCount = mPrintJobs.size();
+ for (int i = 0; i < printJobCount; i++) {
+ PrintJobInfo printJob = mPrintJobs.get(i);
+ if (isActiveState(printJob.getState())
+ && printJob.getPrinterId().getServiceName().equals(service)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isActiveState(int printJobState) {
+ return printJobState == PrintJobInfo.STATE_CREATED
+ || printJobState == PrintJobInfo.STATE_QUEUED
+ || printJobState == PrintJobInfo.STATE_STARTED;
+ }
+
+ public boolean setPrintJobTag(int printJobId, String tag) {
+ synchronized (mLock) {
+ PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
+ if (printJob != null) {
+ String printJobTag = printJob.getTag();
+ if (printJobTag == null) {
+ if (tag == null) {
+ return false;
+ }
+ } else if (printJobTag.equals(tag)) {
+ return false;
+ }
+ printJob.setTag(tag);
+ if (shouldPersistPrintJob(printJob)) {
+ mPersistanceManager.writeStateLocked();
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void setPrintJobCopiesNoPersistence(int printJobId, int copies) {
+ synchronized (mLock) {
+ PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
+ if (printJob != null) {
+ printJob.setCopies(copies);
+ }
+ }
+ }
+
+ public void setPrintJobPrintDocumentInfoNoPersistence(int printJobId, PrintDocumentInfo info) {
+ synchronized (mLock) {
+ PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
+ if (printJob != null) {
+ printJob.setDocumentInfo(info);
+ }
+ }
+ }
+
+ public void setPrintJobAttributesNoPersistence(int printJobId, PrintAttributes attributes) {
+ synchronized (mLock) {
+ PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
+ if (printJob != null) {
+ printJob.setAttributes(attributes);
+ }
+ }
+ }
+
+ public void setPrintJobPrinterNoPersistence(int printJobId, PrinterInfo printer) {
+ synchronized (mLock) {
+ PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
+ if (printJob != null) {
+ printJob.setPrinterId(printer.getId());
+ printJob.setPrinterName(printer.getName());
+ }
+ }
+ }
+
+ public void setPrintJobPagesNoPersistence(int printJobId, PageRange[] pages) {
+ synchronized (mLock) {
+ PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
+ if (printJob != null) {
+ printJob.setPages(pages);
+ }
+ }
+ }
+
+ private boolean shouldPersistPrintJob(PrintJobInfo printJob) {
+ return printJob.getState() >= PrintJobInfo.STATE_QUEUED;
+ }
+
+ private void notifyOnAllPrintJobsHandled() {
+ // This has to run on the tread that is persisting the current state
+ // since this call may result in the system unbinding from the spooler
+ // and as a result the spooler process may get killed before the write
+ // completes.
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ sendOnAllPrintJobsHandled();
+ return null;
+ }
+ }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
+ }
+
+ private final class PersistenceManager {
+ private static final String PERSIST_FILE_NAME = "print_spooler_state.xml";
+
+ private static final String TAG_SPOOLER = "spooler";
+ private static final String TAG_JOB = "job";
+
+ private static final String TAG_PRINTER_ID = "printerId";
+ private static final String TAG_PAGE_RANGE = "pageRange";
+ private static final String TAG_ATTRIBUTES = "attributes";
+ private static final String TAG_DOCUMENT_INFO = "documentInfo";
+
+ private static final String ATTR_ID = "id";
+ private static final String ATTR_LABEL = "label";
+ private static final String ATTR_STATE = "state";
+ private static final String ATTR_APP_ID = "appId";
+ private static final String ATTR_USER_ID = "userId";
+ private static final String ATTR_TAG = "tag";
+ private static final String ATTR_COPIES = "copies";
+
+ private static final String TAG_MEDIA_SIZE = "mediaSize";
+ private static final String TAG_RESOLUTION = "resolution";
+ private static final String TAG_MARGINS = "margins";
+ private static final String TAG_INPUT_TRAY = "inputTray";
+ private static final String TAG_OUTPUT_TRAY = "outputTray";
+
+ private static final String ATTR_DUPLEX_MODE = "duplexMode";
+ private static final String ATTR_COLOR_MODE = "colorMode";
+ private static final String ATTR_FITTING_MODE = "fittingMode";
+ private static final String ATTR_ORIENTATION = "orientation";
+
+ private static final String ATTR_LOCAL_ID = "printerName";
+ private static final String ATTR_SERVICE_NAME = "serviceName";
+
+ private static final String ATTR_WIDTH_MILS = "widthMils";
+ private static final String ATTR_HEIGHT_MILS = "heightMils";
+
+ private static final String ATTR_HORIZONTAL_DPI = "horizontalDip";
+ private static final String ATTR_VERTICAL_DPI = "verticalDpi";
+
+ private static final String ATTR_LEFT_MILS = "leftMils";
+ private static final String ATTR_TOP_MILS = "topMils";
+ private static final String ATTR_RIGHT_MILS = "rightMils";
+ private static final String ATTR_BOTTOM_MILS = "bottomMils";
+
+ private static final String ATTR_START = "start";
+ private static final String ATTR_END = "end";
+
+ private static final String ATTR_NAME = "name";
+ private static final String ATTR_PAGE_COUNT = "pageCount";
+ private static final String ATTR_CONTENT_TYPE = "contentType";
+
+ private final AtomicFile mStatePersistFile;
+
+ private boolean mWriteStateScheduled;
+
+ private PersistenceManager() {
+ mStatePersistFile = new AtomicFile(new File(getFilesDir(),
+ PERSIST_FILE_NAME));
+ }
+
+ public void writeStateLocked() {
+ if (!PERSISTNECE_MANAGER_ENABLED) {
+ return;
+ }
+ if (mWriteStateScheduled) {
+ return;
+ }
+ mWriteStateScheduled = true;
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ synchronized (mLock) {
+ mWriteStateScheduled = false;
+ doWriteStateLocked();
+ }
+ return null;
+ }
+ }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
+ }
+
+ private void doWriteStateLocked() {
+ if (DEBUG_PERSISTENCE) {
+ Log.i(LOG_TAG, "[PERSIST START]");
+ }
+ FileOutputStream out = null;
+ try {
+ out = mStatePersistFile.startWrite();
+
+ XmlSerializer serializer = new FastXmlSerializer();
+ serializer.setOutput(out, "utf-8");
+ serializer.startDocument(null, true);
+ serializer.startTag(null, TAG_SPOOLER);
+
+ List<PrintJobInfo> printJobs = mPrintJobs;
+
+ final int printJobCount = printJobs.size();
+ for (int j = 0; j < printJobCount; j++) {
+ PrintJobInfo printJob = printJobs.get(j);
+
+ final int state = printJob.getState();
+ if (state < PrintJobInfo.STATE_QUEUED
+ || state > PrintJobInfo.STATE_CANCELED) {
+ continue;
+ }
+
+ serializer.startTag(null, TAG_JOB);
+
+ serializer.attribute(null, ATTR_ID, String.valueOf(printJob.getId()));
+ serializer.attribute(null, ATTR_LABEL, printJob.getLabel().toString());
+ serializer.attribute(null, ATTR_STATE, String.valueOf(printJob.getState()));
+ serializer.attribute(null, ATTR_APP_ID, String.valueOf(printJob.getAppId()));
+ serializer.attribute(null, ATTR_USER_ID, String.valueOf(printJob.getUserId()));
+ String tag = printJob.getTag();
+ if (tag != null) {
+ serializer.attribute(null, ATTR_TAG, tag);
+ }
+ serializer.attribute(null, ATTR_COPIES, String.valueOf(printJob.getCopies()));
+
+ PrinterId printerId = printJob.getPrinterId();
+ if (printerId != null) {
+ serializer.startTag(null, TAG_PRINTER_ID);
+ serializer.attribute(null, ATTR_LOCAL_ID, printerId.getLocalId());
+ serializer.attribute(null, ATTR_SERVICE_NAME, printerId.getServiceName()
+ .flattenToString());
+ serializer.endTag(null, TAG_PRINTER_ID);
+ }
+
+ PageRange[] pages = printJob.getPages();
+ if (pages != null) {
+ for (int i = 0; i < pages.length; i++) {
+ serializer.startTag(null, TAG_PAGE_RANGE);
+ serializer.attribute(null, ATTR_START, String.valueOf(
+ pages[i].getStart()));
+ serializer.attribute(null, ATTR_END, String.valueOf(
+ pages[i].getEnd()));
+ serializer.endTag(null, TAG_PAGE_RANGE);
+ }
+ }
+
+ PrintAttributes attributes = printJob.getAttributes();
+ if (attributes != null) {
+ serializer.startTag(null, TAG_ATTRIBUTES);
+
+ final int duplexMode = attributes.getDuplexMode();
+ serializer.attribute(null, ATTR_DUPLEX_MODE,
+ String.valueOf(duplexMode));
+
+ final int colorMode = attributes.getColorMode();
+ serializer.attribute(null, ATTR_COLOR_MODE,
+ String.valueOf(colorMode));
+
+ final int fittingMode = attributes.getFittingMode();
+ serializer.attribute(null, ATTR_FITTING_MODE,
+ String.valueOf(fittingMode));
+
+ final int orientation = attributes.getOrientation();
+ serializer.attribute(null, ATTR_ORIENTATION,
+ String.valueOf(orientation));
+
+ MediaSize mediaSize = attributes.getMediaSize();
+ if (mediaSize != null) {
+ serializer.startTag(null, TAG_MEDIA_SIZE);
+ serializer.attribute(null, ATTR_ID, mediaSize.getId());
+ serializer.attribute(null, ATTR_LABEL, mediaSize.getLabel()
+ .toString());
+ serializer.attribute(null, ATTR_WIDTH_MILS, String.valueOf(
+ mediaSize.getWidthMils()));
+ serializer.attribute(null, ATTR_HEIGHT_MILS, String.valueOf(
+ mediaSize.getHeightMils()));
+ serializer.endTag(null, TAG_MEDIA_SIZE);
+ }
+
+ Resolution resolution = attributes.getResolution();
+ if (resolution != null) {
+ serializer.startTag(null, TAG_RESOLUTION);
+ serializer.attribute(null, ATTR_ID, resolution.getId());
+ serializer.attribute(null, ATTR_LABEL, resolution.getLabel()
+ .toString());
+ serializer.attribute(null, ATTR_HORIZONTAL_DPI, String.valueOf(
+ resolution.getHorizontalDpi()));
+ serializer.attribute(null, ATTR_VERTICAL_DPI, String.valueOf(
+ resolution.getVerticalDpi()));
+ serializer.endTag(null, TAG_RESOLUTION);
+ }
+
+ Margins margins = attributes.getMargins();
+ if (margins != null) {
+ serializer.startTag(null, TAG_MARGINS);
+ serializer.attribute(null, ATTR_LEFT_MILS, String.valueOf(
+ margins.getLeftMils()));
+ serializer.attribute(null, ATTR_TOP_MILS, String.valueOf(
+ margins.getTopMils()));
+ serializer.attribute(null, ATTR_RIGHT_MILS, String.valueOf(
+ margins.getRightMils()));
+ serializer.attribute(null, ATTR_BOTTOM_MILS, String.valueOf(
+ margins.getBottomMils()));
+ serializer.endTag(null, TAG_MARGINS);
+ }
+
+ Tray inputTray = attributes.getInputTray();
+ if (inputTray != null) {
+ serializer.startTag(null, TAG_INPUT_TRAY);
+ serializer.attribute(null, ATTR_ID, inputTray.getId());
+ serializer.attribute(null, ATTR_LABEL, inputTray.getLabel()
+ .toString());
+ serializer.endTag(null, TAG_INPUT_TRAY);
+ }
+
+ Tray outputTray = attributes.getOutputTray();
+ if (outputTray != null) {
+ serializer.startTag(null, TAG_OUTPUT_TRAY);
+ serializer.attribute(null, ATTR_ID, outputTray.getId());
+ serializer.attribute(null, ATTR_LABEL, outputTray.getLabel()
+ .toString());
+ serializer.endTag(null, TAG_OUTPUT_TRAY);
+ }
+
+ serializer.endTag(null, TAG_ATTRIBUTES);
+ }
+
+ PrintDocumentInfo documentInfo = printJob.getDocumentInfo();
+ if (documentInfo != null) {
+ serializer.startTag(null, TAG_DOCUMENT_INFO);
+ serializer.attribute(null, ATTR_NAME, documentInfo.getName());
+ serializer.attribute(null, ATTR_CONTENT_TYPE, String.valueOf(
+ documentInfo.getContentType()));
+ serializer.attribute(null, ATTR_PAGE_COUNT, String.valueOf(
+ documentInfo.getPageCount()));
+ serializer.endTag(null, TAG_DOCUMENT_INFO);
+ }
+
+ serializer.endTag(null, TAG_JOB);
+
+ if (DEBUG_PERSISTENCE) {
+ Log.i(LOG_TAG, "[PERSISTED] " + printJob);
+ }
+ }
+
+ serializer.endTag(null, TAG_SPOOLER);
+ serializer.endDocument();
+ mStatePersistFile.finishWrite(out);
+ if (DEBUG_PERSISTENCE) {
+ Log.i(LOG_TAG, "[PERSIST END]");
+ }
+ } catch (IOException e) {
+ Slog.w(LOG_TAG, "Failed to write state, restoring backup.", e);
+ mStatePersistFile.failWrite(out);
+ } finally {
+ IoUtils.closeQuietly(out);
+ }
+ }
+
+ public void readStateLocked() {
+ if (!PERSISTNECE_MANAGER_ENABLED) {
+ return;
+ }
+ FileInputStream in = null;
+ try {
+ in = mStatePersistFile.openRead();
+ } catch (FileNotFoundException e) {
+ Log.i(LOG_TAG, "No existing print spooler state.");
+ return;
+ }
+ try {
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(in, null);
+ parseState(parser);
+ } catch (IllegalStateException ise) {
+ Slog.w(LOG_TAG, "Failed parsing ", ise);
+ } catch (NullPointerException npe) {
+ Slog.w(LOG_TAG, "Failed parsing ", npe);
+ } catch (NumberFormatException nfe) {
+ Slog.w(LOG_TAG, "Failed parsing ", nfe);
+ } catch (XmlPullParserException xppe) {
+ Slog.w(LOG_TAG, "Failed parsing ", xppe);
+ } catch (IOException ioe) {
+ Slog.w(LOG_TAG, "Failed parsing ", ioe);
+ } catch (IndexOutOfBoundsException iobe) {
+ Slog.w(LOG_TAG, "Failed parsing ", iobe);
+ } finally {
+ IoUtils.closeQuietly(in);
+ }
+ }
+
+ private void parseState(XmlPullParser parser)
+ throws IOException, XmlPullParserException {
+ parser.next();
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.START_TAG, TAG_SPOOLER);
+ parser.next();
+
+ while (parsePrintJob(parser)) {
+ parser.next();
+ }
+
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.END_TAG, TAG_SPOOLER);
+ }
+
+ private boolean parsePrintJob(XmlPullParser parser)
+ throws IOException, XmlPullParserException {
+ skipEmptyTextTags(parser);
+ if (!accept(parser, XmlPullParser.START_TAG, TAG_JOB)) {
+ return false;
+ }
+
+ PrintJobInfo printJob = new PrintJobInfo();
+
+ final int printJobId = Integer.parseInt(parser.getAttributeValue(null, ATTR_ID));
+ printJob.setId(printJobId);
+ String label = parser.getAttributeValue(null, ATTR_LABEL);
+ printJob.setLabel(label);
+ final int state = Integer.parseInt(parser.getAttributeValue(null, ATTR_STATE));
+ printJob.setState(state);
+ final int appId = Integer.parseInt(parser.getAttributeValue(null, ATTR_APP_ID));
+ printJob.setAppId(appId);
+ final int userId = Integer.parseInt(parser.getAttributeValue(null, ATTR_USER_ID));
+ printJob.setUserId(userId);
+ String tag = parser.getAttributeValue(null, ATTR_TAG);
+ printJob.setTag(tag);
+ String copies = parser.getAttributeValue(null, ATTR_COPIES);
+ printJob.setCopies(Integer.parseInt(copies));
+
+ parser.next();
+
+ skipEmptyTextTags(parser);
+ if (accept(parser, XmlPullParser.START_TAG, TAG_PRINTER_ID)) {
+ String localId = parser.getAttributeValue(null, ATTR_LOCAL_ID);
+ ComponentName service = ComponentName.unflattenFromString(parser.getAttributeValue(
+ null, ATTR_SERVICE_NAME));
+ printJob.setPrinterId(new PrinterId(service, localId));
+ parser.next();
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.END_TAG, TAG_PRINTER_ID);
+ parser.next();
+ }
+
+ skipEmptyTextTags(parser);
+ List<PageRange> pageRanges = null;
+ while (accept(parser, XmlPullParser.START_TAG, TAG_PAGE_RANGE)) {
+ final int start = Integer.parseInt(parser.getAttributeValue(null, ATTR_START));
+ final int end = Integer.parseInt(parser.getAttributeValue(null, ATTR_END));
+ PageRange pageRange = new PageRange(start, end);
+ if (pageRanges == null) {
+ pageRanges = new ArrayList<PageRange>();
+ }
+ pageRanges.add(pageRange);
+ parser.next();
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.END_TAG, TAG_PAGE_RANGE);
+ parser.next();
+ }
+ if (pageRanges != null) {
+ PageRange[] pageRangesArray = new PageRange[pageRanges.size()];
+ pageRanges.toArray(pageRangesArray);
+ printJob.setPages(pageRangesArray);
+ }
+
+ skipEmptyTextTags(parser);
+ if (accept(parser, XmlPullParser.START_TAG, TAG_ATTRIBUTES)) {
+
+ PrintAttributes.Builder builder = new PrintAttributes.Builder();
+
+ String duplexMode = parser.getAttributeValue(null, ATTR_DUPLEX_MODE);
+ builder.setDuplexMode(Integer.parseInt(duplexMode));
+
+ String colorMode = parser.getAttributeValue(null, ATTR_COLOR_MODE);
+ builder.setColorMode(Integer.parseInt(colorMode));
+
+ String fittingMode = parser.getAttributeValue(null, ATTR_FITTING_MODE);
+ builder.setFittingMode(Integer.parseInt(fittingMode));
+
+ String orientation = parser.getAttributeValue(null, ATTR_ORIENTATION);
+ builder.setOrientation(Integer.parseInt(orientation));
+
+ parser.next();
+
+ skipEmptyTextTags(parser);
+ if (accept(parser, XmlPullParser.START_TAG, TAG_MEDIA_SIZE)) {
+ String id = parser.getAttributeValue(null, ATTR_ID);
+ label = parser.getAttributeValue(null, ATTR_LABEL);
+ final int widthMils = Integer.parseInt(parser.getAttributeValue(null,
+ ATTR_WIDTH_MILS));
+ final int heightMils = Integer.parseInt(parser.getAttributeValue(null,
+ ATTR_HEIGHT_MILS));
+ MediaSize mediaSize = new MediaSize(id, label, widthMils, heightMils);
+ builder.setMediaSize(mediaSize);
+ parser.next();
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.END_TAG, TAG_MEDIA_SIZE);
+ parser.next();
+ }
+
+ skipEmptyTextTags(parser);
+ if (accept(parser, XmlPullParser.START_TAG, TAG_RESOLUTION)) {
+ String id = parser.getAttributeValue(null, ATTR_ID);
+ label = parser.getAttributeValue(null, ATTR_LABEL);
+ final int horizontalDpi = Integer.parseInt(parser.getAttributeValue(null,
+ ATTR_HORIZONTAL_DPI));
+ final int verticalDpi = Integer.parseInt(parser.getAttributeValue(null,
+ ATTR_VERTICAL_DPI));
+ Resolution resolution = new Resolution(id, label, horizontalDpi, verticalDpi);
+ builder.setResolution(resolution);
+ parser.next();
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.END_TAG, TAG_RESOLUTION);
+ parser.next();
+ }
+
+ skipEmptyTextTags(parser);
+ if (accept(parser, XmlPullParser.START_TAG, TAG_MARGINS)) {
+ final int leftMils = Integer.parseInt(parser.getAttributeValue(null,
+ ATTR_LEFT_MILS));
+ final int topMils = Integer.parseInt(parser.getAttributeValue(null,
+ ATTR_TOP_MILS));
+ final int rightMils = Integer.parseInt(parser.getAttributeValue(null,
+ ATTR_RIGHT_MILS));
+ final int bottomMils = Integer.parseInt(parser.getAttributeValue(null,
+ ATTR_BOTTOM_MILS));
+ Margins margins = new Margins(leftMils, topMils, rightMils, bottomMils);
+ builder.setMargins(margins);
+ parser.next();
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.END_TAG, TAG_MARGINS);
+ parser.next();
+ }
+
+ skipEmptyTextTags(parser);
+ if (accept(parser, XmlPullParser.START_TAG, TAG_INPUT_TRAY)) {
+ String id = parser.getAttributeValue(null, ATTR_ID);
+ label = parser.getAttributeValue(null, ATTR_LABEL);
+ Tray tray = new Tray(id, label);
+ builder.setInputTray(tray);
+ parser.next();
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.END_TAG, TAG_INPUT_TRAY);
+ parser.next();
+ }
+
+ skipEmptyTextTags(parser);
+ if (accept(parser, XmlPullParser.START_TAG, TAG_OUTPUT_TRAY)) {
+ String id = parser.getAttributeValue(null, ATTR_ID);
+ label = parser.getAttributeValue(null, ATTR_LABEL);
+ Tray tray = new Tray(id, label);
+ builder.setOutputTray(tray);
+ parser.next();
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.END_TAG, TAG_OUTPUT_TRAY);
+ parser.next();
+ }
+
+ printJob.setAttributes(builder.create());
+
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.END_TAG, TAG_ATTRIBUTES);
+ parser.next();
+ }
+
+ skipEmptyTextTags(parser);
+ if (accept(parser, XmlPullParser.START_TAG, TAG_DOCUMENT_INFO)) {
+ String name = parser.getAttributeValue(null, ATTR_NAME);
+ final int pageCount = Integer.parseInt(parser.getAttributeValue(null,
+ ATTR_PAGE_COUNT));
+ final int contentType = Integer.parseInt(parser.getAttributeValue(null,
+ ATTR_CONTENT_TYPE));
+ PrintDocumentInfo info = new PrintDocumentInfo.Builder(name)
+ .setPageCount(pageCount)
+ .setContentType(contentType).create();
+ printJob.setDocumentInfo(info);
+ parser.next();
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.END_TAG, TAG_DOCUMENT_INFO);
+ parser.next();
+ }
+
+ mPrintJobs.add(printJob);
+
+ if (DEBUG_PERSISTENCE) {
+ Log.i(LOG_TAG, "[RESTORED] " + printJob);
+ }
+
+ skipEmptyTextTags(parser);
+ expect(parser, XmlPullParser.END_TAG, TAG_JOB);
+
+ return true;
+ }
+
+ private void expect(XmlPullParser parser, int type, String tag)
+ throws IOException, XmlPullParserException {
+ if (!accept(parser, type, tag)) {
+ throw new XmlPullParserException("Exepected event: " + type
+ + " and tag: " + tag + " but got event: " + parser.getEventType()
+ + " and tag:" + parser.getName());
+ }
+ }
+
+ private void skipEmptyTextTags(XmlPullParser parser)
+ throws IOException, XmlPullParserException {
+ while (accept(parser, XmlPullParser.TEXT, null)
+ && "\n".equals(parser.getText())) {
+ parser.next();
+ }
+ }
+
+ private boolean accept(XmlPullParser parser, int type, String tag)
+ throws IOException, XmlPullParserException {
+ if (parser.getEventType() != type) {
+ return false;
+ }
+ if (tag != null) {
+ if (!tag.equals(parser.getName())) {
+ return false;
+ }
+ } else if (parser.getName() != null) {
+ return false;
+ }
+ return true;
+ }
+ }
+
+ public static abstract class PrinterDiscoverySession {
+
+ private PrintSpoolerService mService;
+
+ private boolean mIsStarted;
+
+ public PrinterDiscoverySession() {
+ mService = PrintSpoolerService.peekInstance();
+ mService.createPrinterDiscoverySession();
+ mService.setPrinterDiscoverySessionClient(this);
+ }
+
+ public final void startPrinterDisovery(List<PrinterId> priorityList) {
+ mIsStarted = true;
+ mService.startPrinterDiscovery(priorityList);
+ }
+
+ public final void stopPrinterDiscovery() {
+ mIsStarted = false;
+ mService.stopPrinterDiscovery();
+ }
+
+ public void requestPrinterUpdated(PrinterId printerId) {
+ mService.requestPrinterUpdate(printerId);
+ }
+
+ public final void destroy() {
+ mService.setPrinterDiscoverySessionClient(null);
+ mService.destroyPrinterDiscoverySession();
+ }
+
+ public final boolean isStarted() {
+ return mIsStarted;
+ }
+
+ public abstract void onPrintersAdded(List<PrinterInfo> printers);
+
+ public abstract void onPrintersRemoved(List<PrinterId> printerIds);
+
+ public abstract void onPrintersUpdated(List<PrinterInfo> printers);
+ }
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterActivity.java b/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterActivity.java
new file mode 100644
index 0000000..141dbd1
--- /dev/null
+++ b/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterActivity.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.printspooler;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.print.PrinterId;
+
+import com.android.printspooler.SelectPrinterFragment.OnPrinterSelectedListener;
+
+public class SelectPrinterActivity extends Activity implements OnPrinterSelectedListener {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.select_printer_activity);
+ }
+
+ @Override
+ public void onPrinterSelected(PrinterId printer) {
+ Intent intent = new Intent();
+ intent.putExtra(PrintJobConfigActivity.INTENT_EXTRA_PRINTER_ID, printer);
+ setResult(RESULT_OK, intent);
+ finish();
+ }
+}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterFragment.java b/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterFragment.java
new file mode 100644
index 0000000..9ca3a86
--- /dev/null
+++ b/packages/PrintSpooler/src/com/android/printspooler/SelectPrinterFragment.java
@@ -0,0 +1,401 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.printspooler;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.Fragment;
+import android.app.FragmentTransaction;
+import android.app.ListFragment;
+import android.app.LoaderManager;
+import android.content.ComponentName;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.Loader;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.os.Bundle;
+import android.print.PrinterId;
+import android.print.PrinterInfo;
+import android.printservice.PrintServiceInfo;
+import android.text.TextUtils;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.BaseAdapter;
+import android.widget.Filter;
+import android.widget.Filterable;
+import android.widget.ListView;
+import android.widget.SearchView;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This is a fragment for selecting a printer.
+ */
+public final class SelectPrinterFragment extends ListFragment {
+
+ private static final int LOADER_ID_PRINTERS_LOADER = 1;
+
+ private static final String FRAGMRNT_TAG_ADD_PRINTER_DIALOG =
+ "FRAGMRNT_TAG_ADD_PRINTER_DIALOG";
+
+ private static final String FRAGMRNT_ARGUMENT_PRINT_SERVICE_INFOS =
+ "FRAGMRNT_ARGUMENT_PRINT_SERVICE_INFOS";
+
+ private final ArrayList<PrintServiceInfo> mAddPrinterServices =
+ new ArrayList<PrintServiceInfo>();
+
+ public static interface OnPrinterSelectedListener {
+ public void onPrinterSelected(PrinterId printerId);
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setHasOptionsMenu(true);
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ setListAdapter(new DestinationAdapter());
+ }
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ super.onCreateOptionsMenu(menu, inflater);
+ inflater.inflate(R.menu.select_printer_activity, menu);
+
+ MenuItem searchItem = menu.findItem(R.id.action_search);
+ SearchView searchView = (SearchView) searchItem.getActionView();
+ searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
+ @Override
+ public boolean onQueryTextSubmit(String query) {
+ return true;
+ }
+
+ @Override
+ public boolean onQueryTextChange(String searchString) {
+ ((DestinationAdapter) getListAdapter()).getFilter().filter(searchString);
+ return true;
+ }
+ });
+
+ if (mAddPrinterServices.isEmpty()) {
+ menu.removeItem(R.id.action_add_printer);
+ }
+ }
+
+ @Override
+ public void onResume() {
+ updateAddPrintersAdapter();
+ getActivity().invalidateOptionsMenu();
+ super.onResume();
+ }
+
+ @Override
+ public void onListItemClick(ListView list, View view, int position, long id) {
+ PrinterInfo printer = (PrinterInfo) list.getAdapter().getItem(position);
+ Activity activity = getActivity();
+ if (activity instanceof OnPrinterSelectedListener) {
+ ((OnPrinterSelectedListener) activity).onPrinterSelected(printer.getId());
+ } else {
+ throw new IllegalStateException("the host activity must implement"
+ + " OnPrinterSelectedListener");
+ }
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == R.id.action_add_printer) {
+ showAddPrinterSelectionDialog();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ private void updateAddPrintersAdapter() {
+ mAddPrinterServices.clear();
+
+ // Get all print services.
+ List<ResolveInfo> resolveInfos = getActivity().getPackageManager().queryIntentServices(
+ new Intent(android.printservice.PrintService.SERVICE_INTERFACE),
+ PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
+
+ // No print services - done.
+ if (resolveInfos.isEmpty()) {
+ return;
+ }
+
+ // Find the services with valid add printers activities.
+ final int resolveInfoCount = resolveInfos.size();
+ for (int i = 0; i < resolveInfoCount; i++) {
+ ResolveInfo resolveInfo = resolveInfos.get(i);
+
+ PrintServiceInfo printServiceInfo = PrintServiceInfo.create(
+ resolveInfo, getActivity());
+ String addPrintersActivity = printServiceInfo.getAddPrintersActivityName();
+
+ // No add printers activity declared - done.
+ if (TextUtils.isEmpty(addPrintersActivity)) {
+ continue;
+ }
+
+ ComponentName addPrintersComponentName = new ComponentName(
+ resolveInfo.serviceInfo.packageName,
+ addPrintersActivity);
+ Intent addPritnersIntent = new Intent(Intent.ACTION_MAIN)
+ .setComponent(addPrintersComponentName);
+
+ // The add printers activity is valid - add it.
+ if (!getActivity().getPackageManager().queryIntentActivities(
+ addPritnersIntent, 0).isEmpty()) {
+ mAddPrinterServices.add(printServiceInfo);
+ }
+ }
+ }
+
+ private void showAddPrinterSelectionDialog() {
+ FragmentTransaction transaction = getFragmentManager().beginTransaction();
+ Fragment oldFragment = getFragmentManager().findFragmentByTag(
+ FRAGMRNT_TAG_ADD_PRINTER_DIALOG);
+ if (oldFragment != null) {
+ transaction.remove(oldFragment);
+ }
+ AddPrinterAlertDialogFragment newFragment = new AddPrinterAlertDialogFragment();
+ Bundle arguments = new Bundle();
+ arguments.putParcelableArrayList(FRAGMRNT_ARGUMENT_PRINT_SERVICE_INFOS,
+ mAddPrinterServices);
+ newFragment.setArguments(arguments);
+ transaction.add(newFragment, FRAGMRNT_TAG_ADD_PRINTER_DIALOG);
+ transaction.commit();
+ }
+
+ public static class AddPrinterAlertDialogFragment extends DialogFragment {
+
+ private static final String DEFAULT_MARKET_QUERY_STRING =
+ "market://search?q=print";
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
+ .setTitle(R.string.choose_print_service);
+
+ final List<PrintServiceInfo> printServices = (List<PrintServiceInfo>) (List<?>)
+ getArguments().getParcelableArrayList(FRAGMRNT_ARGUMENT_PRINT_SERVICE_INFOS);
+
+ ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(),
+ android.R.layout.simple_list_item_1);
+ final int printServiceCount = printServices.size();
+ for (int i = 0; i < printServiceCount; i++) {
+ PrintServiceInfo printService = printServices.get(i);
+ adapter.add(printService.getResolveInfo().loadLabel(
+ getActivity().getPackageManager()).toString());
+ }
+
+ builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ PrintServiceInfo printService = printServices.get(which);
+ ComponentName componentName = new ComponentName(
+ printService.getResolveInfo().serviceInfo.packageName,
+ printService.getAddPrintersActivityName());
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setComponent(componentName);
+ startActivity(intent);
+ }
+ });
+
+ Uri marketUri = Uri.parse(DEFAULT_MARKET_QUERY_STRING);
+ final Intent marketIntent = new Intent(Intent.ACTION_VIEW, marketUri);
+ if (getActivity().getPackageManager().resolveActivity(marketIntent, 0) != null) {
+ builder.setPositiveButton(R.string.search_play_store,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int whichButton) {
+ startActivity(marketIntent);
+ }
+ });
+ }
+
+ return builder.create();
+ }
+ }
+
+ private final class DestinationAdapter extends BaseAdapter
+ implements LoaderManager.LoaderCallbacks<List<PrinterInfo>>, Filterable {
+
+ private final Object mLock = new Object();
+
+ private final List<PrinterInfo> mPrinters = new ArrayList<PrinterInfo>();
+
+ private final List<PrinterInfo> mFilteredPrinters = new ArrayList<PrinterInfo>();
+
+ private CharSequence mLastSearchString;
+
+ public DestinationAdapter() {
+ getLoaderManager().initLoader(LOADER_ID_PRINTERS_LOADER, null, this);
+ }
+
+ @Override
+ public Filter getFilter() {
+ return new Filter() {
+ @Override
+ protected FilterResults performFiltering(CharSequence constraint) {
+ synchronized (mLock) {
+ if (TextUtils.isEmpty(constraint)) {
+ return null;
+ }
+ FilterResults results = new FilterResults();
+ List<PrinterInfo> filteredPrinters = new ArrayList<PrinterInfo>();
+ String constraintLowerCase = constraint.toString().toLowerCase();
+ final int printerCount = mPrinters.size();
+ for (int i = 0; i < printerCount; i++) {
+ PrinterInfo printer = mPrinters.get(i);
+ if (printer.getName().toLowerCase().contains(constraintLowerCase)) {
+ filteredPrinters.add(printer);
+ }
+ }
+ results.values = filteredPrinters;
+ results.count = filteredPrinters.size();
+ return results;
+ }
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ protected void publishResults(CharSequence constraint, FilterResults results) {
+ synchronized (mLock) {
+ mLastSearchString = constraint;
+ mFilteredPrinters.clear();
+ if (results == null) {
+ mFilteredPrinters.addAll(mPrinters);
+ } else {
+ List<PrinterInfo> printers = (List<PrinterInfo>) results.values;
+ mFilteredPrinters.addAll(printers);
+ }
+ }
+ notifyDataSetChanged();
+ }
+ };
+ }
+
+ @Override
+ public int getCount() {
+ synchronized (mLock) {
+ return mFilteredPrinters.size();
+ }
+ }
+
+ @Override
+ public Object getItem(int position) {
+ synchronized (mLock) {
+ return mFilteredPrinters.get(position);
+ }
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public View getDropDownView(int position, View convertView,
+ ViewGroup parent) {
+ return getView(position, convertView, parent);
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ if (convertView == null) {
+ convertView = getActivity().getLayoutInflater().inflate(
+ R.layout.spinner_dropdown_item, parent, false);
+ }
+
+ CharSequence title = null;
+ CharSequence subtitle = null;
+
+ PrinterInfo printer = (PrinterInfo) getItem(position);
+ title = printer.getName();
+ try {
+ PackageManager pm = getActivity().getPackageManager();
+ PackageInfo packageInfo = pm.getPackageInfo(printer.getId()
+ .getServiceName().getPackageName(), 0);
+ subtitle = packageInfo.applicationInfo.loadLabel(pm);
+ } catch (NameNotFoundException nnfe) {
+ /* ignore */
+ }
+
+ TextView titleView = (TextView) convertView.findViewById(R.id.title);
+ titleView.setText(title);
+
+ TextView subtitleView = (TextView) convertView.findViewById(R.id.subtitle);
+ if (!TextUtils.isEmpty(subtitle)) {
+ subtitleView.setText(subtitle);
+ subtitleView.setVisibility(View.VISIBLE);
+ } else {
+ subtitleView.setText(null);
+ subtitleView.setVisibility(View.GONE);
+ }
+
+ return convertView;
+ }
+
+ @Override
+ public Loader<List<PrinterInfo>> onCreateLoader(int id, Bundle args) {
+ if (id == LOADER_ID_PRINTERS_LOADER) {
+ return new FusedPrintersProvider(getActivity());
+ }
+ return null;
+ }
+
+ @Override
+ public void onLoadFinished(Loader<List<PrinterInfo>> loader,
+ List<PrinterInfo> printers) {
+ synchronized (mLock) {
+ mPrinters.clear();
+ mPrinters.addAll(printers);
+ mFilteredPrinters.clear();
+ mFilteredPrinters.addAll(printers);
+ if (!TextUtils.isEmpty(mLastSearchString)) {
+ getFilter().filter(mLastSearchString);
+ }
+ }
+ notifyDataSetChanged();
+ }
+
+ @Override
+ public void onLoaderReset(Loader<List<PrinterInfo>> loader) {
+ synchronized (mLock) {
+ mPrinters.clear();
+ mFilteredPrinters.clear();
+ }
+ notifyDataSetInvalidated();
+ }
+ }
+}
diff --git a/packages/SystemUI/ic_sysbar_internal.psd b/packages/SystemUI/ic_sysbar_internal.psd
deleted file mode 100644
index 929c872..0000000
--- a/packages/SystemUI/ic_sysbar_internal.psd
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/lightning.png b/packages/SystemUI/res/drawable-nodpi/lightning.png
new file mode 100644
index 0000000..29de308
--- /dev/null
+++ b/packages/SystemUI/res/drawable-nodpi/lightning.png
Binary files differ
diff --git a/packages/SystemUI/res/layout/quick_settings_tile_battery.xml b/packages/SystemUI/res/layout/quick_settings_tile_battery.xml
index c41e9b9..f3b894c 100644
--- a/packages/SystemUI/res/layout/quick_settings_tile_battery.xml
+++ b/packages/SystemUI/res/layout/quick_settings_tile_battery.xml
@@ -19,14 +19,14 @@
android:layout_height="match_parent"
android:layout_gravity="top"
android:orientation="vertical">
- <ImageView
+ <com.android.systemui.BatteryMeterView
android:id="@+id/image"
android:layout_marginTop="@dimen/qs_tile_margin_above_icon"
android:layout_marginBottom="@dimen/qs_tile_margin_below_icon"
- android:layout_width="@dimen/qs_tile_icon_size"
- android:layout_height="@dimen/qs_tile_icon_size"
+ android:layout_width="22dp"
+ android:layout_height="32dp"
+ android:padding="3dp"
android:layout_gravity="top|center_horizontal"
- android:scaleType="centerInside"
/>
<TextView
style="@style/TextAppearance.QuickSettings.TileView"
@@ -36,4 +36,4 @@
android:layout_gravity="top|center_horizontal"
android:gravity="top|center_horizontal"
/>
-</LinearLayout> \ No newline at end of file
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/signal_cluster_view.xml b/packages/SystemUI/res/layout/signal_cluster_view.xml
index aab5083..66b06ef 100644
--- a/packages/SystemUI/res/layout/signal_cluster_view.xml
+++ b/packages/SystemUI/res/layout/signal_cluster_view.xml
@@ -20,8 +20,9 @@
<com.android.systemui.statusbar.SignalClusterView
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_height="wrap_content"
+ android:layout_height="match_parent"
android:layout_width="wrap_content"
+ android:gravity="center"
android:orientation="horizontal"
>
<FrameLayout
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index b27536d..4741cec 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -95,11 +95,13 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
- <ImageView
+ <!-- battery must be padded below by 1px to match assets -->
+ <com.android.systemui.BatteryMeterView
android:id="@+id/battery"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:paddingStart="4dip"
+ android:layout_height="16dp"
+ android:layout_width="10dp"
+ android:paddingBottom="1px"
+ android:layout_marginStart="4dip"
/>
</LinearLayout>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 9b2c127..2bed730 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -201,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"OUTO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Kennisgewings verskyn hier"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Verkry enige tyd toegang tot hulle deur af te sleep.\nSleep weer af vir stelselkontroles."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Sleep rand van skerm om balk te wys"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Sleep van rand van skerm af om stelselbalk te wys"</string>
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 4aa452d..ebbad16 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -164,7 +164,7 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi ተያይዟል"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"ለGPS በመፈለግ ላይ"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"በ GPS የተዘጋጀ ሥፍራ"</string>
- <string name="accessibility_location_active" msgid="2427290146138169014">"ገባሪ የአካባቢ ጥያቄዎች"</string>
+ <string name="accessibility_location_active" msgid="2427290146138169014">"የአካባቢ ጥያቄዎች ነቅተዋል"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"ሁሉንም ማሳወቂያዎች አጽዳ"</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"የመተግበሪያ መረጃ"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"ማያ ገጽ በራስ ሰር ይዞራል።"</string>
@@ -201,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"ራስ-ሰር"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"ማሳወቂያዎች እዚህ ላይ ይታያሉ"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"ወደ ታች በማንሸራተት በማንኛውም ጊዜ ይድረሱባቸው።\nSwipe የስርዓት መቆጣጠሪያዎችን ለማምጣት እንደገና ወደ ታች ያንሸራትቱ።"</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"አሞሌውን ለማሳየት የማያ ገጹን ጠርዝ ላይ ያንሸራትቱ"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"አሞሌውን ለማሳየት ከማያ ገጹ ጠርዝ ጀምረው ያንሸራትቱ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index f7f5e37..7aac94e 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -201,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"تلقائي"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"تظهر الإشعارات هنا"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"يمكنك الدخول إليها في أي وقت بالتمرير السريع إلى أسفل.\nيمكنك التمرير السريع إلى أسفل مرة أخرى للوصول إلى عناصر تحكم النظام."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"مرر سريعًا لحافة الشاشة لإظهار الشريط"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"مرر سريعًا من حافة الشاشة لإظهار شريط النظام"</string>
</resources>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
new file mode 100644
index 0000000..d22f3e6
--- /dev/null
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="7164937344850004466">"Sistemin İstifadə İnterfeysi"</string>
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Təmizlə"</string>
+ <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"Siyahıdan sil"</string>
+ <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Tətbiq infosu"</string>
+ <string name="status_bar_no_recent_apps" msgid="6576392951053994640">"Yeni tətbiq yoxdur"</string>
+ <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Son tətbiqləri kənarlaşdır"</string>
+ <plurals name="status_bar_accessibility_recent_apps">
+ <item quantity="one" msgid="5854176083865845541">"1 son tətbiq"</item>
+ <item quantity="other" msgid="1040784359794890744">"%d son tətbiq"</item>
+ </plurals>
+ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Bildiriş yoxdu"</string>
+ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Davam edir"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Bildirişlər"</string>
+ <string name="battery_low_title" msgid="2783104807551211639">"Adapteri qoşun"</string>
+ <string name="battery_low_subtitle" msgid="1752040062087829196">"Batareya azalır."</string>
+ <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> qalıb"</string>
+ <string name="invalid_charger" msgid="4549105996740522523">"USB ilə elektrik doldurma dəstəklənmir.\nYalnız adapter istifadə edin."</string>
+ <string name="battery_low_why" msgid="7279169609518386372">"Batareya istifadəsi"</string>
+ <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Ayarlar"</string>
+ <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
+ <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Təyyarə rejimi"</string>
+ <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Ekranın avto-dönüşü"</string>
+ <string name="status_bar_settings_mute_label" msgid="554682549917429396">"SUSDUR"</string>
+ <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AVTO"</string>
+ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Bildirişlər"</string>
+ <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth tezerinq"</string>
+ <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Daxiletmə metodlarını ayarlayın"</string>
+ <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Fiziki klaviatura"</string>
+ <string name="usb_device_permission_prompt" msgid="834698001271562057">"<xliff:g id="APPLICATION">%1$s</xliff:g> tətbiqinə USB cihazına daxil olmağa icazə verilsin?"</string>
+ <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"<xliff:g id="APPLICATION">%1$s</xliff:g> tətbiqinə USB aksesuarına qoşulmağa icazə verirsiniz?"</string>
+ <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"USB cihaz qoşulu olan zaman <xliff:g id="ACTIVITY">%1$s</xliff:g> açılsın mı?"</string>
+ <string name="usb_accessory_confirm_prompt" msgid="3808984931830229888">"USB aksesuar qoşulu olan zaman <xliff:g id="ACTIVITY">%1$s</xliff:g> açılsın mı?"</string>
+ <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Heç bir quraşdırılmış tətbiq bu USB aksesuar ilə işləmir. Bu aksesuar haqqında daha ətraflı məlumatı <xliff:g id="URL">%1$s</xliff:g> adresindən öyrənin"</string>
+ <string name="title_usb_accessory" msgid="4966265263465181372">"USB aksesuar"</string>
+ <string name="label_view" msgid="6304565553218192990">"Göstər"</string>
+ <string name="always_use_device" msgid="1450287437017315906">"Bu USB cihaz üçün defolt olaraq istifadə edin."</string>
+ <string name="always_use_accessory" msgid="1210954576979621596">"Bu USB aksesuar üçün defolt istifadə edin"</string>
+ <string name="usb_debugging_title" msgid="4513918393387141949">"USB sazlamaya icazə verilsin?"</string>
+ <string name="usb_debugging_message" msgid="2220143855912376496">"Kompüterin RSA barmaq izi: \n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+ <string name="usb_debugging_always" msgid="303335496705863070">"Bu kompüterdən həmişə icazə verilsin"</string>
+ <string name="compat_mode_on" msgid="6623839244840638213">"Ekranı doldurmaq üçün yaxınlaşdır"</string>
+ <string name="compat_mode_off" msgid="4434467572461327898">"Ekranı doldurmaq üçün uzat"</string>
+ <string name="compat_mode_help_header" msgid="7969493989397529910">"Uyğunluq zoomu"</string>
+ <string name="compat_mode_help_body" msgid="4946726776359270040">"Tətbiq kiçik bir ekran üçün nəzərdə tutulduğu zaman, zoom kontrolu saatın yanında görünür."</string>
+ <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Skrinşot yadda saxlanılır..."</string>
+ <string name="screenshot_saving_title" msgid="8242282144535555697">"Skrinşot yadda saxlanır..."</string>
+ <string name="screenshot_saving_text" msgid="2419718443411738818">"Skrinşot yadda saxlanır."</string>
+ <string name="screenshot_saved_title" msgid="6461865960961414961">"Skrinşot çəkildi."</string>
+ <string name="screenshot_saved_text" msgid="1152839647677558815">"Skrinşotunuza baxmaq üçün toxunun"</string>
+ <string name="screenshot_failed_title" msgid="705781116746922771">"Skrinşot götürülə bilinmədi."</string>
+ <string name="screenshot_failed_text" msgid="8134011269572415402">"Skrinşotu yadda saxlamaq alınmadı, yəqin yaddaş istifadə olunur."</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"USB fayl transferi seçimləri"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Media pleyer (MTP) kimi montaj edin"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Kamera kimi birləşdir (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="2312667578562201583">"Mac üçün Android File Transfer tətbiqini quraşdırın"</string>
+ <string name="accessibility_back" msgid="567011538994429120">"Geri"</string>
+ <string name="accessibility_home" msgid="8217216074895377641">"Ana səhifə"</string>
+ <string name="accessibility_menu" msgid="316839303324695949">"Menyu"</string>
+ <string name="accessibility_recent" msgid="8571350598987952883">"Son tətbiqlər"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Daxiletmə metodu düyməsinə keç"</string>
+ <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Uyğunluq zoom düyməsi."</string>
+ <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Daha böyük ekranda uzaqlaşdır."</string>
+ <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth qoşulub."</string>
+ <string name="accessibility_bluetooth_disconnected" msgid="7416648669976870175">"Bluetooth əlaqəsi kəsildi."</string>
+ <string name="accessibility_no_battery" msgid="358343022352820946">"Batareya yoxdur."</string>
+ <string name="accessibility_battery_one_bar" msgid="7774887721891057523">"Batareya bir xətdir."</string>
+ <string name="accessibility_battery_two_bars" msgid="8500650438735009973">"Batareya iki xətdir."</string>
+ <string name="accessibility_battery_three_bars" msgid="2302983330865040446">"Batareya üç xətdir."</string>
+ <string name="accessibility_battery_full" msgid="8909122401720158582">"Batareya doludur"</string>
+ <string name="accessibility_no_phone" msgid="4894708937052611281">"Telefon yoxdur."</string>
+ <string name="accessibility_phone_one_bar" msgid="687699278132664115">"Şəbəkə bir xətdir."</string>
+ <string name="accessibility_phone_two_bars" msgid="8384905382804815201">"Şəbəkə iki xətdir."</string>
+ <string name="accessibility_phone_three_bars" msgid="8521904843919971885">"Şəbəkə üç xətdir."</string>
+ <string name="accessibility_phone_signal_full" msgid="6471834868580757898">"Tam şəbəkə."</string>
+ <string name="accessibility_no_data" msgid="4791966295096867555">"Məlumat yoxdur."</string>
+ <string name="accessibility_data_one_bar" msgid="1415625833238273628">"Data bir xətdir."</string>
+ <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Data iki xətdir."</string>
+ <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Data üç xətdir."</string>
+ <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Data siqnalı tamdır."</string>
+ <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wifi sönülüdür."</string>
+ <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wifi bağlantı kəsildi."</string>
+ <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Wifi bir xətdir."</string>
+ <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Wifi iki xətdir."</string>
+ <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Wifi üç xətdir."</string>
+ <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Wifi siqnalı tamdır."</string>
+ <string name="accessibility_no_wimax" msgid="4329180129727630368">"WiMAX yoxdur."</string>
+ <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX bir xətt."</string>
+ <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX iki xətdir."</string>
+ <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX üç xətdir."</string>
+ <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX siqnalı tamdır."</string>
+ <string name="accessibility_no_signal" msgid="7064645320782585167">"Siqnal yoxdur."</string>
+ <string name="accessibility_not_connected" msgid="6395326276213402883">"Qoşulu deyil."</string>
+ <string name="accessibility_zero_bars" msgid="3806060224467027887">"Sıfır xətt."</string>
+ <string name="accessibility_one_bar" msgid="1685730113192081895">"Bir xətt."</string>
+ <string name="accessibility_two_bars" msgid="6437363648385206679">"İki xətt."</string>
+ <string name="accessibility_three_bars" msgid="2648241415119396648">"Üç xətdir."</string>
+ <string name="accessibility_signal_full" msgid="9122922886519676839">"Siqnal tamdır."</string>
+ <string name="accessibility_desc_on" msgid="2385254693624345265">"Aktiv."</string>
+ <string name="accessibility_desc_off" msgid="6475508157786853157">"Deaktiv"</string>
+ <string name="accessibility_desc_connected" msgid="8366256693719499665">"Qoşuludur."</string>
+ <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+ <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+ <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
+ <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
+ <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
+ <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
+ <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+ <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Rouminq"</string>
+ <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
+ <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
+ <string name="accessibility_no_sim" msgid="8274017118472455155">"SIM yoxdur"</string>
+ <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth tezering."</string>
+ <string name="accessibility_airplane_mode" msgid="834748999790763092">"Uçuş rejimi"</string>
+ <string name="accessibility_battery_level" msgid="7451474187113371965">"Batareya <xliff:g id="NUMBER">%d</xliff:g> faizdir."</string>
+ <string name="accessibility_settings_button" msgid="799583911231893380">"Sistem parametrləri"</string>
+ <string name="accessibility_notifications_button" msgid="4498000369779421892">"Bildirişlər."</string>
+ <string name="accessibility_remove_notification" msgid="3603099514902182350">"Bildirişi təmizlə."</string>
+ <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS aktivdir."</string>
+ <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS əldə edilir."</string>
+ <string name="accessibility_tty_enabled" msgid="4613200365379426561">"TeleTypewriter aktivləşdirilib."</string>
+ <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Zəng vibrasiyası"</string>
+ <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Zəngvuran səssiz."</string>
+ <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> çıxarıldı."</string>
+ <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Bildiriş uzaqlaşdırıldı."</string>
+ <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Bildiriş kölgəsi."</string>
+ <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Tez ayarlar."</string>
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Axırıncı tətbiqlər."</string>
+ <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"İstifadəçi <xliff:g id="USER">%s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+ <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mobil <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Batareya <xliff:g id="STATE">%s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Təyyarə Rejimi <xliff:g id="STATE">%s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarm <xliff:g id="TIME">%s</xliff:g> üçün qurulub."</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G data qeyri-aktivdir"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G data deaktiv edildi"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Mobil data qeyri-aktivdir"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="2086815304858964954">"Data qeyri-aktivdir"</string>
+ <string name="data_usage_disabled_dialog" msgid="3853117269051806280">"Göstərilmiş data istifadə limitinə çatdınız.\n\nƏgər datanı yenidən aktivləşdirsəniz, operator tərəfindən əlavə tariflər tətbiq oluna bilər."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="7729772039208664606">"Datanı yenidən aktiv et"</string>
+ <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"İnternet bağlantısı yoxdur"</string>
+ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi qoşulub"</string>
+ <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS Axtarışı"</string>
+ <string name="gps_notification_found_text" msgid="4619274244146446464">"Yer GPS tərəfindən müəyyən edildi"</string>
+ <string name="accessibility_location_active" msgid="2427290146138169014">"Məkan sorğuları arxivi"</string>
+ <string name="accessibility_clear_all" msgid="5235938559247164925">"Bütün bildirişləri sil."</string>
+ <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Tətbiq infosu"</string>
+ <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekran avtomatik döndəriləcək."</string>
+ <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Ekran landşaft orientasiyasında kilidlənib."</string>
+ <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Ekran portret orientasiyasında kilidlənib."</string>
+ <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+ <string name="start_dreams" msgid="7219575858348719790">"Xəyal"</string>
+ <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+ <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Uçuş rejimi"</string>
+ <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Dolur, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+ <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Dolub"</string>
+ <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+ <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Cihaz)"</string>
+ <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth bağlıdır"</string>
+ <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Parlaqlıq"</string>
+ <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Avtofırlanma"</string>
+ <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Fırlatma kilidlidir"</string>
+ <string name="quick_settings_ime_label" msgid="7073463064369468429">"Daxiletmə metodu"</string>
+ <string name="quick_settings_location_label" msgid="5011327048748762257">"Yer"</string>
+ <string name="quick_settings_location_off_label" msgid="7464544086507331459">"Yer Deaktiv"</string>
+ <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Media cihazı"</string>
+ <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+ <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Yalnız fövqəladə zənglər"</string>
+ <string name="quick_settings_settings_label" msgid="5326556592578065401">"Nizamlar"</string>
+ <string name="quick_settings_time_label" msgid="4635969182239736408">"Vaxt"</string>
+ <string name="quick_settings_user_label" msgid="5238995632130897840">"Mən"</string>
+ <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Bağlantı yoxdur"</string>
+ <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Şəbəkə yoxdur"</string>
+ <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi sönülüdür"</string>
+ <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi Ekran"</string>
+ <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Simsiz Ekran"</string>
+ <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Parlaqlıq"</string>
+ <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AVTO"</string>
+ <string name="status_bar_help_title" msgid="1199237744086469217">"Bildirişlər burada görünür"</string>
+ <string name="status_bar_help_text" msgid="7874607155052076323">"Aşağı sürüşdürməklə istənilən vaxt onları əldə edin.\nSistemi nəzarəti üçün yenə də aşağı sürüşdürün."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index aaca584..76d0580 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -206,8 +206,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АЎТА"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Апавяшчэнні з\'яўляюцца тут"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Атрымлівайце доступ да іх у любы час, праводзячы пальцам уніз.\nПравядзіце пальцам уніз яшчэ раз, каб атрымаць доступ да сродкаў кіравання сістэмай."</string>
- <!-- no translation found for hiding_navigation_confirmation_message (3227814171674734332) -->
- <skip />
- <!-- no translation found for hiding_navigation_confirmation_message_long (7854368870786524950) -->
- <skip />
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index b10f5ff..605dd97 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -164,8 +164,7 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi: Има връзка"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Търси се GPS"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"Местоположението е зададено от GPS"</string>
- <!-- no translation found for accessibility_location_active (2427290146138169014) -->
- <skip />
+ <string name="accessibility_location_active" msgid="2427290146138169014">"Активни заявки за местоположение"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Изчистване на всички известия."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Информация за приложението"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Екранът ще се завърта автоматично."</string>
@@ -202,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АВТ."</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Известията се показват тук"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Осъществявайте достъп до тях по всяко време, като прекарате пръст надолу.\nНаправете го отново за системните контроли."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Прекарайте пръст по ръба на екрана, за да се покаже лентата"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Прекарайте пръст от ръба на екрана, за да се покаже системната лента"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 0a95005..83e7020 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -166,8 +166,7 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi: connectada"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"S\'està cercant un GPS"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"S\'ha establert la ubicació per GPS"</string>
- <!-- no translation found for accessibility_location_active (2427290146138169014) -->
- <skip />
+ <string name="accessibility_location_active" msgid="2427290146138169014">"Sol·licituds d\'ubicació actives"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Esborra totes les notificacions."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informació de l\'aplicació"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"La pantalla girarà automàticament."</string>
@@ -204,6 +203,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMÀTICA"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Les notificacions apareixen aquí"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Accedeix-hi en qualsevol moment: només has de fer lliscar el dit cap avall.\nTorna a fer lliscar el dit cap avall per fer que es mostrin els controls del sistema."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Fes lliscar el dit per la vora de la pantalla perquè es mostri la barra"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Fes lliscar el dit des de la vora de la pantalla perquè es mostri la barra del sistema"</string>
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 178238f..4497735 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -203,6 +203,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATICKY"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Zde se zobrazují oznámení"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Můžete je kdykoli zobrazit tím, že přejedete prstem dolů.\nPřejedete-li prstem dolů ještě jednou, zobrazí se ovládací prvky systému."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Panel zobrazíte přejetím přes okraj obrazovky"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Systémový panel zobrazíte přejetím přes okraj obrazovky"</string>
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 1c772b5..be42612 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -164,8 +164,7 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi er forbundet"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Søger efter GPS"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"Placeringen er angivet ved hjælp af GPS"</string>
- <!-- no translation found for accessibility_location_active (2427290146138169014) -->
- <skip />
+ <string name="accessibility_location_active" msgid="2427290146138169014">"Aktive placeringsanmodninger"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Ryd alle meddelelser."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Oplysninger om appen"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skærmen roterer automatisk."</string>
@@ -202,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Underretninger vises her"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Få adgang til dem når som helst ved at stryge ned.\nStryg ned igen for at komme til systemindstillingerne."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Stryg fra skærmkanten for at se bjælken"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Stryg med fingeren fra skærmens kant for at få vist systembjælken"</string>
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 86ea82d..052990c 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -166,8 +166,7 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"WLAN verbunden"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS wird gesucht"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"Standort durch GPS festgelegt"</string>
- <!-- no translation found for accessibility_location_active (2427290146138169014) -->
- <skip />
+ <string name="accessibility_location_active" msgid="2427290146138169014">"Standortanfragen aktiv"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Alle Benachrichtigungen löschen"</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"App-Details"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Bildschirm wird automatisch gedreht."</string>
@@ -204,6 +203,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Benachrichtigungen erscheinen hier"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Greifen Sie jederzeit auf sie zu, indem Sie nach unten wischen.\nWischen Sie für Systemeinstellungen erneut nach unten."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Zum Einblenden der Leiste vom Rand weg wischen"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Zum Einblenden der Systemleiste vom Display-Rand weg wischen"</string>
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index f965773..d23b8d5 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -203,6 +203,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"ΑΥΤΟΜΑΤΗ"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Οι ειδοποιήσεις εμφανίζονται εδώ"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Μεταβείτε σε αυτές ανά πάσα στιγμή σύροντας προς τα κάτω.\nΣύρετε ξανά προς τα κάτω για τα στοιχεία ελέγχου συστήματος."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Σύρετε από την άκρη της οθόνης για να εμφανίσετε τη γραμμή"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Σύρετε από την άκρη της οθόνης για να εμφανίσετε τη γραμμή συστήματος"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index a7d6213..2ac1040 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -201,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Notifications appear here"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Access them any time by swiping down.\nSwipe down again for system controls."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Swipe edge of screen to reveal bar"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Swipe from edge of screen to reveal system bar"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
new file mode 100644
index 0000000..2ac1040
--- /dev/null
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="7164937344850004466">"System UI"</string>
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Clear"</string>
+ <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"Remove from list"</string>
+ <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"App info"</string>
+ <string name="status_bar_no_recent_apps" msgid="6576392951053994640">"No recent apps"</string>
+ <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Dismiss recent apps"</string>
+ <plurals name="status_bar_accessibility_recent_apps">
+ <item quantity="one" msgid="5854176083865845541">"1 recent app"</item>
+ <item quantity="other" msgid="1040784359794890744">"%d recent apps"</item>
+ </plurals>
+ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"No notifications"</string>
+ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Ongoing"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifications"</string>
+ <string name="battery_low_title" msgid="2783104807551211639">"Connect charger"</string>
+ <string name="battery_low_subtitle" msgid="1752040062087829196">"The battery is getting low."</string>
+ <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> remaining"</string>
+ <string name="invalid_charger" msgid="4549105996740522523">"USB charging not supported.\nUse only the supplied charger."</string>
+ <string name="battery_low_why" msgid="7279169609518386372">"Battery use"</string>
+ <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Settings"</string>
+ <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
+ <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Aeroplane mode"</string>
+ <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Auto-rotate screen"</string>
+ <string name="status_bar_settings_mute_label" msgid="554682549917429396">"MUTE"</string>
+ <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTO"</string>
+ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Notifications"</string>
+ <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth tethered"</string>
+ <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Set up input methods"</string>
+ <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Physical keyboard"</string>
+ <string name="usb_device_permission_prompt" msgid="834698001271562057">"Allow the app <xliff:g id="APPLICATION">%1$s</xliff:g> to access the USB device?"</string>
+ <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Allow the app <xliff:g id="APPLICATION">%1$s</xliff:g> to access the USB accessory?"</string>
+ <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Open <xliff:g id="ACTIVITY">%1$s</xliff:g> when this USB device is connected?"</string>
+ <string name="usb_accessory_confirm_prompt" msgid="3808984931830229888">"Open <xliff:g id="ACTIVITY">%1$s</xliff:g> when this USB accessory is connected?"</string>
+ <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"No installed apps work with this USB accessory. Learn more about this accessory at <xliff:g id="URL">%1$s</xliff:g>"</string>
+ <string name="title_usb_accessory" msgid="4966265263465181372">"USB accessory"</string>
+ <string name="label_view" msgid="6304565553218192990">"View"</string>
+ <string name="always_use_device" msgid="1450287437017315906">"Use by default for this USB device"</string>
+ <string name="always_use_accessory" msgid="1210954576979621596">"Use by default for this USB accessory"</string>
+ <string name="usb_debugging_title" msgid="4513918393387141949">"Allow USB debugging?"</string>
+ <string name="usb_debugging_message" msgid="2220143855912376496">"The computer\'s RSA key fingerprint is:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+ <string name="usb_debugging_always" msgid="303335496705863070">"Always allow from this computer"</string>
+ <string name="compat_mode_on" msgid="6623839244840638213">"Zoom to fill screen"</string>
+ <string name="compat_mode_off" msgid="4434467572461327898">"Stretch to fill screen"</string>
+ <string name="compat_mode_help_header" msgid="7969493989397529910">"Compatibility zoom"</string>
+ <string name="compat_mode_help_body" msgid="4946726776359270040">"When an app was designed for a smaller screen, a zoom control will appear by the clock."</string>
+ <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Saving screenshot…"</string>
+ <string name="screenshot_saving_title" msgid="8242282144535555697">"Saving screenshot…"</string>
+ <string name="screenshot_saving_text" msgid="2419718443411738818">"Screenshot is being saved."</string>
+ <string name="screenshot_saved_title" msgid="6461865960961414961">"Screenshot captured."</string>
+ <string name="screenshot_saved_text" msgid="1152839647677558815">"Touch to view your screenshot."</string>
+ <string name="screenshot_failed_title" msgid="705781116746922771">"Couldn\'t capture screenshot."</string>
+ <string name="screenshot_failed_text" msgid="8134011269572415402">"Couldn\'t save screenshot. Storage may be in use."</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"USB file transfer options"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Mount as a media player (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Mount as a camera (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="2312667578562201583">"Install Android File Transfer application for Mac"</string>
+ <string name="accessibility_back" msgid="567011538994429120">"Back"</string>
+ <string name="accessibility_home" msgid="8217216074895377641">"Home"</string>
+ <string name="accessibility_menu" msgid="316839303324695949">"Menu"</string>
+ <string name="accessibility_recent" msgid="8571350598987952883">"Recent apps"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Switch input method button."</string>
+ <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Compatibility zoom button."</string>
+ <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom smaller to larger screen."</string>
+ <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth connected."</string>
+ <string name="accessibility_bluetooth_disconnected" msgid="7416648669976870175">"Bluetooth disconnected."</string>
+ <string name="accessibility_no_battery" msgid="358343022352820946">"No battery."</string>
+ <string name="accessibility_battery_one_bar" msgid="7774887721891057523">"Battery one bar."</string>
+ <string name="accessibility_battery_two_bars" msgid="8500650438735009973">"Battery two bars."</string>
+ <string name="accessibility_battery_three_bars" msgid="2302983330865040446">"Battery three bars."</string>
+ <string name="accessibility_battery_full" msgid="8909122401720158582">"Battery full."</string>
+ <string name="accessibility_no_phone" msgid="4894708937052611281">"No phone."</string>
+ <string name="accessibility_phone_one_bar" msgid="687699278132664115">"Phone one bar."</string>
+ <string name="accessibility_phone_two_bars" msgid="8384905382804815201">"Phone two bars."</string>
+ <string name="accessibility_phone_three_bars" msgid="8521904843919971885">"Phone three bars."</string>
+ <string name="accessibility_phone_signal_full" msgid="6471834868580757898">"Phone signal full."</string>
+ <string name="accessibility_no_data" msgid="4791966295096867555">"No data."</string>
+ <string name="accessibility_data_one_bar" msgid="1415625833238273628">"Data one bar."</string>
+ <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Data two bars."</string>
+ <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Data three bars."</string>
+ <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Data signal full."</string>
+ <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wi-Fi off."</string>
+ <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wi-Fi disconnected."</string>
+ <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Wi-Fi one bar."</string>
+ <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Wi-Fi two bars."</string>
+ <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Wi-Fi three bars."</string>
+ <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Wi-Fi signal full."</string>
+ <string name="accessibility_no_wimax" msgid="4329180129727630368">"No WiMAX."</string>
+ <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX one bar."</string>
+ <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX two bars."</string>
+ <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX three bars."</string>
+ <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX signal full."</string>
+ <string name="accessibility_no_signal" msgid="7064645320782585167">"No signal."</string>
+ <string name="accessibility_not_connected" msgid="6395326276213402883">"Not connected."</string>
+ <string name="accessibility_zero_bars" msgid="3806060224467027887">"Zero bars."</string>
+ <string name="accessibility_one_bar" msgid="1685730113192081895">"One bar."</string>
+ <string name="accessibility_two_bars" msgid="6437363648385206679">"Two bars."</string>
+ <string name="accessibility_three_bars" msgid="2648241415119396648">"Three bars."</string>
+ <string name="accessibility_signal_full" msgid="9122922886519676839">"Signal full."</string>
+ <string name="accessibility_desc_on" msgid="2385254693624345265">"On."</string>
+ <string name="accessibility_desc_off" msgid="6475508157786853157">"Off."</string>
+ <string name="accessibility_desc_connected" msgid="8366256693719499665">"Connected."</string>
+ <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+ <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+ <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
+ <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
+ <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
+ <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
+ <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+ <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
+ <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
+ <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
+ <string name="accessibility_no_sim" msgid="8274017118472455155">"No SIM."</string>
+ <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth tethering"</string>
+ <string name="accessibility_airplane_mode" msgid="834748999790763092">"Aeroplane mode"</string>
+ <string name="accessibility_battery_level" msgid="7451474187113371965">"Battery <xliff:g id="NUMBER">%d</xliff:g> per cent."</string>
+ <string name="accessibility_settings_button" msgid="799583911231893380">"System settings"</string>
+ <string name="accessibility_notifications_button" msgid="4498000369779421892">"Notifications."</string>
+ <string name="accessibility_remove_notification" msgid="3603099514902182350">"Clear notification."</string>
+ <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS enabled."</string>
+ <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS acquiring."</string>
+ <string name="accessibility_tty_enabled" msgid="4613200365379426561">"TeleTypewriter enabled."</string>
+ <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Ringer vibrate."</string>
+ <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Ringer silent."</string>
+ <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> dismissed."</string>
+ <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notification dismissed."</string>
+ <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Notification shade."</string>
+ <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Quick settings."</string>
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Recent apps"</string>
+ <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"User <xliff:g id="USER">%s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+ <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Mobile <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Battery <xliff:g id="STATE">%s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Aeroplane Mode <xliff:g id="STATE">%s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarm set for <xliff:g id="TIME">%s</xliff:g>."</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G data disabled"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G data disabled"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Mobile data disabled"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="2086815304858964954">"Data disabled"</string>
+ <string name="data_usage_disabled_dialog" msgid="3853117269051806280">"You\'ve reached the specified data usage limit.\n\nIf you re-enable data, you may be charged by the operator."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="7729772039208664606">"Reenable data"</string>
+ <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"No Internet connection"</string>
+ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi connected"</string>
+ <string name="gps_notification_searching_text" msgid="8574247005642736060">"Searching for GPS"</string>
+ <string name="gps_notification_found_text" msgid="4619274244146446464">"Location set by GPS"</string>
+ <string name="accessibility_location_active" msgid="2427290146138169014">"Location requests active"</string>
+ <string name="accessibility_clear_all" msgid="5235938559247164925">"Clear all notifications."</string>
+ <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"App info"</string>
+ <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Screen will rotate automatically."</string>
+ <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Screen is locked in landscape orientation."</string>
+ <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Screen is locked in portrait orientation."</string>
+ <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+ <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
+ <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+ <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Aeroplane mode"</string>
+ <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Charging, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+ <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Charged"</string>
+ <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+ <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> Devices)"</string>
+ <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth Off"</string>
+ <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Brightness"</string>
+ <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Auto Rotate"</string>
+ <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Rotation Locked"</string>
+ <string name="quick_settings_ime_label" msgid="7073463064369468429">"Input Method"</string>
+ <string name="quick_settings_location_label" msgid="5011327048748762257">"Location"</string>
+ <string name="quick_settings_location_off_label" msgid="7464544086507331459">"Location Off"</string>
+ <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Media device"</string>
+ <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+ <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Emergency Calls Only"</string>
+ <string name="quick_settings_settings_label" msgid="5326556592578065401">"Settings"</string>
+ <string name="quick_settings_time_label" msgid="4635969182239736408">"Time"</string>
+ <string name="quick_settings_user_label" msgid="5238995632130897840">"Me"</string>
+ <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Not Connected"</string>
+ <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"No Network"</string>
+ <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi Off"</string>
+ <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi Display"</string>
+ <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Wireless Display"</string>
+ <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Brightness"</string>
+ <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
+ <string name="status_bar_help_title" msgid="1199237744086469217">"Notifications appear here"</string>
+ <string name="status_bar_help_text" msgid="7874607155052076323">"Access them any time by swiping down.\nSwipe down again for system controls."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index bdd0363..d11d413 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -166,8 +166,7 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi conectado"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Buscando GPS"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"La ubicación se estableció por GPS"</string>
- <!-- no translation found for accessibility_location_active (2427290146138169014) -->
- <skip />
+ <string name="accessibility_location_active" msgid="2427290146138169014">"Solicitudes de ubicación activas"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Eliminar todas las notificaciones"</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Información de la aplicación"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"La pantalla girará automáticamente."</string>
@@ -204,6 +203,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMÁTICO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Las notificaciones aparecen aquí."</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Desliza el dedo hacia abajo para acceder al contenido.\nVuelve a deslizar el dedo hacia abajo para acceder a los controles del sistema."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Desliza el dedo desde el borde de la pantalla para mostrar la barra."</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Desliza el dedo desde el borde de la pantalla para mostrar la barra del sistema."</string>
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index a81a2b4..068af45 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -201,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Las notificaciones aparecen aquí"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Desliza el dedo hacia abajo para acceder al contenido.\nVuelve a deslizar el dedo hacia abajo para acceder a los controles del sistema."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Desliza el borde de la pantalla para mostrar la barra"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Desliza el borde de la pantalla para mostrar la barra del sistema"</string>
</resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index c4fda13..28ece65 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -201,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMAATNE"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Märguanded ilmuvad siia"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Juurdepääs igal ajal sõrmega alla pühkides.\nSüsteemi juhtnuppude jaoks pühkige uuesti alla."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Riba kuvamiseks pühkige ekraani serva"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Süsteemiriba kuvamiseks pühkige ekraani servast"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index a84b9b4..2ba0427 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -201,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"خودکار"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"اعلان‌ها در اینجا نمایش داده می‌شوند"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"با کشیدن انگشت به طرف پایین به آنها دسترسی پیدا کنید.\nبرای کنترل‌های سیستم دوباره انگشت خود را به سمت پایین بکشید."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"برای نمایش نوار، انگشت خود را از لبه‌ صفحه به داخل بکشید"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"برای نمایش نوار سیستم، انگشت خود را از لبه‌ صفحه به داخل بکشید"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index f2cce06..b652cb0 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -201,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Ilmoitukset näkyvät tässä"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Näet ilmoitukset liu\'uttamalla sormea alas ruudulla.\nVoit palauttaa järjestelmän ohjaimet näkyviin liu\'uttamalla sormea alas uudelleen."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Tuo palkki näkyviin liu\'uttamalla ruudun reunasta"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Tuo järjestelmäpalkki näkyviin liu\'uttamalla ruudun reunasta"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
new file mode 100644
index 0000000..8fb7340
--- /dev/null
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -0,0 +1,206 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="7164937344850004466">"IU système"</string>
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Effacer"</string>
+ <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"Supprimer de la liste"</string>
+ <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Informations sur l\'application"</string>
+ <string name="status_bar_no_recent_apps" msgid="6576392951053994640">"Aucune application récente"</string>
+ <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Masquer les applications récentes"</string>
+ <plurals name="status_bar_accessibility_recent_apps">
+ <item quantity="one" msgid="5854176083865845541">"1 application récente"</item>
+ <item quantity="other" msgid="1040784359794890744">"%d applications récentes"</item>
+ </plurals>
+ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Aucune notification"</string>
+ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"En cours"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifications"</string>
+ <string name="battery_low_title" msgid="2783104807551211639">"Brancher le chargeur"</string>
+ <string name="battery_low_subtitle" msgid="1752040062087829196">"Le niveau de la batterie est faible."</string>
+ <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> restant(s)"</string>
+ <string name="invalid_charger" msgid="4549105996740522523">"Chargement USB non compatible.\nVous devez utiliser le chargeur fourni."</string>
+ <string name="battery_low_why" msgid="7279169609518386372">"Utilisation de la batterie"</string>
+ <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Paramètres"</string>
+ <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
+ <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Mode Avion"</string>
+ <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Rotation auto de l\'écran"</string>
+ <string name="status_bar_settings_mute_label" msgid="554682549917429396">"MUET"</string>
+ <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"AUTOMATIQUE"</string>
+ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Notifications"</string>
+ <string name="bluetooth_tethered" msgid="7094101612161133267">"Connexion Bluetooth partagée"</string>
+ <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Configurer les modes de saisie"</string>
+ <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Clavier physique"</string>
+ <string name="usb_device_permission_prompt" msgid="834698001271562057">"Autoriser l\'application <xliff:g id="APPLICATION">%1$s</xliff:g> à accéder au périphérique USB?"</string>
+ <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Autoriser l\'application <xliff:g id="APPLICATION">%1$s</xliff:g> à accéder à l\'accessoire USB?"</string>
+ <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Ouvrir <xliff:g id="ACTIVITY">%1$s</xliff:g> lors de la connexion de ce périphérique USB?"</string>
+ <string name="usb_accessory_confirm_prompt" msgid="3808984931830229888">"Ouvrir <xliff:g id="ACTIVITY">%1$s</xliff:g> lors de la connexion de cet accessoire USB?"</string>
+ <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Aucune application installée compatible avec accessoire USB. En savoir plus sur <xliff:g id="URL">%1$s</xliff:g>"</string>
+ <string name="title_usb_accessory" msgid="4966265263465181372">"Accessoire USB"</string>
+ <string name="label_view" msgid="6304565553218192990">"Afficher"</string>
+ <string name="always_use_device" msgid="1450287437017315906">"Utiliser par défaut pour ce périphérique USB"</string>
+ <string name="always_use_accessory" msgid="1210954576979621596">"Utiliser par défaut pour cet accessoire USB"</string>
+ <string name="usb_debugging_title" msgid="4513918393387141949">"Autoriser le débogage USB?"</string>
+ <string name="usb_debugging_message" msgid="2220143855912376496">"Empreinte numérique de la clé RSA de l\'ordinateur : \n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+ <string name="usb_debugging_always" msgid="303335496705863070">"Toujours autoriser sur cet ordinateur"</string>
+ <string name="compat_mode_on" msgid="6623839244840638213">"Zoomer pour remplir l\'écran"</string>
+ <string name="compat_mode_off" msgid="4434467572461327898">"Étirer pour remplir l\'écran"</string>
+ <string name="compat_mode_help_header" msgid="7969493989397529910">"Zoom de compatibilité"</string>
+ <string name="compat_mode_help_body" msgid="4946726776359270040">"Si une application a été conçue pour un écran plus petit, une commande de zoom s\'affiche à côté de l\'horloge."</string>
+ <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Enregistrement capture écran…"</string>
+ <string name="screenshot_saving_title" msgid="8242282144535555697">"Enregistrement capture écran…"</string>
+ <string name="screenshot_saving_text" msgid="2419718443411738818">"Enregistrement de la capture d\'écran en cours…"</string>
+ <string name="screenshot_saved_title" msgid="6461865960961414961">"Capture d\'écran réussie"</string>
+ <string name="screenshot_saved_text" msgid="1152839647677558815">"Appuyez pour afficher votre capture d\'écran."</string>
+ <string name="screenshot_failed_title" msgid="705781116746922771">"Impossible de réaliser une capture d\'écran"</string>
+ <string name="screenshot_failed_text" msgid="8134011269572415402">"Impossible enregistrer capture d\'écran. Périphérique de stockage peut-être en cours d\'utilisation."</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"Options transfert fichiers USB"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Installer comme un lecteur multimédia (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Installer comme un appareil photo (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="2312667578562201583">"Installer application Android File Transfer (Mac)"</string>
+ <string name="accessibility_back" msgid="567011538994429120">"Précédent"</string>
+ <string name="accessibility_home" msgid="8217216074895377641">"Domicile"</string>
+ <string name="accessibility_menu" msgid="316839303324695949">"Menu"</string>
+ <string name="accessibility_recent" msgid="8571350598987952883">"Applications récentes"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Bouton \"Changer le mode de saisie\""</string>
+ <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Bouton \"Zoom de compatibilité\""</string>
+ <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Zoom de compatibilité avec la taille de l\'écran"</string>
+ <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth connecté"</string>
+ <string name="accessibility_bluetooth_disconnected" msgid="7416648669976870175">"Bluetooth déconnecté"</string>
+ <string name="accessibility_no_battery" msgid="358343022352820946">"Batterie vide"</string>
+ <string name="accessibility_battery_one_bar" msgid="7774887721891057523">"Niveau de batterie : faible"</string>
+ <string name="accessibility_battery_two_bars" msgid="8500650438735009973">"Niveau de batterie : moyen"</string>
+ <string name="accessibility_battery_three_bars" msgid="2302983330865040446">"Niveau de batterie : bon"</string>
+ <string name="accessibility_battery_full" msgid="8909122401720158582">"Batterie pleine"</string>
+ <string name="accessibility_no_phone" msgid="4894708937052611281">"Aucun signal"</string>
+ <string name="accessibility_phone_one_bar" msgid="687699278132664115">"Signal : faible"</string>
+ <string name="accessibility_phone_two_bars" msgid="8384905382804815201">"Signal : moyen"</string>
+ <string name="accessibility_phone_three_bars" msgid="8521904843919971885">"Signal : bon"</string>
+ <string name="accessibility_phone_signal_full" msgid="6471834868580757898">"Signal excellent"</string>
+ <string name="accessibility_no_data" msgid="4791966295096867555">"Aucun signal"</string>
+ <string name="accessibility_data_one_bar" msgid="1415625833238273628">"Signal faible"</string>
+ <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Signal moyen"</string>
+ <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Signal bon"</string>
+ <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Signal excellent"</string>
+ <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wi-Fi désactivé"</string>
+ <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wi-Fi déconnecté"</string>
+ <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Signal Wi-Fi faible"</string>
+ <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Signal Wi-Fi moyen"</string>
+ <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Signal Wi-Fi bon"</string>
+ <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Signal Wi-Fi excellent"</string>
+ <string name="accessibility_no_wimax" msgid="4329180129727630368">"Aucun signal WiMAX"</string>
+ <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"Signal WiMAX : faible"</string>
+ <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"Signal WiMAX : moyen"</string>
+ <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"Signal WiMAX : bon"</string>
+ <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"Signal WiMAX : excellent"</string>
+ <string name="accessibility_no_signal" msgid="7064645320782585167">"Aucun signal"</string>
+ <string name="accessibility_not_connected" msgid="6395326276213402883">"Non connecté"</string>
+ <string name="accessibility_zero_bars" msgid="3806060224467027887">"Aucun signal"</string>
+ <string name="accessibility_one_bar" msgid="1685730113192081895">"Signal faible"</string>
+ <string name="accessibility_two_bars" msgid="6437363648385206679">"Moyen"</string>
+ <string name="accessibility_three_bars" msgid="2648241415119396648">"Bon"</string>
+ <string name="accessibility_signal_full" msgid="9122922886519676839">"Signal excellent"</string>
+ <string name="accessibility_desc_on" msgid="2385254693624345265">"Activé"</string>
+ <string name="accessibility_desc_off" msgid="6475508157786853157">"Désactivé"</string>
+ <string name="accessibility_desc_connected" msgid="8366256693719499665">"Connecté"</string>
+ <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+ <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1x"</string>
+ <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"3G+"</string>
+ <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
+ <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3G+"</string>
+ <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
+ <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+ <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Itinérance"</string>
+ <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"EDGE"</string>
+ <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
+ <string name="accessibility_no_sim" msgid="8274017118472455155">"Aucune carte SIM"</string>
+ <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Partage de connexion Bluetooth"</string>
+ <string name="accessibility_airplane_mode" msgid="834748999790763092">"Mode Avion"</string>
+ <!-- String.format failed for translation -->
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <string name="accessibility_settings_button" msgid="799583911231893380">"Paramètres système"</string>
+ <string name="accessibility_notifications_button" msgid="4498000369779421892">"Notifications"</string>
+ <string name="accessibility_remove_notification" msgid="3603099514902182350">"Supprimer la notification"</string>
+ <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS activé"</string>
+ <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"Acquisition de données GPS"</string>
+ <string name="accessibility_tty_enabled" msgid="4613200365379426561">"Téléscripteur activé"</string>
+ <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Sonnerie en mode vibreur"</string>
+ <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Sonnerie en mode silencieux"</string>
+ <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"Application \"<xliff:g id="APP">%s</xliff:g>\" ignorée."</string>
+ <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Notification masquée"</string>
+ <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Volet des notifications"</string>
+ <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Paramètres rapides"</string>
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Applications récentes"</string>
+ <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Utilisateur : <xliff:g id="USER">%s</xliff:g>"</string>
+ <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>, <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+ <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Signal mobile : <xliff:g id="SIGNAL">%1$s</xliff:g>, <xliff:g id="TYPE">%2$s</xliff:g>, <xliff:g id="NETWORK">%3$s</xliff:g>"</string>
+ <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Batterie : <xliff:g id="STATE">%s</xliff:g>"</string>
+ <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Mode Avion : <xliff:g id="STATE">%s</xliff:g>"</string>
+ <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth : <xliff:g id="STATE">%s</xliff:g>"</string>
+ <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarme réglée sur <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Données 2G-3G désactivées"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Données 4G désactivées"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Données mobiles désactivées"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="2086815304858964954">"Données désactivées"</string>
+ <string name="data_usage_disabled_dialog" msgid="3853117269051806280">"Vous avez atteint le plafond de consommation de données spécifié.\n\nSi vous utilisez des données supplémentaires, celles-ci pourront être facturées par l\'opérateur."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="7729772039208664606">"Réactiver connexion données"</string>
+ <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Aucune connexion Internet"</string>
+ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Connecté au Wi-Fi"</string>
+ <string name="gps_notification_searching_text" msgid="8574247005642736060">"Recherche de GPS..."</string>
+ <string name="gps_notification_found_text" msgid="4619274244146446464">"Position définie par GPS"</string>
+ <string name="accessibility_location_active" msgid="2427290146138169014">"Demandes de localisation actives"</string>
+ <string name="accessibility_clear_all" msgid="5235938559247164925">"Supprimer toutes les notifications"</string>
+ <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informations sur l\'application"</string>
+ <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"L\'écran pivote automatiquement."</string>
+ <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"L\'écran est verrouillé en mode paysage."</string>
+ <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"L\'écran est verrouillé en mode portrait."</string>
+ <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+ <string name="start_dreams" msgid="7219575858348719790">"Écran de veille"</string>
+ <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+ <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Mode Avion"</string>
+ <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"En charge (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
+ <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Chargée"</string>
+ <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+ <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> appareils)"</string>
+ <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"BLUETOOTH DÉSACTIVÉ"</string>
+ <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Luminosité"</string>
+ <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Rotation automatique"</string>
+ <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Rotation verrouillée"</string>
+ <string name="quick_settings_ime_label" msgid="7073463064369468429">"Mode de saisie"</string>
+ <string name="quick_settings_location_label" msgid="5011327048748762257">"Position"</string>
+ <string name="quick_settings_location_off_label" msgid="7464544086507331459">"Localisation désactivée"</string>
+ <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Appareil multimédia"</string>
+ <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+ <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Appels d\'urgence uniquement"</string>
+ <string name="quick_settings_settings_label" msgid="5326556592578065401">"Paramètres"</string>
+ <string name="quick_settings_time_label" msgid="4635969182239736408">"Heures"</string>
+ <string name="quick_settings_user_label" msgid="5238995632130897840">"Moi"</string>
+ <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Non connecté"</string>
+ <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Aucun réseau"</string>
+ <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi désactivé"</string>
+ <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Affichage Wi-Fi"</string>
+ <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Affichage sans fil"</string>
+ <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Luminosité"</string>
+ <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATIQUE"</string>
+ <string name="status_bar_help_title" msgid="1199237744086469217">"Les notifications s’affichent ici"</string>
+ <string name="status_bar_help_text" msgid="7874607155052076323">"Accédez-y à tout moment en faisant glisser le doigt vers le bas.\nRépétez l\'opération pour accéder aux commandes du système."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 7fe1143..d00e4a3 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -166,8 +166,7 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Connecté au Wi-Fi"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Recherche de GPS..."</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"Position définie par GPS"</string>
- <!-- no translation found for accessibility_location_active (2427290146138169014) -->
- <skip />
+ <string name="accessibility_location_active" msgid="2427290146138169014">"Demandes de localisation actives"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Supprimer toutes les notifications"</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informations sur l\'application"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"L\'écran pivote automatiquement."</string>
@@ -204,6 +203,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATIQUE"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Les notifications s’affichent ici"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Accédez-y à tout moment en faisant glisser le doigt vers le bas.\nRépétez l\'opération pour accéder aux commandes du système."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Faites glisser le doigt sur le côté de l\'écran pour afficher la barre."</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Faites glisser le doigt à partir d\'un côté de l\'écran pour afficher la barre système."</string>
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index a1de7a1..45b5813 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -201,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"स्वत:"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"सूचनाएं यहां दिखाई देती हैं"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"नीचे स्वाइप करके उन तक कभी भी पहुंचें.\nसिस्टम नियंत्रणों के लिए पुन: नीचे स्वाइप करें."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"बार को प्रदर्शित करने के लिए स्क्रीन के किनारे को स्वाइप करें"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"सिस्टम बार को प्रदर्शित करने के लिए स्क्रीन के किनारे से स्वाइप करें"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index f8ff35d..9f8559c 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -201,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATSKI"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Obavijesti se prikazuju ovdje"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Pristupite im u bilo kojem trenutku tako da prstom trznete prema dolje. \nPonovo prstom trznite prema dolje za kontrole sustava."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Prijeđite prstom po rubu zaslona da bi se prikazala traka"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Prijeđite prstom od ruba zaslona da bi se prikazala traka sustava"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 118baed..f2dcd93 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -201,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"automatikus"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Az értesítések itt jelennek meg."</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Bármikor elérheti őket, ha lefelé húzza az ujját.\nHúzza le az ujját még egyszer a rendszerbeállítások eléréséhez."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Csúsztassa ujját a képernyő szélén a sáv megjelenítéséhez"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Csúsztassa ujját a képernyő szélétől a rendszersáv megjelenítéséhez"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
new file mode 100644
index 0000000..4241898
--- /dev/null
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="7164937344850004466">"Համակարգային UI"</string>
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Մաքրել"</string>
+ <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"Հեռացնել ցանկից"</string>
+ <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Տեղեկություններ ծրագրի մասին"</string>
+ <string name="status_bar_no_recent_apps" msgid="6576392951053994640">"Թարմ հավելվածներ չկան"</string>
+ <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Անտեսել վերջին ծրագրերը"</string>
+ <plurals name="status_bar_accessibility_recent_apps">
+ <item quantity="one" msgid="5854176083865845541">"1 նոր ծրագիր"</item>
+ <item quantity="other" msgid="1040784359794890744">"%d նոր ծրագիր"</item>
+ </plurals>
+ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Ծանուցումներ չկան"</string>
+ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Ընթացիկ"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Ծանուցումներ"</string>
+ <string name="battery_low_title" msgid="2783104807551211639">"Միացրեք լիցքավորիչը"</string>
+ <string name="battery_low_subtitle" msgid="1752040062087829196">"Մարտկոցը լիցքաթափվում է:"</string>
+ <string name="battery_low_percent_format" msgid="1077244949318261761">"մնում է <xliff:g id="NUMBER">%d%%</xliff:g>"</string>
+ <string name="invalid_charger" msgid="4549105996740522523">"USB լիցքավորումը չի աջակցվում:\nՕգտվեք միայն գործող լիցքավորիչից:"</string>
+ <string name="battery_low_why" msgid="7279169609518386372">"Մարտկոցի օգտագործումը"</string>
+ <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Կարգավորումներ"</string>
+ <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
+ <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Ինքնաթիռային ռեժիմ"</string>
+ <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Ինքնապտտվող էկրան"</string>
+ <string name="status_bar_settings_mute_label" msgid="554682549917429396">"Համրեցնել"</string>
+ <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"Ինքնաշխատ"</string>
+ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Ծանուցումներ"</string>
+ <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth-ը կապված է"</string>
+ <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Կարգավորել մուտքագրման եղանակները"</string>
+ <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Ֆիզիկական ստեղնաշար"</string>
+ <string name="usb_device_permission_prompt" msgid="834698001271562057">"Թույլատրե՞լ <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածի մուտքը USB սարք:"</string>
+ <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"Թույլատրե՞լ, որ <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածը մուտք գործի USB լրասարք:"</string>
+ <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Բացե՞լ <xliff:g id="ACTIVITY">%1$s</xliff:g>-ը, երբ այս USB կրիչը կապակցված է:"</string>
+ <string name="usb_accessory_confirm_prompt" msgid="3808984931830229888">"Բացե՞լ <xliff:g id="ACTIVITY">%1$s</xliff:g>-ը, երբ այս USB լրասարքը կապակցված է:"</string>
+ <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Այս USB լրասարքի հետ ոչ մի հավելված չի աշխատում: Իմացեք ավելին այս լրասարքի մասին <xliff:g id="URL">%1$s</xliff:g>-ում"</string>
+ <string name="title_usb_accessory" msgid="4966265263465181372">"USB լրասարք"</string>
+ <string name="label_view" msgid="6304565553218192990">"Դիտել"</string>
+ <string name="always_use_device" msgid="1450287437017315906">"Օգտագործել լռելյայն այս USB սարքի համար"</string>
+ <string name="always_use_accessory" msgid="1210954576979621596">"Օգտագործել լռելյայն այս USB լրասարքի համար"</string>
+ <string name="usb_debugging_title" msgid="4513918393387141949">"Թույլատրե՞լ USB-ի կարգաբերումը:"</string>
+ <string name="usb_debugging_message" msgid="2220143855912376496">"Համակարգչի RSA-ի բանալի մատնահետքն է`\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+ <string name="usb_debugging_always" msgid="303335496705863070">"Միշտ թույլատրել այս համակարգչից"</string>
+ <string name="compat_mode_on" msgid="6623839244840638213">"Խոշորացնել` էկրանը լցնելու համար"</string>
+ <string name="compat_mode_off" msgid="4434467572461327898">"Ձգել` էկրանը լցնելու համար"</string>
+ <string name="compat_mode_help_header" msgid="7969493989397529910">"Համատեղելիության խոշորացում"</string>
+ <string name="compat_mode_help_body" msgid="4946726776359270040">"Երբ հավելվածը նախագծված է ավելի փոքր էկրանի համար, խոշորացման կարգավորիչը կհայտնվի ժամացույցի կողքին:"</string>
+ <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Պահում է էկրանի հանույթը…"</string>
+ <string name="screenshot_saving_title" msgid="8242282144535555697">"Պահում է էկրանի հանույթը..."</string>
+ <string name="screenshot_saving_text" msgid="2419718443411738818">"Էկրանի հանույթը պահվում է:"</string>
+ <string name="screenshot_saved_title" msgid="6461865960961414961">"Էկրանի հանույթը լուսանկարվել է:"</string>
+ <string name="screenshot_saved_text" msgid="1152839647677558815">"Հպեք ձեր էկրանի հանույթը տեսնելու համար:"</string>
+ <string name="screenshot_failed_title" msgid="705781116746922771">"Չհաջողվեց լուսանկարել էկրանի հանույթը:"</string>
+ <string name="screenshot_failed_text" msgid="8134011269572415402">"Չհաջողվեց պահել էկրանի հանույթը: Հնարավոր է` պահոցն օգտագործման մեջ է:"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"USB ֆայլերի փոխանցման ընտրանքներ"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Միացնել որպես մեդիա նվագարկիչ (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Միացնել որպես ֆոտոխցիկ (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="2312667578562201583">"Տեղադրել Android ֆայլերի փոխանցման հավելվածը Mac-ի համար"</string>
+ <string name="accessibility_back" msgid="567011538994429120">"Հետ"</string>
+ <string name="accessibility_home" msgid="8217216074895377641">"Տուն"</string>
+ <string name="accessibility_menu" msgid="316839303324695949">"Ցանկ"</string>
+ <string name="accessibility_recent" msgid="8571350598987952883">"Վերջին ծրագրերը"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Միացնել մուտքագրման եղանակի կոճակը:"</string>
+ <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Համատեղելիության խոշորացման կոճակը:"</string>
+ <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Դիտափոխել փոքրից ավելի մեծ էկրան:"</string>
+ <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth-ը միացված է:"</string>
+ <string name="accessibility_bluetooth_disconnected" msgid="7416648669976870175">"Bluetooth-ն անջատված է:"</string>
+ <string name="accessibility_no_battery" msgid="358343022352820946">"Մարտկոց չկա:"</string>
+ <string name="accessibility_battery_one_bar" msgid="7774887721891057523">"Մարտկոցի մեկ գիծ:"</string>
+ <string name="accessibility_battery_two_bars" msgid="8500650438735009973">"Մարտկոցի երկու գիծ:"</string>
+ <string name="accessibility_battery_three_bars" msgid="2302983330865040446">"Մարտկոցի երեք գիծ:"</string>
+ <string name="accessibility_battery_full" msgid="8909122401720158582">"Մարտկոցը լիքն է:"</string>
+ <string name="accessibility_no_phone" msgid="4894708937052611281">"Հեռախոս չկա:"</string>
+ <string name="accessibility_phone_one_bar" msgid="687699278132664115">"Հեռախոսի մեկ գիծ:"</string>
+ <string name="accessibility_phone_two_bars" msgid="8384905382804815201">"Հեռախոսի երկու գիծ:"</string>
+ <string name="accessibility_phone_three_bars" msgid="8521904843919971885">"Հեռախոսի երեք գիծ:"</string>
+ <string name="accessibility_phone_signal_full" msgid="6471834868580757898">"Հեռախոսի ազդանշանը լիքն է:"</string>
+ <string name="accessibility_no_data" msgid="4791966295096867555">"Տվյալներ չկան:"</string>
+ <string name="accessibility_data_one_bar" msgid="1415625833238273628">"Տվյալների մեկ գիծ:"</string>
+ <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Տվյալների երկու գիծ:"</string>
+ <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Տվյալների երեք գիծ:"</string>
+ <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Տվյալների ազդանշանը լրիվ է:"</string>
+ <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wifi-ը անջատված է:"</string>
+ <string name="accessibility_no_wifi" msgid="1425476551827924474">"WiFi-ը անջատված է:"</string>
+ <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Wifi-ի մեկ գիծ:"</string>
+ <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Wifi-ի երկու գիծ:"</string>
+ <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"WiFi-ի երեք գիծ:"</string>
+ <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Wifi-ի ազդանշանը լիքն է:"</string>
+ <string name="accessibility_no_wimax" msgid="4329180129727630368">"WiMAX չկա:"</string>
+ <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX-ի մեկ գիծ:"</string>
+ <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX-ի երկու գիծ:"</string>
+ <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX-ի երեք գիծ:"</string>
+ <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX-ի ազդանշանը լիքն է:"</string>
+ <string name="accessibility_no_signal" msgid="7064645320782585167">"Ազդանշան չկա:"</string>
+ <string name="accessibility_not_connected" msgid="6395326276213402883">"Միացված չէ:"</string>
+ <string name="accessibility_zero_bars" msgid="3806060224467027887">"Զրո գիծ:"</string>
+ <string name="accessibility_one_bar" msgid="1685730113192081895">"Մեկ գիծ:"</string>
+ <string name="accessibility_two_bars" msgid="6437363648385206679">"Երկու գիծ:"</string>
+ <string name="accessibility_three_bars" msgid="2648241415119396648">"Երեք գիծ:"</string>
+ <string name="accessibility_signal_full" msgid="9122922886519676839">"Ազդանշանը լրիվ է:"</string>
+ <string name="accessibility_desc_on" msgid="2385254693624345265">"Միացված է:"</string>
+ <string name="accessibility_desc_off" msgid="6475508157786853157">"Անջատված է:"</string>
+ <string name="accessibility_desc_connected" msgid="8366256693719499665">"Միացված է:"</string>
+ <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+ <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+ <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
+ <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
+ <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
+ <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
+ <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+ <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Ռոումինգ"</string>
+ <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
+ <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
+ <string name="accessibility_no_sim" msgid="8274017118472455155">"SIM չկա:"</string>
+ <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth-ը կապվում է:"</string>
+ <string name="accessibility_airplane_mode" msgid="834748999790763092">"Ինքնաթիռային ռեժիմ"</string>
+ <string name="accessibility_battery_level" msgid="7451474187113371965">"Մարտկոցը <xliff:g id="NUMBER">%d</xliff:g> տոկոս է:"</string>
+ <string name="accessibility_settings_button" msgid="799583911231893380">"Համակարգի կարգավորումներ:"</string>
+ <string name="accessibility_notifications_button" msgid="4498000369779421892">"Ծանուցումներ:"</string>
+ <string name="accessibility_remove_notification" msgid="3603099514902182350">"Մաքրել ծանուցումը:"</string>
+ <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS-ը միացված է:"</string>
+ <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS-ի ստացում:"</string>
+ <string name="accessibility_tty_enabled" msgid="4613200365379426561">"Հեռամուտքագրիչը միացված է:"</string>
+ <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Զանգի թրթռոց:"</string>
+ <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Զանգակը լռեցված է:"</string>
+ <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g>-ը անտեսված է:"</string>
+ <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Ծանուցումը անտեսվեց:"</string>
+ <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Ծանուցումների վահանակ:"</string>
+ <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Արագ կարգավորումներ:"</string>
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Վերջին հավելվածները:"</string>
+ <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Օգտվող <xliff:g id="USER">%s</xliff:g>:"</string>
+ <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>: <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+ <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Շարժական <xliff:g id="SIGNAL">%1$s</xliff:g>: <xliff:g id="TYPE">%2$s</xliff:g>: <xliff:g id="NETWORK">%3$s</xliff:g>:"</string>
+ <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Մարտկոցը <xliff:g id="STATE">%s</xliff:g> է:"</string>
+ <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Ինքնաթիռային ռեժիմը <xliff:g id="STATE">%s</xliff:g> է:"</string>
+ <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth-ը <xliff:g id="STATE">%s</xliff:g> է:"</string>
+ <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Զարթուցիչը դրված է <xliff:g id="TIME">%s</xliff:g>-ին:"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G տվյալները անջատված են"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G տվյալները անջատված են"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Շարժական տվյալները անջատված են"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="2086815304858964954">"Տվյալները անջատված են"</string>
+ <string name="data_usage_disabled_dialog" msgid="3853117269051806280">"Դուք հասել եք նշված տվյալների օգտագործման սահմանին:\n\n Եթե դուք կրկին ակտիվացնեք տվյալները, այն կարող է գանձվել օպերատորի կողմից:"</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="7729772039208664606">"Վերամիացնել տվյալները"</string>
+ <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Ինտերնետ կապ չկա"</string>
+ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi-ը միացված է"</string>
+ <string name="gps_notification_searching_text" msgid="8574247005642736060">"Որոնում է GPS"</string>
+ <string name="gps_notification_found_text" msgid="4619274244146446464">"Տեղադրությունը կարգավորվել է GPS-ի կողմից"</string>
+ <string name="accessibility_location_active" msgid="2427290146138169014">"Տեղադրության հարցումներն ակտիվ են"</string>
+ <string name="accessibility_clear_all" msgid="5235938559247164925">"Մաքրել բոլոր ծանուցումները:"</string>
+ <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Տեղեկություններ ծրագրի մասին"</string>
+ <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Էկրանը ինքնուրույն կպտտվի:"</string>
+ <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Էկրանը կողպված է հորիզոնական դիրքավորման մեջ:"</string>
+ <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Էկրանը կողպված է ուղղաձիգ դիրքավորմամբ:"</string>
+ <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+ <string name="start_dreams" msgid="7219575858348719790">"Ցերեկային ռեժիմ"</string>
+ <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+ <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Ինքնաթիռային ռեժիմ"</string>
+ <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Լիցքավորում` <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+ <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Լիցքավորված է"</string>
+ <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+ <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> սարք)"</string>
+ <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth-ն անջատված է"</string>
+ <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Պայծառություն"</string>
+ <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Ինքնապտտում"</string>
+ <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Պտտումը կողպված է"</string>
+ <string name="quick_settings_ime_label" msgid="7073463064369468429">"Մուտքագրման եղանակը"</string>
+ <string name="quick_settings_location_label" msgid="5011327048748762257">"Տեղադրություն"</string>
+ <string name="quick_settings_location_off_label" msgid="7464544086507331459">"Անջատել տեղադրությունը"</string>
+ <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Մեդիա սարք"</string>
+ <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+ <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Միայն արտակարգ իրավիճակների զանգեր"</string>
+ <string name="quick_settings_settings_label" msgid="5326556592578065401">"Կարգավորումներ"</string>
+ <string name="quick_settings_time_label" msgid="4635969182239736408">"Ժամանակը"</string>
+ <string name="quick_settings_user_label" msgid="5238995632130897840">"Ես"</string>
+ <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Միացված չէ"</string>
+ <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Ցանց չկա"</string>
+ <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi-ը անջատված է"</string>
+ <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi ցուցադրիչ"</string>
+ <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Անլար էկրան"</string>
+ <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Պայծառություն"</string>
+ <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"Ինքնաշխատ"</string>
+ <string name="status_bar_help_title" msgid="1199237744086469217">"Ծանուցումները հայտնվում են այստեղ"</string>
+ <string name="status_bar_help_text" msgid="7874607155052076323">"Դրանք մատչեք ցանկացած պահի` սահահարվածելով:\nԿրկին սահահարվածեք ներքև` համակարգային կառավարման համար:"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 013bd99..6846056 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -164,8 +164,7 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi tersambung"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Menelusuri GPS"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"Lokasi yang disetel oleh GPS"</string>
- <!-- no translation found for accessibility_location_active (2427290146138169014) -->
- <skip />
+ <string name="accessibility_location_active" msgid="2427290146138169014">"Permintaan lokasi aktif"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Menghapus semua pemberitahuan."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Info aplikasi"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Layar akan diputar secara otomatis."</string>
@@ -202,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"OTOMATIS"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Pemberitahuan muncul di sini"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Akses kapan saja dengan menggesek ke bawah.\nGesek ke bawah sekali lagi untuk kontrol sistem."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Gesek tepi layar untuk membuka bilah"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Gesek dari bagian tepi layar untuk membuka bilah sistem"</string>
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index ff539be..a889342 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -203,6 +203,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Le notifiche vengono visualizzate qui"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Puoi accedervi in qualsiasi momento scorrendo verso il basso.\nFai scorrere di nuovo verso il basso per visualizzare i controlli del sistema."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Fai scorrere il bordo dello schermo per visualizzare la barra"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Fai scorrere il dito dal bordo dello schermo per visualizzare la barra di sistema"</string>
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index c80ad7c..899f092 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -164,8 +164,7 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi מחובר"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"מחפש GPS"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"מיקום מוגדר על ידי GPS"</string>
- <!-- no translation found for accessibility_location_active (2427290146138169014) -->
- <skip />
+ <string name="accessibility_location_active" msgid="2427290146138169014">"בקשות מיקום פעילות"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"נקה את כל ההתראות."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"פרטי יישום"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"המסך יסתובב באופן אוטומטי."</string>
@@ -202,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"אוטומטי"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"הודעות מופיעות כאן"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"גש אליהם בכל עת על ידי החלקה למטה.\nהחלק למטה שוב למעבר למרכז הבקרה של המערכת."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"החלק מקצה המסך כדי להציג את הסרגל"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"החלק מקצה המסך כדי להציג את סרגל המערכת"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 73aa558..e92e8be 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -166,8 +166,7 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi接続済み"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"GPSで検索中"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPSにより現在地が設定されました"</string>
- <!-- no translation found for accessibility_location_active (2427290146138169014) -->
- <skip />
+ <string name="accessibility_location_active" msgid="2427290146138169014">"現在地リクエストがアクティブ"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"通知をすべて消去。"</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"アプリ情報"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"画面は自動的に回転します。"</string>
@@ -204,6 +203,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"自動"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"ここに通知が表示されます"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"下にスワイプすると、いつでも通知を表示できます。\nシステムを管理するにはもう一度下にスワイプしてください。"</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"バーを表示するには、画面の端からスワイプします"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"システムバーを表示するには、画面の端からスワイプします"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
new file mode 100644
index 0000000..bcbe4de
--- /dev/null
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="7164937344850004466">"სისტემის UI"</string>
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"გასუფთავება"</string>
+ <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"სიიდან ამოშლა"</string>
+ <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"აპის შესახებ"</string>
+ <string name="status_bar_no_recent_apps" msgid="6576392951053994640">"ბოლოს გამოყენებული აპების სია ცარიელია"</string>
+ <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"ბოლო აპების გაუქმება"</string>
+ <plurals name="status_bar_accessibility_recent_apps">
+ <item quantity="one" msgid="5854176083865845541">"1 ბოლო აპი"</item>
+ <item quantity="other" msgid="1040784359794890744">"%d ბოლო აპი"</item>
+ </plurals>
+ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"შეტყობინებები არ არის."</string>
+ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"მიმდინარე"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"შეტყობინებები"</string>
+ <string name="battery_low_title" msgid="2783104807551211639">"შეაერთეთ დამტენი."</string>
+ <string name="battery_low_subtitle" msgid="1752040062087829196">"ბატარეა ჯდება."</string>
+ <string name="battery_low_percent_format" msgid="1077244949318261761">"დარჩენილია <xliff:g id="NUMBER">%d%%</xliff:g>"</string>
+ <string name="invalid_charger" msgid="4549105996740522523">"USB-ით დატენვა არ არის მხარდაჭერილი.\nგამოიყენეთ მხოლოდ ელექტრო-დამტენი."</string>
+ <string name="battery_low_why" msgid="7279169609518386372">"ელემენტის გამოყენება"</string>
+ <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"პარამეტრები"</string>
+ <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
+ <string name="status_bar_settings_airplane" msgid="4879879698500955300">"თვითმფრინავის რეჟიმი"</string>
+ <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"ავტოროტაციის ეკრანი"</string>
+ <string name="status_bar_settings_mute_label" msgid="554682549917429396">"დადუმება"</string>
+ <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"ავტომატური"</string>
+ <string name="status_bar_settings_notifications" msgid="397146176280905137">"შეტყობინებები"</string>
+ <string name="bluetooth_tethered" msgid="7094101612161133267">"Bluetooth მიერთებულია."</string>
+ <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"შეყვანის მეთოდების დაყენება"</string>
+ <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"ფიზიკური კლავიატურა"</string>
+ <string name="usb_device_permission_prompt" msgid="834698001271562057">"გსურთ, მისცეთ აპლიკაციას „<xliff:g id="APPLICATION">%1$s</xliff:g>“ USB მეხსიერებასთან წვდომის უფლება?"</string>
+ <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"გსურთ, მისცეთ აპლიკაციას „<xliff:g id="APPLICATION">%1$s</xliff:g>“ USB აქსესუართან წვდომის უფლება?"</string>
+ <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"გსურთ <xliff:g id="ACTIVITY">%1$s</xliff:g> , როდესაც ეს USB მოწყობილობა შეერთებულია?"</string>
+ <string name="usb_accessory_confirm_prompt" msgid="3808984931830229888">"გსურთ <xliff:g id="ACTIVITY">%1$s</xliff:g> , როდესაც ეს USB მოწყობილობა შეერთებულია?"</string>
+ <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"არცერთი დაყენებული აპი არ მუშაობს ამ USB აქსესუართან. შეიტყვეთ მეტი ამ აქსესუარის შესახებ <xliff:g id="URL">%1$s</xliff:g>"</string>
+ <string name="title_usb_accessory" msgid="4966265263465181372">"USB აქსესუარი"</string>
+ <string name="label_view" msgid="6304565553218192990">"ნახვა"</string>
+ <string name="always_use_device" msgid="1450287437017315906">"ამ USB მოწყობილობის ნაგულისხმევად გამოყენება"</string>
+ <string name="always_use_accessory" msgid="1210954576979621596">"ავტომატურად გამოიყენე ამ USB აქსესუარისთვის."</string>
+ <string name="usb_debugging_title" msgid="4513918393387141949">"გააქტიურდეს USB გამართვა?"</string>
+ <string name="usb_debugging_message" msgid="2220143855912376496">"კომპიუტერის RSA გასაღების თითის ანაბეჭდია:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+ <string name="usb_debugging_always" msgid="303335496705863070">"ყოველთვის დართე ნება ამ კომპიუტერიდან."</string>
+ <string name="compat_mode_on" msgid="6623839244840638213">"მასშტაბი შეცვალეთ ეკრანის შესავსებად."</string>
+ <string name="compat_mode_off" msgid="4434467572461327898">"გაწიეთ ეკრანის შესავსებად."</string>
+ <string name="compat_mode_help_header" msgid="7969493989397529910">"თავსებადობის მასშტაბი"</string>
+ <string name="compat_mode_help_body" msgid="4946726776359270040">"თუ აპი გათვლილია მცირე ეკრანისთვის, საათის გვერდით გაჩნდება მასშტაბის მართვის ელემენტი."</string>
+ <string name="screenshot_saving_ticker" msgid="7403652894056693515">"სკრინშოტის შენახვა…"</string>
+ <string name="screenshot_saving_title" msgid="8242282144535555697">"ეკრანის სურათის შენახვა…"</string>
+ <string name="screenshot_saving_text" msgid="2419718443411738818">"ეკრანის სურათი შენახულია."</string>
+ <string name="screenshot_saved_title" msgid="6461865960961414961">"სკრინშოტი გადაღებულია."</string>
+ <string name="screenshot_saved_text" msgid="1152839647677558815">"შეეხეთ ეკრანის სურათის სანახავად."</string>
+ <string name="screenshot_failed_title" msgid="705781116746922771">"ვერ მოხერხდა ეკრანის ანაბეჭდის გადაღება."</string>
+ <string name="screenshot_failed_text" msgid="8134011269572415402">"ეკრანის სურათი ვერ შეინახა. შესაძლოა, მეხსიერება უკვე დაკავებულია."</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"USB ფაილის ტრანსფერის პარამეტრები"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"მედია-საკრავად (MTP) ჩართვა"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"მიუერთეთ როგორც კამერა (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="2312667578562201583">"Android File Transfer აპის დაყენება Mac-თვის"</string>
+ <string name="accessibility_back" msgid="567011538994429120">"უკან"</string>
+ <string name="accessibility_home" msgid="8217216074895377641">"საწყისი"</string>
+ <string name="accessibility_menu" msgid="316839303324695949">"მენიუ"</string>
+ <string name="accessibility_recent" msgid="8571350598987952883">"ბოლოს გამოყენებული აპები"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"შეყვანის მეთოდის გადართვის ღილაკი."</string>
+ <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"თავსებადი მასშტაბირების ღილაკი."</string>
+ <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"შეცვალეთ პატარა ეკრანი უფრო დიდით."</string>
+ <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Bluetooth დაკავშირებულია."</string>
+ <string name="accessibility_bluetooth_disconnected" msgid="7416648669976870175">"Bluetooth კავშირი გაწყვეტილია."</string>
+ <string name="accessibility_no_battery" msgid="358343022352820946">"ბატარეა დამჯდარია."</string>
+ <string name="accessibility_battery_one_bar" msgid="7774887721891057523">"ბატარეია ერთ ზოლზეა."</string>
+ <string name="accessibility_battery_two_bars" msgid="8500650438735009973">"ელემენტი ორ ზოლზე."</string>
+ <string name="accessibility_battery_three_bars" msgid="2302983330865040446">"ელემენტი სამ ზოლზე."</string>
+ <string name="accessibility_battery_full" msgid="8909122401720158582">"ელემენტი სავსეა."</string>
+ <string name="accessibility_no_phone" msgid="4894708937052611281">"ტელეფონი არ არის."</string>
+ <string name="accessibility_phone_one_bar" msgid="687699278132664115">"ტელეფონის სიგნალი ერთ ზოლზეა."</string>
+ <string name="accessibility_phone_two_bars" msgid="8384905382804815201">"ტელეფონის სიგნალი ორ ზოლზეა."</string>
+ <string name="accessibility_phone_three_bars" msgid="8521904843919971885">"ტელეფონის სიგნალი სამ ზოლზეა."</string>
+ <string name="accessibility_phone_signal_full" msgid="6471834868580757898">"ტელეფონის სიგნალი სრულია."</string>
+ <string name="accessibility_no_data" msgid="4791966295096867555">"მონაცემები არ არის."</string>
+ <string name="accessibility_data_one_bar" msgid="1415625833238273628">"თარიღი ზოლზე."</string>
+ <string name="accessibility_data_two_bars" msgid="6166018492360432091">"მონაცემების გადაცემა: ორი ზოლი"</string>
+ <string name="accessibility_data_three_bars" msgid="9167670452395038520">"მონაცემების გადაცემა: სამი ზოლი"</string>
+ <string name="accessibility_data_signal_full" msgid="2708384608124519369">"მონაცემთა გადაცემის საიმედო სიგნალი."</string>
+ <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wifi გამორთულია."</string>
+ <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wifi არ არის დაკავშირებული."</string>
+ <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Wifi სიგნალი ერთ ზოლზეა."</string>
+ <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Wifi სიგნალი ორ ზოლზეა."</string>
+ <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Wifi სამი ზოლი."</string>
+ <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Wifi სიგნალი სრულია."</string>
+ <string name="accessibility_no_wimax" msgid="4329180129727630368">"WiMAX არ არის."</string>
+ <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX ერთი სვეტი."</string>
+ <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX-ის ორი ზოლი."</string>
+ <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX-ის სამი ზოლი."</string>
+ <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX სიგნალი სრულია."</string>
+ <string name="accessibility_no_signal" msgid="7064645320782585167">"სიგნალი არ არის."</string>
+ <string name="accessibility_not_connected" msgid="6395326276213402883">"არ არის დაკავშირებული."</string>
+ <string name="accessibility_zero_bars" msgid="3806060224467027887">"სიგნალი ნულ ზოლზეა."</string>
+ <string name="accessibility_one_bar" msgid="1685730113192081895">"ერთი ზოლი."</string>
+ <string name="accessibility_two_bars" msgid="6437363648385206679">"ორი სვეტი."</string>
+ <string name="accessibility_three_bars" msgid="2648241415119396648">"სამი ზოლი."</string>
+ <string name="accessibility_signal_full" msgid="9122922886519676839">"სრული სიგნალი."</string>
+ <string name="accessibility_desc_on" msgid="2385254693624345265">"ჩართული"</string>
+ <string name="accessibility_desc_off" msgid="6475508157786853157">"გამორთულია."</string>
+ <string name="accessibility_desc_connected" msgid="8366256693719499665">"დაკავშირებულია."</string>
+ <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+ <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+ <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
+ <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
+ <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5გბ"</string>
+ <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
+ <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+ <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"როუმინგი"</string>
+ <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
+ <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
+ <string name="accessibility_no_sim" msgid="8274017118472455155">"SIM არ არის."</string>
+ <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth-ის ჩართვა"</string>
+ <string name="accessibility_airplane_mode" msgid="834748999790763092">"თვითმფრინავის რეჟიმი"</string>
+ <string name="accessibility_battery_level" msgid="7451474187113371965">"ბატარეა: <xliff:g id="NUMBER">%d</xliff:g> პროცენტი."</string>
+ <string name="accessibility_settings_button" msgid="799583911231893380">"სისტემის პარამეტრები."</string>
+ <string name="accessibility_notifications_button" msgid="4498000369779421892">"შეტყობინებები"</string>
+ <string name="accessibility_remove_notification" msgid="3603099514902182350">"შეტყობინებების გასუფთავება."</string>
+ <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS გააქტიურდა."</string>
+ <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS-ის დადგენა."</string>
+ <string name="accessibility_tty_enabled" msgid="4613200365379426561">"ტელეტაიპი ჩართულია."</string>
+ <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"ვიბრაციის რეჟიმი."</string>
+ <string name="accessibility_ringer_silent" msgid="9061243307939135383">"უხმო რეჟიმი."</string>
+ <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> ამოშლილია სიიდან."</string>
+ <string name="accessibility_notification_dismissed" msgid="854211387186306927">"შეტყობინება წაიშალა."</string>
+ <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"შეტყობინებების ფარდა"</string>
+ <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"სწრაფი პარამეტრები"</string>
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"ბოლო აპები."</string>
+ <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"მომხმარებელი: <xliff:g id="USER">%s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+ <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"მობილურის <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"ელემენტი: <xliff:g id="STATE">%s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"თვითმფრინავის რეჟიმი <xliff:g id="STATE">%s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"მაღვიძარა დაყენებულია: <xliff:g id="TIME">%s</xliff:g>"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G ინტერნეტი გაითიშა."</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G მონაცემები გათიშულია"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"მობილური ინტერნეტი გაითიშა."</string>
+ <string name="data_usage_disabled_dialog_title" msgid="2086815304858964954">"ინტერნეტი გაითიშა."</string>
+ <string name="data_usage_disabled_dialog" msgid="3853117269051806280">"თქვენ მიაღწიეთ ინტერნეტის გამოყენების განსაზღვრულ ლიმიტს.\n\nთუ გააქტიურებთ ინტერნეტს, შესაძლოა მობილური ოპერატორისთვის დამატებითი თანხის გადახდა მოგიწიოთ."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="7729772039208664606">"მონაცემების ხელახლა ჩართვა"</string>
+ <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"ინტერნეტ კავშირი არ არის"</string>
+ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi დაკავშირებულია"</string>
+ <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS-ის ძებნა"</string>
+ <string name="gps_notification_found_text" msgid="4619274244146446464">"GPS-ით დადგენილი მდებარეობა"</string>
+ <string name="accessibility_location_active" msgid="2427290146138169014">"მდებარეობის მოთხოვნები აქტიურია"</string>
+ <string name="accessibility_clear_all" msgid="5235938559247164925">"ყველა შეტყობინების წაშლა"</string>
+ <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"აპის შესახებ"</string>
+ <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"ეკრანი შეტრიალდება ავტომატურად."</string>
+ <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"ეკრანი დაბლოკილია თარაზულ ორიენტაციაში"</string>
+ <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"ეკრანი დაბლოკილია პორტრეტის ორიენტაციაში."</string>
+ <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+ <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
+ <string name="ethernet_label" msgid="7967563676324087464">"ეთერნეტი"</string>
+ <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"თვითმფრინავის რეჟიმი"</string>
+ <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"დამუხტვა, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+ <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"დამუხტულია"</string>
+ <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+ <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> მოწყობილობა)"</string>
+ <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth გამორთულია"</string>
+ <string name="quick_settings_brightness_label" msgid="6968372297018755815">"სიკაშკაშე"</string>
+ <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"ავტოროტაცია"</string>
+ <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"როტაციის ჩაკეტვა"</string>
+ <string name="quick_settings_ime_label" msgid="7073463064369468429">"შეყვანის მეთოდი"</string>
+ <string name="quick_settings_location_label" msgid="5011327048748762257">"მდებარეობა"</string>
+ <string name="quick_settings_location_off_label" msgid="7464544086507331459">"მდებარეობა გამორთულია"</string>
+ <string name="quick_settings_media_device_label" msgid="1302906836372603762">"მედია მოწყობილობა"</string>
+ <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+ <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"მხოლოდ გადაუდებელი დახმარების ზარებისთვის"</string>
+ <string name="quick_settings_settings_label" msgid="5326556592578065401">"პარამეტრები"</string>
+ <string name="quick_settings_time_label" msgid="4635969182239736408">"დრო"</string>
+ <string name="quick_settings_user_label" msgid="5238995632130897840">"მე"</string>
+ <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"არ არის დაკავშირებული."</string>
+ <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"ქსელი არ არის"</string>
+ <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi გამორთულია"</string>
+ <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi ეკრანი"</string>
+ <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"უსადენო ეკრანი"</string>
+ <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"განათება"</string>
+ <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"ავტომატურად"</string>
+ <string name="status_bar_help_title" msgid="1199237744086469217">"შეტყობინებები აქ გამოჩნდება"</string>
+ <string name="status_bar_help_text" msgid="7874607155052076323">"მათზე წვდომისათვის, ნებისმიერ დროს გადაფურცლეთ ქვემოთ.\nსისტემის კონტროლისთვისაც გადაფურცლეთ ქვემოთ."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
new file mode 100644
index 0000000..f972925
--- /dev/null
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="7164937344850004466">"ចំណុច​ប្រទាក់​ប្រព័ន្ធ"</string>
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"សម្អាត"</string>
+ <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"យក​ចេញ​ពី​បញ្ជី"</string>
+ <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"ព័ត៌មាន​កម្មវិធី"</string>
+ <string name="status_bar_no_recent_apps" msgid="6576392951053994640">"គ្មាន​កម្មវិធី​ថ្មីៗ"</string>
+ <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"បដិសេធ​កម្មវិធី​ថ្មីៗ"</string>
+ <plurals name="status_bar_accessibility_recent_apps">
+ <item quantity="one" msgid="5854176083865845541">"កម្មវិធី​ថ្មី ១"</item>
+ <item quantity="other" msgid="1040784359794890744">"កម្មវិធី​ថ្មីៗ %d"</item>
+ </plurals>
+ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"គ្មាន​ការ​ជូន​ដំណឹង"</string>
+ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"បន្ត"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"ការ​ជូន​ដំណឹង"</string>
+ <string name="battery_low_title" msgid="2783104807551211639">"ភ្ជាប់​ឧបករណ៍​បញ្ចូល​ថ្ម"</string>
+ <string name="battery_low_subtitle" msgid="1752040062087829196">"ជិត​អស់​ថ្ម​ហើយ។"</string>
+ <string name="battery_low_percent_format" msgid="1077244949318261761">"នៅ​សល់ <xliff:g id="NUMBER">%d%%</xliff:g>"</string>
+ <string name="invalid_charger" msgid="4549105996740522523">"មិន​គាំទ្រ​ការ​បញ្ចូល​តាម​យូអេសប៊ី។\nប្រើ​តែ​ឧបករណ៍​បញ្ចូល​ថ្ម​ដែល​បាន​ផ្ដល់។"</string>
+ <string name="battery_low_why" msgid="7279169609518386372">"ការ​ប្រើ​ថ្ម"</string>
+ <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"ការ​កំណត់"</string>
+ <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"វ៉ាយហ្វាយ"</string>
+ <string name="status_bar_settings_airplane" msgid="4879879698500955300">"ពេល​ជិះ​យន្តហោះ"</string>
+ <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"បង្វិល​អេក្រង់​ស្វ័យ​ប្រវត្តិ"</string>
+ <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ស្ងាត់"</string>
+ <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"ស្វ័យប្រវត្តិ"</string>
+ <string name="status_bar_settings_notifications" msgid="397146176280905137">"ការ​ជូន​ដំណឹង"</string>
+ <string name="bluetooth_tethered" msgid="7094101612161133267">"បាន​ភ្ជាប់​ប៊្លូធូស"</string>
+ <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"រៀបចំ​វិធីសាស្ត្រ​បញ្ចូល"</string>
+ <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"ក្ដារ​ចុច​ពិតប្រាកដ"</string>
+ <string name="usb_device_permission_prompt" msgid="834698001271562057">"ឲ្យ​កម្មវិធី <xliff:g id="APPLICATION">%1$s</xliff:g> ចូល​ដំណើរការ​ឧបករណ៍​យូអេសប៊ី?"</string>
+ <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"ឲ្យ​កម្មវិធី <xliff:g id="APPLICATION">%1$s</xliff:g> ចូល​ដំណើរការ​ឧបករណ៍​យូអេសប៊ី?"</string>
+ <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"បើក <xliff:g id="ACTIVITY">%1$s</xliff:g> ពេល​បាន​ភ្ជាប់​ឧបករណ៍​យូអេសប៊ី​នេះ?"</string>
+ <string name="usb_accessory_confirm_prompt" msgid="3808984931830229888">"បើក <xliff:g id="ACTIVITY">%1$s</xliff:g> ពេល​បាន​ភ្ជាប់​ឧបករណ៍​យូអេសប៊ី?"</string>
+ <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"គ្មាន​កម្មវិធី​បាន​ដំឡើង​ដំណើរការ​ជា​មួយ​ឧបករណ៍​យូអេសប៊ី។ ស្វែងយល់​បន្ថែម​អំពី​ឧបករណ៍​នេះ​នៅ <xliff:g id="URL">%1$s</xliff:g>"</string>
+ <string name="title_usb_accessory" msgid="4966265263465181372">"ឧបករណ៍​យូអេសប៊ី"</string>
+ <string name="label_view" msgid="6304565553218192990">"មើល"</string>
+ <string name="always_use_device" msgid="1450287437017315906">"ប្រើ​តាម​លំនាំដើម​សម្រាប់​ឧបករណ៍​យូអេសប៊ី​នេះ"</string>
+ <string name="always_use_accessory" msgid="1210954576979621596">"ប្រើ​តាម​លំនាំដើម​សម្រាប់​ខ្សែ​យូអេសប៊ី​នេះ"</string>
+ <string name="usb_debugging_title" msgid="4513918393387141949">"អនុញ្ញាត​ការ​កែ​កំហុស​យូអេសប៊ី?"</string>
+ <string name="usb_debugging_message" msgid="2220143855912376496">"ស្នាម​ម្រាម​ដៃ​ RSA របស់​កុំព្យូទ័រ​គឺ៖ \n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+ <string name="usb_debugging_always" msgid="303335496705863070">"អនុញ្ញាត​ជា​និច្ច​សម្រាប់​កុំព្យូទ័រ​នេះ"</string>
+ <string name="compat_mode_on" msgid="6623839244840638213">"ពង្រីក​​ដើម្បី​ឲ្យ​ពេញ​អេក្រង់"</string>
+ <string name="compat_mode_off" msgid="4434467572461327898">"ទាញ​ដើម្បី​ឲ្យ​ពេញ​អេក្រង់"</string>
+ <string name="compat_mode_help_header" msgid="7969493989397529910">"ការ​ពង្រីក​ត្រូវ​គ្នា"</string>
+ <string name="compat_mode_help_body" msgid="4946726776359270040">"ពេល​កម្មវិធី​ត្រូវ​បាន​រៀបចំ​សម្រាប់​អេក្រង់​តូច ការ​គ្រប់គ្រង​ការ​ពង្រីក​នឹង​បង្ហាញ​តាម​នាឡិកា។"</string>
+ <string name="screenshot_saving_ticker" msgid="7403652894056693515">"កំពុង​រក្សាទុក​រូបថត​អេក្រង់…"</string>
+ <string name="screenshot_saving_title" msgid="8242282144535555697">"កំពុង​រក្សាទុក​រូបថត​អេក្រង់..."</string>
+ <string name="screenshot_saving_text" msgid="2419718443411738818">"រូបថត​អេក្រង់​កំពុង​ត្រូវ​បាន​រក្សាទុក។"</string>
+ <string name="screenshot_saved_title" msgid="6461865960961414961">"បាន​ចាប់​យក​រូបថត​អេក្រង់។"</string>
+ <string name="screenshot_saved_text" msgid="1152839647677558815">"ប៉ះ ​ដើម្បី​មើល​រូបថត​អេក្រង់​របស់​អ្នក​។"</string>
+ <string name="screenshot_failed_title" msgid="705781116746922771">"មិន​អាច​ចាប់​យក​រូប​ថត​អេក្រង់​។"</string>
+ <string name="screenshot_failed_text" msgid="8134011269572415402">"មិន​អាច​រក្សាទុក​រូបថត​អេក្រង់​។ ឧបករណ៍​ផ្ទុក​អាច​កំពុង​ប្រើ​​។"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"ជម្រើស​ផ្ទេរ​ឯកសារ​តាម​យូអេសប៊ី"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"ភ្ជាប់​ជា​កម្មវិធី​ចាក់​មេឌៀ (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"ភ្ជាប់​ជា​ម៉ាស៊ីន​ថត (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="2312667578562201583">"ដំឡើង​កម្មវិធី​ផ្ទេរ​ឯកសារ Android សម្រាប់ Mac"</string>
+ <string name="accessibility_back" msgid="567011538994429120">"ថយក្រោយ"</string>
+ <string name="accessibility_home" msgid="8217216074895377641">"គេហ​ទំព័រ"</string>
+ <string name="accessibility_menu" msgid="316839303324695949">"ម៉ឺនុយ"</string>
+ <string name="accessibility_recent" msgid="8571350598987952883">"កម្មវិធី​ថ្មីៗ"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ប្ដូរ​ប៊ូតុង​វិធីសាស្ត្រ​បញ្ចូល។"</string>
+ <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"ប៊ូតុង​ពង្រីក​ត្រូវ​គ្នា។"</string>
+ <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ពង្រីក/បង្រួម​​អេក្រង់​ពី​​ទៅធំ"</string>
+ <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"បាន​តភ្ជាប់​ប៊្លូធូស។"</string>
+ <string name="accessibility_bluetooth_disconnected" msgid="7416648669976870175">"បាន​ផ្ដាច់​​ប៊្លូធូស។"</string>
+ <string name="accessibility_no_battery" msgid="358343022352820946">"គ្មាន​ថ្ម។"</string>
+ <string name="accessibility_battery_one_bar" msgid="7774887721891057523">"ថ្ម​មួយ​កាំ។"</string>
+ <string name="accessibility_battery_two_bars" msgid="8500650438735009973">"ថ្ម​ពីរ​កាំ។"</string>
+ <string name="accessibility_battery_three_bars" msgid="2302983330865040446">"ថ្ម​ទាំង​បី​​កាំ​។"</string>
+ <string name="accessibility_battery_full" msgid="8909122401720158582">"ថ្ម​ពេញ​ហើយ។"</string>
+ <string name="accessibility_no_phone" msgid="4894708937052611281">"គ្មាន​ទូរស័ព្ទ។"</string>
+ <string name="accessibility_phone_one_bar" msgid="687699278132664115">"សេវា​ទូរស័ព្ទ​មួយ​កាំ។"</string>
+ <string name="accessibility_phone_two_bars" msgid="8384905382804815201">"សេវា​ទូរស័ព្ទ​ពីរ​កាំ។"</string>
+ <string name="accessibility_phone_three_bars" msgid="8521904843919971885">"សេវា​ទូរស័ព្ទ​បី​កាំ​។"</string>
+ <string name="accessibility_phone_signal_full" msgid="6471834868580757898">"សេវា​ទូរស័ព្ទ​ពេញ។"</string>
+ <string name="accessibility_no_data" msgid="4791966295096867555">"គ្មាន​ទិន្នន័យ​។"</string>
+ <string name="accessibility_data_one_bar" msgid="1415625833238273628">"ទិន្នន័យ​មួយ​​កាំ។"</string>
+ <string name="accessibility_data_two_bars" msgid="6166018492360432091">"ទិន្នន័យ​ពីរ​​កាំ។"</string>
+ <string name="accessibility_data_three_bars" msgid="9167670452395038520">"ទិន្នន័យ​បី​កាំ។"</string>
+ <string name="accessibility_data_signal_full" msgid="2708384608124519369">"សញ្ញា​ទិន្នន័យ​ពេញ។"</string>
+ <string name="accessibility_wifi_off" msgid="3177380296697933627">"បិទ​វ៉ាយហ្វាយ។"</string>
+ <string name="accessibility_no_wifi" msgid="1425476551827924474">"បាន​ផ្ដាច់​វ៉ាយហ្វាយ។"</string>
+ <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"សញ្ញា​វ៉ាយហ្វាយ​មួយ​កាំ។"</string>
+ <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"សេវា​វ៉ាយហ្វាយ​ពីរ​កាំ។"</string>
+ <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"វ៉ាយហ្វាយ​បី​កាំ។"</string>
+ <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"សញ្ញា​វ៉ាយហ្វាយ​ពេញ។"</string>
+ <string name="accessibility_no_wimax" msgid="4329180129727630368">"គ្មាន WiMAX ។"</string>
+ <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX មួយ​កាំ។"</string>
+ <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX ពីរ​កាំ។"</string>
+ <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX បី​កាំ។"</string>
+ <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"សញ្ញា WiMAX ពេញ។"</string>
+ <string name="accessibility_no_signal" msgid="7064645320782585167">"គ្មាន​សញ្ញា។"</string>
+ <string name="accessibility_not_connected" msgid="6395326276213402883">"មិន​បាន​តភ្ជាប់​។"</string>
+ <string name="accessibility_zero_bars" msgid="3806060224467027887">"សូន្យ​កាំ។"</string>
+ <string name="accessibility_one_bar" msgid="1685730113192081895">"មួយ​កាំ។"</string>
+ <string name="accessibility_two_bars" msgid="6437363648385206679">"ពីរ​កាំ។"</string>
+ <string name="accessibility_three_bars" msgid="2648241415119396648">"បី​កាំ។"</string>
+ <string name="accessibility_signal_full" msgid="9122922886519676839">"សញ្ញា​ពេញ​​។"</string>
+ <string name="accessibility_desc_on" msgid="2385254693624345265">"បើក។"</string>
+ <string name="accessibility_desc_off" msgid="6475508157786853157">"បិទ"</string>
+ <string name="accessibility_desc_connected" msgid="8366256693719499665">"បាន​តភ្ជាប់។"</string>
+ <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+ <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+ <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
+ <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
+ <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
+ <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
+ <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+ <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"រ៉ូ​មីង"</string>
+ <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
+ <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"វ៉ាយហ្វាយ"</string>
+ <string name="accessibility_no_sim" msgid="8274017118472455155">"គ្មាន​ស៊ីម​កាត។"</string>
+ <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"ការ​ភ្ជាប់​ប៊្លូធូស។"</string>
+ <string name="accessibility_airplane_mode" msgid="834748999790763092">"របៀប​​ជិះ​យន្តហោះ"</string>
+ <string name="accessibility_battery_level" msgid="7451474187113371965">"ថ្ម <xliff:g id="NUMBER">%d</xliff:g> ភាគរយ។"</string>
+ <string name="accessibility_settings_button" msgid="799583911231893380">"ការ​កំណត់​ប្រព័ន្ធ​។"</string>
+ <string name="accessibility_notifications_button" msgid="4498000369779421892">"ការ​ជូន​ដំណឹង។"</string>
+ <string name="accessibility_remove_notification" msgid="3603099514902182350">"សម្អាត​ការ​ជូន​ដំណឹង។"</string>
+ <string name="accessibility_gps_enabled" msgid="3511469499240123019">"បាន​បើក GPS ។"</string>
+ <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"ទទួល​​ GPS ។"</string>
+ <string name="accessibility_tty_enabled" msgid="4613200365379426561">"បាន​បើក​ម៉ាស៊ីន​អង្គុលីលេខ"</string>
+ <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"កម្មវិធី​រោទ៍​ញ័រ។"</string>
+ <string name="accessibility_ringer_silent" msgid="9061243307939135383">"កម្មវិធី​រោទ៍​ស្ងាត់។"</string>
+ <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> បដិសេធ។"</string>
+ <string name="accessibility_notification_dismissed" msgid="854211387186306927">"បាន​បដិសេធ​ការ​ជូនដំណឹង"</string>
+ <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"ពណ៌​ការ​ជូន​ដំណឹង"</string>
+ <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"ការ​កំណត់​រហ័ស។"</string>
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"កម្មវិធី​ថ្មី​ៗ។"</string>
+ <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"អ្នក​ប្រើ <xliff:g id="USER">%s</xliff:g> ។"</string>
+ <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+ <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"ចល័ត <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"ថ្ម <xliff:g id="STATE">%s</xliff:g> ។"</string>
+ <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"របៀប​ជិះ​យន្ត​ហោះ <xliff:g id="STATE">%s</xliff:g> ។"</string>
+ <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"ប៊្លូធូស <xliff:g id="STATE">%s</xliff:g> ។"</string>
+ <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"កំណត់​សំឡេង​រោទ៍​សម្រាប់ <xliff:g id="TIME">%s</xliff:g> ។"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"បាន​បិទ​ទិន្នន័យ 2G-3G"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"បាន​បិទ​ទិន្នន័យ 4G"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"បាន​បិទ​ទិន្នន័យ​ចល័ត"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="2086815304858964954">"បាន​បិទ​ទិន្នន័យ"</string>
+ <string name="data_usage_disabled_dialog" msgid="3853117269051806280">"អ្នក​បាន​ដល់​ដែន​កំណត់​ប្រើ​ទិន្នន័យ​បាន​បញ្ជាក់។\n\nបើ​អ្នក​បើក​ទិន្នន័យ​ឡើងវិញ អ្នក​អាច​ត្រូវ​បាន​ប្ដូរ​ដោយ​ប្រតិបត្តិ​ករ។"</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="7729772039208664606">"បើក​​ទិន្នន័យ​ឡើងវិញ"</string>
+ <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"គ្មាន​ការ​តភ្ជាប់​អ៊ីនធឺណិត"</string>
+ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"បាន​ភ្ជាប់​វ៉ាយហ្វាយ"</string>
+ <string name="gps_notification_searching_text" msgid="8574247005642736060">"ស្វែងរក GPS"</string>
+ <string name="gps_notification_found_text" msgid="4619274244146446464">"ទីតាំង​​​​​កំណត់​ដោយ GPS"</string>
+ <string name="accessibility_location_active" msgid="2427290146138169014">"សំណើ​ទីតាំង​សកម្ម"</string>
+ <string name="accessibility_clear_all" msgid="5235938559247164925">"សម្អាត​ការ​ជូន​ដំណឹង​ទាំងអស់។"</string>
+ <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"ព័ត៌មាន​កម្មវិធី"</string>
+ <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"នឹង​បង្វិល​អេក្រង់​ស្វ័យ​ប្រវត្តិ។"</string>
+ <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"អេក្រង់​ជាប់​សោ​ក្នុង​ទិស​ផ្ដេក។"</string>
+ <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"បា​ន​ចាក់​សោ​អេក្រង់​​ក្នុង​ទិស​បញ្ឈរ។"</string>
+ <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+ <string name="start_dreams" msgid="7219575858348719790">"ស្រមើ​ស្រមៃ"</string>
+ <string name="ethernet_label" msgid="7967563676324087464">"អ៊ីសឺរណិត"</string>
+ <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"របៀប​​ជិះ​យន្តហោះ"</string>
+ <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"បញ្ចូល​ថ្ម <xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
+ <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"បាន​បញ្ចូល​ពេញ"</string>
+ <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"ប៊្លូធូស"</string>
+ <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ប៊្លូធូស (ឧបករណ៍ <xliff:g id="NUMBER">%d</xliff:g>)"</string>
+ <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"បិទ​ប៊្លូធូស"</string>
+ <string name="quick_settings_brightness_label" msgid="6968372297018755815">"ពន្លឺ"</string>
+ <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"បង្វិល​​ស្វ័យ​ប្រវត្តិ"</string>
+ <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"បាន​ចាក់​សោ​ការ​បង្វិល"</string>
+ <string name="quick_settings_ime_label" msgid="7073463064369468429">"វិធីសាស្ត្រ​បញ្ចូល"</string>
+ <string name="quick_settings_location_label" msgid="5011327048748762257">"ទី​តាំង"</string>
+ <string name="quick_settings_location_off_label" msgid="7464544086507331459">"ទីតាំង​បិទ"</string>
+ <string name="quick_settings_media_device_label" msgid="1302906836372603762">"ឧបករណ៍​មេឌៀ"</string>
+ <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+ <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"សម្រាប់​តែ​ការ​ហៅ​ពេល​អាសន្ន"</string>
+ <string name="quick_settings_settings_label" msgid="5326556592578065401">"ការ​កំណត់"</string>
+ <string name="quick_settings_time_label" msgid="4635969182239736408">"ពេលវេលា"</string>
+ <string name="quick_settings_user_label" msgid="5238995632130897840">"ខ្ញុំ"</string>
+ <string name="quick_settings_wifi_label" msgid="9135344704899546041">"វ៉ាយហ្វាយ"</string>
+ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"មិន​បាន​តភ្ជាប់"</string>
+ <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"គ្មាន​បណ្ដាញ"</string>
+ <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"បិទ​វ៉ាយហ្វាយ"</string>
+ <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"បង្ហា​ញ​វ៉ាយហ្វាយ"</string>
+ <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"​បង្ហាញ​បណ្ដាញ​ឥត​ខ្សែ"</string>
+ <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"ពន្លឺ"</string>
+ <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"ស្វ័យប្រវត្តិ"</string>
+ <string name="status_bar_help_title" msgid="1199237744086469217">"ការ​ជូន​ដំណឹង​​បង្ហាញ​​នៅ​ទីនេះ"</string>
+ <string name="status_bar_help_text" msgid="7874607155052076323">"ចូល​ដំណើរការ​ពួក​វា​ពេល​ណា​មួយ​ដោយ​អូស​ចុះក្រោម។\nអូស​ចុះក្រោម​ម្ដង​ទៀត​ ដើម្បី​ពិនិត្យ​ប្រព័ន្ធ។"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 403c94b..6319184 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -164,8 +164,7 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi 연결됨"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS 검색 중"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS에서 위치 설정"</string>
- <!-- no translation found for accessibility_location_active (2427290146138169014) -->
- <skip />
+ <string name="accessibility_location_active" msgid="2427290146138169014">"위치 요청 있음"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"모든 알림 지우기"</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"앱 정보"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"화면이 자동으로 회전됩니다."</string>
@@ -202,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"자동"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"알림이 여기에 표시됨"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"아래로 스와이프하여 언제든 액세스하세요.\n한 번 더 아래로 스와이프하면 시스템 관리로 이동합니다."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"화면 가장자리에서 스와이프하여 표시줄 표시"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"화면 가장자리에서 스와이프하여 시스템 표시줄 표시"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
new file mode 100644
index 0000000..85b10f7
--- /dev/null
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="7164937344850004466">"ສ່ວນຕິດຕໍ່ຜູ່ໃຊ້ຂອງລະບົບ"</string>
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"ລຶບ"</string>
+ <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"ເອົາອອກຈາກລາຍການ"</string>
+ <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"ຂໍ້ມູນແອັບຯ"</string>
+ <string name="status_bar_no_recent_apps" msgid="6576392951053994640">"ບໍ່ມີແອັບຯທີ່ຫາກໍໃຊ້"</string>
+ <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"ປິດແອັບຯຫຼ້າສຸດທີ່ໃຊ້"</string>
+ <plurals name="status_bar_accessibility_recent_apps">
+ <item quantity="one" msgid="5854176083865845541">"1 ແອັບຯຫຼ້າສຸດ"</item>
+ <item quantity="other" msgid="1040784359794890744">"%d ແອັບຯຫຼ້າສຸດ"</item>
+ </plurals>
+ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"ບໍ່ມີການແຈ້ງເຕືອນ"</string>
+ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"ດຳເນີນຢູ່"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"ການແຈ້ງເຕືອນ"</string>
+ <string name="battery_low_title" msgid="2783104807551211639">"ເຊື່ອມຕໍ່ສາຍສາກ"</string>
+ <string name="battery_low_subtitle" msgid="1752040062087829196">"ແບັດເຕີຣີເຫຼືອໜ້ອຍແລ້ວ."</string>
+ <string name="battery_low_percent_format" msgid="1077244949318261761">"ຍັງເຫຼືອອີກ <xliff:g id="NUMBER">%d%%</xliff:g>"</string>
+ <string name="invalid_charger" msgid="4549105996740522523">"ບໍ່ຮອງຮັບການສາກໄຟດ້ວຍ USB.\nຕ້ອງໃຊ້ສະເພາະເຄື່ອງສາກທີ່ແຖມມານຳເທົ່ານັ້ນ."</string>
+ <string name="battery_low_why" msgid="7279169609518386372">"ການນຳໃຊ້ແບັດເຕີຣີ"</string>
+ <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"ການຕັ້ງຄ່າ"</string>
+ <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
+ <string name="status_bar_settings_airplane" msgid="4879879698500955300">"ໂໝດເທິງຍົນ"</string>
+ <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"ໝຸນໜ້າຈໍອັດຕະໂນມັດ"</string>
+ <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ປິດສຽງ"</string>
+ <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"ອັດຕະໂນມັດ"</string>
+ <string name="status_bar_settings_notifications" msgid="397146176280905137">"ການແຈ້ງເຕືອນ"</string>
+ <string name="bluetooth_tethered" msgid="7094101612161133267">"ປ່ອຍສັນຍານຜ່ານ Bluetooth ແລ້ວ"</string>
+ <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"ຕັ້ງຄ່າວິທີການປ້ອນຂໍ້ມູນ"</string>
+ <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"ແປ້ນພິມແທ້"</string>
+ <string name="usb_device_permission_prompt" msgid="834698001271562057">"ອະນຸຍາດໃຫ້ແອັບຯ <xliff:g id="APPLICATION">%1$s</xliff:g> ເຂົ້າເຖິງອຸປະກອນ USB?"</string>
+ <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"ອະນຸຍາດໃຫ້ແອັບຯ <xliff:g id="APPLICATION">%1$s</xliff:g> ເຂົ້າເຖິງອຸປະກອນພ່ວງ USB?"</string>
+ <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"ເປີດ <xliff:g id="ACTIVITY">%1$s</xliff:g> ເມື່ອເຊື່ອມຕໍ່ກັບອຸປະກອນ USB ນີ້ຫຼືບໍ່?"</string>
+ <string name="usb_accessory_confirm_prompt" msgid="3808984931830229888">"ເປີດ <xliff:g id="ACTIVITY">%1$s</xliff:g> ເມື່ອມີການເຊື່ອມຕໍ່ກັບອຸປະກອນເສີມ USB ນີ້ຫຼືບໍ່?"</string>
+ <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"ບໍ່ມີແອັບຯໃດທີ່ຕິດຕັ້ງໄປແລ້ວ ສາມາດເຮັດວຽກຮ່ວມກັບອຸປະກອນເສີມ USB ນີ້ໄດ້. ສຶກສາເພີ່ມເຕີມກ່ຽວກັບອຸປະກອນເສີມນີ້ທີ່ <xliff:g id="URL">%1$s</xliff:g>"</string>
+ <string name="title_usb_accessory" msgid="4966265263465181372">"ອຸປະກອນເສີມ USB"</string>
+ <string name="label_view" msgid="6304565553218192990">"ເບິ່ງ"</string>
+ <string name="always_use_device" msgid="1450287437017315906">"ໃຊ້ເປັນຄ່າເລີ່ມຕົ້ນສຳລັບອຸປະກອນ USB ນີ້"</string>
+ <string name="always_use_accessory" msgid="1210954576979621596">"ໃຊ້ຄ່າເລີ່ມຕົ້ນສຳລັບອຸປະກອນເສີມ USB ນີ້."</string>
+ <string name="usb_debugging_title" msgid="4513918393387141949">"ອະນຸຍາດການດີບັ໊ກຜ່ານ USB?"</string>
+ <string name="usb_debugging_message" msgid="2220143855912376496">"ລາຍນິ້ມື RSA ຂອງຄອມພິວເຕີແມ່ນ:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+ <string name="usb_debugging_always" msgid="303335496705863070">"ອະນຸຍາດຈາກຄອມພິວເຕີນີ້ຕະຫຼອດ"</string>
+ <string name="compat_mode_on" msgid="6623839244840638213">"ຊູມໃຫ້ເຕັມໜ້າຈໍ"</string>
+ <string name="compat_mode_off" msgid="4434467572461327898">"ປັບໃຫ້ເຕັມໜ້າຈໍ"</string>
+ <string name="compat_mode_help_header" msgid="7969493989397529910">"ຄວາມເຂົ້າກັນໄດ້ຂອງການຊູມ"</string>
+ <string name="compat_mode_help_body" msgid="4946726776359270040">"ເມື່ອແອັບຯຖືກອອກແບບມາສຳລັບໜ້າຈໍນ້ອຍກວ່າ​, ຕົວຄວບຄຸມການຊູມຈະປາກົດຢູ່ໃກ້ກັບໂມງ."</string>
+ <string name="screenshot_saving_ticker" msgid="7403652894056693515">"ກຳລັງບັນທຶກຮູບໜ້າຈໍ"</string>
+ <string name="screenshot_saving_title" msgid="8242282144535555697">"ກຳລັງບັນທຶກພາບໜ້າຈໍ..."</string>
+ <string name="screenshot_saving_text" msgid="2419718443411738818">"ກຳລັງບັນທຶກພາບໜ້າຈໍ."</string>
+ <string name="screenshot_saved_title" msgid="6461865960961414961">"ຖ່າຍຮູບໜ້າຈໍແລ້ວ"</string>
+ <string name="screenshot_saved_text" msgid="1152839647677558815">"ແຕະເພື່ອເບິ່ງພາບໜ້າຈໍຂອງທ່ານ."</string>
+ <string name="screenshot_failed_title" msgid="705781116746922771">"ບໍ່ສາມາດຖ່າຍຮູບໜ້າຈໍໄດ້"</string>
+ <string name="screenshot_failed_text" msgid="8134011269572415402">"ບໍ່ສາມາດບັນທຶກພາບໜ້າຈໍໄດ້. ບ່ອນຈັດເກັບອາດກຳລັງຖືກນຳໃຊ້ຢູ່."</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"USB ໂຕເລືອກການຍ້າຍໄຟລ໌"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"ເຊື່ອມຕໍ່ເປັນ media player (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"ເຊື່ອມຕໍ່ເປັນກ້ອງຖ່າຍຮູບ (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="2312667578562201583">"ຕິດຕັ້ງແອັບຯ Android File Transfer ສຳລັບ Mac"</string>
+ <string name="accessibility_back" msgid="567011538994429120">"ກັບຄືນ"</string>
+ <string name="accessibility_home" msgid="8217216074895377641">"ໜ້າທຳອິດ"</string>
+ <string name="accessibility_menu" msgid="316839303324695949">"ເມນູ"</string>
+ <string name="accessibility_recent" msgid="8571350598987952883">"ແອັບຯຫຼ້າສຸດ"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ປຸ່ມສະລັບຮູບແບບການປ້ອນຂໍ້ມູນ."</string>
+ <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"ປຸ່ມຊູມທີ່ໃຊ້ຮ່ວມກັນໄດ້."</string>
+ <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"ຊູມຈໍນ້ອຍໄປເປັນຈໍຂະຫນາດໃຫຍ່."</string>
+ <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ເຊື່ອມຕໍ່ Bluetooth ແລ້ວ."</string>
+ <string name="accessibility_bluetooth_disconnected" msgid="7416648669976870175">"Bluetooth ຖືກຕັດການເຊື່ອມຕໍ່ແລ້ວ."</string>
+ <string name="accessibility_no_battery" msgid="358343022352820946">"ແບັດເຕີຣີໝົດ."</string>
+ <string name="accessibility_battery_one_bar" msgid="7774887721891057523">"ແບັດເຕີຣີນຶ່ງຂີດ."</string>
+ <string name="accessibility_battery_two_bars" msgid="8500650438735009973">"ແບັດເຕີຣີສອງຂີດ."</string>
+ <string name="accessibility_battery_three_bars" msgid="2302983330865040446">"ແບັດເຕີຣີສາມຂີດ."</string>
+ <string name="accessibility_battery_full" msgid="8909122401720158582">"ແບັດເຕີຣີເຕັມ."</string>
+ <string name="accessibility_no_phone" msgid="4894708937052611281">"ບໍ່ມີໂທລະສັບ."</string>
+ <string name="accessibility_phone_one_bar" msgid="687699278132664115">"ສັນຍານນຶ່ງຂີດ."</string>
+ <string name="accessibility_phone_two_bars" msgid="8384905382804815201">"ສັນຍານສອງຂີດ."</string>
+ <string name="accessibility_phone_three_bars" msgid="8521904843919971885">"ສັນຍານສາມຂີດ."</string>
+ <string name="accessibility_phone_signal_full" msgid="6471834868580757898">"ສັນຍານເຕັມ."</string>
+ <string name="accessibility_no_data" msgid="4791966295096867555">"ບໍ່ມີຂໍ້ມູນ."</string>
+ <string name="accessibility_data_one_bar" msgid="1415625833238273628">"ຂໍ້ມູນນຶ່ງຂີດ."</string>
+ <string name="accessibility_data_two_bars" msgid="6166018492360432091">"ຂໍ້ມູນສອງຂີດ."</string>
+ <string name="accessibility_data_three_bars" msgid="9167670452395038520">"ຂໍ້ມູນສາມຂີດ."</string>
+ <string name="accessibility_data_signal_full" msgid="2708384608124519369">"ສັນ​ຍານຂໍ້ມູນ​ເຕັມ."</string>
+ <string name="accessibility_wifi_off" msgid="3177380296697933627">"WiFi ປິດຢູ່."</string>
+ <string name="accessibility_no_wifi" msgid="1425476551827924474">"ຕັດການເຊື່ອມຕໍ່ Wi-Fi ແລ້ວ."</string>
+ <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"ສັນຍານ Wi-Fi ນຶ່ງຂີດ."</string>
+ <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"ສັນຍານ Wi-Fi ສອງຂີດ."</string>
+ <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Wifi ສາມຂີດ."</string>
+ <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"ສັນຍານ Wi-Fi ເຕັມ"</string>
+ <string name="accessibility_no_wimax" msgid="4329180129727630368">"ບໍ່ມີ WiMAX."</string>
+ <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX ນຶ່ງຂີດ."</string>
+ <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX ສອງຂີດ."</string>
+ <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX ສາມຂີດ."</string>
+ <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"ສັນ​ຍານ WiMAX ເຕັມ."</string>
+ <string name="accessibility_no_signal" msgid="7064645320782585167">"ບໍ່ມີສັນຍານ."</string>
+ <string name="accessibility_not_connected" msgid="6395326276213402883">"ບໍ່ໄດ້ເຊື່ອມຕໍ່."</string>
+ <string name="accessibility_zero_bars" msgid="3806060224467027887">"ບໍ່ມີຈັກຂີດ."</string>
+ <string name="accessibility_one_bar" msgid="1685730113192081895">"ນຶ່ງຂີດ."</string>
+ <string name="accessibility_two_bars" msgid="6437363648385206679">"ສອງຂີດ."</string>
+ <string name="accessibility_three_bars" msgid="2648241415119396648">"ສາມຂີດ."</string>
+ <string name="accessibility_signal_full" msgid="9122922886519676839">"ສັນຍານເຕັມ."</string>
+ <string name="accessibility_desc_on" msgid="2385254693624345265">"ເປີດ."</string>
+ <string name="accessibility_desc_off" msgid="6475508157786853157">"ປິດ."</string>
+ <string name="accessibility_desc_connected" msgid="8366256693719499665">"ເຊື່ອມ​ຕໍ່ແລ້ວ."</string>
+ <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+ <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+ <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
+ <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
+ <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
+ <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
+ <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+ <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"ໂຣມມິງ"</string>
+ <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
+ <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
+ <string name="accessibility_no_sim" msgid="8274017118472455155">"ບໍ່ມີຊິມ."</string>
+ <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"ການປ່ອຍສັນຍານ Bluetooth."</string>
+ <string name="accessibility_airplane_mode" msgid="834748999790763092">"ໂໝດໃນຍົນ."</string>
+ <string name="accessibility_battery_level" msgid="7451474187113371965">"ແບັດເຕີຣີ <xliff:g id="NUMBER">%d</xliff:g> ເປີເຊັນ."</string>
+ <string name="accessibility_settings_button" msgid="799583911231893380">"ການຕັ້ງຄ່າລະບົບ."</string>
+ <string name="accessibility_notifications_button" msgid="4498000369779421892">"ການແຈ້ງເຕືອນ."</string>
+ <string name="accessibility_remove_notification" msgid="3603099514902182350">"ລຶບລ້າງການແຈ້ງເຕືອນ."</string>
+ <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS ເປີດແລ້ວ."</string>
+ <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"ກຳລັງຊອກຫາ GPS."</string>
+ <string name="accessibility_tty_enabled" msgid="4613200365379426561">"TeleTypewriter ຖືກເປີດຢູ່."</string>
+ <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"ສັ່ນເຕືອນພ້ອມສຽງເອີ້ນເຂົ້າ."</string>
+ <string name="accessibility_ringer_silent" msgid="9061243307939135383">"ປິດສຽງ."</string>
+ <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"ປິດ <xliff:g id="APP">%s</xliff:g> ແລ້ວ."</string>
+ <string name="accessibility_notification_dismissed" msgid="854211387186306927">"ປິດການແຈ້ງເຕືອນແລ້ວ."</string>
+ <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"ໜ້າຈໍແຈ້ງເຕືອນ."</string>
+ <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"ການຕັ້ງຄ່າດ່ວນ."</string>
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"ແອັບຯທີ່ຫາກໍໃຊ້."</string>
+ <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"ຜູ່ໃຊ້ <xliff:g id="USER">%s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+ <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"ມືຖື <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"ແບັດເຕີຣີ <xliff:g id="STATE">%s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"ໂໝດໃນຍົນ <xliff:g id="STATE">%s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"ຕັ້ງໂມງປຸກ <xliff:g id="TIME">%s</xliff:g> ແລ້ວ."</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"ອິນເຕີເນັດ 2G​, 3G ຖືກປິດແລ້ວ"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"ການນຳໃຊ້ຂໍ້ມູນ 4G ຖືກປິດແລ້ວ"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"ອິນເຕີເນັດໃນມືຖືຖືກປິດການນຳໃຊ້ແລ້ວ"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="2086815304858964954">"ອິນເຕີເນັດຖືກປິດການນຳໃຊ້ແລ້ວ"</string>
+ <string name="data_usage_disabled_dialog" msgid="3853117269051806280">"ທ່ານໄດ້ໃຊ້ຂໍ້ມູນຈົນຮອດຈຳນວນທີ່ຈຳກັດໄວ້ແລ້ວ.\n\nຫາກທ່ານເປີດນຳໃຊ້ຂໍ້ມູນຄືນອີກຄັ້ງ, ທ່ານອາດຖືກຮຽກເກັບເງິນໂດຍຜູ່ໃຫ້ບໍລິການໄດ້."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="7729772039208664606">"ເປີດນຳໃຊ້ຂໍ້ມູນຄືນໃໝ່"</string>
+ <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"ບໍ່ມີການເຊື່ອມຕໍ່ອິນເຕີເນັດ"</string>
+ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"ເຊື່ອມ​ຕໍ່ Wi-​-Fi ແລ້ວ"</string>
+ <string name="gps_notification_searching_text" msgid="8574247005642736060">"ກຳລັງຊອກຫາ GPS"</string>
+ <string name="gps_notification_found_text" msgid="4619274244146446464">"ສະຖານທີ່ກຳນົດໂດຍ GPS"</string>
+ <string name="accessibility_location_active" msgid="2427290146138169014">"ການຮ້ອງຂໍສະຖານທີ່ທີ່ເຮັດວຽກຢູ່"</string>
+ <string name="accessibility_clear_all" msgid="5235938559247164925">"ລຶບການແຈ້ງເຕືອນທັງໝົດ."</string>
+ <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"ຂໍ້ມູນແອັບຯ"</string>
+ <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"ໜ້າຈໍຈະໝຸນໂດຍອັດຕະໂນມັດ."</string>
+ <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"ໜ້າຈໍຖືກລັອກໃນລວງນອນ."</string>
+ <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"ໜ້າຈໍຖືກລັອກຢູ່ໃນໂໝດແນວຕັ້ງ."</string>
+ <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+ <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
+ <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+ <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"ໂໝດຢູ່ໃນຍົນ"</string>
+ <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"ກຳລັງສາກ, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+ <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"ສາກເຕັມແລ້ວ"</string>
+ <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
+ <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> ອຸປະກອນ)"</string>
+ <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth ປິດ"</string>
+ <string name="quick_settings_brightness_label" msgid="6968372297018755815">"ຄວາມສະຫວ່າງ"</string>
+ <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"ໝຸນໜ້າຈໍອັດຕະໂນມັດ"</string>
+ <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"ລັອກການປ່ຽນລວງ"</string>
+ <string name="quick_settings_ime_label" msgid="7073463064369468429">"ວິທີການປ້ອນຂໍ້ມູນ"</string>
+ <string name="quick_settings_location_label" msgid="5011327048748762257">"ສະຖານທີ່"</string>
+ <string name="quick_settings_location_off_label" msgid="7464544086507331459">"ຂໍ້ມູນສະຖານທີ່ປິດຢູ່"</string>
+ <string name="quick_settings_media_device_label" msgid="1302906836372603762">"ອຸປະກອນສື່"</string>
+ <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+ <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"ໂທສຸກເສີນເທົ່ານັ້ນ"</string>
+ <string name="quick_settings_settings_label" msgid="5326556592578065401">"ການຕັ້ງຄ່າ"</string>
+ <string name="quick_settings_time_label" msgid="4635969182239736408">"ເວລາ"</string>
+ <string name="quick_settings_user_label" msgid="5238995632130897840">"ຂ້ອຍ"</string>
+ <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi​-Fi"</string>
+ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"ບໍ່ໄດ້ເຊື່ອມຕໍ່"</string>
+ <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"ບໍ່ມີເຄືອຂ່າຍ"</string>
+ <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi​-Fi ປິດ"</string>
+ <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"ຈໍສະແດງຜົນ Wi-Fi"</string>
+ <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"ການສະແດງຜົນໄຮ້ສາຍ"</string>
+ <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"ຄວາມແຈ້ງ"</string>
+ <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"ອັດຕະໂນມັດ"</string>
+ <string name="status_bar_help_title" msgid="1199237744086469217">"ການແຈ້ງເຕືອນຈະປາກົດບ່ອນນີ້"</string>
+ <string name="status_bar_help_text" msgid="7874607155052076323">"ເຂົ້າເຖິງໄດ້ທຸກເມື່ອໂດຍການປັດນິ້ວລົງ.\nປັດລົງອີກເທື່ອນຶ່ງສຳລັບການຄວບຄຸມລະບົບ."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 11b67ed..4400d37 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -164,8 +164,7 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Prisij. prie „Wi-Fi“"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Ieškoma GPS"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS nustatyta vieta"</string>
- <!-- no translation found for accessibility_location_active (2427290146138169014) -->
- <skip />
+ <string name="accessibility_location_active" msgid="2427290146138169014">"Vietovės užklausos aktyvios"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Išvalyti visus pranešimus."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Programos informacija"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekranas bus sukamas automatiškai."</string>
@@ -202,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATINIS"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Pranešimai rodomi čia"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Perbraukę žemyn bet kuriuo metu pasieksite pranešimus.\nJei norite naudoti sistemos valdiklius, perbraukite žemyn dar kartą."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Jei norite, kad būtų rodoma juosta, perbraukite ekrano krašte"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Jei norite, kad būtų rodoma sistemos juosta, perbraukite iš ekrano krašto"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 85ab3fd..b2bee8c 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -164,8 +164,7 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Izv. sav. ar Wi-Fi"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Notiek GPS meklēšana..."</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS iestatītā atrašanās vieta"</string>
- <!-- no translation found for accessibility_location_active (2427290146138169014) -->
- <skip />
+ <string name="accessibility_location_active" msgid="2427290146138169014">"Aktīvi atrašanās vietu pieprasījumi"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Notīrīt visus paziņojumus"</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informācija par lietotni"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekrāns tiks pagriezts automātiski."</string>
@@ -202,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMĀTISKI"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Šeit tiek rādīti paziņojumi"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Piekļūstiet tiem jebkurā laikā, velkot uz leju.\nVēlreiz velciet, lai tiktu parādītas sistēmas vadīklas."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Velciet no ekrāna malas, lai piekļūtu joslai."</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Velciet no ekrāna malas, lai piekļūtu sistēmas joslai."</string>
</resources>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
new file mode 100644
index 0000000..f5b45e1
--- /dev/null
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="7164937344850004466">"Систем UI"</string>
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Цэвэрлэх"</string>
+ <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"Жагсаалтаас устгах"</string>
+ <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Апп мэдээлэл"</string>
+ <string name="status_bar_no_recent_apps" msgid="6576392951053994640">"Сүүлийн апп хоосон"</string>
+ <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Сүүлийн апп-уудыг хаах"</string>
+ <plurals name="status_bar_accessibility_recent_apps">
+ <item quantity="one" msgid="5854176083865845541">"1 сүүлийн апп"</item>
+ <item quantity="other" msgid="1040784359794890744">"%d сүүлийн апп"</item>
+ </plurals>
+ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Мэдэгдэл байхгүй"</string>
+ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Гарсан"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Мэдэгдэл"</string>
+ <string name="battery_low_title" msgid="2783104807551211639">"Цэнэглэгчийг холбоно уу"</string>
+ <string name="battery_low_subtitle" msgid="1752040062087829196">"Батерей дуусаж байна."</string>
+ <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> үлдсэн"</string>
+ <string name="invalid_charger" msgid="4549105996740522523">"USB цэнэглэлт дэмжигдэхгүй байна.\nЗөвхөн нийлүүлэгдсэн цэнэглэгчийг ашиглана уу."</string>
+ <string name="battery_low_why" msgid="7279169609518386372">"Батерей ашиглах"</string>
+ <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Тохиргоо"</string>
+ <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
+ <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Нислэгийн горим"</string>
+ <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Дэлгэцийг автоматаар эргүүлэх"</string>
+ <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ХААХ"</string>
+ <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"АВТОМАТ"</string>
+ <string name="status_bar_settings_notifications" msgid="397146176280905137">"Мэдэгдэл"</string>
+ <string name="bluetooth_tethered" msgid="7094101612161133267">"Блютүүтыг модем болгож байна"</string>
+ <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"Оруулах аргыг тохируулах"</string>
+ <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"Бодит гар"</string>
+ <string name="usb_device_permission_prompt" msgid="834698001271562057">"<xliff:g id="APPLICATION">%1$s</xliff:g> апп-г USB төхөөрөмжид хандахыг зөвшөөрөх үү?"</string>
+ <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"<xliff:g id="APPLICATION">%1$s</xliff:g> апп-г USB төхөөрөмжид хандахыг зөвшөөрөх үү?"</string>
+ <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"Энэ USB төхөөрөмж холбогдох үед <xliff:g id="ACTIVITY">%1$s</xliff:g>-г нээх үү?"</string>
+ <string name="usb_accessory_confirm_prompt" msgid="3808984931830229888">"Энэ USB төхөөрөмж холбогдох үед <xliff:g id="ACTIVITY">%1$s</xliff:g>-г нээх үү?"</string>
+ <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"Энэ USB хэрэгсэл дээр суулгасан апп ажиллаагүй байна. Энэ хэрэгслийн талаар <xliff:g id="URL">%1$s</xliff:g>-с дэлгэрэнгүй үзнэ үү."</string>
+ <string name="title_usb_accessory" msgid="4966265263465181372">"USB төхөөрөмж"</string>
+ <string name="label_view" msgid="6304565553218192990">"Үзэх"</string>
+ <string name="always_use_device" msgid="1450287437017315906">"Энэ USB төхөөрөмжийг үндсэн болгон ашиглах"</string>
+ <string name="always_use_accessory" msgid="1210954576979621596">"Энэ USB төхөөрөмжийг үндсэн болгон ашиглах"</string>
+ <string name="usb_debugging_title" msgid="4513918393387141949">"USB дебаг хийхийг зөвшөөрөх үү?"</string>
+ <string name="usb_debugging_message" msgid="2220143855912376496">"Компьютерийн RSA түлхүүрийн хурууны хээ :\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+ <string name="usb_debugging_always" msgid="303335496705863070">"Энэ компьютерээс орохыг байнга зөвшөөрөх"</string>
+ <string name="compat_mode_on" msgid="6623839244840638213">"Дэлгэц дүүргэх бол өсгөнө үү"</string>
+ <string name="compat_mode_off" msgid="4434467572461327898">"Дэлгэц дүүргэх бол татна уу"</string>
+ <string name="compat_mode_help_header" msgid="7969493989397529910">"Зохицсон өсгөлт"</string>
+ <string name="compat_mode_help_body" msgid="4946726776359270040">"Жижиг дэлгэцэнд зориулагдсан апп-н хувьд өсгөх контрол цагаар гарч ирнэ."</string>
+ <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Дэлгэцийн агшинг хадгалж байна…"</string>
+ <string name="screenshot_saving_title" msgid="8242282144535555697">"Дэлгэцийн агшинг хадгалж байна…"</string>
+ <string name="screenshot_saving_text" msgid="2419718443411738818">"Дэлгэцийн агшин хадгалагдав."</string>
+ <string name="screenshot_saved_title" msgid="6461865960961414961">"Дэлгэцийн агшинг авсан."</string>
+ <string name="screenshot_saved_text" msgid="1152839647677558815">"Дэлгэцийн агшныг харах бол хүрнэ үү."</string>
+ <string name="screenshot_failed_title" msgid="705781116746922771">"Дэлгэцийн агшинг авч чадсангүй."</string>
+ <string name="screenshot_failed_text" msgid="8134011269572415402">"Дэлгэцийн агшинг хадгалж чадсангүй. Сан ашиглагдаж байгаа бололтой."</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"USB файл шилжүүлэх сонголт"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"Медиа тоглуулагч(MTP) болгон залгах"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"Камер болгон(PTP) залгах"</string>
+ <string name="installer_cd_button_title" msgid="2312667578562201583">"Мас-д зориулсан Андройд Файл Шилжүүлэх апп-г суулгана уу"</string>
+ <string name="accessibility_back" msgid="567011538994429120">"Буцах"</string>
+ <string name="accessibility_home" msgid="8217216074895377641">"Гэрийн"</string>
+ <string name="accessibility_menu" msgid="316839303324695949">"Цэс"</string>
+ <string name="accessibility_recent" msgid="8571350598987952883">"Сүүлийн апп"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Оруулах аргыг сэлгэх товч."</string>
+ <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"Тохиромжтой өсгөх товч."</string>
+ <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"Жижгээс том дэлгэцрүү өсгөх."</string>
+ <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"Блютүүт холбогдсон."</string>
+ <string name="accessibility_bluetooth_disconnected" msgid="7416648669976870175">"Блютүүт тасрав."</string>
+ <string name="accessibility_no_battery" msgid="358343022352820946">"Батерей байхгүй."</string>
+ <string name="accessibility_battery_one_bar" msgid="7774887721891057523">"Батерей нэг баганатай."</string>
+ <string name="accessibility_battery_two_bars" msgid="8500650438735009973">"Батерей хоёр баганатай."</string>
+ <string name="accessibility_battery_three_bars" msgid="2302983330865040446">"Батерей гурван баганатай."</string>
+ <string name="accessibility_battery_full" msgid="8909122401720158582">"Батерей дүүрэн."</string>
+ <string name="accessibility_no_phone" msgid="4894708937052611281">"Утас байхгүй."</string>
+ <string name="accessibility_phone_one_bar" msgid="687699278132664115">"Утас нэг баганатай."</string>
+ <string name="accessibility_phone_two_bars" msgid="8384905382804815201">"Утас хоёр баганатай."</string>
+ <string name="accessibility_phone_three_bars" msgid="8521904843919971885">"Утас гурван баганатай."</string>
+ <string name="accessibility_phone_signal_full" msgid="6471834868580757898">"Утасны дохио дүүрэн."</string>
+ <string name="accessibility_no_data" msgid="4791966295096867555">"Дата байхгүй."</string>
+ <string name="accessibility_data_one_bar" msgid="1415625833238273628">"Дата нэг баганатай."</string>
+ <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Дата хоёр баганатай."</string>
+ <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Дата гурван баганатай."</string>
+ <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Дата дохио дүүрэн."</string>
+ <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wifi унтарсан."</string>
+ <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wifi салав."</string>
+ <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Wifi нэг баганатай."</string>
+ <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Wifi хоёр баганатай."</string>
+ <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Wifi гурван баганатай."</string>
+ <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Wifi дохио дүүрэн."</string>
+ <string name="accessibility_no_wimax" msgid="4329180129727630368">"WiMAX байхгүй."</string>
+ <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX нэг багана."</string>
+ <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX хоёр баганатай."</string>
+ <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX гурван баганатай."</string>
+ <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX дохио дүүрэн."</string>
+ <string name="accessibility_no_signal" msgid="7064645320782585167">"Дохио байхгүй."</string>
+ <string name="accessibility_not_connected" msgid="6395326276213402883">"Холбогдоогүй."</string>
+ <string name="accessibility_zero_bars" msgid="3806060224467027887">"Тэг баганатай."</string>
+ <string name="accessibility_one_bar" msgid="1685730113192081895">"Нэг баганатай."</string>
+ <string name="accessibility_two_bars" msgid="6437363648385206679">"Хоёр багана."</string>
+ <string name="accessibility_three_bars" msgid="2648241415119396648">"Гурван баганатай."</string>
+ <string name="accessibility_signal_full" msgid="9122922886519676839">"Дохио дүүрэн."</string>
+ <string name="accessibility_desc_on" msgid="2385254693624345265">"Идэвхижсэн."</string>
+ <string name="accessibility_desc_off" msgid="6475508157786853157">"Унтраах"</string>
+ <string name="accessibility_desc_connected" msgid="8366256693719499665">"Холбогдсон."</string>
+ <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+ <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+ <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
+ <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
+ <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
+ <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
+ <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+ <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Рүүминг"</string>
+ <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
+ <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
+ <string name="accessibility_no_sim" msgid="8274017118472455155">"SIM байхгүй."</string>
+ <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Блютүүт модем болж байна."</string>
+ <string name="accessibility_airplane_mode" msgid="834748999790763092">"Нислэгийн горим"</string>
+ <string name="accessibility_battery_level" msgid="7451474187113371965">"Батерей <xliff:g id="NUMBER">%d</xliff:g> хувьтай."</string>
+ <string name="accessibility_settings_button" msgid="799583911231893380">"Системийн тохиргоо."</string>
+ <string name="accessibility_notifications_button" msgid="4498000369779421892">"Мэдэгдэл."</string>
+ <string name="accessibility_remove_notification" msgid="3603099514902182350">"Мэдэгдлийг цэвэрлэх."</string>
+ <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS идэвхтэй."</string>
+ <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS хайж байна."</string>
+ <string name="accessibility_tty_enabled" msgid="4613200365379426561">"TeleTypewriter идэвхтэй болов."</string>
+ <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"Хонхны чичиргээ."</string>
+ <string name="accessibility_ringer_silent" msgid="9061243307939135383">"Хонхыг хаах."</string>
+ <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> байхгүй."</string>
+ <string name="accessibility_notification_dismissed" msgid="854211387186306927">"Мэдэгдэл хаагдсан."</string>
+ <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"Мэдэгдлийн хураангуй самбар"</string>
+ <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"Шуурхай тохиргоо."</string>
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"Сүүлийн апп"</string>
+ <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"Хэрэглэгч <xliff:g id="USER">%s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+ <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Мобайл <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Батерей <xliff:g id="STATE">%s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"Нислэгийн горим <xliff:g id="STATE">%s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Блютүүт <xliff:g id="STATE">%s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Сэрүүлгийг <xliff:g id="TIME">%s</xliff:g>-д тохируулсан."</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G дата идэвхгүй болов"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G дата идэвхгүй байна"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Мобайл дата идэвхгүй болов"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="2086815304858964954">"Дата идэвхгүй болов"</string>
+ <string name="data_usage_disabled_dialog" msgid="3853117269051806280">"Та заасан дата ашиглалтын хязгаарт хүрэв.\n\nХэрэв та датаг дахин идэвхжүүлбэл операторт төлбөр төлөх хэрэгтэй."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="7729772039208664606">"Дата дахин идэвхжүүлэх"</string>
+ <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Интернет холболт байхгүй"</string>
+ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi холбогдсон"</string>
+ <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS хайж байна"</string>
+ <string name="gps_notification_found_text" msgid="4619274244146446464">"GPS байршил"</string>
+ <string name="accessibility_location_active" msgid="2427290146138169014">"Байршлын хүсэлтүүд идэвхтэй"</string>
+ <string name="accessibility_clear_all" msgid="5235938559247164925">"Бүх мэдэгдлийг цэвэрлэх."</string>
+ <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Апп мэдээлэл"</string>
+ <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Дэлгэц автоматаар эргэнэ."</string>
+ <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"Дэлгэц хэвтээ чиглэлд түгжигдсэн."</string>
+ <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"Дэлгэц босоо чиглэлээр түгжигдсэн."</string>
+ <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+ <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
+ <string name="ethernet_label" msgid="7967563676324087464">"Этернет"</string>
+ <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Нислэгийн горим"</string>
+ <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"Цэнэглэж байна, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+ <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"Цэнэглэгдсэн"</string>
+ <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Блютүүт"</string>
+ <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Блютүүт (<xliff:g id="NUMBER">%d</xliff:g> төхөөрөмж)"</string>
+ <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Блютүүт унтраалттай"</string>
+ <string name="quick_settings_brightness_label" msgid="6968372297018755815">"Тодрол"</string>
+ <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Автомат эргэх"</string>
+ <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Эргүүлэлт түгжигдсэн"</string>
+ <string name="quick_settings_ime_label" msgid="7073463064369468429">"Оруулах арга"</string>
+ <string name="quick_settings_location_label" msgid="5011327048748762257">"Байршил"</string>
+ <string name="quick_settings_location_off_label" msgid="7464544086507331459">"Байршил идэвхгүй"</string>
+ <string name="quick_settings_media_device_label" msgid="1302906836372603762">"Медиа төхөөрөмж"</string>
+ <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+ <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Зөвхөн яаралтай дуудлага"</string>
+ <string name="quick_settings_settings_label" msgid="5326556592578065401">"Тохиргоо"</string>
+ <string name="quick_settings_time_label" msgid="4635969182239736408">"Цаг"</string>
+ <string name="quick_settings_user_label" msgid="5238995632130897840">"Би"</string>
+ <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Холбогдоогүй"</string>
+ <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Сүлжээгүй"</string>
+ <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi унтарсан"</string>
+ <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi Дэлгэц"</string>
+ <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"Утасгүй дэлгэц"</string>
+ <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Тодрол"</string>
+ <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АВТОМАТ"</string>
+ <string name="status_bar_help_title" msgid="1199237744086469217">"Мэдэгдэл энд харагдана"</string>
+ <string name="status_bar_help_text" msgid="7874607155052076323">"Доош татаад тэдгээрт хандана уу.\nДахин доош татаад систем контролд хандана уу."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index b6b3577..9c76eae 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -201,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Pemberitahuan dipaparkan di sini"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Akses panel pada bila-bila masa dengan meleret ke bawah.\nLeret ke bawah sekali lagi untuk mendapatkan kawalan sistem."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Leret ke bahagian tepi skrin untuk menampakkan bar"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Leret dari tepi skrin untuk menampakkan bar sistem"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 6f7d727..d850cf3 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -164,8 +164,7 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi tilkoblet"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Søker etter GPS"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"Posisjon angitt av GPS"</string>
- <!-- no translation found for accessibility_location_active (2427290146138169014) -->
- <skip />
+ <string name="accessibility_location_active" msgid="2427290146138169014">"Aktive stedsforespørsler"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Fjern alle varslinger."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Info om app"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skjermen roterer automatisk."</string>
@@ -202,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Varslene vises her"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Bruk dem når som helst ved å sveipe nedover.\nSveip nedover igjen for å gå til systemkontrollene."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Sveip på kanten av skjermen for å få frem feltet"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Sveip fra kanten på skjermen for å få frem systemfeltet"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
new file mode 100644
index 0000000..c3eee01
--- /dev/null
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="7164937344850004466">"प्रणाली UI"</string>
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"हटाउनुहोस्"</string>
+ <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"सूचीबाट हटाउनुहोस्"</string>
+ <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"अनुप्रयोगको जानकारी"</string>
+ <string name="status_bar_no_recent_apps" msgid="6576392951053994640">"कुनै नयाँ अनुप्रयोगहरू छैनन्"</string>
+ <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"नयाँ अनुप्रयोगहरू खारेज गर्नुहोस्"</string>
+ <plurals name="status_bar_accessibility_recent_apps">
+ <item quantity="one" msgid="5854176083865845541">"१ भरखरै अनुप्रयोग"</item>
+ <item quantity="other" msgid="1040784359794890744">"%d भरखरैका अनुप्रयोगहरू"</item>
+ </plurals>
+ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"कुनै सूचनाहरू छैन"</string>
+ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"चलिरहेको"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"सूचनाहरू"</string>
+ <string name="battery_low_title" msgid="2783104807551211639">"चार्जर जडान गर्नुहोस्"</string>
+ <string name="battery_low_subtitle" msgid="1752040062087829196">"ब्याट्रि न्यून हुँदै छ।"</string>
+ <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> बाँकी"</string>
+ <string name="invalid_charger" msgid="4549105996740522523">"USB चार्ज गर्न समर्थित छैन।\n आपूर्ति गरिएको चार्जर मात्र प्रयोग गर्नुहोस्।"</string>
+ <string name="battery_low_why" msgid="7279169609518386372">"ब्याट्रि प्रयोग"</string>
+ <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"सेटिङहरू"</string>
+ <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"वाइ-फाइ"</string>
+ <string name="status_bar_settings_airplane" msgid="4879879698500955300">"हवाइजहाज मोड"</string>
+ <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"स्वत:घुम्ने स्क्रिन"</string>
+ <string name="status_bar_settings_mute_label" msgid="554682549917429396">"म्युट गर्नुहोस्"</string>
+ <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"स्वतः"</string>
+ <string name="status_bar_settings_notifications" msgid="397146176280905137">"सूचनाहरू"</string>
+ <string name="bluetooth_tethered" msgid="7094101612161133267">"ब्लुटुथ टेथर भयो"</string>
+ <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"इनपुट विधिहरू सेटअप गर्नुहोस्"</string>
+ <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"फिजिकल किबोर्ड"</string>
+ <string name="usb_device_permission_prompt" msgid="834698001271562057">"<xliff:g id="APPLICATION">%1$s</xliff:g> USB उपकरणलाई पहुँच दिनको लागि अनुप्रयोगलाई अनुमति दिने हो?"</string>
+ <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"<xliff:g id="APPLICATION">%1$s</xliff:g> USB पाटपुर्जालाई पहुँच दिनको लागि अनुप्रयोगलाई अनुमति दिने हो?"</string>
+ <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"यो USB उपकरण जोडिएको बेला <xliff:g id="ACTIVITY">%1$s</xliff:g> खोल्ने हो?"</string>
+ <string name="usb_accessory_confirm_prompt" msgid="3808984931830229888">"यो USB सहायक जडान हुँदा <xliff:g id="ACTIVITY">%1$s</xliff:g> खोल्ने हो?"</string>
+ <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"यस USB उपकरणसँग स्थापित अनुप्रयोग काम गर्दैन। यस उपकरणको बारेमा <xliff:g id="URL">%1$s</xliff:g> मा धेरै जान्नुहोस्"</string>
+ <string name="title_usb_accessory" msgid="4966265263465181372">"USB सहयोगी"</string>
+ <string name="label_view" msgid="6304565553218192990">"दृश्य"</string>
+ <string name="always_use_device" msgid="1450287437017315906">"यो USB उपकरणको लागि पूर्वनिर्धारितबाट प्रयोग गर्नुहोस्"</string>
+ <string name="always_use_accessory" msgid="1210954576979621596">"यस USB सहायक सामानको लागि पूर्वनिर्धारितद्वारा प्रयोग गर्नुहोस्"</string>
+ <string name="usb_debugging_title" msgid="4513918393387141949">"USB डिबग गर्नको लागि अनुमति दिने हो?"</string>
+ <string name="usb_debugging_message" msgid="2220143855912376496">"कम्प्युटरको RSA कुञ्जी औंलाछाप:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+ <string name="usb_debugging_always" msgid="303335496705863070">"यो कम्प्युटरबाट सधैँ अनुमति दिनुहोस्"</string>
+ <string name="compat_mode_on" msgid="6623839244840638213">"स्क्रिन भर्न जुम गर्नुहोस्"</string>
+ <string name="compat_mode_off" msgid="4434467572461327898">"स्क्रिन भर्न तन्काउनुहोस्"</string>
+ <string name="compat_mode_help_header" msgid="7969493989397529910">"अनुकूलता जुम"</string>
+ <string name="compat_mode_help_body" msgid="4946726776359270040">"जब कुनै अनुप्रयोग सानो स्क्रिनको लागि बनाइएको हुन्छ, तब जुम नियन्त्रण घडीको नजिक देखिन्छ।"</string>
+ <string name="screenshot_saving_ticker" msgid="7403652894056693515">"स्क्रिनसट बचत गर्दै…"</string>
+ <string name="screenshot_saving_title" msgid="8242282144535555697">"स्क्रिनसट बचत गर्दै…"</string>
+ <string name="screenshot_saving_text" msgid="2419718443411738818">"स्क्रिनसट बचत हुँदै छ।"</string>
+ <string name="screenshot_saved_title" msgid="6461865960961414961">"स्क्रिनसट क्याप्चर गरियो।"</string>
+ <string name="screenshot_saved_text" msgid="1152839647677558815">"तपाईँको स्क्रिनसट हेर्न छुनुहोस्।"</string>
+ <string name="screenshot_failed_title" msgid="705781116746922771">"स्क्रिनसट क्याप्चर गर्न सकिएन।"</string>
+ <string name="screenshot_failed_text" msgid="8134011269572415402">"स्क्रिनसटलाई बचत गर्न सकेन। भण्डारण उपयोगमा हुन सक्छ।"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"USB फाइल सार्ने विकल्पहरू"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"मिडिया प्लेयर(MTP)को रूपमा माउन्ट गर्नुहोस्"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"क्यामेराको रूपमा माउन्ट गर्नुहोस् (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="2312667578562201583">"म्याकको लागि एन्ड्रोइड फाइल ट्रान्सफर अनुप्रयोग स्थापना गर्नुहोस्"</string>
+ <string name="accessibility_back" msgid="567011538994429120">"पछाडि"</string>
+ <string name="accessibility_home" msgid="8217216074895377641">"गृह"</string>
+ <string name="accessibility_menu" msgid="316839303324695949">"मेनु"</string>
+ <string name="accessibility_recent" msgid="8571350598987952883">"भर्खरका अनुप्रयोगहरू"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"इनपुट विधि बटन स्विच गर्नुहोस्।"</string>
+ <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"मिलाउने जुम बटन।"</string>
+ <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"स्क्रिनलाई सानोबाट ठूलो पार्नुहोस्।"</string>
+ <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"ब्लुटुथ जडान भयो।"</string>
+ <string name="accessibility_bluetooth_disconnected" msgid="7416648669976870175">"ब्लुटुथसँग विच्छेद गरियो।"</string>
+ <string name="accessibility_no_battery" msgid="358343022352820946">"कुनै ब्याट्रि छैन।"</string>
+ <string name="accessibility_battery_one_bar" msgid="7774887721891057523">"ब्याट्रि एउटा पट्टि।"</string>
+ <string name="accessibility_battery_two_bars" msgid="8500650438735009973">"ब्याट्रिका दुईवटा पट्टिहरू"</string>
+ <string name="accessibility_battery_three_bars" msgid="2302983330865040446">"ब्याट्रिका तिनवटा पट्टिहरू"</string>
+ <string name="accessibility_battery_full" msgid="8909122401720158582">"ब्याट्रि पूर्ण छ।"</string>
+ <string name="accessibility_no_phone" msgid="4894708937052611281">"फोन छैन्।"</string>
+ <string name="accessibility_phone_one_bar" msgid="687699278132664115">"फोन एउटा पट्टि।"</string>
+ <string name="accessibility_phone_two_bars" msgid="8384905382804815201">"फोन दुई पट्टि।"</string>
+ <string name="accessibility_phone_three_bars" msgid="8521904843919971885">"फोन तिन पट्टिहरू।"</string>
+ <string name="accessibility_phone_signal_full" msgid="6471834868580757898">"फोन सङ्केत भरिएको।"</string>
+ <string name="accessibility_no_data" msgid="4791966295096867555">"डेटा छैन।"</string>
+ <string name="accessibility_data_one_bar" msgid="1415625833238273628">"डेटाको एउटा पट्टि।"</string>
+ <string name="accessibility_data_two_bars" msgid="6166018492360432091">"डेटा दुई बाधाहरू।"</string>
+ <string name="accessibility_data_three_bars" msgid="9167670452395038520">"डेटा तिन बाधाहरू।"</string>
+ <string name="accessibility_data_signal_full" msgid="2708384608124519369">"डेटा संकेत पूर्ण।"</string>
+ <string name="accessibility_wifi_off" msgid="3177380296697933627">"वाइफाइ बन्द।"</string>
+ <string name="accessibility_no_wifi" msgid="1425476551827924474">"वाइफाइ विच्छेद भयो।"</string>
+ <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"वाइफाइ एक पट्टि।"</string>
+ <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"वाइफाइ दुई पट्टि।"</string>
+ <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"वाइफाइ तिन बारहरू।"</string>
+ <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"वाइफाइ सङ्केत भरिएको।"</string>
+ <string name="accessibility_no_wimax" msgid="4329180129727630368">"वाइम्यास छैन।"</string>
+ <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX एउटा पट्टि।"</string>
+ <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"वाइम्याक्स दुईवटा बारहरू।"</string>
+ <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"वाइम्याक्स तिनवटा बारहरू।"</string>
+ <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"वाइम्याक्स सङ्केत भरिएका।"</string>
+ <string name="accessibility_no_signal" msgid="7064645320782585167">"सङ्केत छैन।"</string>
+ <string name="accessibility_not_connected" msgid="6395326276213402883">"जडान नगरिएको।"</string>
+ <string name="accessibility_zero_bars" msgid="3806060224467027887">"शून्य पट्टि।"</string>
+ <string name="accessibility_one_bar" msgid="1685730113192081895">"एउटा बार।"</string>
+ <string name="accessibility_two_bars" msgid="6437363648385206679">"दुई पट्टिहरू।"</string>
+ <string name="accessibility_three_bars" msgid="2648241415119396648">"तिनवटा पट्टिहरू"</string>
+ <string name="accessibility_signal_full" msgid="9122922886519676839">"सङ्केत पूर्ण छ।"</string>
+ <string name="accessibility_desc_on" msgid="2385254693624345265">"चालु।"</string>
+ <string name="accessibility_desc_off" msgid="6475508157786853157">"बन्द गर्नुहोस्।"</string>
+ <string name="accessibility_desc_connected" msgid="8366256693719499665">"जडान गरिएको।"</string>
+ <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+ <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+ <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
+ <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
+ <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
+ <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
+ <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+ <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"रोमिङ"</string>
+ <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
+ <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"वाइ-फाइ"</string>
+ <string name="accessibility_no_sim" msgid="8274017118472455155">"SIM छैन।"</string>
+ <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"ब्लुटुथ टिथर गर्दै।"</string>
+ <string name="accessibility_airplane_mode" msgid="834748999790763092">"हवाइजहाज मोड।"</string>
+ <string name="accessibility_battery_level" msgid="7451474187113371965">"ब्याट्रि <xliff:g id="NUMBER">%d</xliff:g> प्रतिशत"</string>
+ <string name="accessibility_settings_button" msgid="799583911231893380">"प्रणाली सेटिङहरू"</string>
+ <string name="accessibility_notifications_button" msgid="4498000369779421892">"सूचनाहरू।"</string>
+ <string name="accessibility_remove_notification" msgid="3603099514902182350">"सूचना खाली गर्नुहोस्।"</string>
+ <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS सक्षम गरिएको"</string>
+ <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS प्राप्त हुँदैछ।"</string>
+ <string name="accessibility_tty_enabled" msgid="4613200365379426561">"टेलि टाइपराइटर सक्षम गरियो।"</string>
+ <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"बज्ने कम्पन हुन्छ।"</string>
+ <string name="accessibility_ringer_silent" msgid="9061243307939135383">"घन्टी मौन।"</string>
+ <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> खारेज गरिएको छ।"</string>
+ <string name="accessibility_notification_dismissed" msgid="854211387186306927">"सूचना खारेज।"</string>
+ <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"सूचना कक्ष।"</string>
+ <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"द्रुत सेटिङहरू"</string>
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"वर्तमान अनुप्रयोगहरू"</string>
+ <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"प्रयोगकर्ता <xliff:g id="USER">%s</xliff:g>।"</string>
+ <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>। <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+ <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"मोवाइल <xliff:g id="SIGNAL">%1$s</xliff:g>। <xliff:g id="TYPE">%2$s</xliff:g>। <xliff:g id="NETWORK">%3$s</xliff:g>।"</string>
+ <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"ब्याट्रि <xliff:g id="STATE">%s</xliff:g>।"</string>
+ <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"हवाजहाज मोड <xliff:g id="STATE">%s</xliff:g>।"</string>
+ <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"ब्लुटुथ <xliff:g id="STATE">%s</xliff:g>।"</string>
+ <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"<xliff:g id="TIME">%s</xliff:g>को लागि सङ्केत घन्टी सेट गरिएको"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G डेटा अक्षम गरियो"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G डेटा असक्षम गरियो"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"मोबाइल डेटा अक्षम गरियो"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="2086815304858964954">"डेटा अक्षम गरियो"</string>
+ <string name="data_usage_disabled_dialog" msgid="3853117269051806280">"तपाईँ निर्दिष्ट डेटा उपयोग सीमामा पुग्नु भएको छ।\n\nयदि तपाईँले डेटालाई पुनःसक्षम पार्नु भयो भने तपाईँलाई अर्को संचालकबाट शुल्क लगाउन सक्छ।"</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="7729772039208664606">"डेटा पुनः सक्षम गर्नुहोस्"</string>
+ <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"इन्टरनेट जडान छैन"</string>
+ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"वाइ-फाइ जडित"</string>
+ <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPSको लागि खोजी गर्दै"</string>
+ <string name="gps_notification_found_text" msgid="4619274244146446464">"GPS द्वारा स्थान सेट गरिएको"</string>
+ <string name="accessibility_location_active" msgid="2427290146138169014">"स्थान अनुरोधहरू सक्रिय"</string>
+ <string name="accessibility_clear_all" msgid="5235938559247164925">"सबै सूचनाहरू हटाउनुहोस्।"</string>
+ <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"अनुप्रयोगको जानकारी"</string>
+ <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"स्क्रिन स्वतः घुम्ने छ।"</string>
+ <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"स्क्रिनलाई ल्यान्डस्केप अवस्थामा बन्द गरिएको छ।"</string>
+ <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"स्क्रिन पोर्टेट अभिमूखमा लक गरिएको छ।"</string>
+ <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+ <string name="start_dreams" msgid="7219575858348719790">"दिवासपना"</string>
+ <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
+ <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"उडान मोड"</string>
+ <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"चार्ज हुँदै, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+ <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"चार्ज भयो"</string>
+ <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"ब्लुटुथ"</string>
+ <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"ब्लुटुथ (<xliff:g id="NUMBER">%d</xliff:g> उपकरणहरू)"</string>
+ <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"ब्लुटुथ बन्द"</string>
+ <string name="quick_settings_brightness_label" msgid="6968372297018755815">"चमक"</string>
+ <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"स्वतः घुमाइ"</string>
+ <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"घुम्ने लक गरेको"</string>
+ <string name="quick_settings_ime_label" msgid="7073463064369468429">"आगत विधि"</string>
+ <string name="quick_settings_location_label" msgid="5011327048748762257">"स्थान"</string>
+ <string name="quick_settings_location_off_label" msgid="7464544086507331459">"स्थान बन्द छ"</string>
+ <string name="quick_settings_media_device_label" msgid="1302906836372603762">"मिडिया उपकरण"</string>
+ <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+ <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"आकस्मिक कल मात्र"</string>
+ <string name="quick_settings_settings_label" msgid="5326556592578065401">"सेटिङहरू"</string>
+ <string name="quick_settings_time_label" msgid="4635969182239736408">"समय"</string>
+ <string name="quick_settings_user_label" msgid="5238995632130897840">"मलाई"</string>
+ <string name="quick_settings_wifi_label" msgid="9135344704899546041">"वाइ-फाइ"</string>
+ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"जोडिएको छैन"</string>
+ <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"नेटवर्क छैन"</string>
+ <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"वाइ-फाइ बन्द"</string>
+ <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"वाइ-फाइ प्रदर्शन"</string>
+ <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"ताररहित प्रदर्शन"</string>
+ <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"उज्यालपन"</string>
+ <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"स्वतः"</string>
+ <string name="status_bar_help_title" msgid="1199237744086469217">"यहाँ जानकारीहरू देखा पर्छन्"</string>
+ <string name="status_bar_help_text" msgid="7874607155052076323">"तल हुत्त्याएर तिनीहरूलाई सधैं पहुँच गर्नुहोस्\nप्रणाली नियन्त्रणको लागि पुनः तल हुत्त्याउनुहोस्"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 02a5b45..5b6ebab 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -201,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATISCH"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Meldingen worden hier weergegeven"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"U kunt de meldingen op elk gewenst moment openen door met uw vinger omlaag te vegen.\nVeeg nogmaals met uw vinger omlaag om de systeembesturingselementen weer te geven."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Veeg vanaf de rand om balk weer te geven"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Veeg vanaf de rand van het scherm om de systeembalk weer te geven"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index d17c45e..6bff7af 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -164,8 +164,7 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi: połączono"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Wyszukiwanie sygnału GPS"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"Lokalizacja z GPSa"</string>
- <!-- no translation found for accessibility_location_active (2427290146138169014) -->
- <skip />
+ <string name="accessibility_location_active" msgid="2427290146138169014">"Prośby o lokalizację są aktywne"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Usuń wszystkie powiadomienia."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"O aplikacji"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekran zostanie obrócony automatycznie."</string>
@@ -202,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATYCZNA"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Tutaj pokazują się powiadomienia"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Możesz je otworzyć w dowolnej chwili, przesuwając w dół.\nPrzesuń jeszcze raz w dół, by otworzyć ustawienia systemowe."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Przesuń palcem od krawędzi ekranu, by odkryć pasek"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Przesuń palcem od krawędzi ekranu, by odkryć pasek systemu"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index b520319..6aa94e0 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -164,8 +164,7 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi ligado"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"A procurar GPS"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"Localização definida por GPS"</string>
- <!-- no translation found for accessibility_location_active (2427290146138169014) -->
- <skip />
+ <string name="accessibility_location_active" msgid="2427290146138169014">"Pedidos de localização ativos"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Limpar todas as notificações."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informações da aplicação"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"O ecrã será rodado automaticamente."</string>
@@ -202,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMÁTICO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"As notificações são apresentadas aqui"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Pode aceder em qualquer altura, deslizando rapidamente para baixo com o dedo.\nDeslize novamente para baixo para aceder aos controlos do sistema."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Deslize da extremidade do ecrã para revelar a barra"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Deslize da extremidade do ecrã para revelar a barra do sistema"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 2a2f336..aa972fb 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -166,8 +166,7 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi conectado"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Buscando GPS"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"Local definido por GPS"</string>
- <!-- no translation found for accessibility_location_active (2427290146138169014) -->
- <skip />
+ <string name="accessibility_location_active" msgid="2427290146138169014">"Solicitações de localização ativas"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Limpar todas as notificações."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informações do aplicativo"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"A tela girará automaticamente."</string>
@@ -204,6 +203,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"As notificações aparecem aqui"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Acesse a qualquer momento deslizando para baixo.\nDeslize para baixo novamente para acessar os controles do sistema."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Deslize a borda da tela para ver a barra"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Deslize a partir da borda da tela ver a barra do sistema"</string>
</resources>
diff --git a/packages/SystemUI/res/values-rm/strings.xml b/packages/SystemUI/res/values-rm/strings.xml
index 22a857e..05b7453 100644
--- a/packages/SystemUI/res/values-rm/strings.xml
+++ b/packages/SystemUI/res/values-rm/strings.xml
@@ -372,8 +372,4 @@
<skip />
<!-- no translation found for status_bar_help_text (7874607155052076323) -->
<skip />
- <!-- no translation found for hiding_navigation_confirmation_message (3227814171674734332) -->
- <skip />
- <!-- no translation found for hiding_navigation_confirmation_message_long (7854368870786524950) -->
- <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 375d12c..9c5ad00 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -164,8 +164,7 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi conectat"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Se caută GPS"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"Locaţie setată prin GPS"</string>
- <!-- no translation found for accessibility_location_active (2427290146138169014) -->
- <skip />
+ <string name="accessibility_location_active" msgid="2427290146138169014">"Solicitări locație active"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Ștergeţi toate notificările."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informaţii despre aplicaţie"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ecranul se va roti în mod automat."</string>
@@ -202,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMAT"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Notificările se afişează aici"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Accesaţi-le oricând glisând în jos.\nGlisaţi în jos din nou pentru comenzile sistemului."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Glisați dinspre marginea ecranului pentru a afișa bara"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Glisați dinspre marginea ecranului pentru a afișa bara de sistem"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 15adf90..3020624 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -166,8 +166,7 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi подключено"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Поиск GPS"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"Координаты по GPS"</string>
- <!-- no translation found for accessibility_location_active (2427290146138169014) -->
- <skip />
+ <string name="accessibility_location_active" msgid="2427290146138169014">"Есть активные запросы на определение местоположения"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Удалить все уведомления"</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"О приложении"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Экран будет поворачиваться автоматически."</string>
@@ -206,6 +205,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АВТОНАСТРОЙКА"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Это панель уведомлений"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Ее можно открыть, пролистнув экран вниз.\nЧтобы открыть настройки, проведите пальцем вниз ещё раз."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Чтобы открыть панель, проведите пальцем от края к центру экрана"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Чтобы открыть панель навигации, проведите пальцем от края к центру экрана"</string>
</resources>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
new file mode 100644
index 0000000..f28cd16
--- /dev/null
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="7164937344850004466">"පද්ධති UI"</string>
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"හිස් කරන්න"</string>
+ <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"ලැයිස්තුවෙන් ඉවත් කරන්න"</string>
+ <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"යෙදුම් තොරතුරු"</string>
+ <string name="status_bar_no_recent_apps" msgid="6576392951053994640">"මෑත උපාංග නැත"</string>
+ <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"මෑත යෙදුම් ඉවතලන්න"</string>
+ <plurals name="status_bar_accessibility_recent_apps">
+ <item quantity="one" msgid="5854176083865845541">"මෑත යෙදුම් 1 ක්"</item>
+ <item quantity="other" msgid="1040784359794890744">"මෑත යෙදුම් %d ක්"</item>
+ </plurals>
+ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"දැනුම්දීම් නැත"</string>
+ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"දැනට පවතින"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"දැනුම්දීම්"</string>
+ <string name="battery_low_title" msgid="2783104807551211639">"අරෝපකයට සම්බන්ධ කරන්න"</string>
+ <string name="battery_low_subtitle" msgid="1752040062087829196">"බැටරිය අඩු වෙමින් පවතී."</string>
+ <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> ක් ඉතිරියි"</string>
+ <string name="invalid_charger" msgid="4549105996740522523">"USB ආරෝපණය සහය නොදක්වයි.\nසපයන ලද ආරෝපකය පමණක් භාවිතා කරන්න."</string>
+ <string name="battery_low_why" msgid="7279169609518386372">"බැටරි භාවිතය"</string>
+ <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"සැකසීම්"</string>
+ <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
+ <string name="status_bar_settings_airplane" msgid="4879879698500955300">"අහස්යානා ආකාරය"</string>
+ <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"ස්වයංක්‍රීයව-භ්‍රමණය වන තිරය"</string>
+ <string name="status_bar_settings_mute_label" msgid="554682549917429396">"නිශ්ශබ්ද කරන්න"</string>
+ <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"ස්වයංක්‍රීය"</string>
+ <string name="status_bar_settings_notifications" msgid="397146176280905137">"දැනුම්දීම්"</string>
+ <string name="bluetooth_tethered" msgid="7094101612161133267">"බ්ලූටූත් ටෙදර් කරා"</string>
+ <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"ආදාන ක්‍රම සකසන්න"</string>
+ <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"භෞතික යතුරු පුවරුව"</string>
+ <string name="usb_device_permission_prompt" msgid="834698001271562057">"USB උපාංගය ප්‍රවේශ කිරීමට <xliff:g id="APPLICATION">%1$s</xliff:g> යෙදුමට අවසර දෙනවාද?"</string>
+ <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"USB මෙවලම ප්‍රවේශ කිරීමට <xliff:g id="APPLICATION">%1$s</xliff:g> යෙදුමට අවසර දෙනවාද?"</string>
+ <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"මෙම USB උපාංගය සම්බන්ධ විට <xliff:g id="ACTIVITY">%1$s</xliff:g> විවෘත කරන්නද?"</string>
+ <string name="usb_accessory_confirm_prompt" msgid="3808984931830229888">"මෙම USB මෙවලමට සම්බන්ධ වී ඇති විට <xliff:g id="ACTIVITY">%1$s</xliff:g> විවෘත කරන්නද?"</string>
+ <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"මෙම USB මෙවලම සමග ක්‍රියා කරන ස්ථාපිත යෙදුම් නොමැත. <xliff:g id="URL">%1$s</xliff:g> වලින් මෙම මෙවලම ගැන තව දැනගන්න"</string>
+ <string name="title_usb_accessory" msgid="4966265263465181372">"USB මෙවලම"</string>
+ <string name="label_view" msgid="6304565553218192990">"පෙනුම"</string>
+ <string name="always_use_device" msgid="1450287437017315906">"මෙම USB උපාංගය සඳහා සුපුරුද්දෙන් භාවිතා කරන්න"</string>
+ <string name="always_use_accessory" msgid="1210954576979621596">"මේ USB මෙවලම සඳහා සුපුරුද්දෙන් භාවිතා කරන්න."</string>
+ <string name="usb_debugging_title" msgid="4513918393387141949">"USB නිදොස්කරණයට අවසර දෙනවද?"</string>
+ <string name="usb_debugging_message" msgid="2220143855912376496">"මෙම පරිගණකයේ RSA යතුරු ඇඟිලි සටහන වන්නේ:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+ <string name="usb_debugging_always" msgid="303335496705863070">"සැම විටම මෙම පරිගණකයෙන් ඉඩ ලබා දෙන්න"</string>
+ <string name="compat_mode_on" msgid="6623839244840638213">"තිරය පිරවීමට විශාලනය කරන්න"</string>
+ <string name="compat_mode_off" msgid="4434467572461327898">"තිරය පිරවීමට අදින්න"</string>
+ <string name="compat_mode_help_header" msgid="7969493989397529910">"ගැළපෙන විශාලනය"</string>
+ <string name="compat_mode_help_body" msgid="4946726776359270040">"කුඩා තිරයක් සඳහා යෙදුමක් නිර්මාණය කළ විට, විශාලනය පාලකය ඔරලෝසුව ළඟින් පෙන්වයි."</string>
+ <string name="screenshot_saving_ticker" msgid="7403652894056693515">"තිර රුව සුරකිමින්…"</string>
+ <string name="screenshot_saving_title" msgid="8242282144535555697">"තිර රුව සුරැකෙමින් පවතී…"</string>
+ <string name="screenshot_saving_text" msgid="2419718443411738818">"තිර රුව සුරැකෙමින් පවතී."</string>
+ <string name="screenshot_saved_title" msgid="6461865960961414961">"තිර රුව ග්‍රහණය කරන ලදි."</string>
+ <string name="screenshot_saved_text" msgid="1152839647677558815">"ඔබගේ තිර රුව බැලීමට ස්පර්ශ කරන්න."</string>
+ <string name="screenshot_failed_title" msgid="705781116746922771">"තිර රුව ග්‍රහණය කිරීමට නොහැකි විය."</string>
+ <string name="screenshot_failed_text" msgid="8134011269572415402">"තිර රුව සුරැකීමට නොහැකි විය. ආචයනය භාවිතාවේ තිබෙනවා විය හැක."</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"USB ගොනු හුවමාරු විකල්ප"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"මධ්‍ය ධාවකයක් (MTP) ලෙස සවි කරන්න"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"කැමරාවක් (PTP) ලෙස සවි කරන්න"</string>
+ <string name="installer_cd_button_title" msgid="2312667578562201583">"Mac සඳහා Android ගොනු හුවමාරු යෙදුම ස්ථාපනය කරන්න"</string>
+ <string name="accessibility_back" msgid="567011538994429120">"ආපසු"</string>
+ <string name="accessibility_home" msgid="8217216074895377641">"මුල් පිටුව"</string>
+ <string name="accessibility_menu" msgid="316839303324695949">"මෙනුව"</string>
+ <string name="accessibility_recent" msgid="8571350598987952883">"මෑත යෙදුම්"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ආදාන ක්‍රමය මාරු කිරීමේ බොත්තම."</string>
+ <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"ගැළපෙන විශාලන බොත්තම."</string>
+ <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"විශාල තිරය වෙත කුඩාව විශාලනය කරන්න."</string>
+ <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"බ්ලූටූත් සම්බන්ධිතයි."</string>
+ <string name="accessibility_bluetooth_disconnected" msgid="7416648669976870175">"බ්ලූටූත් විසන්ධි කර ඇත."</string>
+ <string name="accessibility_no_battery" msgid="358343022352820946">"බැටරිය නැත."</string>
+ <string name="accessibility_battery_one_bar" msgid="7774887721891057523">"බැටරිය තීරු එකයි."</string>
+ <string name="accessibility_battery_two_bars" msgid="8500650438735009973">"බැටරිය තීරු දෙකයි."</string>
+ <string name="accessibility_battery_three_bars" msgid="2302983330865040446">"බැටරිය තීරු තුනයි."</string>
+ <string name="accessibility_battery_full" msgid="8909122401720158582">"බැටරිය පිරී ඇත."</string>
+ <string name="accessibility_no_phone" msgid="4894708937052611281">"දුරකථනයක් නැත."</string>
+ <string name="accessibility_phone_one_bar" msgid="687699278132664115">"දුරකථනය තීරු එකයි."</string>
+ <string name="accessibility_phone_two_bars" msgid="8384905382804815201">"දුරකථනය තීරු දෙකයි."</string>
+ <string name="accessibility_phone_three_bars" msgid="8521904843919971885">"දුරකථනය තීරු තුනයි."</string>
+ <string name="accessibility_phone_signal_full" msgid="6471834868580757898">"දුරකථනයේ සංඥාව පිරී ඇත."</string>
+ <string name="accessibility_no_data" msgid="4791966295096867555">"දත්ත නැත."</string>
+ <string name="accessibility_data_one_bar" msgid="1415625833238273628">"දත්ත තීරු එකයි."</string>
+ <string name="accessibility_data_two_bars" msgid="6166018492360432091">"දත්ත තීරු 2."</string>
+ <string name="accessibility_data_three_bars" msgid="9167670452395038520">"දත්ත තීරු 3."</string>
+ <string name="accessibility_data_signal_full" msgid="2708384608124519369">"දත්ත සංඥාව පිරී ඇත."</string>
+ <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wifi අක්‍රියයි."</string>
+ <string name="accessibility_no_wifi" msgid="1425476551827924474">"Wifi සම්බන්ධ කර නොමැත."</string>
+ <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Wifi තීරු එකයි."</string>
+ <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Wifi තීරු දෙකයි."</string>
+ <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"WiFi තීරු තුනයි."</string>
+ <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Wifi සංඥාව පිරී ඇත."</string>
+ <string name="accessibility_no_wimax" msgid="4329180129727630368">"WiMAX නැත."</string>
+ <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX තීරු එකයි."</string>
+ <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX තීරු දෙකයි."</string>
+ <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX තීරු තුනයි."</string>
+ <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX සංඥාව පිරී ඇත."</string>
+ <string name="accessibility_no_signal" msgid="7064645320782585167">"සංඥා නැත."</string>
+ <string name="accessibility_not_connected" msgid="6395326276213402883">"සම්බන්ධ වී නැත."</string>
+ <string name="accessibility_zero_bars" msgid="3806060224467027887">"තීරු ශුන්‍යයි."</string>
+ <string name="accessibility_one_bar" msgid="1685730113192081895">"තීරු එක."</string>
+ <string name="accessibility_two_bars" msgid="6437363648385206679">"තීරු දෙකයි."</string>
+ <string name="accessibility_three_bars" msgid="2648241415119396648">"තීරු තුනයි."</string>
+ <string name="accessibility_signal_full" msgid="9122922886519676839">"සංඥාව පිරී ඇත."</string>
+ <string name="accessibility_desc_on" msgid="2385254693624345265">"සක්‍රීයයි."</string>
+ <string name="accessibility_desc_off" msgid="6475508157786853157">"අක්‍රිය කරන්න."</string>
+ <string name="accessibility_desc_connected" msgid="8366256693719499665">"සම්බන්ධිතයි."</string>
+ <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+ <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+ <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
+ <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
+ <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
+ <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
+ <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+ <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"රෝමිං"</string>
+ <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
+ <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
+ <string name="accessibility_no_sim" msgid="8274017118472455155">"SIM නැත."</string>
+ <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"බ්ලූටූත් ටෙදරින්."</string>
+ <string name="accessibility_airplane_mode" msgid="834748999790763092">"අහස්යානා ආකාරය."</string>
+ <string name="accessibility_battery_level" msgid="7451474187113371965">"බැටරි ප්‍රතිශතය <xliff:g id="NUMBER">%d</xliff:g>"</string>
+ <string name="accessibility_settings_button" msgid="799583911231893380">"පද්ධති සැකසීම්."</string>
+ <string name="accessibility_notifications_button" msgid="4498000369779421892">"දැනුම්දීම්."</string>
+ <string name="accessibility_remove_notification" msgid="3603099514902182350">"දැනුම්දීම හිස් කරන්න."</string>
+ <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS සබල කර ඇත."</string>
+ <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS ලබා ගනිමින්."</string>
+ <string name="accessibility_tty_enabled" msgid="4613200365379426561">"TeleTypewriter ක්‍රියාත්මකයි."</string>
+ <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"හඬ නඟනය කම්පනය වේ."</string>
+ <string name="accessibility_ringer_silent" msgid="9061243307939135383">"හඬ නඟනය නිශ්ශබ්දයි."</string>
+ <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> අස් කර ඇත."</string>
+ <string name="accessibility_notification_dismissed" msgid="854211387186306927">"දැනුම්දීම නිෂ්ප්‍රභා කරඇත."</string>
+ <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"දැනුම්දීම් ආවරණය."</string>
+ <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"ක්ෂණික සැකසීම්."</string>
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"මෑත කාලීන යෙදුම්."</string>
+ <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"පරිශීලකයා <xliff:g id="USER">%s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+ <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"ජංගම <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"බැටරිය <xliff:g id="STATE">%s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"අහස්යානා ආකාරය <xliff:g id="STATE">%s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"බ්ලූටූත් <xliff:g id="STATE">%s</xliff:g>."</string>
+ <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"<xliff:g id="TIME">%s</xliff:g> සඳහා සීනුව සකස් කර ඇත."</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G දත්ත අබල කර ඇත"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G දත්ත අබල කරන ලදි"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"ජංගම දත්ත අබල කර ඇත"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="2086815304858964954">"දත්ත අබල කර ඇත"</string>
+ <string name="data_usage_disabled_dialog" msgid="3853117269051806280">"ඔබ නියමිත දත්ත භාවිත සීමාවට ළඟා වී ඇත.\n\nඔබ දත්ත නැවත සබල කළහොත් වාහකයා ඔබගෙන් ඇතැම් විට අය කරගත හැක."</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="7729772039208664606">"නැවත දත්ත සබල කරන්න"</string>
+ <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"අන්තර්ජාල සම්බන්ධතාවයක් නැත"</string>
+ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi සම්බන්ධිතයි"</string>
+ <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS සඳහා සොයමින්"</string>
+ <string name="gps_notification_found_text" msgid="4619274244146446464">"GPS මඟින් ස්ථානය සකසා ඇත"</string>
+ <string name="accessibility_location_active" msgid="2427290146138169014">"පිහිටීම් ඉල්ලීම් සක්‍රියයි"</string>
+ <string name="accessibility_clear_all" msgid="5235938559247164925">"සියලු දැනුම්දීම් හිස් කරන්න."</string>
+ <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"යෙදුම් තොරතුරු"</string>
+ <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"තිරය ස්වයංක්‍රීයව කරකැවේ."</string>
+ <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"තිරය තිරස් දිශානතියෙහි අගුළු දමා ඇත."</string>
+ <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"තිරය සිරස් දිශානතිය තුළ අගුළු වැටී ඇත."</string>
+ <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+ <string name="start_dreams" msgid="7219575858348719790">"දවල් හීනය"</string>
+ <string name="ethernet_label" msgid="7967563676324087464">"ඊතර නෙට්"</string>
+ <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"අහස්යානා ආකාරය"</string>
+ <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"ආරෝපණය වෙමින්, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+ <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"අරෝපිතයි"</string>
+ <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"බ්ලූටූත්"</string>
+ <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"බ්ලූටූත් (උපාංග <xliff:g id="NUMBER">%d</xliff:g>)"</string>
+ <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"බ්ලූටූත් අක්‍රියයි"</string>
+ <string name="quick_settings_brightness_label" msgid="6968372297018755815">"දීප්තිය"</string>
+ <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"ස්වයංක්‍රීය කරකැවීම"</string>
+ <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"භ්‍රමණය අගුළු දමා ඇත"</string>
+ <string name="quick_settings_ime_label" msgid="7073463064369468429">"ආදාන ක්‍රමය"</string>
+ <string name="quick_settings_location_label" msgid="5011327048748762257">"ස්ථානය"</string>
+ <string name="quick_settings_location_off_label" msgid="7464544086507331459">"ස්ථානය අක්‍රියයි"</string>
+ <string name="quick_settings_media_device_label" msgid="1302906836372603762">"මාධ්‍ය උපාංගය"</string>
+ <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+ <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"හදිසි ඇමතුම් පමණි"</string>
+ <string name="quick_settings_settings_label" msgid="5326556592578065401">"සැකසීම්"</string>
+ <string name="quick_settings_time_label" msgid="4635969182239736408">"වේලාව"</string>
+ <string name="quick_settings_user_label" msgid="5238995632130897840">"මම"</string>
+ <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"සම්බන්ධ වී නොමැත"</string>
+ <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"ජාලයක් නැත"</string>
+ <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi අක්‍රියයි"</string>
+ <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi සංදර්ශකය"</string>
+ <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"නොරැහැන් සංදර්ශකය"</string>
+ <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"දීප්තිමත් බව"</string>
+ <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"ස්වයංක්‍රීය"</string>
+ <string name="status_bar_help_title" msgid="1199237744086469217">"දැනුම්දීම් මෙතන පෙන්නුම් කරයි"</string>
+ <string name="status_bar_help_text" msgid="7874607155052076323">"පහලට සර්පණය කිරීමෙන් ඕනෑම වෙලාවක ඒවා වෙත පිවිසෙන්න.\nපද්ධති පාලක සඳහා නැවත පහළට සර්පණය කරන්න."</string>
+</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index bb70f36..59af9ab 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -166,8 +166,7 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi: pripojené"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Vyhľadávanie satelitov GPS"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"Poloha nastavená pomocou GPS"</string>
- <!-- no translation found for accessibility_location_active (2427290146138169014) -->
- <skip />
+ <string name="accessibility_location_active" msgid="2427290146138169014">"Žiadosti o polohu sú aktívne"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Vymazať všetky upozornenia."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informácie o aplikácii"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Obrazovka sa automaticky otočí."</string>
@@ -204,6 +203,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTOMATICKY"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Tu sa zobrazujú upozornenia"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Môžete ich kedykoľvek zobraziť tak, že posuniete prstom nadol.\nAk posuniete prstom nadol ešte raz, zobrazia sa ovládacie prvky systému."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Panel zobrazíte posunutím cez okraj obrazovky"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Systémový panel zobrazíte posunutím cez okraj obrazovky"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 46a5826..338ff44 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -164,8 +164,7 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi povezan"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Iskanje GPS-a"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"Lokacija nastavljena z GPS-om"</string>
- <!-- no translation found for accessibility_location_active (2427290146138169014) -->
- <skip />
+ <string name="accessibility_location_active" msgid="2427290146138169014">"Aktivne zahteve za lokacijo"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Izbriši vsa obvestila."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Podatki o aplikaciji"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Zaslon se bo samodejno zasukal."</string>
@@ -202,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"SAMODEJNO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Obvestila so prikazana tukaj"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Do njih lahko kadar koli dostopate tako, da povlečete navzdol.\nZa prikaz sistemskih kontrolnikov znova povlecite navzdol."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Vrstico prikažete tako, da povlečete z roba zaslona"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Sistemsko vrstico prikažete tako, da povlečete z roba zaslona"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 163bc06..b501d69 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -201,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АУТОМАТСКА"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Обавештења се појављују овде"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Приступите им у било ком тренутку листањем надоле.\nПоново листајте надоле да би се приказале системске контроле."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Превуците по ивици екрана да би се приказала трака"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Превуците од ивице екрана да би се приказала системска трака"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index c5335f4..560a00e 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -164,8 +164,7 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi-ansluten"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Sökning efter GPS pågår"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"Platsen har identifierats av GPS"</string>
- <!-- no translation found for accessibility_location_active (2427290146138169014) -->
- <skip />
+ <string name="accessibility_location_active" msgid="2427290146138169014">"Det finns aktiva platsbegäranden"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Ta bort alla meddelanden."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Info om appen"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skärmen roteras automatiskt."</string>
@@ -202,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Meddelanden visas här"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Du kommer åt dem när som helst genom att dra nedåt.\nDra nedåt igen om du vill visa systemkontroller."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Dra från kanten av skärmen om du vill visa fältet"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Dra från kanten av skärmen om du vill visa systemfältet"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index a0fb0a8..e3338de 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -199,6 +199,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"KIOTOMATIKI"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Arifa zitaonekana hapa"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Zifikie wakati wowote kwa kutelezesha chini.\nTelezesha chini tena kupata vidhibiti vya mfumo."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Telezesha kidole kutoka ukingo wa skrini ili kuonyesha upau"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Telezesha kidole kutoka ukingo wa skrini ili kuonyesha upau wa mfumo"</string>
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 2552e5c..3127eb3 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -201,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"อัตโนมัติ"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"การแจ้งเตือนจะแสดงขึ้นที่นี่"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"เข้าถึงได้ทุกเมื่อด้วยการกวาดนิ้วลง\nกวาดนิ้วลงอีกครั้งสำหรับการควบคุมระบบ"</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"กวาดขอบของหน้าจอเพื่อแสดงแถบ"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"กวาดจากขอบของหน้าจอเพื่อแสดงแถบระบบ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index dfc6c7d..9d4d9de 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -201,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Dito lumalabas ang mga notification"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"I-access ang mga ito anumang oras sa pamamagitan ng pag-swipe pababa.\nMuling mag-swipe pababa para sa mga kontrol ng system."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Mag-swipe sa gilid ng screen upang ipakita ang bar"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Mag-swipe mula sa gilid ng screen upang ipakita ang system bar"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index f7b34de..b885344 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -164,8 +164,7 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Kablosuz bağlandı"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS aranıyor"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"Konum GPS ile belirlendi"</string>
- <!-- no translation found for accessibility_location_active (2427290146138169014) -->
- <skip />
+ <string name="accessibility_location_active" msgid="2427290146138169014">"Konum bilgisi istekleri etkin"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Tüm bildirimleri temizle"</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Uygulama bilgileri"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekran otomatik olarak dönecektir."</string>
@@ -202,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"OTOMATİK"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Bildirimler burada görünür"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Aşağıya hızlıca kaydırarak bunlara istediğiniz zaman erişebilirsiniz.\nSistem denetimleri için tekrar hızlıca aşağı kaydırın."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Çubuğu görüntülemek için ekranın kenarından hızlıca kaydırın"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Sistem çubuğunu görüntülemek için ekranın kenarından hızlıca kaydırın"</string>
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 23e276b..1f3c131 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -164,8 +164,7 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi під’єднано"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Виконується пошук GPS-сигналу"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"Місцезнаходження встановлено за допомогою GPS"</string>
- <!-- no translation found for accessibility_location_active (2427290146138169014) -->
- <skip />
+ <string name="accessibility_location_active" msgid="2427290146138169014">"Запити про місцезнаходження активні"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Очистити всі сповіщення."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Інформація про програму"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Екран обертатиметься автоматично."</string>
@@ -202,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"АВТО"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Сповіщення з’являються тут"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Отримуйте до них доступ будь-коли, провівши пальцем униз.\nЗнову проведіть униз, щоб відкрити елементи керування системи."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Гортайте від краю екрана, щоб з’явилась панель"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Проведіть пальцем від краю екрана, щоб з’явилась навігаційна панель"</string>
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 31fc2c8..1bea172 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -164,8 +164,7 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Đã kết nối Wi-Fi"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Đang tìm kiếm GPS"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"Vị trí đặt bởi GPS"</string>
- <!-- no translation found for accessibility_location_active (2427290146138169014) -->
- <skip />
+ <string name="accessibility_location_active" msgid="2427290146138169014">"Yêu cầu về thông tin vị trí đang hoạt động"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Xóa tất cả thông báo."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Thông tin về ứng dụng"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Màn hình sẽ xoay tự động."</string>
@@ -202,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"TỰ ĐỘNG"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Thông báo xuất hiện tại đây"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Truy cập vào chúng bất kỳ lúc nào bằng cách vuốt xuống.\nVuốt lại xuống để hiển thị các điều khiển hệ thống."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Vuốt cạnh màn hình để hiển thị thanh"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Vuốt từ cạnh màn hình để hiển thị thanh hệ thống"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index b8b56c9..867cb17 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -166,8 +166,7 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"WLAN 已连接"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"正在搜索 GPS"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"已通过 GPS 确定位置"</string>
- <!-- no translation found for accessibility_location_active (2427290146138169014) -->
- <skip />
+ <string name="accessibility_location_active" msgid="2427290146138169014">"应用发出了有效位置信息请求"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"清除所有通知。"</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"应用信息"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"屏幕会自动旋转。"</string>
@@ -204,6 +203,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"自动"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"通知会显示在这里"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"向下滑动可随时查看通知。\n再次向下滑动可使用系统控制功能。"</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"从屏幕边缘向里滑可显示系统栏"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"从屏幕边缘向里滑动即可显示系统栏"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
new file mode 100644
index 0000000..ab38c59
--- /dev/null
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -0,0 +1,206 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="7164937344850004466">"系統用戶介面"</string>
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"清除"</string>
+ <string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"從清單中移除"</string>
+ <string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"應用程式資訊"</string>
+ <string name="status_bar_no_recent_apps" msgid="6576392951053994640">"沒有最近的應用程式"</string>
+ <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"關閉最近使用的應用程式"</string>
+ <plurals name="status_bar_accessibility_recent_apps">
+ <item quantity="one" msgid="5854176083865845541">"1 個最近使用的應用程式"</item>
+ <item quantity="other" msgid="1040784359794890744">"%d 個最近使用的應用程式"</item>
+ </plurals>
+ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"無通知"</string>
+ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"持續進行"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"通知"</string>
+ <string name="battery_low_title" msgid="2783104807551211639">"連接充電器"</string>
+ <string name="battery_low_subtitle" msgid="1752040062087829196">"電池即將用盡。"</string>
+ <string name="battery_low_percent_format" msgid="1077244949318261761">"剩餘 <xliff:g id="NUMBER">%d%%</xliff:g>"</string>
+ <string name="invalid_charger" msgid="4549105996740522523">"不支援 USB 充電。\n僅能使用隨附的充電器。"</string>
+ <string name="battery_low_why" msgid="7279169609518386372">"電池使用情況"</string>
+ <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"設定"</string>
+ <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
+ <string name="status_bar_settings_airplane" msgid="4879879698500955300">"飛行模式"</string>
+ <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"自動旋轉螢幕"</string>
+ <string name="status_bar_settings_mute_label" msgid="554682549917429396">"關閉"</string>
+ <string name="status_bar_settings_auto_brightness_label" msgid="511453614962324674">"自動"</string>
+ <string name="status_bar_settings_notifications" msgid="397146176280905137">"通知"</string>
+ <string name="bluetooth_tethered" msgid="7094101612161133267">"已經由藍牙進行網絡共享"</string>
+ <string name="status_bar_input_method_settings_configure_input_methods" msgid="3504292471512317827">"設定輸入方式"</string>
+ <string name="status_bar_use_physical_keyboard" msgid="7551903084416057810">"實體鍵盤"</string>
+ <string name="usb_device_permission_prompt" msgid="834698001271562057">"允許「<xliff:g id="APPLICATION">%1$s</xliff:g>」應用程式存取 USB 裝置嗎?"</string>
+ <string name="usb_accessory_permission_prompt" msgid="5171775411178865750">"允許「<xliff:g id="APPLICATION">%1$s</xliff:g>」應用程式存取 USB 配件嗎?"</string>
+ <string name="usb_device_confirm_prompt" msgid="5161205258635253206">"連接這個 USB 裝置時啟用 <xliff:g id="ACTIVITY">%1$s</xliff:g> 嗎?"</string>
+ <string name="usb_accessory_confirm_prompt" msgid="3808984931830229888">"連接這個 USB 配件時啟用 <xliff:g id="ACTIVITY">%1$s</xliff:g> 嗎?"</string>
+ <string name="usb_accessory_uri_prompt" msgid="513450621413733343">"已安裝的應用程式均無法存取這個 USB 配件,如要進一步瞭解這個配件,請瀏覽 <xliff:g id="URL">%1$s</xliff:g>"</string>
+ <string name="title_usb_accessory" msgid="4966265263465181372">"USB 配件"</string>
+ <string name="label_view" msgid="6304565553218192990">"觀看"</string>
+ <string name="always_use_device" msgid="1450287437017315906">"預設用於這個 USB 裝置"</string>
+ <string name="always_use_accessory" msgid="1210954576979621596">"預設用於這個 USB 配件"</string>
+ <string name="usb_debugging_title" msgid="4513918393387141949">"允許 USB 除錯嗎?"</string>
+ <string name="usb_debugging_message" msgid="2220143855912376496">"這部電腦的 RSA 密鑰指紋如下:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
+ <string name="usb_debugging_always" msgid="303335496705863070">"一律允許透過這部電腦進行"</string>
+ <string name="compat_mode_on" msgid="6623839244840638213">"放大為全螢幕"</string>
+ <string name="compat_mode_off" msgid="4434467572461327898">"放大為全螢幕"</string>
+ <string name="compat_mode_help_header" msgid="7969493989397529910">"兼容性縮放"</string>
+ <string name="compat_mode_help_body" msgid="4946726776359270040">"執行專為較小螢幕設計的應用程式時,系統會在時鐘旁顯示縮放控制項。"</string>
+ <string name="screenshot_saving_ticker" msgid="7403652894056693515">"正在儲存屏幕擷取畫面..."</string>
+ <string name="screenshot_saving_title" msgid="8242282144535555697">"正在儲存屏幕擷取畫面..."</string>
+ <string name="screenshot_saving_text" msgid="2419718443411738818">"正在儲存屏幕擷取畫面。"</string>
+ <string name="screenshot_saved_title" msgid="6461865960961414961">"已擷取屏幕畫面。"</string>
+ <string name="screenshot_saved_text" msgid="1152839647677558815">"輕觸即可查看屏幕擷取畫面。"</string>
+ <string name="screenshot_failed_title" msgid="705781116746922771">"無法擷取屏幕畫面。"</string>
+ <string name="screenshot_failed_text" msgid="8134011269572415402">"無法儲存屏幕擷取畫面,儲存裝置可能正在使用。"</string>
+ <string name="usb_preference_title" msgid="6551050377388882787">"USB 檔案傳輸選項"</string>
+ <string name="use_mtp_button_title" msgid="4333504413563023626">"掛接為媒體播放器 (MTP)"</string>
+ <string name="use_ptp_button_title" msgid="7517127540301625751">"掛接為相機 (PTP)"</string>
+ <string name="installer_cd_button_title" msgid="2312667578562201583">"安裝 Mac 專用的「Android 檔案傳輸」應用程式"</string>
+ <string name="accessibility_back" msgid="567011538994429120">"返回"</string>
+ <string name="accessibility_home" msgid="8217216074895377641">"首頁"</string>
+ <string name="accessibility_menu" msgid="316839303324695949">"選單"</string>
+ <string name="accessibility_recent" msgid="8571350598987952883">"最近使用的應用程式"</string>
+ <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"切換輸入法按鈕。"</string>
+ <string name="accessibility_compatibility_zoom_button" msgid="8461115318742350699">"相容性縮放按鈕。"</string>
+ <string name="accessibility_compatibility_zoom_example" msgid="4220687294564945780">"將較小螢幕的畫面放大在較大螢幕上顯示。"</string>
+ <string name="accessibility_bluetooth_connected" msgid="2707027633242983370">"藍牙連線已建立。"</string>
+ <string name="accessibility_bluetooth_disconnected" msgid="7416648669976870175">"藍牙連線已中斷。"</string>
+ <string name="accessibility_no_battery" msgid="358343022352820946">"未安裝電池。"</string>
+ <string name="accessibility_battery_one_bar" msgid="7774887721891057523">"電池電量為一格。"</string>
+ <string name="accessibility_battery_two_bars" msgid="8500650438735009973">"電池電量為兩格。"</string>
+ <string name="accessibility_battery_three_bars" msgid="2302983330865040446">"電池電量為三格。"</string>
+ <string name="accessibility_battery_full" msgid="8909122401720158582">"電池已滿。"</string>
+ <string name="accessibility_no_phone" msgid="4894708937052611281">"沒有電話訊號。"</string>
+ <string name="accessibility_phone_one_bar" msgid="687699278132664115">"電話訊號強度為一格。"</string>
+ <string name="accessibility_phone_two_bars" msgid="8384905382804815201">"電話訊號強度為兩格。"</string>
+ <string name="accessibility_phone_three_bars" msgid="8521904843919971885">"電話訊號強度為三格。"</string>
+ <string name="accessibility_phone_signal_full" msgid="6471834868580757898">"電話訊號滿格。"</string>
+ <string name="accessibility_no_data" msgid="4791966295096867555">"沒有數據網絡。"</string>
+ <string name="accessibility_data_one_bar" msgid="1415625833238273628">"數據網絡訊號強度為一格。"</string>
+ <string name="accessibility_data_two_bars" msgid="6166018492360432091">"數據網絡訊號強度為兩格。"</string>
+ <string name="accessibility_data_three_bars" msgid="9167670452395038520">"數據網絡訊號強度為三格。"</string>
+ <string name="accessibility_data_signal_full" msgid="2708384608124519369">"數據網絡訊號滿格。"</string>
+ <string name="accessibility_wifi_off" msgid="3177380296697933627">"WiFi 已關閉。"</string>
+ <string name="accessibility_no_wifi" msgid="1425476551827924474">"WiFi 連線已中斷。"</string>
+ <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"WiFi 訊號強度為一格。"</string>
+ <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"WiFi 訊號強度為兩格。"</string>
+ <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"WiFi 訊號強度為三格。"</string>
+ <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"WiFi 訊號已滿。"</string>
+ <string name="accessibility_no_wimax" msgid="4329180129727630368">"沒有 WiMAX 訊號。"</string>
+ <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX 訊號強度一格。"</string>
+ <string name="accessibility_wimax_two_bars" msgid="9176236858336502288">"WiMAX 訊號強度兩格。"</string>
+ <string name="accessibility_wimax_three_bars" msgid="6116551636752103927">"WiMAX 訊號強度三格。"</string>
+ <string name="accessibility_wimax_signal_full" msgid="2768089986795579558">"WiMAX 訊號滿格。"</string>
+ <string name="accessibility_no_signal" msgid="7064645320782585167">"沒有訊號。"</string>
+ <string name="accessibility_not_connected" msgid="6395326276213402883">"未連線。"</string>
+ <string name="accessibility_zero_bars" msgid="3806060224467027887">"訊號強度為零格。"</string>
+ <string name="accessibility_one_bar" msgid="1685730113192081895">"訊號強度為一格。"</string>
+ <string name="accessibility_two_bars" msgid="6437363648385206679">"訊號強度為兩格。"</string>
+ <string name="accessibility_three_bars" msgid="2648241415119396648">"訊號強度為三格。"</string>
+ <string name="accessibility_signal_full" msgid="9122922886519676839">"訊號已滿。"</string>
+ <string name="accessibility_desc_on" msgid="2385254693624345265">"開啟。"</string>
+ <string name="accessibility_desc_off" msgid="6475508157786853157">"關閉。"</string>
+ <string name="accessibility_desc_connected" msgid="8366256693719499665">"已連線。"</string>
+ <string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
+ <string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
+ <string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
+ <string name="accessibility_data_connection_3g" msgid="8628562305003568260">"3G"</string>
+ <string name="accessibility_data_connection_3.5g" msgid="8664845609981692001">"3.5G"</string>
+ <string name="accessibility_data_connection_4g" msgid="7741000750630089612">"4G"</string>
+ <string name="accessibility_data_connection_lte" msgid="5413468808637540658">"LTE"</string>
+ <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
+ <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"漫遊"</string>
+ <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
+ <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
+ <string name="accessibility_no_sim" msgid="8274017118472455155">"無 SIM 卡。"</string>
+ <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"藍牙數據連線。"</string>
+ <string name="accessibility_airplane_mode" msgid="834748999790763092">"飛航模式。"</string>
+ <!-- String.format failed for translation -->
+ <!-- no translation found for accessibility_battery_level (7451474187113371965) -->
+ <skip />
+ <string name="accessibility_settings_button" msgid="799583911231893380">"系統設定"</string>
+ <string name="accessibility_notifications_button" msgid="4498000369779421892">"通知。"</string>
+ <string name="accessibility_remove_notification" msgid="3603099514902182350">"清除通知。"</string>
+ <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS 已啟用。"</string>
+ <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"正在取得 GPS 訊號。"</string>
+ <string name="accessibility_tty_enabled" msgid="4613200365379426561">"TeleTypewriter (TTY) 已啟用。"</string>
+ <string name="accessibility_ringer_vibrate" msgid="666585363364155055">"鈴聲震動。"</string>
+ <string name="accessibility_ringer_silent" msgid="9061243307939135383">"鈴聲靜音。"</string>
+ <string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"「<xliff:g id="APP">%s</xliff:g>」已關閉。"</string>
+ <string name="accessibility_notification_dismissed" msgid="854211387186306927">"通知已關閉。"</string>
+ <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"通知欄。"</string>
+ <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"快速設定。"</string>
+ <string name="accessibility_desc_recent_apps" msgid="9014032916410590027">"最近使用的應用程式"</string>
+ <string name="accessibility_quick_settings_user" msgid="1104846699869476855">"用戶:<xliff:g id="USER">%s</xliff:g>。"</string>
+ <string name="accessibility_quick_settings_wifi" msgid="6099781031669728709">"<xliff:g id="SIGNAL">%1$s</xliff:g>、<xliff:g id="NETWORK">%2$s</xliff:g>"</string>
+ <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"流動數據連線:<xliff:g id="SIGNAL">%1$s</xliff:g>、<xliff:g id="TYPE">%2$s</xliff:g>、<xliff:g id="NETWORK">%3$s</xliff:g>。"</string>
+ <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"電池電量:<xliff:g id="STATE">%s</xliff:g>。"</string>
+ <string name="accessibility_quick_settings_airplane" msgid="4196876722090224753">"飛航模式:<xliff:g id="STATE">%s</xliff:g>。"</string>
+ <string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"藍牙:<xliff:g id="STATE">%s</xliff:g>。"</string>
+ <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"鬧鐘已設定為:<xliff:g id="TIME">%s</xliff:g>。"</string>
+ <string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"已停用 2G-3G 數據"</string>
+ <string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"已停用 4G 數據"</string>
+ <string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"已停用流動數據"</string>
+ <string name="data_usage_disabled_dialog_title" msgid="2086815304858964954">"數據停用"</string>
+ <string name="data_usage_disabled_dialog" msgid="3853117269051806280">"您已到達指定的數據用量上限。\n\n如果您重新啟用數據傳輸,流動網絡供應商可能會向您收費。"</string>
+ <string name="data_usage_disabled_dialog_enable" msgid="7729772039208664606">"重新啟用數據"</string>
+ <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"沒有互聯網連線"</string>
+ <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi 已連線"</string>
+ <string name="gps_notification_searching_text" msgid="8574247005642736060">"正在搜尋 GPS"</string>
+ <string name="gps_notification_found_text" msgid="4619274244146446464">"GPS 已定位"</string>
+ <string name="accessibility_location_active" msgid="2427290146138169014">"位置要求啟動中"</string>
+ <string name="accessibility_clear_all" msgid="5235938559247164925">"清除所有通知。"</string>
+ <string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"應用程式資訊"</string>
+ <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"屏幕會自動旋轉。"</string>
+ <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"屏幕已鎖定為橫向模式。"</string>
+ <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"屏幕已鎖定為垂直模式。"</string>
+ <string name="jelly_bean_dream_name" msgid="5992026543636816792">"BeanFlinger"</string>
+ <string name="start_dreams" msgid="7219575858348719790">"Daydream"</string>
+ <string name="ethernet_label" msgid="7967563676324087464">"以太網"</string>
+ <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"飛行模式"</string>
+ <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"充電中 (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
+ <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"充電完成"</string>
+ <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"藍牙"</string>
+ <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"藍牙 (<xliff:g id="NUMBER">%d</xliff:g> 部裝置)"</string>
+ <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"藍牙關閉"</string>
+ <string name="quick_settings_brightness_label" msgid="6968372297018755815">"亮度"</string>
+ <string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"自動旋轉"</string>
+ <string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"已鎖定屏幕旋轉功能"</string>
+ <string name="quick_settings_ime_label" msgid="7073463064369468429">"輸入法"</string>
+ <string name="quick_settings_location_label" msgid="5011327048748762257">"位置"</string>
+ <string name="quick_settings_location_off_label" msgid="7464544086507331459">"位置關閉"</string>
+ <string name="quick_settings_media_device_label" msgid="1302906836372603762">"媒體裝置"</string>
+ <string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
+ <string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"只可撥打緊急電話"</string>
+ <string name="quick_settings_settings_label" msgid="5326556592578065401">"設定"</string>
+ <string name="quick_settings_time_label" msgid="4635969182239736408">"時間"</string>
+ <string name="quick_settings_user_label" msgid="5238995632130897840">"我"</string>
+ <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
+ <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"未連線"</string>
+ <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"沒有網絡"</string>
+ <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi 關閉"</string>
+ <string name="quick_settings_wifi_display_label" msgid="6893592964463624333">"Wi-Fi Display"</string>
+ <string name="quick_settings_wifi_display_no_connection_label" msgid="2355298740765736918">"無線顯示"</string>
+ <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"亮度"</string>
+ <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"自動"</string>
+ <string name="status_bar_help_title" msgid="1199237744086469217">"通知會在這裡顯示"</string>
+ <string name="status_bar_help_text" msgid="7874607155052076323">"向下快速滑動可隨時存取通知。\n再次向下快速滑動則可使用系統控制介面。"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index a0bb92a..1d5b2ac 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -203,6 +203,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"自動"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"系統會在這裡顯示通知"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"向下滑動即可隨時存取通知。\n再次向下滑動即可使用系統控制項。"</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"從螢幕邊緣向內滑動即可顯示導覽列"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"從螢幕邊緣向內滑動即可顯示導覽列"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 53e7db0..662d3cb 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -201,6 +201,4 @@
<string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"OKUZENZAKALELAYO"</string>
<string name="status_bar_help_title" msgid="1199237744086469217">"Izaziso zivela lapha"</string>
<string name="status_bar_help_text" msgid="7874607155052076323">"Kufinyelele noma kunini ngokuswayiphela phansi.\nSwayiphela phansi futhi ngezilawuli zesistimu."</string>
- <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Swayipha kunqenqema lwesikrini ukuze uveze ibha"</string>
- <string name="hiding_navigation_confirmation_message_long" msgid="7854368870786524950">"Swayipha kusuka kunqenqema ukuze uveze ibha yesistimu"</string>
</resources>
diff --git a/packages/SystemUI/res/values/arrays.xml b/packages/SystemUI/res/values/arrays.xml
index cd6aaf6..506722d 100644
--- a/packages/SystemUI/res/values/arrays.xml
+++ b/packages/SystemUI/res/values/arrays.xml
@@ -40,4 +40,16 @@
<item>@null</item>
</array>
+ <!-- BatteryMeterView parameters -->
+ <array name="batterymeter_color_levels">
+ <item>4</item>
+ <item>15</item>
+ <item>100</item>
+ </array>
+ <array name="batterymeter_color_values">
+ <item>#FFFF0000</item>
+ <item>#FFFE6600</item>
+ <item>#FF3792B4</item>
+ </array>
+
</resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 4a7d090..5718db2 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -20,6 +20,10 @@
<drawable name="notification_number_text_color">#ffffffff</drawable>
<drawable name="ticker_background_color">#ff1d1d1d</drawable>
<drawable name="status_bar_background">#ff000000</drawable>
+ <color name="status_bar_background_semi_transparent">#55000000</color>
+ <color name="status_bar_background_transparent">#00000000</color>
+ <color name="navigation_bar_background_transparent_start">#7f000000</color>
+ <color name="navigation_bar_background_transparent_end">#00000000</color>
<color name="notification_panel_solid_background">#ff000000</color>
<drawable name="status_bar_recents_app_thumbnail_background">#88000000</drawable>
<color name="status_bar_recents_app_label_color">#ffffffff</color>
@@ -30,4 +34,6 @@
<drawable name="heads_up_notification_bg_pressed">#ff33B5E5</drawable>
<drawable name="notification_header_bg">#FF000000</drawable>
<color name="notification_panel_scrim_color">#B0000000</color>
+
+ <color name="batterymeter_frame_color">#FF404040</color>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 33a85c3..c849aa6 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -504,9 +504,6 @@
<!-- Body of help text shown when the notification panel is pulled down for the very first time. [CHAR LIMIT=NONE] -->
<string name="status_bar_help_text">Access them anytime by swiping down.\nSwipe down again for system controls.</string>
- <!-- Toast bar message when hiding the navigation bar -->
- <string name="hiding_navigation_confirmation_message">Swipe edge of screen to reveal bar</string>
-
- <!-- Longer version of toast bar message when hiding the navigation bar (if room) -->
- <string name="hiding_navigation_confirmation_message_long">Swipe from edge of screen to reveal system bar</string>
+ <!-- Glyph to be overlaid atop the battery when the level is extremely low. Do not translate. -->
+ <string name="battery_meter_very_low_overlay_symbol">!</string>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
new file mode 100755
index 0000000..aa4362e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Typeface;
+import android.graphics.drawable.Drawable;
+import android.os.BatteryManager;
+import android.provider.Settings;
+import android.util.AttributeSet;
+import android.view.View;
+
+public class BatteryMeterView extends View {
+ public static final String TAG = BatteryMeterView.class.getSimpleName();
+ public static final String ACTION_LEVEL_TEST = "com.android.systemui.BATTERY_LEVEL_TEST";
+
+ public static final boolean ENABLE_PERCENT = true;
+ public static final boolean SINGLE_DIGIT_PERCENT = false;
+ public static final boolean SHOW_100_PERCENT = false;
+
+ public static final int FULL = 96;
+ public static final int EMPTY = 4;
+
+ int[] mColors;
+
+ boolean mShowPercent = true;
+ Paint mFramePaint, mBatteryPaint, mWarningTextPaint, mTextPaint;
+ int mButtonHeight;
+ private float mTextHeight, mWarningTextHeight;
+ Drawable mLightning;
+
+ private int mHeight;
+ private int mWidth;
+ private String mWarningString;
+
+ private class BatteryTracker extends BroadcastReceiver {
+ // current battery status
+ int level;
+ String percentStr;
+ int plugType;
+ boolean plugged;
+ int health;
+ int status;
+ String technology;
+ int voltage;
+ int temperature;
+ boolean testmode = false;
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
+ if (testmode && ! intent.getBooleanExtra("testmode", false)) return;
+
+ level = (int)(100f
+ * intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)
+ / intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100));
+
+ plugType = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
+ plugged = plugType != 0;
+ health = intent.getIntExtra(BatteryManager.EXTRA_HEALTH,
+ BatteryManager.BATTERY_HEALTH_UNKNOWN);
+ status = intent.getIntExtra(BatteryManager.EXTRA_STATUS,
+ BatteryManager.BATTERY_STATUS_UNKNOWN);
+ technology = intent.getStringExtra(BatteryManager.EXTRA_TECHNOLOGY);
+ voltage = intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, 0);
+ temperature = intent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, 0);
+
+ setContentDescription(
+ context.getString(R.string.accessibility_battery_level, level));
+ postInvalidate();
+ } else if (action.equals(ACTION_LEVEL_TEST)) {
+ testmode = true;
+ post(new Runnable() {
+ int curLevel = 0;
+ int incr = 1;
+ int saveLevel = level;
+ int savePlugged = plugType;
+ Intent dummy = new Intent(Intent.ACTION_BATTERY_CHANGED);
+ @Override
+ public void run() {
+ if (curLevel < 0) {
+ testmode = false;
+ dummy.putExtra("level", saveLevel);
+ dummy.putExtra("plugged", savePlugged);
+ dummy.putExtra("testmode", false);
+ } else {
+ dummy.putExtra("level", curLevel);
+ dummy.putExtra("plugged", incr > 0 ? BatteryManager.BATTERY_PLUGGED_AC : 0);
+ dummy.putExtra("testmode", true);
+ }
+ getContext().sendBroadcast(dummy);
+
+ if (!testmode) return;
+
+ curLevel += incr;
+ if (curLevel == 100) {
+ incr *= -1;
+ }
+ postDelayed(this, 200);
+ }
+ });
+ }
+ }
+ }
+
+ BatteryTracker mTracker = new BatteryTracker();
+
+ @Override
+ public void onAttachedToWindow() {
+ super.onAttachedToWindow();
+
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_BATTERY_CHANGED);
+ filter.addAction(ACTION_LEVEL_TEST);
+ getContext().registerReceiver(mTracker, filter);
+ }
+
+ @Override
+ public void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+
+ getContext().unregisterReceiver(mTracker);
+ }
+
+ public BatteryMeterView(Context context) {
+ this(context, null, 0);
+ }
+
+ public BatteryMeterView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public BatteryMeterView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ final Resources res = context.getResources();
+ TypedArray levels = res.obtainTypedArray(R.array.batterymeter_color_levels);
+ TypedArray colors = res.obtainTypedArray(R.array.batterymeter_color_values);
+
+ final int N = levels.length();
+ mColors = new int[2*N];
+ for (int i=0; i<N; i++) {
+ mColors[2*i] = levels.getInt(i, 0);
+ mColors[2*i+1] = colors.getColor(i, 0);
+ }
+
+ mShowPercent = ENABLE_PERCENT && 0 != Settings.System.getInt(
+ context.getContentResolver(), "status_bar_show_battery_percent", 0);
+
+ mWarningString = context.getString(R.string.battery_meter_very_low_overlay_symbol);
+
+ mFramePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mFramePaint.setColor(res.getColor(R.color.batterymeter_frame_color));
+ mBatteryPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mBatteryPaint.setColor(0xFF00FF00); // will be replaced by something from mColors
+
+ mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mTextPaint.setColor(0xFFFFFFFF);
+ Typeface font = Typeface.create("sans-serif-condensed", Typeface.NORMAL);
+ mTextPaint.setTypeface(font);
+ mTextPaint.setTextAlign(Paint.Align.CENTER);
+
+ mWarningTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ mWarningTextPaint.setColor(mColors[1]);
+ font = Typeface.create("sans-serif", Typeface.BOLD);
+ mWarningTextPaint.setTypeface(font);
+ mWarningTextPaint.setTextAlign(Paint.Align.CENTER);
+
+ mLightning = getResources().getDrawable(R.drawable.lightning);
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ mHeight = h;
+ mWidth = w;
+ mWarningTextPaint.setTextSize(h * 0.75f);
+ mWarningTextHeight = -mWarningTextPaint.getFontMetrics().ascent;
+ }
+
+ private int getColorForLevel(int percent) {
+ int thresh, color = 0;
+ for (int i=0; i<mColors.length; i+=2) {
+ thresh = mColors[i];
+ color = mColors[i+1];
+ if (percent <= thresh) return color;
+ }
+ return color;
+ }
+
+ @Override
+ public void draw(Canvas c) {
+ final int level = mTracker.level;
+ float drawFrac = (float) level / 100f;
+ final int pt = getPaddingTop();
+ final int pl = getPaddingLeft();
+ final int pr = getPaddingRight();
+ final int pb = getPaddingBottom();
+ int height = mHeight - pt - pb;
+ int width = mWidth - pl - pr;
+
+ mButtonHeight = (int) (height * 0.12f);
+
+ final RectF frame = new RectF(0, 0, width, height);
+ frame.offset(pl, pt);
+
+ // Log.v("BatteryGauge", String.format("canvas: %dx%d frame: %s",
+ // c.getWidth(), c.getHeight(), frame.toString()));
+
+ final RectF buttonframe = new RectF(
+ frame.left + width * 0.25f,
+ frame.top,
+ frame.right - width * 0.25f,
+ frame.top + mButtonHeight);
+
+ frame.top += mButtonHeight;
+
+ // first, draw the battery shape
+ c.drawRect(frame, mFramePaint);
+
+ // fill 'er up
+ final int pct = mTracker.level;
+ final int color = getColorForLevel(pct);
+ mBatteryPaint.setColor(color);
+
+ if (level >= FULL) {
+ drawFrac = 1f;
+ } else if (level <= EMPTY) {
+ drawFrac = 0f;
+ }
+
+ c.drawRect(buttonframe,
+ drawFrac == 1f ? mBatteryPaint : mFramePaint);
+
+ RectF clip = new RectF(frame);
+ clip.top += (frame.height() * (1f - drawFrac));
+
+ c.save(Canvas.CLIP_SAVE_FLAG);
+ c.clipRect(clip);
+ c.drawRect(frame, mBatteryPaint);
+ c.restore();
+
+ if (level <= EMPTY) {
+ final float x = mWidth * 0.5f;
+ final float y = (mHeight + mWarningTextHeight) * 0.48f;
+ c.drawText(mWarningString, x, y, mWarningTextPaint);
+ } else if (mTracker.plugged) {
+ final Rect r = new Rect(
+ (int)frame.left + width / 4, (int)frame.top + height / 5,
+ (int)frame.right - width / 4, (int)frame.bottom - height / 6);
+ mLightning.setBounds(r);
+ mLightning.draw(c);
+ } else if (mShowPercent && !(mTracker.level == 100 && !SHOW_100_PERCENT)) {
+ mTextPaint.setTextSize(height *
+ (SINGLE_DIGIT_PERCENT ? 0.75f
+ : (mTracker.level == 100 ? 0.38f : 0.5f)));
+ mTextHeight = -mTextPaint.getFontMetrics().ascent;
+
+ final String str = String.valueOf(SINGLE_DIGIT_PERCENT ? (pct/10) : pct);
+ final float x = mWidth * 0.5f;
+ final float y = (mHeight + mTextHeight) * 0.47f;
+ c.drawText(str,
+ x,
+ y,
+ mTextPaint);
+
+// Paint pt = new Paint();
+// pt.setStrokeWidth(1f);
+// pt.setStyle(Paint.Style.STROKE);
+// pt.setColor(0xFFFF0000);
+// c.drawRect(x, y-mTextHeight, x+tw, y, pt);
+//
+// Slog.v(TAG, "tw=" + tw + " th=" + mTextHeight);
+//
+// pt.setColor(0xFFFF00FF);
+// c.drawRect(1, 1, mWidth, mHeight, pt);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index f17b143..ff84243 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -135,9 +135,9 @@ public class SignalClusterView
public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
// Standard group layout onPopulateAccessibilityEvent() implementations
// ignore content description, so populate manually
- if (mWifiVisible && mWifiGroup.getContentDescription() != null)
+ if (mWifiVisible && mWifiGroup != null && mWifiGroup.getContentDescription() != null)
event.getText().add(mWifiGroup.getContentDescription());
- if (mMobileVisible && mMobileGroup.getContentDescription() != null)
+ if (mMobileVisible && mMobileGroup != null && mMobileGroup.getContentDescription() != null)
event.getText().add(mMobileGroup.getContentDescription());
return super.dispatchPopulateAccessibilityEvent(event);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
new file mode 100644
index 0000000..e40c4e5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BarTransitions.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.animation.ArgbEvaluator;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.util.Log;
+import android.view.View;
+
+import com.android.systemui.R;
+
+public class BarTransitions {
+ private static final boolean DEBUG = false;
+
+ public static final int MODE_OPAQUE = 0;
+ public static final int MODE_SEMI_TRANSPARENT = 1;
+ public static final int MODE_TRANSPARENT = 2;
+
+ private final String mTag;
+ private final View mTarget;
+ private final int mOpaque;
+ private final int mSemiTransparent;
+
+ protected Drawable mTransparent;
+ private int mMode;
+
+ private final AnimatorUpdateListener mBackgroundColorListener = new AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animator) {
+ mTarget.setBackgroundColor((Integer) animator.getAnimatedValue());
+ }
+ };
+
+ public BarTransitions(Context context, View target) {
+ mTag = "BarTransitions." + target.getClass().getSimpleName();
+ mTarget = target;
+ final Resources res = context.getResources();
+ mOpaque = res.getColor(R.drawable.status_bar_background);
+ mSemiTransparent = res.getColor(R.color.status_bar_background_semi_transparent);
+ }
+
+ public void setTransparent(Drawable transparent) {
+ mTransparent = transparent;
+ if (mMode == MODE_TRANSPARENT) {
+ transitionTo(MODE_TRANSPARENT);
+ }
+ }
+
+ public void transitionTo(int mode) {
+ transitionTo(mode, false);
+ }
+
+ public void transitionTo(int mode, boolean animate) {
+ if (mMode == mode) return;
+ int oldMode = mMode;
+ mMode = mode;
+ if (!ActivityManager.isHighEndGfx()) return;
+ if (DEBUG) Log.d(mTag, modeToString(oldMode) + " -> " + modeToString(mode));
+ onTransition(oldMode, mMode, animate);
+ }
+
+ protected void onTransition(int oldMode, int newMode, boolean animate) {
+ if (animate && oldMode == MODE_SEMI_TRANSPARENT && newMode == MODE_OPAQUE) {
+ startColorAnimation(mSemiTransparent, mOpaque);
+ } else if (animate && oldMode == MODE_OPAQUE && newMode == MODE_SEMI_TRANSPARENT) {
+ startColorAnimation(mOpaque, mSemiTransparent);
+ } else if (newMode == MODE_OPAQUE || newMode == MODE_SEMI_TRANSPARENT) {
+ mTarget.setBackgroundColor(newMode == MODE_OPAQUE ? mOpaque : mSemiTransparent);
+ } else {
+ mTarget.setBackground(newMode == MODE_TRANSPARENT? mTransparent
+ : newMode == MODE_SEMI_TRANSPARENT ? new ColorDrawable(mSemiTransparent)
+ : new ColorDrawable(mOpaque));
+ }
+ }
+
+ private void startColorAnimation(int from, int to) {
+ ValueAnimator anim = ValueAnimator.ofObject(new ArgbEvaluator(), from, to);
+ anim.addUpdateListener(mBackgroundColorListener);
+ anim.start();
+ }
+
+ public static String modeToString(int mode) {
+ if (mode == MODE_OPAQUE) return "MODE_OPAQUE";
+ if (mode == MODE_SEMI_TRANSPARENT) return "MODE_SEMI_TRANSPARENT";
+ if (mode == MODE_TRANSPARENT) return "MODE_TRANSPARENT";
+ throw new IllegalArgumentException("Unknown mode " + mode);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index de33b87..62f8596 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -25,6 +25,8 @@ import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.GradientDrawable;
+import android.graphics.drawable.GradientDrawable.Orientation;
import android.os.Handler;
import android.os.Message;
import android.os.ServiceManager;
@@ -45,6 +47,7 @@ import com.android.systemui.R;
import com.android.systemui.statusbar.BaseStatusBar;
import com.android.systemui.statusbar.DelegateViewHelper;
import com.android.systemui.statusbar.policy.DeadZone;
+import com.android.systemui.statusbar.policy.KeyButtonView;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -79,6 +82,7 @@ public class NavigationBarView extends LinearLayout {
private DelegateViewHelper mDelegateHelper;
private DeadZone mDeadZone;
+ private final NavigationBarTransitions mBarTransitions;
// workaround for LayoutTransitions leaving the nav buttons in a weird state (bug 5549288)
final static boolean WORKAROUND_INVALID_LAYOUT = true;
@@ -107,6 +111,68 @@ public class NavigationBarView extends LinearLayout {
}
}
+ private final class NavigationBarTransitions extends BarTransitions {
+
+ private final Drawable mTransparentBottom;
+ private final Drawable mTransparentRight;
+
+ public NavigationBarTransitions(Context context) {
+ super(context, NavigationBarView.this);
+ final Resources res = mContext.getResources();
+ final int[] gradientColors = new int[] {
+ res.getColor(R.color.navigation_bar_background_transparent_start),
+ res.getColor(R.color.navigation_bar_background_transparent_end)
+ };
+ mTransparentBottom = new GradientDrawable(Orientation.BOTTOM_TOP, gradientColors);
+ mTransparentRight = new GradientDrawable(Orientation.RIGHT_LEFT, gradientColors);
+ }
+
+ public void setVertical(boolean isVertical) {
+ mTransparent = isVertical ? mTransparentRight : mTransparentBottom;
+ }
+
+ @Override
+ protected void onTransition(int oldMode, int newMode, boolean animate) {
+ super.onTransition(oldMode, newMode, animate);
+ final float alpha = newMode == MODE_OPAQUE ? KeyButtonView.DEFAULT_QUIESCENT_ALPHA : 1f;
+ setKeyButtonViewQuiescentAlpha(getBackButton(), alpha);
+ setKeyButtonViewQuiescentAlpha(getHomeButton(), alpha);
+ setKeyButtonViewQuiescentAlpha(getRecentsButton(), alpha);
+ setKeyButtonViewQuiescentAlpha(getMenuButton(), alpha);
+ }
+
+ private void setKeyButtonViewQuiescentAlpha(View button, float alpha) {
+ if (button instanceof KeyButtonView) {
+ ((KeyButtonView) button).setQuiescentAlpha(alpha);
+ }
+ }
+ }
+
+ public NavigationBarView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ mHidden = false;
+
+ mDisplay = ((WindowManager)context.getSystemService(
+ Context.WINDOW_SERVICE)).getDefaultDisplay();
+ mBarService = IStatusBarService.Stub.asInterface(
+ ServiceManager.getService(Context.STATUS_BAR_SERVICE));
+
+ final Resources res = mContext.getResources();
+ mBarSize = res.getDimensionPixelSize(R.dimen.navigation_bar_size);
+ mVertical = false;
+ mShowMenu = false;
+ mDelegateHelper = new DelegateViewHelper(this);
+
+ getIcons(res);
+
+ mBarTransitions = new NavigationBarTransitions(context);
+ }
+
+ public BarTransitions getBarTransitions() {
+ return mBarTransitions;
+ }
+
public void setDelegateView(View view) {
mDelegateHelper.setDelegateView(view);
}
@@ -155,25 +221,6 @@ public class NavigationBarView extends LinearLayout {
return mCurrentView.findViewById(R.id.search_light);
}
- public NavigationBarView(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- mHidden = false;
-
- mDisplay = ((WindowManager)context.getSystemService(
- Context.WINDOW_SERVICE)).getDefaultDisplay();
- mBarService = IStatusBarService.Stub.asInterface(
- ServiceManager.getService(Context.STATUS_BAR_SERVICE));
-
- final Resources res = mContext.getResources();
- mBarSize = res.getDimensionPixelSize(R.dimen.navigation_bar_size);
- mVertical = false;
- mShowMenu = false;
- mDelegateHelper = new DelegateViewHelper(this);
-
- getIcons(res);
- }
-
private void getIcons(Resources res) {
mBackIcon = res.getDrawable(R.drawable.ic_sysbar_back);
mBackLandIcon = res.getDrawable(R.drawable.ic_sysbar_back_land);
@@ -406,6 +453,7 @@ public class NavigationBarView extends LinearLayout {
}
setNavigationIconHints(mNavigationIconHints, true);
+ mBarTransitions.setVertical(mVertical);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index d0a6385..4b2c3e1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -76,6 +76,7 @@ public class PanelView extends FrameLayout {
private boolean mClosing;
private boolean mRubberbanding;
private boolean mTracking;
+ private int mTrackingPointer;
private TimeAnimator mTimeAnimator;
private ObjectAnimator mPeekAnimator;
@@ -118,7 +119,7 @@ public class PanelView extends FrameLayout {
int i = 0;
float totalweight = 0f;
float weight = 10f;
- for (final Iterator<MotionEventCopy> iter = mEventBuf.descendingIterator();
+ for (final Iterator<MotionEventCopy> iter = mEventBuf.iterator();
iter.hasNext();) {
final MotionEventCopy event = iter.next();
if (last != null) {
@@ -126,13 +127,22 @@ public class PanelView extends FrameLayout {
final float dx = (event.x - last.x);
final float dy = (event.y - last.y);
if (FlingTracker.DEBUG) {
- Log.v("FlingTracker", String.format(" [%d] dx=%.1f dy=%.1f dt=%.0f vx=%.1f vy=%.1f",
- i,
+ Log.v("FlingTracker", String.format(
+ " [%d] (t=%d %.1f,%.1f) dx=%.1f dy=%.1f dt=%f vx=%.1f vy=%.1f",
+ i, event.t, event.x, event.y,
dx, dy, dt,
(dx/dt),
(dy/dt)
));
}
+ if (event.t == last.t) {
+ // Really not sure what to do with events that happened at the same time,
+ // so we'll skip subsequent events.
+ if (DEBUG_NAN) {
+ Log.v("FlingTracker", "skipping simultaneous event at t=" + event.t);
+ }
+ continue;
+ }
mVX += weight * dx / dt;
mVY += weight * dy / dt;
totalweight += weight;
@@ -158,18 +168,18 @@ public class PanelView extends FrameLayout {
}
}
public float getXVelocity() {
- if (Float.isNaN(mVX)) {
+ if (Float.isNaN(mVX) || Float.isInfinite(mVX)) {
if (DEBUG_NAN) {
- Log.v("FlingTracker", "warning: vx=NaN");
+ Log.v("FlingTracker", "warning: vx=" + mVX);
}
mVX = 0;
}
return mVX;
}
public float getYVelocity() {
- if (Float.isNaN(mVY)) {
+ if (Float.isNaN(mVY) || Float.isInfinite(mVX)) {
if (DEBUG_NAN) {
- Log.v("FlingTracker", "warning: vx=NaN");
+ Log.v("FlingTracker", "warning: vx=" + mVY);
}
mVY = 0;
}
@@ -371,14 +381,21 @@ public class PanelView extends FrameLayout {
mHandleView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
- final float y = event.getY();
- final float rawY = event.getRawY();
- if (DEBUG) logf("handle.onTouch: a=%s y=%.1f rawY=%.1f off=%.1f",
+ int pointerIndex = event.findPointerIndex(mTrackingPointer);
+ if (pointerIndex < 0) {
+ pointerIndex = 0;
+ mTrackingPointer = event.getPointerId(pointerIndex);
+ }
+ final float y = event.getY(pointerIndex);
+ final float rawDelta = event.getRawY() - event.getY();
+ final float rawY = y + rawDelta;
+ if (DEBUG) logf("handle.onTouch: a=%s p=[%d,%d] y=%.1f rawY=%.1f off=%.1f",
MotionEvent.actionToString(event.getAction()),
+ mTrackingPointer, pointerIndex,
y, rawY, mTouchOffset);
PanelView.this.getLocationOnScreen(mAbsPos);
- switch (event.getAction()) {
+ switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
mTracking = true;
mHandleView.setPressed(true);
@@ -388,13 +405,26 @@ public class PanelView extends FrameLayout {
trackMovement(event);
mTimeAnimator.cancel(); // end any outstanding animations
mBar.onTrackingStarted(PanelView.this);
- mTouchOffset = (rawY - mAbsPos[1]) - PanelView.this.getExpandedHeight();
+ mTouchOffset = (rawY - mAbsPos[1]) - mExpandedHeight;
if (mExpandedHeight == 0) {
mJustPeeked = true;
runPeekAnimation();
}
break;
+ case MotionEvent.ACTION_POINTER_UP:
+ final int upPointer = event.getPointerId(event.getActionIndex());
+ if (mTrackingPointer == upPointer) {
+ // gesture is ongoing, find a new pointer to track
+ final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1;
+ final float newY = event.getY(newIndex);
+ final float newRawY = newY + rawDelta;
+ mTrackingPointer = event.getPointerId(newIndex);
+ mTouchOffset = (newRawY - mAbsPos[1]) - mExpandedHeight;
+ mInitialTouchY = newY;
+ }
+ break;
+
case MotionEvent.ACTION_MOVE:
final float h = rawY - mAbsPos[1] - mTouchOffset;
if (h > mPeekHeight) {
@@ -415,6 +445,7 @@ public class PanelView extends FrameLayout {
case MotionEvent.ACTION_CANCEL:
mFinalTouchY = y;
mTracking = false;
+ mTrackingPointer = -1;
mHandleView.setPressed(false);
postInvalidate(); // catch the press state change
mBar.onTrackingStopped(PanelView.this);
@@ -613,6 +644,10 @@ public class PanelView extends FrameLayout {
return mClosing;
}
+ public boolean isTracking() {
+ return mTracking;
+ }
+
public void setBar(PanelBar panelBar) {
mBar = panelBar;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index c914a34..ad53fea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -16,6 +16,10 @@
package com.android.systemui.statusbar.phone;
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
@@ -57,7 +61,6 @@ import android.view.Gravity;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
-import android.view.View.MeasureSpec;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewPropertyAnimator;
@@ -72,7 +75,7 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
-import android.widget.Toast;
+
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.EventLogTags;
import com.android.systemui.R;
@@ -129,14 +132,7 @@ public class PhoneStatusBar extends BaseStatusBar {
private static final int STATUS_OR_NAV_TRANSIENT =
View.STATUS_BAR_TRANSIENT | View.NAVIGATION_BAR_TRANSIENT;
- private static final int TRANSIENT_NAV_HIDING =
- View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_ALLOW_TRANSIENT;
private static final long AUTOHIDE_TIMEOUT_MS = 3000;
- private static final float TRANSPARENT_ALPHA = 0.7f;
-
- private static final int BAR_MODE_NORMAL = 0;
- private static final int BAR_MODE_TRANSIENT = 1;
- private static final int BAR_MODE_TRANSPARENT = 2;
// fling gesture tuning parameters, scaled to display density
private float mSelfExpandVelocityPx; // classic value: 2000px/s
@@ -314,37 +310,6 @@ public class PhoneStatusBar extends BaseStatusBar {
}
};
- private Toast mHidingNavigationConfirmation;
- private boolean mHidingNavigationConfirmationDismissed;
-
- private final View.OnTouchListener mDismissHidingNavigationConfirmationOnTouchOutside =
- new View.OnTouchListener() {
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- if (event.getActionMasked() == MotionEvent.ACTION_OUTSIDE) {
- dismissHidingNavigationConfirmation();
- }
- return false;
- }
- };
-
- private final Runnable mHidingNavigationConfirmationAction = new Runnable() {
- @Override
- public void run() {
- if (mHidingNavigationConfirmation != null) {
- final boolean isGloballyConfirmed = Prefs.read(mContext)
- .getBoolean(Prefs.HIDING_NAVIGATION_CONFIRMED, false);
- if (!isGloballyConfirmed) {
- // user pressed button, consider this a confirmation
- Prefs.edit(mContext)
- .putBoolean(Prefs.HIDING_NAVIGATION_CONFIRMED, true)
- .apply();
- }
- dismissHidingNavigationConfirmation();
- }
- }
- };
-
private boolean mAutohideSuspended;
private final Runnable mAutohide = new Runnable() {
@@ -542,7 +507,6 @@ public class PhoneStatusBar extends BaseStatusBar {
// Other icons
mLocationController = new LocationController(mContext); // will post a notification
mBatteryController = new BatteryController(mContext);
- mBatteryController.addIconView((ImageView)mStatusBarView.findViewById(R.id.battery));
mNetworkController = new NetworkController(mContext);
mBluetoothController = new BluetoothController(mContext);
mRotationLockController = new RotationLockController(mContext);
@@ -971,7 +935,7 @@ public class PhoneStatusBar extends BaseStatusBar {
}
if (CLOSE_PANEL_WHEN_EMPTIED && mNotificationData.size() == 0
- && !mStatusBarWindow.isPointerDown()) {
+ && !mNotificationPanel.isTracking()) {
animateCollapsePanels();
}
}
@@ -1939,97 +1903,56 @@ public class PhoneStatusBar extends BaseStatusBar {
}
// update status bar mode
- int sbMode = updateBarMode(oldVal, newVal, mStatusBarView,
+ int sbMode = updateBarMode(oldVal, newVal, mStatusBarView.getBarTransitions(),
View.STATUS_BAR_TRANSIENT, View.SYSTEM_UI_FLAG_TRANSPARENT_STATUS);
// update navigation bar mode
- int nbMode = updateBarMode(oldVal, newVal, mNavigationBarView,
+ int nbMode = updateBarMode(oldVal, newVal, mNavigationBarView.getBarTransitions(),
View.NAVIGATION_BAR_TRANSIENT, View.SYSTEM_UI_FLAG_TRANSPARENT_NAVIGATION);
if (sbMode != -1 || nbMode != -1) {
// update transient bar autohide
- if (sbMode == BAR_MODE_TRANSIENT || nbMode == BAR_MODE_TRANSIENT) {
+ if (sbMode == MODE_SEMI_TRANSPARENT || nbMode == MODE_SEMI_TRANSPARENT) {
scheduleAutohide();
} else {
cancelAutohide();
}
}
- // update hiding navigation confirmation
- if (mNavigationBarView != null) {
- boolean oldShowConfirm = (oldVal & TRANSIENT_NAV_HIDING) == TRANSIENT_NAV_HIDING;
- boolean newShowConfirm = (newVal & TRANSIENT_NAV_HIDING) == TRANSIENT_NAV_HIDING;
- if (!oldShowConfirm && newShowConfirm) {
- mHidingNavigationConfirmationDismissed = false;
- }
- setHidingNavigationConfirmationVisible(newShowConfirm);
- }
-
// send updated sysui visibility to window manager
notifyUiVisibilityChanged(mSystemUiVisibility);
}
}
- private int updateBarMode(int oldVis, int newVis, View view,
+ private int updateBarMode(int oldVis, int newVis, BarTransitions transitions,
int transientFlag, int transparentFlag) {
final int oldMode = barMode(oldVis, transientFlag, transparentFlag);
final int newMode = barMode(newVis, transientFlag, transparentFlag);
if (oldMode == newMode) {
return -1; // no mode change
}
- setTransparent(view, newMode != BAR_MODE_NORMAL);
+ transitions.transitionTo(newMode);
return newMode;
}
private int barMode(int vis, int transientFlag, int transparentFlag) {
- return (vis & transientFlag) != 0 ? BAR_MODE_TRANSIENT
- : (vis & transparentFlag) != 0 ? BAR_MODE_TRANSPARENT
- : BAR_MODE_NORMAL;
- }
-
- private void dismissHidingNavigationConfirmation() {
- if (mHidingNavigationConfirmation != null) {
- mHidingNavigationConfirmationDismissed = true;
- mHidingNavigationConfirmation.cancel();
- mHidingNavigationConfirmation = null;
- }
- }
-
- private void setHidingNavigationConfirmationVisible(boolean visible) {
- if (DEBUG) Log.d(TAG, "setHidingNavigationConfirmationVisible " + visible);
- if (visible &&
- mHidingNavigationConfirmation == null && !mHidingNavigationConfirmationDismissed) {
- // create the confirmation toast bar
- int msg = R.string.hiding_navigation_confirmation_message;
- mHidingNavigationConfirmation = Toast.makeBar(mContext, msg, Toast.LENGTH_INFINITE)
- .setAction(com.android.internal.R.string.ok,
- mHidingNavigationConfirmationAction);
- View v = mHidingNavigationConfirmation.getView();
- v.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
- boolean isGloballyConfirmed = Prefs.read(mContext)
- .getBoolean(Prefs.HIDING_NAVIGATION_CONFIRMED, false);
- if (isGloballyConfirmed) {
- // dismiss on outside touch if globally confirmed
- v.setOnTouchListener(mDismissHidingNavigationConfirmationOnTouchOutside);
- }
- // position at the bottom like normal toasts, but use top gravity
- // to avoid jumping around when showing/hiding the nav bar
- v.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
- int offsetY = mContext.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.toast_y_offset);
- mHidingNavigationConfirmation.setGravity(Gravity.TOP,
- 0, mCurrentDisplaySize.y - v.getMeasuredHeight() / 2 - offsetY);
- // show the confirmation
- mHidingNavigationConfirmation.show();
- } else if (!visible) {
- dismissHidingNavigationConfirmation();
- }
+ return (vis & transientFlag) != 0 ? MODE_SEMI_TRANSPARENT
+ : (vis & transparentFlag) != 0 ? MODE_TRANSPARENT
+ : MODE_OPAQUE;
}
@Override
public void resumeAutohide() {
if (mAutohideSuspended) {
scheduleAutohide();
+ animateTransitionTo(BarTransitions.MODE_SEMI_TRANSPARENT);
+ }
+ }
+
+ private void animateTransitionTo(int newMode) {
+ mStatusBarView.getBarTransitions().transitionTo(newMode, true /*animate*/);
+ if (mNavigationBarView != null) {
+ mNavigationBarView.getBarTransitions().transitionTo(newMode, true /*animate*/);
}
}
@@ -2037,6 +1960,7 @@ public class PhoneStatusBar extends BaseStatusBar {
public void suspendAutohide() {
mHandler.removeCallbacks(mAutohide);
mAutohideSuspended = 0 != (mSystemUiVisibility & STATUS_OR_NAV_TRANSIENT);
+ animateTransitionTo(BarTransitions.MODE_OPAQUE);
}
private void cancelAutohide() {
@@ -2063,13 +1987,6 @@ public class PhoneStatusBar extends BaseStatusBar {
mHandler.postDelayed(mAutohide, 25);
}
- private void setTransparent(View view, boolean transparent) {
- float alpha = transparent ? TRANSPARENT_ALPHA : 1;
- if (DEBUG) Log.d(TAG, "Setting " + (view == mStatusBarView ? "status bar" :
- view == mNavigationBarView ? "navigation bar" : "view") + " alpha to " + alpha);
- view.setAlpha(alpha);
- }
-
private void setStatusBarLowProfile(boolean lightsOut) {
if (mLightsOutAnimation == null) {
final View notifications = mStatusBarView.findViewById(R.id.notification_icon_area);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 1554e2c..910d4c4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -17,10 +17,10 @@
package com.android.systemui.statusbar.phone;
import android.app.ActivityManager;
-import android.app.StatusBarManager;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.Resources.NotFoundException;
+import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.EventLog;
import android.util.Log;
@@ -46,6 +46,15 @@ public class PhoneStatusBarView extends PanelBar {
PanelView mLastFullyOpenedPanel = null;
PanelView mNotificationPanel, mSettingsPanel;
private boolean mShouldFade;
+ private final StatusBarTransitions mBarTransitions;
+
+ private final class StatusBarTransitions extends BarTransitions {
+ public StatusBarTransitions(Context context) {
+ super(context, PhoneStatusBarView.this);
+ final Resources res = context.getResources();
+ mTransparent = res.getDrawable(R.color.status_bar_background_transparent);
+ }
+ }
public PhoneStatusBarView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -59,6 +68,11 @@ public class PhoneStatusBarView extends PanelBar {
mSettingsPanelDragzoneFrac = 0f;
}
mFullWidthNotifications = mSettingsPanelDragzoneFrac <= 0f;
+ mBarTransitions = new StatusBarTransitions(context);
+ }
+
+ public BarTransitions getBarTransitions() {
+ return mBarTransitions;
}
public void setBar(PhoneStatusBar bar) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
index 5233f42..5f034a8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
@@ -494,7 +494,9 @@ class QuickSettings {
}
// Battery
- final QuickSettingsBasicTile batteryTile = new QuickSettingsBasicTile(mContext);
+ final QuickSettingsTileView batteryTile = (QuickSettingsTileView)
+ inflater.inflate(R.layout.quick_settings_tile, parent, false);
+ batteryTile.setContent(R.layout.quick_settings_tile_battery, inflater);
batteryTile.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -506,9 +508,6 @@ class QuickSettings {
public void refreshView(QuickSettingsTileView unused, State state) {
QuickSettingsModel.BatteryState batteryState =
(QuickSettingsModel.BatteryState) state;
- Drawable d = batteryState.pluggedIn
- ? mChargingBatteryLevels
- : mBatteryLevels;
String t;
if (batteryState.batteryLevel == 100) {
t = mContext.getString(R.string.quick_settings_battery_charged_label);
@@ -519,9 +518,7 @@ class QuickSettings {
: mContext.getString(R.string.status_bar_settings_battery_meter_format,
batteryState.batteryLevel);
}
- batteryTile.setImageDrawable(d);
- batteryTile.getImageView().setImageLevel(batteryState.batteryLevel);
- batteryTile.setText(t);
+ ((TextView)batteryTile.findViewById(R.id.text)).setText(t);
batteryTile.setContentDescription(
mContext.getString(R.string.accessibility_quick_settings_battery, t));
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 800bc02..a600aae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -42,7 +42,6 @@ public class StatusBarWindowView extends FrameLayout
private NotificationRowLayout latestItems;
private NotificationPanelView mNotificationPanel;
private ScrollView mScrollView;
- private boolean mPointerDown;
PhoneStatusBar mService;
@@ -87,7 +86,6 @@ public class StatusBarWindowView extends FrameLayout
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
- registerPointer(ev);
boolean intercept = false;
if (mNotificationPanel.isFullyExpanded() && mScrollView.getVisibility() == View.VISIBLE) {
intercept = mExpandHelper.onInterceptTouchEvent(ev);
@@ -133,21 +131,5 @@ public class StatusBarWindowView extends FrameLayout
mExpandHelper.cancel();
}
}
-
- private void registerPointer(MotionEvent event) {
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- mPointerDown = true;
- break;
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP:
- mPointerDown = false;
- break;
- }
- }
-
- public boolean isPointerDown() {
- return mPointerDown;
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index f325957..924478c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -16,6 +16,9 @@
package com.android.systemui.statusbar.policy;
+import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
+import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
@@ -26,6 +29,7 @@ import android.graphics.drawable.Drawable;
import android.hardware.input.InputManager;
import android.os.SystemClock;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.HapticFeedbackConstants;
import android.view.InputDevice;
import android.view.KeyCharacterMap;
@@ -41,9 +45,10 @@ import com.android.systemui.R;
public class KeyButtonView extends ImageView {
private static final String TAG = "StatusBar.KeyButtonView";
+ private static final boolean DEBUG = false;
final float GLOW_MAX_SCALE_FACTOR = 1.8f;
- final float BUTTON_QUIESCENT_ALPHA = 0.70f;
+ public static final float DEFAULT_QUIESCENT_ALPHA = 0.70f;
long mDownTime;
int mCode;
@@ -51,6 +56,7 @@ public class KeyButtonView extends ImageView {
Drawable mGlowBG;
int mGlowWidth, mGlowHeight;
float mGlowAlpha = 0f, mGlowScale = 1f, mDrawingAlpha = 1f;
+ float mQuiescentAlpha = DEFAULT_QUIESCENT_ALPHA;
boolean mSupportsLongpress = true;
RectF mRect = new RectF(0f,0f,0f,0f);
AnimatorSet mPressedAnim;
@@ -70,6 +76,15 @@ public class KeyButtonView extends ImageView {
}
};
+ private final AnimatorListener mRecoverToQuiescentListener = new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (mQuiescentAlpha != mDrawingAlpha) {
+ animateToQuiescent().setDuration(200).start();
+ }
+ }
+ };
+
public KeyButtonView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
@@ -86,7 +101,7 @@ public class KeyButtonView extends ImageView {
mGlowBG = a.getDrawable(R.styleable.KeyButtonView_glowBackground);
if (mGlowBG != null) {
- setDrawingAlpha(BUTTON_QUIESCENT_ALPHA);
+ setDrawingAlpha(mQuiescentAlpha);
mGlowWidth = mGlowBG.getIntrinsicWidth();
mGlowHeight = mGlowBG.getIntrinsicHeight();
}
@@ -118,6 +133,16 @@ public class KeyButtonView extends ImageView {
super.onDraw(canvas);
}
+ public void setQuiescentAlpha(float alpha) {
+ alpha = Math.min(Math.max(alpha, 0), 1);
+ if (alpha == mQuiescentAlpha) return;
+ mQuiescentAlpha = alpha;
+ if (DEBUG) Log.d(TAG, "New quiescent alpha = " + mQuiescentAlpha);
+ if (mGlowBG != null) {
+ setDrawingAlpha(mQuiescentAlpha);
+ }
+ }
+
public float getDrawingAlpha() {
if (mGlowBG == null) return 0;
return mDrawingAlpha;
@@ -172,6 +197,12 @@ public class KeyButtonView extends ImageView {
}
}
+ private ObjectAnimator animateToQuiescent() {
+ ObjectAnimator anim = ObjectAnimator.ofFloat(this, "drawingAlpha", mQuiescentAlpha);
+ anim.addListener(mRecoverToQuiescentListener); // mQuiescentAlpha may change mid-animation
+ return anim;
+ }
+
public void setPressed(boolean pressed) {
if (mGlowBG != null) {
if (pressed != isPressed()) {
@@ -182,8 +213,8 @@ public class KeyButtonView extends ImageView {
if (pressed) {
if (mGlowScale < GLOW_MAX_SCALE_FACTOR)
mGlowScale = GLOW_MAX_SCALE_FACTOR;
- if (mGlowAlpha < BUTTON_QUIESCENT_ALPHA)
- mGlowAlpha = BUTTON_QUIESCENT_ALPHA;
+ if (mGlowAlpha < mQuiescentAlpha)
+ mGlowAlpha = mQuiescentAlpha;
setDrawingAlpha(1f);
as.playTogether(
ObjectAnimator.ofFloat(this, "glowAlpha", 1f),
@@ -194,7 +225,7 @@ public class KeyButtonView extends ImageView {
as.playTogether(
ObjectAnimator.ofFloat(this, "glowAlpha", 0f),
ObjectAnimator.ofFloat(this, "glowScale", 1f),
- ObjectAnimator.ofFloat(this, "drawingAlpha", BUTTON_QUIESCENT_ALPHA)
+ animateToQuiescent()
);
as.setDuration(500);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
index fcf04ac..c2ffff8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
@@ -53,7 +53,6 @@ public class LocationController extends BroadcastReceiver {
private StatusBarManager mStatusBarManager;
private boolean mAreActiveLocationRequests;
- private boolean mIsAirplaneMode;
private ArrayList<LocationSettingsChangeCallback> mSettingsChangeCallbacks =
new ArrayList<LocationSettingsChangeCallback>();
@@ -76,9 +75,6 @@ public class LocationController extends BroadcastReceiver {
IntentFilter filter = new IntentFilter();
filter.addAction(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
- // Listen for a change in the airplane mode setting so we can defensively turn off the
- // high power location icon when radios are disabled.
- filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
context.registerReceiver(this, filter);
mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
@@ -100,7 +96,6 @@ public class LocationController extends BroadcastReceiver {
// Examine the current location state and initialize the status view.
updateActiveLocationRequests();
- updateAirplaneMode();
refreshViews();
}
@@ -170,11 +165,9 @@ public class LocationController extends BroadcastReceiver {
return false;
}
- // Updates the status view based on the current state of location requests and airplane mode.
+ // Updates the status view based on the current state of location requests.
private void refreshViews() {
- // The airplane mode check is defensive - there shouldn't be any active high power
- // location requests when airplane mode is on.
- if (!mIsAirplaneMode && mAreActiveLocationRequests) {
+ if (mAreActiveLocationRequests) {
mStatusBarManager.setIcon(LOCATION_STATUS_ICON_PLACEHOLDER, LOCATION_STATUS_ICON_ID, 0,
mContext.getString(R.string.accessibility_location_active));
} else {
@@ -191,25 +184,11 @@ public class LocationController extends BroadcastReceiver {
}
}
- // Reads the airplane mode setting and updates the status view if necessary.
- private void updateAirplaneMode() {
- boolean wasAirplaneMode = mIsAirplaneMode;
- // TODO This probably warrants a utility method in Settings.java.
- mIsAirplaneMode = (Settings.Global.getInt(
- mContext.getContentResolver(),
- Settings.Global.AIRPLANE_MODE_ON, 0) == 1);
- if (mIsAirplaneMode != wasAirplaneMode) {
- refreshViews();
- }
- }
-
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION.equals(action)) {
updateActiveLocationRequests();
- } else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) {
- updateAirplaneMode();
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index fb2348e..34e3013 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -430,7 +430,8 @@ public class NetworkController extends BroadcastReceiver {
@Override
public void onServiceStateChanged(ServiceState state) {
if (DEBUG) {
- Log.d(TAG, "onServiceStateChanged state=" + state.getState());
+ Log.d(TAG, "onServiceStateChanged voiceState=" + state.getVoiceRegState()
+ + " dataState=" + state.getDataRegState());
}
mServiceState = state;
updateTelephonySignalStrength();
@@ -506,10 +507,16 @@ public class NetworkController extends BroadcastReceiver {
private boolean hasService() {
if (mServiceState != null) {
- switch (mServiceState.getState()) {
- case ServiceState.STATE_OUT_OF_SERVICE:
+ // Consider the device to be in service if either voice or data service is available.
+ // Some SIM cards are marketed as data-only and do not support voice service, and on
+ // these SIM cards, we want to show signal bars for data service as well as the "no
+ // service" or "emergency calls only" text that indicates that voice is not available.
+ switch(mServiceState.getVoiceRegState()) {
case ServiceState.STATE_POWER_OFF:
return false;
+ case ServiceState.STATE_OUT_OF_SERVICE:
+ case ServiceState.STATE_EMERGENCY_ONLY:
+ return mServiceState.getDataRegState() == ServiceState.STATE_IN_SERVICE;
default:
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Prefs.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Prefs.java
index 3d51f20..16a92ea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Prefs.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Prefs.java
@@ -25,8 +25,6 @@ public class Prefs {
public static final String SHOWN_COMPAT_MODE_HELP = "shown_compat_mode_help";
public static final String SHOWN_QUICK_SETTINGS_HELP = "shown_quick_settings_help";
- public static final String HIDING_NAVIGATION_CONFIRMED = "hiding_navigation_confirmed";
-
public static SharedPreferences read(Context context) {
return context.getSharedPreferences(Prefs.SHARED_PREFS_NAME, Context.MODE_PRIVATE);
}
diff --git a/packages/services/PacProcessor/Android.mk b/packages/services/PacProcessor/Android.mk
index e4afde6..d9566d5 100644
--- a/packages/services/PacProcessor/Android.mk
+++ b/packages/services/PacProcessor/Android.mk
@@ -18,24 +18,15 @@ LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_SRC_FILES := \
- main_pacserver.cpp \
- ProxyService.cpp \
- IProxyService.cpp
-
-LOCAL_C_INCLUDES += \
- external/chromium-libpac/src
-
-LOCAL_SHARED_LIBRARIES := \
- libutils \
- liblog \
- libpac \
- libbinder \
- libstlport
-
-LOCAL_MODULE := pacserver
LOCAL_MODULE_TAGS := optional
-include external/stlport/libstlport.mk
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
-include $(BUILD_EXECUTABLE)
+LOCAL_PACKAGE_NAME := PacProcessor
+LOCAL_CERTIFICATE := platform
+
+LOCAL_REQUIRED_MODULES := libjni_pacprocessor
+
+include $(BUILD_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/packages/services/PacProcessor/AndroidManifest.xml b/packages/services/PacProcessor/AndroidManifest.xml
new file mode 100644
index 0000000..6740c16
--- /dev/null
+++ b/packages/services/PacProcessor/AndroidManifest.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.pacprocessor">
+
+ <uses-permission android:name="android.permission.INTERNET" />
+
+ <application
+ android:label="@string/app_name">
+
+ <service android:name=".PacService"
+ android:exported="true">
+ </service>
+
+ </application>
+
+</manifest>
diff --git a/packages/services/PacProcessor/IProxyService.cpp b/packages/services/PacProcessor/IProxyService.cpp
deleted file mode 100644
index 3707d85..0000000
--- a/packages/services/PacProcessor/IProxyService.cpp
+++ /dev/null
@@ -1,97 +0,0 @@
-#define LOG_TAG "ProxyTesting"
-
-#include <stdint.h>
-#include <sys/types.h>
-#include <binder/Parcel.h>
-#include <binder/IPCThreadState.h>
-#include <utils/Errors.h>
-#include "IProxyService.h"
-
-#include <utils/Log.h>
-
-#include <private/android_filesystem_config.h>
-
-using namespace android;
-
-String16 BpProxyService::resolveProxies(String16 host, String16 url) {
- String16 ret;
- return ret;
-}
-
-void BpProxyService::setPacFile(String16& scriptContents) {
-
-}
-
-void BpProxyService::startPacSystem() {
-
-}
-void BpProxyService::stopPacSystem() {
-
-}
-
-IMPLEMENT_META_INTERFACE(ProxyService, "com.android.net.IProxyService");
-
-status_t BnProxyService::onTransact(
- uint32_t code, const Parcel& data,
- Parcel* reply, uint32_t flags) {
- int returnInt = 0;
- switch (code) {
- case RESOLVE_PROXIES:
- {
- CHECK_INTERFACE(IProxyService, data, reply);
- String16 host = data.readString16();
- String16 url = data.readString16();
- String16 response = resolveProxies(host, url);
- reply->writeNoException();
- reply->writeString16(response);
- return NO_ERROR;
- } break;
- case SET_PAC:
- {
- CHECK_INTERFACE(IProxyService, data, reply);
- if (notSystemUid()) {
- returnInt = 1;
- } else {
- String16 pacFile = data.readString16();
- setPacFile(pacFile);
- }
- reply->writeNoException();
- reply->writeInt32(returnInt);
- return NO_ERROR;
- } break;
- case START_PAC:
- {
- CHECK_INTERFACE(IProxyService, data, reply);
- if (notSystemUid()) {
- returnInt = 1;
- } else {
- startPacSystem();
- }
- reply->writeNoException();
- reply->writeInt32(returnInt);
- return NO_ERROR;
- } break;
- case STOP_PAC:
- {
- CHECK_INTERFACE(IProxyService, data, reply);
- if (notSystemUid()) {
- returnInt = 1;
- } else {
- stopPacSystem();
- }
- reply->writeNoException();
- reply->writeInt32(returnInt);
- return NO_ERROR;
- } break;
- default:
- return BBinder::onTransact(code, data, reply, flags);
- }
-}
-
-int BnProxyService::getCallingUid() {
- return IPCThreadState::self()->getCallingUid();
-}
-
-bool BnProxyService::notSystemUid() {
- return getCallingUid() != AID_SYSTEM;
-}
diff --git a/packages/services/PacProcessor/IProxyService.h b/packages/services/PacProcessor/IProxyService.h
deleted file mode 100644
index 57c527b..0000000
--- a/packages/services/PacProcessor/IProxyService.h
+++ /dev/null
@@ -1,59 +0,0 @@
-#ifndef IPROXY_SERVICE_H
-#define IPROXY_SERVICE_H
-
-#include <binder/IInterface.h>
-#include <binder/IBinder.h>
-
-namespace android {
-class IProxyService : public IInterface {
-public:
- /**
- * Keep up-to-date with
- * frameworks/base/packages/services/Proxy/com/android/net/IProxyService.aidl
- */
- enum {
- RESOLVE_PROXIES = IBinder::FIRST_CALL_TRANSACTION,
- SET_PAC,
- START_PAC,
- STOP_PAC,
- };
-public:
- DECLARE_META_INTERFACE(ProxyService);
-
-public:
-
- virtual String16 resolveProxies(String16 host, String16 url) = 0;
-
- virtual void setPacFile(String16& scriptContents) = 0;
-
- virtual void startPacSystem() = 0;
- virtual void stopPacSystem() = 0;
-private:
-};
-
-class BpProxyService : public BpInterface<IProxyService> {
-public:
- BpProxyService(const sp<IBinder>& impl) : BpInterface<IProxyService>(impl) {}
-
- virtual String16 resolveProxies(String16 host, String16 url);
-
- virtual void setPacFile(String16& scriptContents);
-
- virtual void startPacSystem();
- virtual void stopPacSystem();
-};
-
-class BnProxyService : public BnInterface<IProxyService> {
-public:
- virtual status_t onTransact(
- uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
-
-private:
- int getCallingUid();
-
- bool notSystemUid();
-};
-}
-
-
-#endif //IPROXY_SERVICE_H
diff --git a/packages/services/PacProcessor/ProxyService.cpp b/packages/services/PacProcessor/ProxyService.cpp
deleted file mode 100644
index 7084a47..0000000
--- a/packages/services/PacProcessor/ProxyService.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-#define LOG_TAG "ProxyService"
-#include <utils/Log.h>
-
-#include <errno.h>
-#include <utils/threads.h>
-#include <binder/IServiceManager.h>
-#include <binder/IPCThreadState.h>
-#include <sys/stat.h>
-#include <proxy_resolver_v8.h>
-#include <sstream>
-
-#include "ProxyService.h"
-
-using namespace net;
-
-using namespace android;
-
-class ProxyErrorLogger : public ProxyErrorListener {
-protected:
- ~ProxyErrorLogger() {
-
- }
-public:
- void AlertMessage(String16 message) {
- String8 str(message);
- ALOGD("Alert: %s", str.string());
- }
- void ErrorMessage(String16 message) {
- String8 str(message);
- ALOGE("Error: %s", str.string());
- }
-};
-
-void ProxyService::instantiate() {
- ALOGV("instantiate");
- defaultServiceManager()->addService(String16("com.android.net.IProxyService"),
- new ProxyService());
-}
-
-ProxyService::ProxyService() {
- hasSetScript = false;
-}
-
-ProxyService::~ProxyService() {
- stopPacSystem();
-}
-
-String16 ProxyService::resolveProxies(String16 host, String16 url) {
- ALOGV("resolve");
- String16 blankRet;
- if (proxyResolver != NULL) {
- if (hasSetScript) {
- String16 ret;
- if (proxyResolver->GetProxyForURL(url, host, &ret) != OK) {
- return blankRet;
- }
- return ret;
- } else {
- ALOGD("Unable to resolve PAC when no script is set!");
- }
- } else {
- ALOGE("Cannot parse while resolver not initialized!");
- }
- return blankRet;
-}
-
-void ProxyService::setPacFile(String16& scriptContents) {
- ALOGV("set");
- if (proxyResolver != NULL) {
- if (proxyResolver->SetPacScript(scriptContents) != OK) {
- ALOGD("Unable to initialize PAC - Resolving will not work");
- } else {
- hasSetScript = true;
- }
- } else {
- ALOGE("PAC script set while resolver not initialized!");
- }
-}
-
-void ProxyService::startPacSystem() {
- ALOGV("start");
- // Stop in case redundant start call
- stopPacSystem();
-
- proxyResolver = new ProxyResolverV8(ProxyResolverJSBindings::CreateDefault(),
- new ProxyErrorLogger());
- hasSetScript = false;
-}
-
-void ProxyService::stopPacSystem() {
- ALOGV("stop");
- if (proxyResolver != NULL) {
- delete proxyResolver;
- proxyResolver = NULL;
- }
-}
diff --git a/packages/services/PacProcessor/ProxyService.h b/packages/services/PacProcessor/ProxyService.h
deleted file mode 100644
index a0861b2..0000000
--- a/packages/services/PacProcessor/ProxyService.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef PROXY_SERVICE_H
-#define PROXY_SERVICE_H
-
-#include <binder/IInterface.h>
-#include "IProxyService.h"
-#include "proxy_resolver_v8.h"
-
-namespace android {
-
-class ProxyService : public BnProxyService {
-public:
- static void instantiate();
-
-private:
- ProxyService();
- virtual ~ProxyService();
-
-public:
- String16 resolveProxies(String16 host, String16 url);
-
- void setPacFile(String16& scriptContents);
-
- void startPacSystem();
- void stopPacSystem();
-
-private:
- net::ProxyResolverV8* proxyResolver;
- bool hasSetScript;
-};
-
-}
-
-#endif //PROXY_SERVICE_H
diff --git a/packages/SystemUI/res/values-land/refs.xml b/packages/services/PacProcessor/com/android/net/IProxyService.aidl
index 62fb77d..4e54aba 100644
--- a/packages/SystemUI/res/values-land/refs.xml
+++ b/packages/services/PacProcessor/com/android/net/IProxyService.aidl
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+/**
* Copyright (c) 2013, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,8 +12,16 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
-*/
--->
-<resources>
- <item type="string" name="hiding_navigation_confirmation_message">@string/hiding_navigation_confirmation_message_long</item>
-</resources>
+ */
+package com.android.net;
+
+/** @hide */
+interface IProxyService
+{
+ String resolvePacFile(String host, String url);
+
+ oneway void setPacFile(String scriptContents);
+
+ oneway void startPacSystem();
+ oneway void stopPacSystem();
+}
diff --git a/packages/services/PacProcessor/jni/Android.mk b/packages/services/PacProcessor/jni/Android.mk
new file mode 100644
index 0000000..f16c90b
--- /dev/null
+++ b/packages/services/PacProcessor/jni/Android.mk
@@ -0,0 +1,41 @@
+#
+# Copyright (C) 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ jni_init.cpp \
+ com_android_pacprocessor_PacNative.cpp
+
+LOCAL_C_INCLUDES += \
+ external/chromium-libpac/src
+
+LOCAL_SHARED_LIBRARIES := \
+ libandroidfw \
+ libandroid_runtime \
+ liblog \
+ libutils \
+ libnativehelper \
+ libpac
+
+LOCAL_MODULE := libjni_pacprocessor
+LOCAL_MODULE_TAGS := optional
+
+include external/stlport/libstlport.mk
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/packages/services/PacProcessor/jni/com_android_pacprocessor_PacNative.cpp b/packages/services/PacProcessor/jni/com_android_pacprocessor_PacNative.cpp
new file mode 100644
index 0000000..c5aa13b
--- /dev/null
+++ b/packages/services/PacProcessor/jni/com_android_pacprocessor_PacNative.cpp
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "PacProcessor"
+
+#include <utils/Log.h>
+#include <utils/Mutex.h>
+#include "android_runtime/AndroidRuntime.h"
+
+#include "jni.h"
+#include "JNIHelp.h"
+
+#include "proxy_resolver_v8.h"
+
+namespace android {
+
+class ProxyErrorLogger : public net::ProxyErrorListener {
+public:
+ ~ProxyErrorLogger() {
+
+ }
+ void AlertMessage(String16 message) {
+ String8 str(message);
+ ALOGD("Alert: %s", str.string());
+ }
+ void ErrorMessage(String16 message) {
+ String8 str(message);
+ ALOGE("Error: %s", str.string());
+ }
+};
+
+net::ProxyResolverV8* proxyResolver = NULL;
+ProxyErrorLogger* logger = NULL;
+bool pacSet = false;
+
+String16 jstringToString16(JNIEnv* env, jstring jstr) {
+ const jchar* str = env->GetStringCritical(jstr, 0);
+ String16 str16(str, env->GetStringLength(jstr));
+ env->ReleaseStringCritical(jstr, str);
+ return str16;
+}
+
+jstring string16ToJstring(JNIEnv* env, String16 string) {
+ const char16_t* str = string.string();
+ size_t len = string.size();
+
+ return env->NewString(str, len);
+}
+
+static jboolean com_android_pacprocessor_PacNative_createV8ParserNativeLocked(JNIEnv* env,
+ jobject) {
+ if (proxyResolver == NULL) {
+ logger = new ProxyErrorLogger();
+ proxyResolver = new net::ProxyResolverV8(net::ProxyResolverJSBindings::CreateDefault(),
+ logger);
+ pacSet = false;
+ return JNI_FALSE;
+ }
+ return JNI_TRUE;
+}
+
+static jboolean com_android_pacprocessor_PacNative_destroyV8ParserNativeLocked(JNIEnv* env,
+ jobject) {
+ if (proxyResolver != NULL) {
+ delete logger;
+ delete proxyResolver;
+ logger = NULL;
+ proxyResolver = NULL;
+ return JNI_FALSE;
+ }
+ return JNI_TRUE;
+}
+
+static jboolean com_android_pacprocessor_PacNative_setProxyScriptNativeLocked(JNIEnv* env, jobject,
+ jstring script) {
+ String16 script16 = jstringToString16(env, script);
+
+ if (proxyResolver == NULL) {
+ ALOGE("V8 Parser not started when setting PAC script");
+ return JNI_TRUE;
+ }
+
+ if (proxyResolver->SetPacScript(script16) != OK) {
+ ALOGE("Unable to set PAC script");
+ return JNI_TRUE;
+ }
+ pacSet = true;
+
+ return JNI_FALSE;
+}
+
+static jstring com_android_pacprocessor_PacNative_makeProxyRequestNativeLocked(JNIEnv* env, jobject,
+ jstring url, jstring host) {
+ String16 url16 = jstringToString16(env, url);
+ String16 host16 = jstringToString16(env, host);
+ String16 ret;
+
+ if (proxyResolver == NULL) {
+ ALOGE("V8 Parser not initialized when running PAC script");
+ return NULL;
+ }
+
+ if (!pacSet) {
+ ALOGW("Attempting to run PAC with no script set");
+ return NULL;
+ }
+
+ if (proxyResolver->GetProxyForURL(url16, host16, &ret) != OK) {
+ String8 ret8(ret);
+ ALOGE("Error Running PAC: %s", ret8.string());
+ return NULL;
+ }
+
+ jstring jret = string16ToJstring(env, ret);
+
+ return jret;
+}
+
+static JNINativeMethod gMethods[] = {
+ { "createV8ParserNativeLocked", "()Z",
+ (void*)com_android_pacprocessor_PacNative_createV8ParserNativeLocked},
+ { "destroyV8ParserNativeLocked", "()Z",
+ (void*)com_android_pacprocessor_PacNative_destroyV8ParserNativeLocked},
+ { "setProxyScriptNativeLocked", "(Ljava/lang/String;)Z",
+ (void*)com_android_pacprocessor_PacNative_setProxyScriptNativeLocked},
+ { "makeProxyRequestNativeLocked", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
+ (void*)com_android_pacprocessor_PacNative_makeProxyRequestNativeLocked},
+};
+
+int register_com_android_pacprocessor_PacNative(JNIEnv* env) {
+ return jniRegisterNativeMethods(env, "com/android/pacprocessor/PacNative",
+ gMethods, NELEM(gMethods));
+}
+
+} /* namespace android */
diff --git a/packages/services/PacProcessor/jni/jni_init.cpp b/packages/services/PacProcessor/jni/jni_init.cpp
new file mode 100644
index 0000000..bda33fb
--- /dev/null
+++ b/packages/services/PacProcessor/jni/jni_init.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "PacProcessor"
+
+#include <utils/Log.h>
+#include "jni.h"
+
+namespace android {
+ extern int register_com_android_pacprocessor_PacNative(JNIEnv *env);
+}
+
+using namespace android;
+
+extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved) {
+ JNIEnv *env;
+ if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+ ALOGE("ERROR: GetEnv failed");
+ return -1;
+ }
+
+ register_com_android_pacprocessor_PacNative(env);
+
+ return JNI_VERSION_1_6;
+}
diff --git a/packages/services/PacProcessor/main_pacserver.cpp b/packages/services/PacProcessor/main_pacserver.cpp
deleted file mode 100644
index 19588b5..0000000
--- a/packages/services/PacProcessor/main_pacserver.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "pacserver"
-//#define LOG_NDEBUG 0
-
-#include <binder/IPCThreadState.h>
-#include <binder/ProcessState.h>
-#include <binder/IServiceManager.h>
-#include <utils/Log.h>
-#include "ProxyService.h"
-#include "proxy_resolver_v8.h"
-#include <stdio.h>
-
-using namespace android;
-
-int main(int argc, char** argv)
-{
- sp<ProcessState> proc(ProcessState::self());
- sp<IServiceManager> sm = defaultServiceManager();
-
- printf("1\n");
- ALOGV("ServiceManager: %p", sm.get());
- ProxyService::instantiate();
- printf("1\n");
-
- ProcessState::self()->startThreadPool();
- printf("1\n");
- IPCThreadState::self()->joinThreadPool();
-}
diff --git a/packages/services/PacProcessor/res/values/strings.xml b/packages/services/PacProcessor/res/values/strings.xml
new file mode 100644
index 0000000..301a2b6
--- /dev/null
+++ b/packages/services/PacProcessor/res/values/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="app_name">PacProcessor</string>
+
+</resources>
diff --git a/packages/services/PacProcessor/src/com/android/pacprocessor/PacNative.java b/packages/services/PacProcessor/src/com/android/pacprocessor/PacNative.java
new file mode 100644
index 0000000..c67fe9f
--- /dev/null
+++ b/packages/services/PacProcessor/src/com/android/pacprocessor/PacNative.java
@@ -0,0 +1,86 @@
+/**
+ * Copyright (c) 2013, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.pacprocessor;
+
+import android.util.Log;
+
+/**
+ * @hide
+ */
+public class PacNative {
+ private static final String TAG = "PacProxy";
+
+ private String mCurrentPac;
+
+ private boolean mIsActive;
+
+ // Only make native calls from inside synchronized blocks.
+ private native boolean createV8ParserNativeLocked();
+ private native boolean destroyV8ParserNativeLocked();
+
+ private native boolean setProxyScriptNativeLocked(String script);
+
+ private native String makeProxyRequestNativeLocked(String url, String host);
+
+ static {
+ System.loadLibrary("jni_pacprocessor");
+ }
+
+ PacNative() {
+
+ }
+
+ public synchronized boolean startPacSupport() {
+ if (createV8ParserNativeLocked()) {
+ Log.e(TAG, "Unable to Create v8 Proxy Parser.");
+ return true;
+ }
+ mIsActive = true;
+ return false;
+ }
+
+ public synchronized boolean stopPacSupport() {
+ if (mIsActive) {
+ if (destroyV8ParserNativeLocked()) {
+ Log.e(TAG, "Unable to Destroy v8 Proxy Parser.");
+ return true;
+ }
+ mIsActive = false;
+ }
+ return false;
+ }
+
+ public synchronized boolean setCurrentProxyScript(String script) {
+ if (setProxyScriptNativeLocked(script)) {
+ Log.e(TAG, "Unable to parse proxy script.");
+ return true;
+ }
+ return false;
+ }
+
+ public synchronized String makeProxyRequest(String url, String host) {
+ String ret = makeProxyRequestNativeLocked(url, host);
+ if ((ret == null) || (ret.length() == 0)) {
+ Log.e(TAG, "v8 Proxy request failed.");
+ ret = null;
+ }
+ return ret;
+ }
+
+ public synchronized boolean isActive() {
+ return mIsActive;
+ }
+}
diff --git a/packages/services/PacProcessor/src/com/android/pacprocessor/PacService.java b/packages/services/PacProcessor/src/com/android/pacprocessor/PacService.java
new file mode 100644
index 0000000..7e76025
--- /dev/null
+++ b/packages/services/PacProcessor/src/com/android/pacprocessor/PacService.java
@@ -0,0 +1,101 @@
+/**
+ * Copyright (c) 2013, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.pacprocessor;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.Process;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.net.IProxyService;
+
+public class PacService extends Service {
+ private static final String TAG = "PacService";
+
+ private PacNative mPacNative;
+ private ProxyServiceStub mStub;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ if (mPacNative == null) {
+ mPacNative = new PacNative();
+ mStub = new ProxyServiceStub(mPacNative);
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if (mPacNative != null) {
+ mPacNative.stopPacSupport();
+ mPacNative = null;
+ mStub = null;
+ }
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ if (mPacNative == null) {
+ mPacNative = new PacNative();
+ mStub = new ProxyServiceStub(mPacNative);
+ }
+ return mStub;
+ }
+
+ private static class ProxyServiceStub extends IProxyService.Stub {
+ private final PacNative mPacNative;
+
+ public ProxyServiceStub(PacNative pacNative) {
+ mPacNative = pacNative;
+ }
+
+ @Override
+ public String resolvePacFile(String host, String url) throws RemoteException {
+ return mPacNative.makeProxyRequest(url, host);
+ }
+
+ @Override
+ public void setPacFile(String script) throws RemoteException {
+ if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ Log.e(TAG, "Only system user is allowed to call setPacFile");
+ throw new SecurityException();
+ }
+ mPacNative.setCurrentProxyScript(script);
+ }
+
+ @Override
+ public void startPacSystem() throws RemoteException {
+ if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ Log.e(TAG, "Only system user is allowed to call startPacSystem");
+ throw new SecurityException();
+ }
+ mPacNative.startPacSupport();
+ }
+
+ @Override
+ public void stopPacSystem() throws RemoteException {
+ if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ Log.e(TAG, "Only system user is allowed to call stopPacSystem");
+ throw new SecurityException();
+ }
+ mPacNative.stopPacSupport();
+ }
+ }
+}
diff --git a/packages/services/Proxy/AndroidManifest.xml b/packages/services/Proxy/AndroidManifest.xml
index 02475c0..09b8327 100644
--- a/packages/services/Proxy/AndroidManifest.xml
+++ b/packages/services/Proxy/AndroidManifest.xml
@@ -6,7 +6,6 @@
<uses-permission android:name="android.permission.INTERNET" />
<application
- android:persistent="true"
android:label="@string/app_label"
android:process="com.android.proxyhandler">
diff --git a/packages/services/Proxy/com/android/net/IProxyService.aidl b/packages/services/Proxy/com/android/net/IProxyService.aidl
deleted file mode 100644
index 7e9ed79..0000000
--- a/packages/services/Proxy/com/android/net/IProxyService.aidl
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.android.net;
-
-/** @hide */
-interface IProxyService
-{
- /**
- * Keep up-to-date with
- * frameworks/base/packages/services/PacProcessor/IProxyService.h
- */
- String resolvePacFile(String host, String url);
-
- int setPacFile(String scriptContents);
-
- int startPacSystem();
- int stopPacSystem();
-}
diff --git a/packages/services/Proxy/src/com/android/proxyhandler/ProxyService.java b/packages/services/Proxy/src/com/android/proxyhandler/ProxyService.java
index 0aea5ee..18ed645 100644
--- a/packages/services/Proxy/src/com/android/proxyhandler/ProxyService.java
+++ b/packages/services/Proxy/src/com/android/proxyhandler/ProxyService.java
@@ -24,24 +24,28 @@ public class ProxyService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null) {
- handleCommand(intent);
+ if (handleCommand(intent)) {
+ return START_REDELIVER_INTENT;
+ }
}
- return START_STICKY;
+ return START_NOT_STICKY;
}
- private void handleCommand(Intent intent) {
+ private boolean handleCommand(Intent intent) {
Bundle bundle = intent.getExtras();
ProxyProperties proxy = null;
if ((bundle != null) && bundle.containsKey(Proxy.EXTRA_PROXY_INFO)) {
proxy = bundle.getParcelable(Proxy.EXTRA_PROXY_INFO);
if ((proxy != null) && !TextUtils.isEmpty(proxy.getPacFileUrl())) {
startProxy(proxy);
+ return true;
} else {
stopSelf();
}
} else {
stopSelf();
}
+ return false;
}
diff --git a/packages/services/Proxy/src/com/android/proxyhandler/ProxyServiceReceiver.java b/packages/services/Proxy/src/com/android/proxyhandler/ProxyServiceReceiver.java
index f5c2ca5..4638def 100644
--- a/packages/services/Proxy/src/com/android/proxyhandler/ProxyServiceReceiver.java
+++ b/packages/services/Proxy/src/com/android/proxyhandler/ProxyServiceReceiver.java
@@ -4,7 +4,9 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.Proxy;
+import android.net.ProxyProperties;
import android.os.Bundle;
+import android.text.TextUtils;
public class ProxyServiceReceiver extends BroadcastReceiver {
@@ -12,11 +14,16 @@ public class ProxyServiceReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Intent service = new Intent(context, ProxyService.class);
Bundle bundle = intent.getExtras();
+ ProxyProperties proxy = null;
if (bundle != null) {
- service.putExtra(Proxy.EXTRA_PROXY_INFO,
- bundle.getParcelable(Proxy.EXTRA_PROXY_INFO));
+ proxy = bundle.getParcelable(Proxy.EXTRA_PROXY_INFO);
+ service.putExtra(Proxy.EXTRA_PROXY_INFO, proxy);
+ }
+ if ((proxy != null) && (!TextUtils.isEmpty(proxy.getPacFileUrl()))) {
+ context.startService(service);
+ } else {
+ context.stopService(service);
}
- context.startService(service);
}
}