summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.mk4
-rw-r--r--CleanSpec.mk1
-rw-r--r--api/current.txt111
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java31
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl3
-rw-r--r--core/java/android/bluetooth/BluetoothDevice.java3
-rw-r--r--core/java/android/bluetooth/BluetoothMap.java300
-rw-r--r--core/java/android/bluetooth/BluetoothProfile.java6
-rw-r--r--core/java/android/bluetooth/BluetoothTetheringDataTracker.java5
-rw-r--r--core/java/android/bluetooth/BluetoothUuid.java13
-rw-r--r--core/java/android/bluetooth/IBluetoothMap.aidl32
-rw-r--r--core/java/android/net/BaseNetworkStateTracker.java5
-rw-r--r--core/java/android/net/CaptivePortalTracker.java44
-rw-r--r--core/java/android/net/ConnectivityManager.java33
-rw-r--r--core/java/android/net/DummyDataStateTracker.java6
-rw-r--r--core/java/android/net/EthernetDataTracker.java5
-rw-r--r--core/java/android/net/IConnectivityManager.aidl4
-rw-r--r--core/java/android/net/MobileDataStateTracker.java12
-rw-r--r--core/java/android/net/NetworkStateTracker.java5
-rw-r--r--core/java/android/net/PacProxySelector.java10
-rw-r--r--core/java/android/nfc/cardemulation/ApduServiceInfo.java3
-rw-r--r--core/java/android/os/AsyncTask.java7
-rw-r--r--core/java/android/os/FileUtils.java86
-rw-r--r--core/java/android/os/Process.java13
-rw-r--r--core/java/android/print/IPrintSpoolerClient.aidl6
-rw-r--r--core/java/android/print/IPrinterDiscoverySessionController.aidl (renamed from core/java/android/print/IPrinterDiscoveryObserver.aidl)11
-rw-r--r--core/java/android/print/IPrinterDiscoverySessionObserver.aidl33
-rw-r--r--core/java/android/print/PrintAttributes.java38
-rw-r--r--core/java/android/print/PrintDocumentInfo.java54
-rw-r--r--core/java/android/print/PrintFileDocumentAdapter.java (renamed from core/java/android/print/FileDocumentAdapter.java)30
-rw-r--r--core/java/android/print/PrintJobInfo.java28
-rw-r--r--core/java/android/print/PrintManager.java7
-rw-r--r--core/java/android/print/PrinterCapabilitiesInfo.aidl19
-rw-r--r--core/java/android/print/PrinterCapabilitiesInfo.java972
-rw-r--r--core/java/android/print/PrinterId.java27
-rw-r--r--core/java/android/print/PrinterInfo.java810
-rw-r--r--core/java/android/printservice/IPrintService.aidl12
-rw-r--r--core/java/android/printservice/PrintDocument.java10
-rw-r--r--core/java/android/printservice/PrintJob.java57
-rw-r--r--core/java/android/printservice/PrintService.java433
-rw-r--r--core/java/android/printservice/PrinterDiscoverySession.java357
-rw-r--r--core/java/android/printservice/package.html24
-rw-r--r--core/java/android/provider/Settings.java17
-rw-r--r--core/java/android/view/View.java36
-rw-r--r--core/java/android/view/ViewRootImpl.java34
-rw-r--r--core/java/android/view/Window.java14
-rw-r--r--core/java/android/view/WindowManager.java14
-rw-r--r--core/java/android/widget/AbsListView.java17
-rw-r--r--core/java/android/widget/FastScroller.java101
-rw-r--r--core/java/android/widget/TextView.java2
-rw-r--r--core/java/android/widget/ZoomButtonsController.java2
-rw-r--r--core/java/com/android/internal/app/IProcessStats.aidl1
-rw-r--r--core/java/com/android/internal/app/ProcessStats.java313
-rw-r--r--core/java/com/android/internal/os/ZygoteInit.java2
-rw-r--r--core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java2
-rw-r--r--core/jni/android/graphics/Canvas.cpp17
-rw-r--r--core/jni/android/graphics/SurfaceTexture.cpp3
-rw-r--r--core/jni/android_os_Debug.cpp4
-rw-r--r--core/jni/android_os_FileUtils.cpp42
-rw-r--r--core/res/res/values-af/strings.xml27
-rw-r--r--core/res/res/values-am/strings.xml23
-rw-r--r--core/res/res/values-ar/strings.xml25
-rw-r--r--core/res/res/values-be/strings.xml7
-rw-r--r--core/res/res/values-bg/strings.xml23
-rw-r--r--core/res/res/values-ca/strings.xml23
-rw-r--r--core/res/res/values-cs/strings.xml29
-rw-r--r--core/res/res/values-da/strings.xml23
-rw-r--r--core/res/res/values-de/strings.xml25
-rw-r--r--core/res/res/values-el/strings.xml23
-rw-r--r--core/res/res/values-en-rGB/strings.xml23
-rw-r--r--core/res/res/values-es-rUS/strings.xml23
-rw-r--r--core/res/res/values-es/strings.xml23
-rw-r--r--core/res/res/values-et/strings.xml25
-rw-r--r--core/res/res/values-fa/strings.xml25
-rw-r--r--core/res/res/values-fi/strings.xml23
-rw-r--r--core/res/res/values-fr/strings.xml29
-rw-r--r--core/res/res/values-hi/strings.xml23
-rw-r--r--core/res/res/values-hr/strings.xml25
-rw-r--r--core/res/res/values-hu/strings.xml23
-rw-r--r--core/res/res/values-in/strings.xml31
-rw-r--r--core/res/res/values-it/strings.xml23
-rw-r--r--core/res/res/values-iw/strings.xml25
-rw-r--r--core/res/res/values-ja/strings.xml23
-rw-r--r--core/res/res/values-ko/strings.xml29
-rw-r--r--core/res/res/values-lt/strings.xml25
-rw-r--r--core/res/res/values-lv/strings.xml25
-rw-r--r--core/res/res/values-ms/strings.xml25
-rw-r--r--core/res/res/values-nb/strings.xml155
-rw-r--r--core/res/res/values-nl/strings.xml23
-rw-r--r--core/res/res/values-pl/strings.xml23
-rw-r--r--core/res/res/values-pt-rPT/strings.xml23
-rw-r--r--core/res/res/values-pt/strings.xml23
-rw-r--r--core/res/res/values-rm/strings.xml6
-rw-r--r--core/res/res/values-ro/strings.xml29
-rw-r--r--core/res/res/values-ru/strings.xml34
-rw-r--r--core/res/res/values-sk/strings.xml23
-rw-r--r--core/res/res/values-sl/strings.xml23
-rw-r--r--core/res/res/values-sr/strings.xml25
-rw-r--r--core/res/res/values-sv/strings.xml23
-rw-r--r--core/res/res/values-sw/strings.xml29
-rw-r--r--core/res/res/values-th/strings.xml25
-rw-r--r--core/res/res/values-tl/strings.xml25
-rw-r--r--core/res/res/values-tr/strings.xml23
-rw-r--r--core/res/res/values-uk/strings.xml25
-rw-r--r--core/res/res/values-vi/strings.xml25
-rw-r--r--core/res/res/values-zh-rCN/strings.xml29
-rw-r--r--core/res/res/values-zh-rTW/strings.xml25
-rw-r--r--core/res/res/values-zu/strings.xml23
-rw-r--r--docs/html/google/gcm/adv.jd367
-rw-r--r--docs/html/google/gcm/ccs.jd771
-rw-r--r--docs/html/google/gcm/client.jd649
-rw-r--r--docs/html/google/gcm/gcm.jd705
-rw-r--r--docs/html/google/gcm/gs.jd497
-rw-r--r--docs/html/google/gcm/http.jd618
-rw-r--r--docs/html/google/gcm/notifications.jd137
-rw-r--r--docs/html/google/gcm/server.jd448
-rw-r--r--docs/html/google/google_toc.cs23
-rw-r--r--docs/html/images/gcm/CCS-ack.pngbin0 -> 55599 bytes
-rw-r--r--docs/html/images/gcm/GCM-arch.pngbin0 -> 26618 bytes
-rw-r--r--graphics/java/android/graphics/Canvas.java16
-rw-r--r--graphics/java/android/graphics/Paint.java2
-rw-r--r--libs/hwui/DisplayListOp.h15
-rw-r--r--libs/hwui/DisplayListRenderer.cpp8
-rw-r--r--libs/hwui/OpenGLRenderer.cpp19
-rw-r--r--libs/hwui/OpenGLRenderer.h9
-rw-r--r--location/lib/java/com/android/location/provider/FusedLocationHardware.java126
-rw-r--r--location/lib/java/com/android/location/provider/FusedLocationHardwareSink.java1
-rw-r--r--location/lib/java/com/android/location/provider/FusedProvider.java2
-rw-r--r--media/mca/filterfw/native/core/gl_env.cpp2
-rw-r--r--media/mca/filterfw/native/core/gl_env.h3
-rw-r--r--obex/javax/obex/ClientOperation.java3
-rw-r--r--obex/javax/obex/HeaderSet.java2
-rw-r--r--obex/javax/obex/Operation.java2
-rw-r--r--obex/javax/obex/ServerOperation.java35
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java2
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/NotificationController.java4
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java108
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/PrintSpooler.java28
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java51
-rw-r--r--packages/SystemUI/res/values-af/strings.xml6
-rw-r--r--packages/SystemUI/res/values-am/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ar/strings.xml6
-rw-r--r--packages/SystemUI/res/values-be/strings.xml6
-rw-r--r--packages/SystemUI/res/values-bg/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ca/strings.xml6
-rw-r--r--packages/SystemUI/res/values-cs/strings.xml12
-rw-r--r--packages/SystemUI/res/values-da/strings.xml6
-rw-r--r--packages/SystemUI/res/values-de/strings.xml6
-rw-r--r--packages/SystemUI/res/values-el/strings.xml6
-rw-r--r--packages/SystemUI/res/values-en-rGB/strings.xml6
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings.xml6
-rw-r--r--packages/SystemUI/res/values-es/strings.xml6
-rw-r--r--packages/SystemUI/res/values-et/strings.xml6
-rw-r--r--packages/SystemUI/res/values-fa/strings.xml6
-rw-r--r--packages/SystemUI/res/values-fi/strings.xml6
-rw-r--r--packages/SystemUI/res/values-fr/strings.xml12
-rw-r--r--packages/SystemUI/res/values-hi/strings.xml6
-rw-r--r--packages/SystemUI/res/values-hr/strings.xml6
-rw-r--r--packages/SystemUI/res/values-hu/strings.xml6
-rw-r--r--packages/SystemUI/res/values-in/strings.xml12
-rw-r--r--packages/SystemUI/res/values-it/strings.xml6
-rw-r--r--packages/SystemUI/res/values-iw/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ja/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml12
-rw-r--r--packages/SystemUI/res/values-lt/strings.xml6
-rw-r--r--packages/SystemUI/res/values-lv/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ms/strings.xml6
-rw-r--r--packages/SystemUI/res/values-nb/strings.xml6
-rw-r--r--packages/SystemUI/res/values-nl/strings.xml6
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml6
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings.xml6
-rw-r--r--packages/SystemUI/res/values-pt/strings.xml6
-rw-r--r--packages/SystemUI/res/values-rm/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ro/strings.xml12
-rw-r--r--packages/SystemUI/res/values-ru/strings.xml12
-rw-r--r--packages/SystemUI/res/values-sk/strings.xml6
-rw-r--r--packages/SystemUI/res/values-sl/strings.xml6
-rw-r--r--packages/SystemUI/res/values-sr/strings.xml6
-rw-r--r--packages/SystemUI/res/values-sv/strings.xml6
-rw-r--r--packages/SystemUI/res/values-sw/strings.xml6
-rw-r--r--packages/SystemUI/res/values-th/strings.xml6
-rw-r--r--packages/SystemUI/res/values-tl/strings.xml6
-rw-r--r--packages/SystemUI/res/values-tr/strings.xml6
-rw-r--r--packages/SystemUI/res/values-uk/strings.xml6
-rw-r--r--packages/SystemUI/res/values-vi/strings.xml6
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings.xml12
-rw-r--r--packages/SystemUI/res/values-zh-rTW/strings.xml6
-rw-r--r--packages/SystemUI/res/values-zu/strings.xml6
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindow.java23
-rw-r--r--services/java/com/android/server/ConnectivityService.java20
-rw-r--r--services/java/com/android/server/DevicePolicyManagerService.java28
-rw-r--r--services/java/com/android/server/LocationManagerService.java5
-rw-r--r--services/java/com/android/server/accessibility/TouchExplorer.java783
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java40
-rw-r--r--services/java/com/android/server/am/ProcessStatsService.java49
-rw-r--r--services/java/com/android/server/connectivity/PacManager.java14
-rw-r--r--services/java/com/android/server/location/FlpHardwareProvider.java42
-rw-r--r--services/java/com/android/server/location/FusedProxy.java34
-rw-r--r--services/java/com/android/server/pm/Settings.java19
-rw-r--r--services/java/com/android/server/print/RemotePrintService.java126
-rw-r--r--services/java/com/android/server/print/RemotePrintSpooler.java37
-rw-r--r--services/java/com/android/server/print/UserState.java39
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java21
-rw-r--r--services/java/com/android/server/wm/WindowStateAnimator.java5
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java8
-rw-r--r--wifi/java/android/net/wifi/WifiStateMachine.java6
-rw-r--r--wifi/java/android/net/wifi/WifiStateTracker.java5
207 files changed, 7335 insertions, 4564 deletions
diff --git a/Android.mk b/Android.mk
index df10876914b9..22ee3a69f14e 100644
--- a/Android.mk
+++ b/Android.mk
@@ -95,6 +95,7 @@ LOCAL_SRC_FILES += \
core/java/android/bluetooth/IBluetoothManager.aidl \
core/java/android/bluetooth/IBluetoothManagerCallback.aidl \
core/java/android/bluetooth/IBluetoothPbap.aidl \
+ core/java/android/bluetooth/IBluetoothMap.aidl \
core/java/android/bluetooth/IBluetoothStateChangeCallback.aidl \
core/java/android/bluetooth/IBluetoothGatt.aidl \
core/java/android/bluetooth/IBluetoothGattCallback.aidl \
@@ -161,8 +162,9 @@ LOCAL_SRC_FILES += \
core/java/android/os/IVibratorService.aidl \
core/java/android/service/notification/INotificationListener.aidl \
core/java/android/print/ILayoutResultCallback.aidl \
+ core/java/android/print/IPrinterDiscoverySessionController.aidl \
+ core/java/android/print/IPrinterDiscoverySessionObserver.aidl \
core/java/android/print/IPrintDocumentAdapter.aidl \
- core/java/android/print/IPrinterDiscoveryObserver.aidl \
core/java/android/print/IPrintClient.aidl \
core/java/android/print/IPrintManager.aidl \
core/java/android/print/IPrintSpooler.aidl \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 73e8fa4bc171..104fe67d2301 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -167,6 +167,7 @@ $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framew
$(call add-clean-step, rm -rf $(HOST_OUT)/obj/STATIC_LIBRARIES/libandroidfw_intermediates/import_includes)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/print/IPrinterDiscoveryObserver.*)
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
# ************************************************
diff --git a/api/current.txt b/api/current.txt
index 3baeea3251d2..ed893a24d3a7 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -18637,11 +18637,11 @@ package android.print {
}
public static final class PrintAttributes.MediaSize {
- ctor public PrintAttributes.MediaSize(java.lang.String, java.lang.CharSequence, int, int);
+ ctor public PrintAttributes.MediaSize(java.lang.String, java.lang.String, int, int);
method public static android.print.PrintAttributes.MediaSize createMediaSize(android.content.pm.PackageManager, int);
method public int getHeightMils();
method public java.lang.String getId();
- method public java.lang.CharSequence getLabel();
+ method public java.lang.String getLabel();
method public int getWidthMils();
field public static final int ISO_A0 = 1; // 0x1
field public static final int ISO_A1 = 2; // 0x2
@@ -18685,17 +18685,17 @@ package android.print {
}
public static final class PrintAttributes.Resolution {
- ctor public PrintAttributes.Resolution(java.lang.String, java.lang.CharSequence, int, int);
+ ctor public PrintAttributes.Resolution(java.lang.String, java.lang.String, int, int);
method public int getHorizontalDpi();
method public java.lang.String getId();
- method public java.lang.CharSequence getLabel();
+ method public java.lang.String getLabel();
method public int getVerticalDpi();
}
public static final class PrintAttributes.Tray {
- ctor public PrintAttributes.Tray(java.lang.String, java.lang.CharSequence);
+ ctor public PrintAttributes.Tray(java.lang.String, java.lang.String);
method public java.lang.String getId();
- method public java.lang.CharSequence getLabel();
+ method public java.lang.String getLabel();
}
public abstract class PrintDocumentAdapter {
@@ -18722,6 +18722,7 @@ package android.print {
public final class PrintDocumentInfo implements android.os.Parcelable {
method public int describeContents();
method public int getContentType();
+ method public java.lang.String getName();
method public int getPageCount();
method public void writeToParcel(android.os.Parcel, int);
field public static final int CONTENT_TYPE_DOCUMENT = 0; // 0x0
@@ -18732,12 +18733,18 @@ package android.print {
}
public static final class PrintDocumentInfo.Builder {
- ctor public PrintDocumentInfo.Builder();
+ ctor public PrintDocumentInfo.Builder(java.lang.String);
method public android.print.PrintDocumentInfo create();
method public android.print.PrintDocumentInfo.Builder setContentType(int);
method public android.print.PrintDocumentInfo.Builder setPageCount(int);
}
+ public final class PrintFileDocumentAdapter extends android.print.PrintDocumentAdapter {
+ ctor public PrintFileDocumentAdapter(android.content.Context, java.io.File, android.print.PrintDocumentInfo);
+ method public void onLayout(android.print.PrintAttributes, android.print.PrintAttributes, android.os.CancellationSignal, android.print.PrintDocumentAdapter.LayoutResultCallback, android.os.Bundle);
+ method public void onWrite(android.print.PageRange[], java.io.FileDescriptor, android.os.CancellationSignal, android.print.PrintDocumentAdapter.WriteResultCallback);
+ }
+
public final class PrintJob {
method public void cancel();
method public int getId();
@@ -18766,50 +18773,66 @@ package android.print {
public final class PrintManager {
method public java.util.List<android.print.PrintJob> getPrintJobs();
- method public android.print.PrintJob print(java.lang.String, java.io.File, android.print.PrintAttributes);
+ method public android.print.PrintJob print(java.lang.String, java.io.File, android.print.PrintDocumentInfo, android.print.PrintAttributes);
method public android.print.PrintJob print(java.lang.String, android.print.PrintDocumentAdapter, android.print.PrintAttributes);
}
- public final class PrinterId implements android.os.Parcelable {
- method public int describeContents();
- method public java.lang.String getPrinterName();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator CREATOR;
- }
-
- public final class PrinterInfo implements android.os.Parcelable {
+ public final class PrinterCapabilitiesInfo implements android.os.Parcelable {
method public int describeContents();
method public int getColorModes();
method public void getDefaults(android.print.PrintAttributes);
method public int getDuplexModes();
method public int getFittingModes();
- method public android.print.PrinterId getId();
method public java.util.List<android.print.PrintAttributes.Tray> getInputTrays();
method public java.util.List<android.print.PrintAttributes.MediaSize> getMediaSizes();
method public android.print.PrintAttributes.Margins getMinMargins();
method public int getOrientations();
method public java.util.List<android.print.PrintAttributes.Tray> getOutputTrays();
method public java.util.List<android.print.PrintAttributes.Resolution> getResolutions();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator CREATOR;
+ }
+
+ public static final class PrinterCapabilitiesInfo.Builder {
+ ctor public PrinterCapabilitiesInfo.Builder(android.print.PrinterId);
+ method public android.print.PrinterCapabilitiesInfo.Builder addInputTray(android.print.PrintAttributes.Tray, boolean);
+ method public android.print.PrinterCapabilitiesInfo.Builder addMediaSize(android.print.PrintAttributes.MediaSize, boolean);
+ method public android.print.PrinterCapabilitiesInfo.Builder addOutputTray(android.print.PrintAttributes.Tray, boolean);
+ method public android.print.PrinterCapabilitiesInfo.Builder addResolution(android.print.PrintAttributes.Resolution, boolean);
+ method public android.print.PrinterCapabilitiesInfo create();
+ method public android.print.PrinterCapabilitiesInfo.Builder setColorModes(int, int);
+ method public android.print.PrinterCapabilitiesInfo.Builder setDuplexModes(int, int);
+ method public android.print.PrinterCapabilitiesInfo.Builder setFittingModes(int, int);
+ method public android.print.PrinterCapabilitiesInfo.Builder setMinMargins(android.print.PrintAttributes.Margins, android.print.PrintAttributes.Margins);
+ method public android.print.PrinterCapabilitiesInfo.Builder setOrientations(int, int);
+ }
+
+ public final class PrinterId implements android.os.Parcelable {
+ method public int describeContents();
+ method public java.lang.String getLocalId();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator CREATOR;
+ }
+
+ public final class PrinterInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method public android.print.PrinterCapabilitiesInfo getCapabilities();
+ method public java.lang.String getDescription();
+ method public android.print.PrinterId getId();
+ method public java.lang.String getName();
method public int getStatus();
- method public boolean hasAllRequiredAttributes();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
field public static final int STATUS_READY = 1; // 0x1
}
public static final class PrinterInfo.Builder {
- ctor public PrinterInfo.Builder(android.print.PrinterId);
- method public android.print.PrinterInfo.Builder addInputTray(android.print.PrintAttributes.Tray, boolean);
- method public android.print.PrinterInfo.Builder addMediaSize(android.print.PrintAttributes.MediaSize, boolean);
- method public android.print.PrinterInfo.Builder addOutputTray(android.print.PrintAttributes.Tray, boolean);
- method public android.print.PrinterInfo.Builder addResolution(android.print.PrintAttributes.Resolution, boolean);
+ ctor public PrinterInfo.Builder(android.print.PrinterId, java.lang.String, int);
+ ctor public PrinterInfo.Builder(android.print.PrinterInfo);
method public android.print.PrinterInfo create();
- method public android.print.PrinterInfo.Builder setColorModes(int, int);
- method public android.print.PrinterInfo.Builder setDuplexModes(int, int);
- method public android.print.PrinterInfo.Builder setFittingModes(int, int);
- method public android.print.PrinterInfo.Builder setMinMargins(android.print.PrintAttributes.Margins, android.print.PrintAttributes.Margins);
- method public android.print.PrinterInfo.Builder setOrientations(int, int);
- method public android.print.PrinterInfo.Builder setStatus(int);
+ method public android.print.PrinterInfo.Builder setCapabilities(android.print.PrinterCapabilitiesInfo);
+ method public android.print.PrinterInfo.Builder setDescription(java.lang.String);
+ method public android.print.PrinterInfo.Builder setName(java.lang.String);
}
}
@@ -18861,6 +18884,9 @@ package android.printservice {
method public android.printservice.PrintDocument getDocument();
method public int getId();
method public android.print.PrintJobInfo getInfo();
+ method public boolean isCancelled();
+ method public boolean isCompleted();
+ method public boolean isFailed();
method public boolean isQueued();
method public boolean isStarted();
method public boolean setTag(java.lang.String);
@@ -18869,23 +18895,30 @@ package android.printservice {
public abstract class PrintService extends android.app.Service {
ctor public PrintService();
- method public final void addDiscoveredPrinters(java.util.List<android.print.PrinterInfo>);
+ method protected final void attachBaseContext(android.content.Context);
method public final android.print.PrinterId generatePrinterId(java.lang.String);
- method public final java.util.List<android.printservice.PrintJob> getPrintJobs();
+ method public final java.util.List<android.printservice.PrintJob> getActivePrintJobs();
method public final android.os.IBinder onBind(android.content.Intent);
method protected void onConnected();
+ method protected abstract android.printservice.PrinterDiscoverySession onCreatePrinterDiscoverySession();
method protected void onDisconnected();
method protected abstract void onPrintJobQueued(android.printservice.PrintJob);
- method protected void onRequestCancelPrintJob(android.printservice.PrintJob);
- method protected void onRequestUpdatePrinters(java.util.List<android.print.PrinterId>);
- method protected abstract void onStartPrinterDiscovery();
- method protected abstract void onStopPrinterDiscovery();
- method public final void removeDiscoveredPrinters(java.util.List<android.print.PrinterId>);
- method public final void updateDiscoveredPrinters(java.util.List<android.print.PrinterInfo>);
+ method protected abstract void onRequestCancelPrintJob(android.printservice.PrintJob);
field public static final java.lang.String SERVICE_INTERFACE = "android.printservice.PrintService";
field public static final java.lang.String SERVICE_META_DATA = "android.printservice";
}
+ public abstract class PrinterDiscoverySession {
+ ctor public PrinterDiscoverySession(android.content.Context);
+ method public final void addPrinters(java.util.List<android.print.PrinterInfo>);
+ method public final boolean isClosed();
+ method public abstract void onClose();
+ method public abstract void onOpen(java.util.List<android.print.PrinterId>);
+ method public abstract void onRequestPrinterUpdate(android.print.PrinterId);
+ method public final void removePrinters(java.util.List<android.print.PrinterId>);
+ method public final void updatePrinters(java.util.List<android.print.PrinterInfo>);
+ }
+
}
package android.provider {
@@ -20724,6 +20757,7 @@ package android.provider {
field public static final java.lang.String ACTION_MEMORY_CARD_SETTINGS = "android.settings.MEMORY_CARD_SETTINGS";
field public static final java.lang.String ACTION_NETWORK_OPERATOR_SETTINGS = "android.settings.NETWORK_OPERATOR_SETTINGS";
field public static final java.lang.String ACTION_NFCSHARING_SETTINGS = "android.settings.NFCSHARING_SETTINGS";
+ field public static final java.lang.String ACTION_NFC_PAYMENT_SETTINGS = "android.settings.NFC_PAYMENT_SETTINGS";
field public static final java.lang.String ACTION_NFC_SETTINGS = "android.settings.NFC_SETTINGS";
field public static final java.lang.String ACTION_PRIVACY_SETTINGS = "android.settings.PRIVACY_SETTINGS";
field public static final java.lang.String ACTION_QUICK_LAUNCH_SETTINGS = "android.settings.QUICK_LAUNCH_SETTINGS";
@@ -27835,6 +27869,7 @@ package android.view {
method public final boolean hasChildren();
method public boolean hasFeature(int);
method protected final boolean hasSoftInputMode();
+ method public void injectInputEvent(android.view.InputEvent);
method public abstract void invalidatePanelMenu(int);
method public final boolean isActive();
method public abstract boolean isFloating();
@@ -27872,6 +27907,7 @@ package android.view {
method public void setGravity(int);
method public void setIcon(int);
method public void setLayout(int, int);
+ method public void setLocalFocus(boolean, boolean);
method public void setLogo(int);
method public void setSoftInputMode(int);
method public abstract void setTitle(java.lang.CharSequence);
@@ -28010,6 +28046,7 @@ package android.view {
field public static final int FLAG_LAYOUT_IN_OVERSCAN = 33554432; // 0x2000000
field public static final int FLAG_LAYOUT_IN_SCREEN = 256; // 0x100
field public static final int FLAG_LAYOUT_NO_LIMITS = 512; // 0x200
+ field public static final int FLAG_LOCAL_FOCUS_MODE = 268435456; // 0x10000000
field public static final int FLAG_NOT_FOCUSABLE = 8; // 0x8
field public static final int FLAG_NOT_TOUCHABLE = 16; // 0x10
field public static final int FLAG_NOT_TOUCH_MODAL = 32; // 0x20
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 17e8dd968006..be831d7a2d2b 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1527,9 +1527,26 @@ public class DevicePolicyManager {
*/
public boolean setDeviceOwner(String packageName) throws IllegalArgumentException,
IllegalStateException {
+ return setDeviceOwner(packageName, null);
+ }
+
+ /**
+ * @hide
+ * Sets the given package as the device owner. The package must already be installed and there
+ * shouldn't be an existing device owner registered, for this call to succeed. Also, this
+ * method must be called before the device is provisioned.
+ * @param packageName the package name of the application to be registered as the device owner.
+ * @param ownerName the human readable name of the institution that owns this device.
+ * @return whether the package was successfully registered as the device owner.
+ * @throws IllegalArgumentException if the package name is null or invalid
+ * @throws IllegalStateException if a device owner is already registered or the device has
+ * already been provisioned.
+ */
+ public boolean setDeviceOwner(String packageName, String ownerName)
+ throws IllegalArgumentException, IllegalStateException {
if (mService != null) {
try {
- return mService.setDeviceOwner(packageName);
+ return mService.setDeviceOwner(packageName, ownerName);
} catch (RemoteException re) {
Log.w(TAG, "Failed to set device owner");
}
@@ -1581,4 +1598,16 @@ public class DevicePolicyManager {
}
return null;
}
+
+ /** @hide */
+ public String getDeviceOwnerName() {
+ if (mService != null) {
+ try {
+ return mService.getDeviceOwnerName();
+ } catch (RemoteException re) {
+ Log.w(TAG, "Failed to get device owner");
+ }
+ }
+ return null;
+ }
}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index b2a65bf37508..9659a91f7098 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -98,7 +98,8 @@ interface IDevicePolicyManager {
void reportFailedPasswordAttempt(int userHandle);
void reportSuccessfulPasswordAttempt(int userHandle);
- boolean setDeviceOwner(String packageName);
+ boolean setDeviceOwner(String packageName, String ownerName);
boolean isDeviceOwner(String packageName);
String getDeviceOwner();
+ String getDeviceOwnerName();
}
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 3ee7142d8d6d..3acd9b00c056 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -343,6 +343,9 @@ public final class BluetoothDevice implements Parcelable {
/**@hide*/
public static final int REQUEST_TYPE_PHONEBOOK_ACCESS = 2;
+ /**@hide*/
+ public static final int REQUEST_TYPE_MESSAGE_ACCESS = 3;
+
/**
* Used as an extra field in {@link #ACTION_CONNECTION_ACCESS_REQUEST} intents,
* Contains package name to return reply intent to.
diff --git a/core/java/android/bluetooth/BluetoothMap.java b/core/java/android/bluetooth/BluetoothMap.java
new file mode 100644
index 000000000000..7de309fb8312
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothMap.java
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.RemoteException;
+import android.os.IBinder;
+import android.os.ServiceManager;
+import android.util.Log;
+
+/**
+ * This class provides the APIs to control the Bluetooth MAP
+ * Profile.
+ *@hide
+ */
+public class BluetoothMap {
+
+ private static final String TAG = "BluetoothMap";
+ private static final boolean DBG = true;
+ private static final boolean VDBG = false;
+
+ /** int extra for MAP_STATE_CHANGED_ACTION */
+ public static final String MAP_STATE =
+ "android.bluetooth.map.intent.MAP_STATE";
+ /** int extra for MAP_STATE_CHANGED_ACTION */
+ public static final String MAP_PREVIOUS_STATE =
+ "android.bluetooth.map.intent.MAP_PREVIOUS_STATE";
+
+ /** Indicates the state of a Map connection state has changed.
+ * This intent will always contain MAP_STATE, MAP_PREVIOUS_STATE and
+ * BluetoothIntent.ADDRESS extras.
+ */
+ public static final String MAP_STATE_CHANGED_ACTION =
+ "android.bluetooth.map.intent.action.MAP_STATE_CHANGED";
+
+ private IBluetoothMap mService;
+ private final Context mContext;
+ private ServiceListener mServiceListener;
+ private BluetoothAdapter mAdapter;
+
+ /** There was an error trying to obtain the state */
+ public static final int STATE_ERROR = -1;
+ /** No client currently connected */
+ public static final int STATE_DISCONNECTED = 0;
+ /** Connection attempt in progress */
+ public static final int STATE_CONNECTING = 1;
+ /** Client is currently connected */
+ public static final int STATE_CONNECTED = 2;
+
+ public static final int RESULT_FAILURE = 0;
+ public static final int RESULT_SUCCESS = 1;
+ /** Connection canceled before completion. */
+ public static final int RESULT_CANCELED = 2;
+
+ /**
+ * An interface for notifying Bluetooth PCE IPC clients when they have
+ * been connected to the BluetoothMap service.
+ */
+ public interface ServiceListener {
+ /**
+ * Called to notify the client when this proxy object has been
+ * connected to the BluetoothMap service. Clients must wait for
+ * this callback before making IPC calls on the BluetoothMap
+ * service.
+ */
+ public void onServiceConnected(BluetoothMap proxy);
+
+ /**
+ * Called to notify the client that this proxy object has been
+ * disconnected from the BluetoothMap service. Clients must not
+ * make IPC calls on the BluetoothMap service after this callback.
+ * This callback will currently only occur if the application hosting
+ * the BluetoothMap service, but may be called more often in future.
+ */
+ public void onServiceDisconnected();
+ }
+
+ final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
+ new IBluetoothStateChangeCallback.Stub() {
+ public void onBluetoothStateChange(boolean up) {
+ if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
+ if (!up) {
+ if (VDBG) Log.d(TAG,"Unbinding service...");
+ synchronized (mConnection) {
+ try {
+ mService = null;
+ mContext.unbindService(mConnection);
+ } catch (Exception re) {
+ Log.e(TAG,"",re);
+ }
+ }
+ } else {
+ synchronized (mConnection) {
+ try {
+ if (mService == null) {
+ if (VDBG) Log.d(TAG,"Binding service...");
+ if (!mContext.bindService(
+ new Intent(IBluetoothMap.class.getName()),
+ mConnection, 0)) {
+ Log.e(TAG, "Could not bind to Bluetooth MAP Service");
+ }
+ }
+ } catch (Exception re) {
+ Log.e(TAG,"",re);
+ }
+ }
+ }
+ }
+ };
+
+ /**
+ * Create a BluetoothMap proxy object.
+ */
+ public BluetoothMap(Context context, ServiceListener l) {
+ mContext = context;
+ mServiceListener = l;
+ mAdapter = BluetoothAdapter.getDefaultAdapter();
+ IBluetoothManager mgr = mAdapter.getBluetoothManager();
+ if (mgr != null) {
+ try {
+ mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
+ } catch (RemoteException e) {
+ Log.e(TAG,"",e);
+ }
+ }
+ if (!context.bindService(new Intent(IBluetoothMap.class.getName()), mConnection, 0)) {
+ Log.e(TAG, "Could not bind to Bluetooth Map Service");
+ }
+ }
+
+ protected void finalize() throws Throwable {
+ try {
+ close();
+ } finally {
+ super.finalize();
+ }
+ }
+
+ /**
+ * Close the connection to the backing service.
+ * Other public functions of BluetoothMap will return default error
+ * results once close() has been called. Multiple invocations of close()
+ * are ok.
+ */
+ public synchronized void close() {
+ IBluetoothManager mgr = mAdapter.getBluetoothManager();
+ if (mgr != null) {
+ try {
+ mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
+ } catch (Exception e) {
+ Log.e(TAG,"",e);
+ }
+ }
+
+ synchronized (mConnection) {
+ if (mService != null) {
+ try {
+ mService = null;
+ mContext.unbindService(mConnection);
+ mConnection = null;
+ } catch (Exception re) {
+ Log.e(TAG,"",re);
+ }
+ }
+ }
+ mServiceListener = null;
+ }
+
+ /**
+ * Get the current state of the BluetoothMap service.
+ * @return One of the STATE_ return codes, or STATE_ERROR if this proxy
+ * object is currently not connected to the Map service.
+ */
+ public int getState() {
+ if (VDBG) log("getState()");
+ if (mService != null) {
+ try {
+ return mService.getState();
+ } catch (RemoteException e) {Log.e(TAG, e.toString());}
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) log(Log.getStackTraceString(new Throwable()));
+ }
+ return BluetoothMap.STATE_ERROR;
+ }
+
+ /**
+ * Get the currently connected remote Bluetooth device (PCE).
+ * @return The remote Bluetooth device, or null if not in connected or
+ * connecting state, or if this proxy object is not connected to
+ * the Map service.
+ */
+ public BluetoothDevice getClient() {
+ if (VDBG) log("getClient()");
+ if (mService != null) {
+ try {
+ return mService.getClient();
+ } catch (RemoteException e) {Log.e(TAG, e.toString());}
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) log(Log.getStackTraceString(new Throwable()));
+ }
+ return null;
+ }
+
+ /**
+ * Returns true if the specified Bluetooth device is connected (does not
+ * include connecting). Returns false if not connected, or if this proxy
+ * object is not currently connected to the Map service.
+ */
+ public boolean isConnected(BluetoothDevice device) {
+ if (VDBG) log("isConnected(" + device + ")");
+ if (mService != null) {
+ try {
+ return mService.isConnected(device);
+ } catch (RemoteException e) {Log.e(TAG, e.toString());}
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) log(Log.getStackTraceString(new Throwable()));
+ }
+ return false;
+ }
+
+ /**
+ * Disconnects the current Map Client. Currently this call blocks,
+ * it may soon be made asynchronous. Returns false if this proxy object is
+ * not currently connected to the Map service.
+ */
+ public boolean disconnect() {
+ if (DBG) log("disconnect()");
+ if (mService != null) {
+ try {
+ mService.disconnect();
+ return true;
+ } catch (RemoteException e) {Log.e(TAG, e.toString());}
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) log(Log.getStackTraceString(new Throwable()));
+ }
+ return false;
+ }
+
+ /**
+ * Check class bits for possible Map support.
+ * This is a simple heuristic that tries to guess if a device with the
+ * given class bits might support Map. It is not accurate for all
+ * devices. It tries to err on the side of false positives.
+ * @return True if this device might support Map.
+ */
+ public static boolean doesClassMatchSink(BluetoothClass btClass) {
+ // TODO optimize the rule
+ switch (btClass.getDeviceClass()) {
+ case BluetoothClass.Device.COMPUTER_DESKTOP:
+ case BluetoothClass.Device.COMPUTER_LAPTOP:
+ case BluetoothClass.Device.COMPUTER_SERVER:
+ case BluetoothClass.Device.COMPUTER_UNCATEGORIZED:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ private ServiceConnection mConnection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ if (DBG) log("Proxy object connected");
+ mService = IBluetoothMap.Stub.asInterface(service);
+ if (mServiceListener != null) {
+ mServiceListener.onServiceConnected(BluetoothMap.this);
+ }
+ }
+ public void onServiceDisconnected(ComponentName className) {
+ if (DBG) log("Proxy object disconnected");
+ mService = null;
+ if (mServiceListener != null) {
+ mServiceListener.onServiceDisconnected();
+ }
+ }
+ };
+
+ private static void log(String msg) {
+ Log.d(TAG, msg);
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index 43079f44f5ba..15740908b0a3 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -98,6 +98,12 @@ public interface BluetoothProfile {
static public final int GATT_SERVER = 8;
/**
+ * MAP Profile
+ * @hide
+ */
+ public static final int MAP = 9;
+
+ /**
* Default priority for devices that we try to auto-connect to and
* and allow incoming connections for the profile
* @hide
diff --git a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
index 81c0a6a87eaf..0aedecb82dd2 100644
--- a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
+++ b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
@@ -152,6 +152,11 @@ public class BluetoothTetheringDataTracker implements NetworkStateTracker {
// not implemented
}
+ @Override
+ public void captivePortalCheckCompleted(boolean isCaptivePortal) {
+ // not implemented
+ }
+
/**
* Re-enable connectivity to a network after a {@link #teardown()}.
*/
diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java
index 596223518146..fe66fbddb78e 100644
--- a/core/java/android/bluetooth/BluetoothUuid.java
+++ b/core/java/android/bluetooth/BluetoothUuid.java
@@ -64,10 +64,14 @@ public final class BluetoothUuid {
ParcelUuid.fromString("0000000f-0000-1000-8000-00805F9B34FB");
public static final ParcelUuid PBAP_PSE =
ParcelUuid.fromString("0000112f-0000-1000-8000-00805F9B34FB");
+ public static final ParcelUuid MAP =
+ ParcelUuid.fromString("00001132-0000-1000-8000-00805F9B34FB");
+ public static final ParcelUuid MNS =
+ ParcelUuid.fromString("00001133-0000-1000-8000-00805F9B34FB");
public static final ParcelUuid[] RESERVED_UUIDS = {
AudioSink, AudioSource, AdvAudioDist, HSP, Handsfree, AvrcpController, AvrcpTarget,
- ObexObjectPush, PANU, NAP};
+ ObexObjectPush, PANU, NAP, MAP, MNS};
public static boolean isAudioSource(ParcelUuid uuid) {
return uuid.equals(AudioSource);
@@ -112,6 +116,13 @@ public final class BluetoothUuid {
public static boolean isBnep(ParcelUuid uuid) {
return uuid.equals(BNEP);
}
+ public static boolean isMap(ParcelUuid uuid) {
+ return uuid.equals(MAP);
+ }
+ public static boolean isMns(ParcelUuid uuid) {
+ return uuid.equals(MNS);
+ }
+
/**
* Returns true if ParcelUuid is present in uuidArray
*
diff --git a/core/java/android/bluetooth/IBluetoothMap.aidl b/core/java/android/bluetooth/IBluetoothMap.aidl
new file mode 100644
index 000000000000..0c18e06a7884
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothMap.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.BluetoothDevice;
+
+/**
+ * System private API for Bluetooth MAP service
+ *
+ * {@hide}
+ */
+interface IBluetoothMap {
+ int getState();
+ BluetoothDevice getClient();
+ boolean connect(in BluetoothDevice device);
+ void disconnect();
+ boolean isConnected(in BluetoothDevice device);
+}
diff --git a/core/java/android/net/BaseNetworkStateTracker.java b/core/java/android/net/BaseNetworkStateTracker.java
index 1165281e39bb..e87f84c56a21 100644
--- a/core/java/android/net/BaseNetworkStateTracker.java
+++ b/core/java/android/net/BaseNetworkStateTracker.java
@@ -102,6 +102,11 @@ public abstract class BaseNetworkStateTracker implements NetworkStateTracker {
}
@Override
+ public void captivePortalCheckCompleted(boolean isCaptivePortal) {
+ // not implemented
+ }
+
+ @Override
public boolean setRadio(boolean turnOn) {
// Base tracker doesn't handle radios
return true;
diff --git a/core/java/android/net/CaptivePortalTracker.java b/core/java/android/net/CaptivePortalTracker.java
index 19d74edf0d5f..74c2c5967a08 100644
--- a/core/java/android/net/CaptivePortalTracker.java
+++ b/core/java/android/net/CaptivePortalTracker.java
@@ -46,6 +46,7 @@ import android.telephony.CellInfoGsm;
import android.telephony.CellInfoLte;
import android.telephony.CellInfoWcdma;
import android.telephony.TelephonyManager;
+import android.text.TextUtils;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
@@ -54,6 +55,7 @@ import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.Inet4Address;
+import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.List;
@@ -65,7 +67,7 @@ import com.android.internal.R;
* @hide
*/
public class CaptivePortalTracker extends StateMachine {
- private static final boolean DBG = false;
+ private static final boolean DBG = true;
private static final String TAG = "CaptivePortalTracker";
private static final String DEFAULT_SERVER = "clients3.google.com";
@@ -301,6 +303,7 @@ public class CaptivePortalTracker extends StateMachine {
} else {
if (DBG) log("Not captive network " + mNetworkInfo);
}
+ notifyPortalCheckCompleted(mNetworkInfo, captive);
if (mDeviceProvisioned) {
if (captive) {
// Setup Wizard will assist the user in connecting to a captive
@@ -331,12 +334,26 @@ public class CaptivePortalTracker extends StateMachine {
return;
}
try {
+ if (DBG) log("notifyPortalCheckComplete: ni=" + info);
mConnService.captivePortalCheckComplete(info);
} catch(RemoteException e) {
e.printStackTrace();
}
}
+ private void notifyPortalCheckCompleted(NetworkInfo info, boolean isCaptivePortal) {
+ if (info == null) {
+ loge("notifyPortalCheckComplete on null");
+ return;
+ }
+ try {
+ if (DBG) log("notifyPortalCheckCompleted: captive=" + isCaptivePortal + " ni=" + info);
+ mConnService.captivePortalCheckCompleted(info, isCaptivePortal);
+ } catch(RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
private boolean isActiveNetwork(NetworkInfo info) {
try {
NetworkInfo active = mConnService.getActiveNetworkInfo();
@@ -382,6 +399,12 @@ public class CaptivePortalTracker extends StateMachine {
sendNetworkConditionsBroadcast(true /* response received */, isCaptivePortal,
requestTimestamp, responseTimestamp);
return isCaptivePortal;
+ } catch (SocketTimeoutException e) {
+ if (DBG) log("Probably a portal: exception " + e);
+ if (requestTimestamp != -1) {
+ sendFailedCaptivePortalCheckBroadcast(requestTimestamp);
+ } // else something went wrong with setting up the urlConnection
+ return true;
} catch (IOException e) {
if (DBG) log("Probably not a portal: exception " + e);
if (requestTimestamp != -1) {
@@ -415,6 +438,7 @@ public class CaptivePortalTracker extends StateMachine {
private void setNotificationVisible(boolean visible) {
// if it should be hidden and it is already hidden, then noop
if (!visible && !mNotificationShown) {
+ if (DBG) log("setNotivicationVisible: false and not shown, so noop");
return;
}
@@ -426,12 +450,14 @@ public class CaptivePortalTracker extends StateMachine {
CharSequence title;
CharSequence details;
int icon;
+ String url = null;
switch (mNetworkInfo.getType()) {
case ConnectivityManager.TYPE_WIFI:
title = r.getString(R.string.wifi_available_sign_in, 0);
details = r.getString(R.string.network_available_sign_in_detailed,
mNetworkInfo.getExtraInfo());
icon = R.drawable.stat_notify_wifi_in_range;
+ url = mUrl;
break;
case ConnectivityManager.TYPE_MOBILE:
title = r.getString(R.string.network_available_sign_in, 0);
@@ -439,12 +465,24 @@ public class CaptivePortalTracker extends StateMachine {
// name has been added to it
details = mTelephonyManager.getNetworkOperatorName();
icon = R.drawable.stat_notify_rssi_in_range;
+ try {
+ url = mConnService.getMobileProvisioningUrl();
+ if (TextUtils.isEmpty(url)) {
+ url = mConnService.getMobileRedirectedProvisioningUrl();
+ }
+ } catch(RemoteException e) {
+ e.printStackTrace();
+ }
+ if (TextUtils.isEmpty(url)) {
+ url = mUrl;
+ }
break;
default:
title = r.getString(R.string.network_available_sign_in, 0);
details = r.getString(R.string.network_available_sign_in_detailed,
mNetworkInfo.getExtraInfo());
icon = R.drawable.stat_notify_rssi_in_range;
+ url = mUrl;
break;
}
@@ -452,15 +490,17 @@ public class CaptivePortalTracker extends StateMachine {
notification.when = 0;
notification.icon = icon;
notification.flags = Notification.FLAG_AUTO_CANCEL;
- Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(mUrl));
+ Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |
Intent.FLAG_ACTIVITY_NEW_TASK);
notification.contentIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
notification.tickerText = title;
notification.setLatestEventInfo(mContext, title, details, notification.contentIntent);
+ if (DBG) log("setNotivicationVisible: make visible");
notificationManager.notify(NOTIFICATION_ID, 1, notification);
} else {
+ if (DBG) log("setNotivicationVisible: cancel notification");
notificationManager.cancel(NOTIFICATION_ID, 1);
}
mNotificationShown = visible;
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 1dbe34e20115..1b418fa5f8a5 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -1324,6 +1324,25 @@ public class ConnectivityManager {
}
/**
+ * Signal that the captive portal check on the indicated network
+ * is complete and whether its a captive portal or not.
+ *
+ * @param info the {@link NetworkInfo} object for the networkType
+ * in question.
+ * @param isCaptivePortal true/false.
+ *
+ * <p>This method requires the call to hold the permission
+ * {@link android.Manifest.permission#CONNECTIVITY_INTERNAL}.
+ * {@hide}
+ */
+ public void captivePortalCheckCompleted(NetworkInfo info, boolean isCaptivePortal) {
+ try {
+ mService.captivePortalCheckCompleted(info, isCaptivePortal);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
* Supply the backend messenger for a network tracker
*
* @param type NetworkType to set
@@ -1401,7 +1420,7 @@ public class ConnectivityManager {
}
/**
- * Get the carrier provisioning url.
+ * Get the mobile provisioning url.
* {@hide}
*/
public String getMobileProvisioningUrl() {
@@ -1411,4 +1430,16 @@ public class ConnectivityManager {
}
return null;
}
+
+ /**
+ * Get the mobile redirected provisioning url.
+ * {@hide}
+ */
+ public String getMobileRedirectedProvisioningUrl() {
+ try {
+ return mService.getMobileRedirectedProvisioningUrl();
+ } catch (RemoteException e) {
+ }
+ return null;
+ }
}
diff --git a/core/java/android/net/DummyDataStateTracker.java b/core/java/android/net/DummyDataStateTracker.java
index 15a81f3e45e8..ee738fd9c715 100644
--- a/core/java/android/net/DummyDataStateTracker.java
+++ b/core/java/android/net/DummyDataStateTracker.java
@@ -120,10 +120,16 @@ public class DummyDataStateTracker implements NetworkStateTracker {
return true;
}
+ @Override
public void captivePortalCheckComplete() {
// not implemented
}
+ @Override
+ public void captivePortalCheckCompleted(boolean isCaptivePortal) {
+ // not implemented
+ }
+
/**
* Record the detailed state of a network, and if it is a
* change from the previous state, send a notification to
diff --git a/core/java/android/net/EthernetDataTracker.java b/core/java/android/net/EthernetDataTracker.java
index 7b803a870092..7999c66e2a8b 100644
--- a/core/java/android/net/EthernetDataTracker.java
+++ b/core/java/android/net/EthernetDataTracker.java
@@ -280,6 +280,11 @@ public class EthernetDataTracker implements NetworkStateTracker {
// not implemented
}
+ @Override
+ public void captivePortalCheckCompleted(boolean isCaptivePortal) {
+ // not implemented
+ }
+
/**
* Turn the wireless radio off for a network.
* @param turnOn {@code true} to turn the radio on, {@code false}
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index b0f7fc62bf30..992ec37cda4b 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -134,6 +134,8 @@ interface IConnectivityManager
void captivePortalCheckComplete(in NetworkInfo info);
+ void captivePortalCheckCompleted(in NetworkInfo info, boolean isCaptivePortal);
+
void supplyMessenger(int networkType, in Messenger messenger);
int findConnectionTypeForIface(in String iface);
@@ -141,4 +143,6 @@ interface IConnectivityManager
int checkMobileProvisioning(boolean sendNotification, int suggestedTimeOutMs, in ResultReceiver resultReceiver);
String getMobileProvisioningUrl();
+
+ String getMobileRedirectedProvisioningUrl();
}
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index 54273eef3a58..e4fd312c0671 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -40,6 +40,7 @@ import com.android.internal.util.AsyncChannel;
import java.io.CharArrayWriter;
import java.io.PrintWriter;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* Track the state of mobile data connectivity. This is done by
@@ -75,6 +76,8 @@ public class MobileDataStateTracker implements NetworkStateTracker {
private Handler mHandler;
private AsyncChannel mDataConnectionTrackerAc;
+ private AtomicBoolean mIsCaptivePortal = new AtomicBoolean(false);
+
/**
* Create a new MobileDataStateTracker
* @param netType the ConnectivityManager network type
@@ -377,6 +380,15 @@ public class MobileDataStateTracker implements NetworkStateTracker {
// not implemented
}
+ @Override
+ public void captivePortalCheckCompleted(boolean isCaptivePortal) {
+ if (mIsCaptivePortal.getAndSet(isCaptivePortal) != isCaptivePortal) {
+ // Captive portal change enable/disable failing fast
+ setEnableFailFastMobileData(
+ isCaptivePortal ? DctConstants.ENABLED : DctConstants.DISABLED);
+ }
+ }
+
/**
* Record the detailed state of a network, and if it is a
* change from the previous state, send a notification to
diff --git a/core/java/android/net/NetworkStateTracker.java b/core/java/android/net/NetworkStateTracker.java
index cf77a1cdbe61..9ed753371907 100644
--- a/core/java/android/net/NetworkStateTracker.java
+++ b/core/java/android/net/NetworkStateTracker.java
@@ -144,6 +144,11 @@ public interface NetworkStateTracker {
public void captivePortalCheckComplete();
/**
+ * Captive portal check has completed
+ */
+ public void captivePortalCheckCompleted(boolean isCaptive);
+
+ /**
* Turn the wireless radio off for a network.
* @param turnOn {@code true} to turn the radio on, {@code false}
*/
diff --git a/core/java/android/net/PacProxySelector.java b/core/java/android/net/PacProxySelector.java
index be3a31dce10b..d3ce2e509e14 100644
--- a/core/java/android/net/PacProxySelector.java
+++ b/core/java/android/net/PacProxySelector.java
@@ -3,6 +3,7 @@ package android.net;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.util.Log;
import com.android.net.IProxyService;
import com.google.android.collect.Lists;
@@ -21,16 +22,25 @@ import java.util.List;
* @hide
*/
public class PacProxySelector extends ProxySelector {
+ private static final String TAG = "PacProxySelector";
public static final String PROXY_SERVICE = "com.android.net.IProxyService";
private IProxyService mProxyService;
public PacProxySelector() {
mProxyService = IProxyService.Stub.asInterface(
ServiceManager.getService(PROXY_SERVICE));
+ if (mProxyService == null) {
+ // Added because of b10267814 where mako is restarting.
+ Log.e(TAG, "PackManager: no proxy service");
+ }
}
@Override
public List<Proxy> select(URI uri) {
+ if (mProxyService == null) {
+ Log.e(TAG, "select: no proxy service return NO_PROXY");
+ return Lists.newArrayList(java.net.Proxy.NO_PROXY);
+ }
String response = null;
String urlString;
try {
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index ffa7d7ebe30b..3f7e3ef22433 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -188,7 +188,8 @@ public final class ApduServiceInfo implements Parcelable {
currentGroup != null) {
final TypedArray a = res.obtainAttributes(attrs,
com.android.internal.R.styleable.AidFilter);
- String aid = a.getString(com.android.internal.R.styleable.AidFilter_name);
+ String aid = a.getString(com.android.internal.R.styleable.AidFilter_name).
+ toUpperCase();
if (isValidAid(aid) && !currentGroup.aids.contains(aid)) {
currentGroup.aids.add(aid);
mAids.add(aid);
diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java
index ce5f1633a8cd..d4a30064707e 100644
--- a/core/java/android/os/AsyncTask.java
+++ b/core/java/android/os/AsyncTask.java
@@ -177,8 +177,9 @@ import java.util.concurrent.atomic.AtomicInteger;
public abstract class AsyncTask<Params, Progress, Result> {
private static final String LOG_TAG = "AsyncTask";
- private static final int CORE_POOL_SIZE = 5;
- private static final int MAXIMUM_POOL_SIZE = 128;
+ private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
+ private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
+ private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE = 1;
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
@@ -190,7 +191,7 @@ public abstract class AsyncTask<Params, Progress, Result> {
};
private static final BlockingQueue<Runnable> sPoolWorkQueue =
- new LinkedBlockingQueue<Runnable>(10);
+ new LinkedBlockingQueue<Runnable>(128);
/**
* An {@link Executor} that can be used to execute tasks in parallel.
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 97ea99ddb419..4d48fd46dd29 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -17,10 +17,17 @@
package android.os;
import android.util.Log;
+import android.util.Slog;
+
+import libcore.io.ErrnoException;
+import libcore.io.IoUtils;
+import libcore.io.Libcore;
+import libcore.io.OsConstants;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
@@ -58,9 +65,84 @@ public class FileUtils {
/** Regular expression for safe filenames: no spaces or metacharacters */
private static final Pattern SAFE_FILENAME_PATTERN = Pattern.compile("[\\w%+,./=_-]+");
- public static native int setPermissions(String file, int mode, int uid, int gid);
+ /**
+ * Set owner and mode of of given {@link File}.
+ *
+ * @param mode to apply through {@code chmod}
+ * @param uid to apply through {@code chown}, or -1 to leave unchanged
+ * @param gid to apply through {@code chown}, or -1 to leave unchanged
+ * @return 0 on success, otherwise errno.
+ */
+ public static int setPermissions(File path, int mode, int uid, int gid) {
+ return setPermissions(path.getAbsolutePath(), mode, uid, gid);
+ }
+
+ /**
+ * Set owner and mode of of given path.
+ *
+ * @param mode to apply through {@code chmod}
+ * @param uid to apply through {@code chown}, or -1 to leave unchanged
+ * @param gid to apply through {@code chown}, or -1 to leave unchanged
+ * @return 0 on success, otherwise errno.
+ */
+ public static int setPermissions(String path, int mode, int uid, int gid) {
+ try {
+ Libcore.os.chmod(path, mode);
+ } catch (ErrnoException e) {
+ Slog.w(TAG, "Failed to chmod(" + path + "): " + e);
+ return e.errno;
+ }
+
+ if (uid >= 0 || gid >= 0) {
+ try {
+ Libcore.os.chown(path, uid, gid);
+ } catch (ErrnoException e) {
+ Slog.w(TAG, "Failed to chown(" + path + "): " + e);
+ return e.errno;
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * Set owner and mode of of given {@link FileDescriptor}.
+ *
+ * @param mode to apply through {@code chmod}
+ * @param uid to apply through {@code chown}, or -1 to leave unchanged
+ * @param gid to apply through {@code chown}, or -1 to leave unchanged
+ * @return 0 on success, otherwise errno.
+ */
+ public static int setPermissions(FileDescriptor fd, int mode, int uid, int gid) {
+ try {
+ Libcore.os.fchmod(fd, mode);
+ } catch (ErrnoException e) {
+ Slog.w(TAG, "Failed to fchmod(): " + e);
+ return e.errno;
+ }
- public static native int getUid(String file);
+ if (uid >= 0 || gid >= 0) {
+ try {
+ Libcore.os.fchown(fd, uid, gid);
+ } catch (ErrnoException e) {
+ Slog.w(TAG, "Failed to fchown(): " + e);
+ return e.errno;
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * Return owning UID of given path, otherwise -1.
+ */
+ public static int getUid(String path) {
+ try {
+ return Libcore.os.stat(path).st_uid;
+ } catch (ErrnoException e) {
+ return -1;
+ }
+ }
/** returns the FAT file system volume ID for the volume mounted
* at the given mount point, or -1 for failure
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index ab0543d0b78e..cf9ddb3b258b 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -100,12 +100,6 @@ public class Process {
public static final int DRM_UID = 1019;
/**
- * Defines the GID for the group that allows write access to the SD card.
- * @hide
- */
- public static final int SDCARD_RW_GID = 1015;
-
- /**
* Defines the UID/GID for the group that controls VPN services.
* @hide
*/
@@ -130,11 +124,18 @@ public class Process {
public static final int MEDIA_RW_GID = 1023;
/**
+ * Access to installed package details
+ * @hide
+ */
+ public static final int PACKAGE_INFO_GID = 1032;
+
+ /**
* Defines the start of a range of UIDs (and GIDs), going from this
* number to {@link #LAST_APPLICATION_UID} that are reserved for assigning
* to applications.
*/
public static final int FIRST_APPLICATION_UID = 10000;
+
/**
* Last of application-specific UIDs starting at
* {@link #FIRST_APPLICATION_UID}.
diff --git a/core/java/android/print/IPrintSpoolerClient.aidl b/core/java/android/print/IPrintSpoolerClient.aidl
index 46857e4eac98..8db2169635af 100644
--- a/core/java/android/print/IPrintSpoolerClient.aidl
+++ b/core/java/android/print/IPrintSpoolerClient.aidl
@@ -17,7 +17,7 @@
package android.print;
import android.content.ComponentName;
-import android.print.IPrinterDiscoveryObserver;
+import android.print.IPrinterDiscoverySessionObserver;
import android.print.PrinterId;
import android.print.PrintJobInfo;
@@ -28,10 +28,8 @@ import android.print.PrintJobInfo;
* @hide
*/
oneway interface IPrintSpoolerClient {
+ void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer);
void onPrintJobQueued(in PrintJobInfo printJob);
- void onStartPrinterDiscovery(IPrinterDiscoveryObserver observer);
- void onStopPrinterDiscovery();
- void onRequestUpdatePrinters(in List<PrinterId> printerIds);
void onAllPrintJobsForServiceHandled(in ComponentName printService);
void onAllPrintJobsHandled();
}
diff --git a/core/java/android/print/IPrinterDiscoveryObserver.aidl b/core/java/android/print/IPrinterDiscoverySessionController.aidl
index deabbcb04d77..13116ef1ccb6 100644
--- a/core/java/android/print/IPrinterDiscoveryObserver.aidl
+++ b/core/java/android/print/IPrinterDiscoverySessionController.aidl
@@ -17,15 +17,14 @@
package android.print;
import android.print.PrinterId;
-import android.print.PrinterInfo;
/**
- * Interface for observing printer discovery.
+* Interface for the controlling part of a printer discovery session.
*
* @hide
*/
-oneway interface IPrinterDiscoveryObserver {
- void onPrintersAdded(in List<PrinterInfo> printers);
- void onPrintersRemoved(in List<PrinterId> printers);
- void onPrintersUpdated(in List<PrinterInfo> printers);
+oneway interface IPrinterDiscoverySessionController {
+ void open(in List<PrinterId> priorityList);
+ void requestPrinterUpdate(in PrinterId printerId);
+ void close();
}
diff --git a/core/java/android/print/IPrinterDiscoverySessionObserver.aidl b/core/java/android/print/IPrinterDiscoverySessionObserver.aidl
new file mode 100644
index 000000000000..a78924c6171b
--- /dev/null
+++ b/core/java/android/print/IPrinterDiscoverySessionObserver.aidl
@@ -0,0 +1,33 @@
+/*
+ * 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 android.print;
+
+import android.print.IPrinterDiscoverySessionController;
+import android.print.PrinterId;
+import android.print.PrinterInfo;
+
+/**
+ * Interface for the observing part of a printer discovery session.
+ *
+ * @hide
+ */
+oneway interface IPrinterDiscoverySessionObserver {
+ void setController(IPrinterDiscoverySessionController controller);
+ void onPrintersAdded(in List<PrinterInfo> printers);
+ void onPrintersRemoved(in List<PrinterId> printerIds);
+ void onPrintersUpdated(in List<PrinterInfo> printerIds);
+}
diff --git a/core/java/android/print/PrintAttributes.java b/core/java/android/print/PrintAttributes.java
index 911e3803d648..a902c7204bbd 100644
--- a/core/java/android/print/PrintAttributes.java
+++ b/core/java/android/print/PrintAttributes.java
@@ -931,7 +931,7 @@ public final class PrintAttributes implements Parcelable {
}
private final String mId;
- private final CharSequence mLabel;
+ private final String mLabel;
private final int mWidthMils;
private final int mHeightMils;
@@ -948,7 +948,7 @@ public final class PrintAttributes implements Parcelable {
* @throws IllegalArgumentException If the widthMils is less than or equal to zero.
* @throws IllegalArgumentException If the heightMils is less than or equal to zero.
*/
- public MediaSize(String id, CharSequence label, int widthMils, int heightMils) {
+ public MediaSize(String id, String label, int widthMils, int heightMils) {
if (TextUtils.isEmpty(id)) {
throw new IllegalArgumentException("id cannot be empty.");
}
@@ -983,7 +983,7 @@ public final class PrintAttributes implements Parcelable {
*
* @return The human readable label.
*/
- public CharSequence getLabel() {
+ public String getLabel() {
return mLabel;
}
@@ -1007,7 +1007,7 @@ public final class PrintAttributes implements Parcelable {
void writeToParcel(Parcel parcel) {
parcel.writeString(mId);
- parcel.writeCharSequence(mLabel);
+ parcel.writeString(mLabel);
parcel.writeInt(mWidthMils);
parcel.writeInt(mHeightMils);
}
@@ -1015,7 +1015,7 @@ public final class PrintAttributes implements Parcelable {
static MediaSize createFromParcel(Parcel parcel) {
return new MediaSize(
parcel.readString(),
- parcel.readCharSequence(),
+ parcel.readString(),
parcel.readInt(),
parcel.readInt());
}
@@ -1076,7 +1076,7 @@ public final class PrintAttributes implements Parcelable {
*/
public static final class Resolution {
private final String mId;
- private final CharSequence mLabel;
+ private final String mLabel;
private final int mHorizontalDpi;
private final int mVerticalDpi;
@@ -1093,7 +1093,7 @@ public final class PrintAttributes implements Parcelable {
* @throws IllegalArgumentException If the horizontalDpi is less than or equal to zero.
* @throws IllegalArgumentException If the verticalDpi is less than or equal to zero.
*/
- public Resolution(String id, CharSequence label, int horizontalDpi, int verticalDpi) {
+ public Resolution(String id, String label, int horizontalDpi, int verticalDpi) {
if (TextUtils.isEmpty(id)) {
throw new IllegalArgumentException("id cannot be empty.");
}
@@ -1128,7 +1128,7 @@ public final class PrintAttributes implements Parcelable {
*
* @return The human readable label.
*/
- public CharSequence getLabel() {
+ public String getLabel() {
return mLabel;
}
@@ -1152,7 +1152,7 @@ public final class PrintAttributes implements Parcelable {
void writeToParcel(Parcel parcel) {
parcel.writeString(mId);
- parcel.writeCharSequence(mLabel);
+ parcel.writeString(mLabel);
parcel.writeInt(mHorizontalDpi);
parcel.writeInt(mVerticalDpi);
}
@@ -1160,7 +1160,7 @@ public final class PrintAttributes implements Parcelable {
static Resolution createFromParcel(Parcel parcel) {
return new Resolution(
parcel.readString(),
- parcel.readCharSequence(),
+ parcel.readString(),
parcel.readInt(),
parcel.readInt());
}
@@ -1364,7 +1364,7 @@ public final class PrintAttributes implements Parcelable {
*/
public static final class Tray {
private final String mId;
- private final CharSequence mLabel;
+ private final String mLabel;
/**
* Creates a new instance.
@@ -1375,7 +1375,7 @@ public final class PrintAttributes implements Parcelable {
* @throws IllegalArgumentException If the id is empty.
* @throws IllegalArgumentException If the label is empty.
*/
- public Tray(String id, CharSequence label) {
+ public Tray(String id, String label) {
if (TextUtils.isEmpty(id)) {
throw new IllegalArgumentException("id cannot be empty.");
}
@@ -1400,19 +1400,19 @@ public final class PrintAttributes implements Parcelable {
*
* @return The human readable label.
*/
- public CharSequence getLabel() {
+ public String getLabel() {
return mLabel;
}
void writeToParcel(Parcel parcel) {
parcel.writeString(mId);
- parcel.writeCharSequence(mLabel);
+ parcel.writeString(mLabel);
}
static Tray createFromParcel(Parcel parcel) {
return new Tray(
parcel.readString(),
- parcel.readCharSequence());
+ parcel.readString());
}
@Override
@@ -1457,7 +1457,7 @@ public final class PrintAttributes implements Parcelable {
}
}
- private static String duplexModeToString(int duplexMode) {
+ static String duplexModeToString(int duplexMode) {
switch (duplexMode) {
case DUPLEX_MODE_NONE: {
return "DUPLEX_MODE_NONE";
@@ -1473,7 +1473,7 @@ public final class PrintAttributes implements Parcelable {
}
}
- private static String colorModeToString(int colorMode) {
+ static String colorModeToString(int colorMode) {
switch (colorMode) {
case COLOR_MODE_MONOCHROME: {
return "COLOR_MODE_MONOCHROME";
@@ -1486,7 +1486,7 @@ public final class PrintAttributes implements Parcelable {
}
}
- private static String orientationToString(int orientation) {
+ static String orientationToString(int orientation) {
switch (orientation) {
case ORIENTATION_PORTRAIT: {
return "ORIENTATION_PORTRAIT";
@@ -1499,7 +1499,7 @@ public final class PrintAttributes implements Parcelable {
}
}
- private static String fittingModeToString(int fittingMode) {
+ static String fittingModeToString(int fittingMode) {
switch (fittingMode) {
case FITTING_MODE_NONE: {
return "FITTING_MODE_NONE";
diff --git a/core/java/android/print/PrintDocumentInfo.java b/core/java/android/print/PrintDocumentInfo.java
index 29e8e7ce9566..653ad4bfc4e4 100644
--- a/core/java/android/print/PrintDocumentInfo.java
+++ b/core/java/android/print/PrintDocumentInfo.java
@@ -18,6 +18,7 @@ package android.print;
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.TextUtils;
/**
* This class encapsulates information about a printed document.
@@ -44,6 +45,7 @@ public final class PrintDocumentInfo implements Parcelable {
*/
public static final int CONTENT_TYPE_PHOTO = 1;
+ private String mName;
private int mPageCount;
private int mContentType;
@@ -61,6 +63,7 @@ public final class PrintDocumentInfo implements Parcelable {
* @param Prototype from which to clone.
*/
private PrintDocumentInfo(PrintDocumentInfo prototype) {
+ mName = prototype.mName;
mPageCount = prototype.mPageCount;
mContentType = prototype.mContentType;
}
@@ -71,11 +74,21 @@ public final class PrintDocumentInfo implements Parcelable {
* @param parcel Data from which to initialize.
*/
private PrintDocumentInfo(Parcel parcel) {
+ mName = parcel.readString();
mPageCount = parcel.readInt();
mContentType = parcel.readInt();
}
/**
+ * Gets the document name.
+ *
+ * @return The document name.
+ */
+ public String getName() {
+ return mName;
+ }
+
+ /**
* Gets the total number of pages.
*
* @return The number of pages.
@@ -106,6 +119,7 @@ public final class PrintDocumentInfo implements Parcelable {
@Override
public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeString(mName);
parcel.writeInt(mPageCount);
parcel.writeInt(mContentType);
}
@@ -114,6 +128,7 @@ public final class PrintDocumentInfo implements Parcelable {
public int hashCode() {
final int prime = 31;
int result = 1;
+ result = prime * result + ((mName != null) ? mName.hashCode() : 0);
result = prime * result + mContentType;
result = prime * result + mPageCount;
return result;
@@ -131,6 +146,9 @@ public final class PrintDocumentInfo implements Parcelable {
return false;
}
PrintDocumentInfo other = (PrintDocumentInfo) obj;
+ if (!TextUtils.equals(mName, other.mName)) {
+ return false;
+ }
if (mContentType != other.mContentType) {
return false;
}
@@ -144,17 +162,47 @@ public final class PrintDocumentInfo implements Parcelable {
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("PrintDocumentInfo{");
- builder.append("pageCount: ").append(mPageCount);
- builder.append(", contentType: ").append(mContentType);
+ builder.append("name=").append(mName);
+ builder.append(", pageCount=").append(mPageCount);
+ builder.append(", contentType=").append(contentTyepToString(mContentType));
builder.append("}");
return builder.toString();
}
+ private String contentTyepToString(int contentType) {
+ switch (contentType) {
+ case CONTENT_TYPE_DOCUMENT: {
+ return "CONTENT_TYPE_DOCUMENT";
+ }
+ case CONTENT_TYPE_PHOTO: {
+ return "CONTENT_TYPE_PHOTO";
+ }
+ default: {
+ return "CONTENT_TYPE_UNKNOWN";
+ }
+ }
+ }
+
/**
* Builder for creating an {@link PrintDocumentInfo}.
*/
public static final class Builder {
- private final PrintDocumentInfo mPrototype = new PrintDocumentInfo();
+ private final PrintDocumentInfo mPrototype;
+
+ /**
+ * Constructor.
+ *
+ * @param name The document name. Cannot be empty.
+ *
+ * @throws IllegalArgumentException If the name is empty.
+ */
+ public Builder(String name) {
+ if (TextUtils.isEmpty(name)) {
+ throw new IllegalArgumentException("name cannot be empty");
+ }
+ mPrototype = new PrintDocumentInfo();
+ mPrototype.mName = name;
+ }
/**
* Sets the total number of pages.
diff --git a/core/java/android/print/FileDocumentAdapter.java b/core/java/android/print/PrintFileDocumentAdapter.java
index d642a61fa6a2..4503eda5be55 100644
--- a/core/java/android/print/FileDocumentAdapter.java
+++ b/core/java/android/print/PrintFileDocumentAdapter.java
@@ -36,34 +36,48 @@ import java.io.InputStream;
import java.io.OutputStream;
/**
- * Adapter for printing files.
+ * Adapter for printing files. This class could be useful if you
+ * want to print a file and intercept when the system is ready
+ * spooling the data, so you can deleted the file if it is a
+ * temporary one.
*/
-final class FileDocumentAdapter extends PrintDocumentAdapter {
+public final class PrintFileDocumentAdapter extends PrintDocumentAdapter {
- private static final String LOG_TAG = "FileDocumentAdapter";
+ private static final String LOG_TAG = "PrintedFileDocumentAdapter";
private final Context mContext;
private final File mFile;
+ private final PrintDocumentInfo mDocumentInfo;
+
private WriteFileAsyncTask mWriteFileAsyncTask;
- public FileDocumentAdapter(Context context, File file) {
+ /**
+ * Constructor.
+ *
+ * @param context Context for accessing resources.
+ * @param file The file to print.
+ * @param documentInfo The information about the printed file.
+ */
+ public PrintFileDocumentAdapter(Context context, File file,
+ PrintDocumentInfo documentInfo) {
if (file == null) {
throw new IllegalArgumentException("File cannot be null!");
}
+ if (documentInfo == null) {
+ throw new IllegalArgumentException("documentInfo cannot be null!");
+ }
mContext = context;
mFile = file;
+ mDocumentInfo = documentInfo;
}
@Override
public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes,
CancellationSignal cancellationSignal, LayoutResultCallback callback,
Bundle metadata) {
- // TODO: When we have a PDF rendering library we should query the page count.
- PrintDocumentInfo info = new PrintDocumentInfo.Builder()
- .setPageCount(PrintDocumentInfo.PAGE_COUNT_UNKNOWN).create();
- callback.onLayoutFinished(info, false);
+ callback.onLayoutFinished(mDocumentInfo, false);
}
@Override
diff --git a/core/java/android/print/PrintJobInfo.java b/core/java/android/print/PrintJobInfo.java
index 096dcd58a02c..2fb4751af76f 100644
--- a/core/java/android/print/PrintJobInfo.java
+++ b/core/java/android/print/PrintJobInfo.java
@@ -109,6 +109,9 @@ public final class PrintJobInfo implements Parcelable {
/** The unique id of the printer. */
private PrinterId mPrinterId;
+ /** The name of the printer - internally used */
+ private String mPrinterName;
+
/** The status of the print job. */
private int mState;
@@ -146,6 +149,7 @@ public final class PrintJobInfo implements Parcelable {
mId = other.mId;
mLabel = other.mLabel;
mPrinterId = other.mPrinterId;
+ mPrinterName = other.mPrinterName;
mState = other.mState;
mAppId = other.mAppId;
mUserId = other.mUserId;
@@ -161,6 +165,7 @@ public final class PrintJobInfo implements Parcelable {
mId = parcel.readInt();
mLabel = parcel.readCharSequence();
mPrinterId = parcel.readParcelable(null);
+ mPrinterName = parcel.readString();
mState = parcel.readInt();
mAppId = parcel.readInt();
mUserId = parcel.readInt();
@@ -245,6 +250,28 @@ public final class PrintJobInfo implements Parcelable {
}
/**
+ * Gets the name of the target printer.
+ *
+ * @return The printer name.
+ *
+ * @hide
+ */
+ public String getPrinterName() {
+ return mPrinterName;
+ }
+
+ /**
+ * Sets the name of the target printer.
+ *
+ * @param printerName The printer name.
+ *
+ * @hide
+ */
+ public void setPrinterName(String printerName) {
+ mPrinterName = printerName;
+ }
+
+ /**
* Gets the current job state.
*
* @return The job state.
@@ -445,6 +472,7 @@ public final class PrintJobInfo implements Parcelable {
parcel.writeInt(mId);
parcel.writeCharSequence(mLabel);
parcel.writeParcelable(mPrinterId, flags);
+ parcel.writeString(mPrinterName);
parcel.writeInt(mState);
parcel.writeInt(mAppId);
parcel.writeInt(mUserId);
diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java
index c067661fca1f..636b9d4cb77b 100644
--- a/core/java/android/print/PrintManager.java
+++ b/core/java/android/print/PrintManager.java
@@ -161,13 +161,16 @@ public final class PrintManager {
*
* @param printJobName A name for the new print job.
* @param pdfFile The PDF file to print.
+ * @param documentInfo Information about the printed document.
* @param attributes The default print job attributes.
* @return The created print job.
*
* @see PrintJob
*/
- public PrintJob print(String printJobName, File pdfFile, PrintAttributes attributes) {
- FileDocumentAdapter documentAdapter = new FileDocumentAdapter(mContext, pdfFile);
+ public PrintJob print(String printJobName, File pdfFile, PrintDocumentInfo documentInfo,
+ PrintAttributes attributes) {
+ PrintFileDocumentAdapter documentAdapter = new PrintFileDocumentAdapter(
+ mContext, pdfFile, documentInfo);
return print(printJobName, documentAdapter, attributes);
}
diff --git a/core/java/android/print/PrinterCapabilitiesInfo.aidl b/core/java/android/print/PrinterCapabilitiesInfo.aidl
new file mode 100644
index 000000000000..0f5fb6b51978
--- /dev/null
+++ b/core/java/android/print/PrinterCapabilitiesInfo.aidl
@@ -0,0 +1,19 @@
+/**
+ * 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 android.print;
+
+parcelable PrinterCapabilitiesInfo;
diff --git a/core/java/android/print/PrinterCapabilitiesInfo.java b/core/java/android/print/PrinterCapabilitiesInfo.java
new file mode 100644
index 000000000000..70b418c2a145
--- /dev/null
+++ b/core/java/android/print/PrinterCapabilitiesInfo.java
@@ -0,0 +1,972 @@
+/*
+ * 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 android.print;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.print.PrintAttributes.Margins;
+import android.print.PrintAttributes.MediaSize;
+import android.print.PrintAttributes.Resolution;
+import android.print.PrintAttributes.Tray;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * This class represents the capabilities of a printer.
+ */
+public final class PrinterCapabilitiesInfo implements Parcelable {
+ /**
+ * Undefined default value.
+ *
+ * @hide
+ */
+ public static final int DEFAULT_UNDEFINED = -1;
+
+ private static final int PROPERTY_MEDIA_SIZE = 0;
+ private static final int PROPERTY_RESOLUTION = 1;
+ private static final int PROPERTY_INPUT_TRAY = 2;
+ private static final int PROPERTY_OUTPUT_TRAY = 3;
+ private static final int PROPERTY_DUPLEX_MODE = 4;
+ private static final int PROPERTY_COLOR_MODE = 5;
+ private static final int PROPERTY_FITTING_MODE = 6;
+ private static final int PROPERTY_ORIENTATION = 7;
+ private static final int PROPERTY_COUNT = 8;
+
+ private static final Margins DEFAULT_MARGINS = new Margins(0, 0, 0, 0);
+
+ private Margins mMinMargins = DEFAULT_MARGINS;
+ private List<MediaSize> mMediaSizes;
+ private List<Resolution> mResolutions;
+ private List<Tray> mInputTrays;
+ private List<Tray> mOutputTrays;
+
+ private int mDuplexModes;
+ private int mColorModes;
+ private int mFittingModes;
+ private int mOrientations;
+
+ private final int[] mDefaults = new int[PROPERTY_COUNT];
+ private Margins mDefaultMargins = DEFAULT_MARGINS;
+
+ /**
+ * @hide
+ */
+ public PrinterCapabilitiesInfo() {
+ Arrays.fill(mDefaults, DEFAULT_UNDEFINED);
+ }
+
+ /**
+ * @hide
+ */
+ public PrinterCapabilitiesInfo(PrinterCapabilitiesInfo prototype) {
+ copyFrom(prototype);
+ }
+
+ /**
+ * @hide
+ */
+ public void copyFrom(PrinterCapabilitiesInfo other) {
+ mMinMargins = other.mMinMargins;
+
+ if (other.mMediaSizes != null) {
+ if (mMediaSizes != null) {
+ mMediaSizes.clear();
+ mMediaSizes.addAll(other.mMediaSizes);
+ } else {
+ mMediaSizes = new ArrayList<MediaSize>(other.mMediaSizes);
+ }
+ } else {
+ mMediaSizes = null;
+ }
+
+ if (other.mResolutions != null) {
+ if (mResolutions != null) {
+ mResolutions.clear();
+ mResolutions.addAll(other.mResolutions);
+ } else {
+ mResolutions = new ArrayList<Resolution>(other.mResolutions);
+ }
+ } else {
+ mResolutions = null;
+ }
+
+ if (other.mInputTrays != null) {
+ if (mInputTrays != null) {
+ mInputTrays.clear();
+ mInputTrays.addAll(other.mInputTrays);
+ } else {
+ mInputTrays = new ArrayList<Tray>(other.mInputTrays);
+ }
+ } else {
+ mInputTrays = null;
+ }
+
+ if (other.mOutputTrays != null) {
+ if (mOutputTrays != null) {
+ mOutputTrays.clear();
+ mOutputTrays.addAll(other.mOutputTrays);
+ } else {
+ mOutputTrays = new ArrayList<Tray>(other.mOutputTrays);
+ }
+ } else {
+ mOutputTrays = null;
+ }
+
+ mDuplexModes = other.mDuplexModes;
+ mColorModes = other.mColorModes;
+ mFittingModes = other.mFittingModes;
+ mOrientations = other.mOrientations;
+
+ final int defaultCount = other.mDefaults.length;
+ for (int i = 0; i < defaultCount; i++) {
+ mDefaults[i] = other.mDefaults[i];
+ }
+
+ mDefaultMargins = other.mDefaultMargins;
+ }
+
+ /**
+ * Gets the supported media sizes.
+ *
+ * @return The media sizes.
+ */
+ public List<MediaSize> getMediaSizes() {
+ return mMediaSizes;
+ }
+
+ /**
+ * Gets the supported resolutions.
+ *
+ * @return The resolutions.
+ */
+ public List<Resolution> getResolutions() {
+ return mResolutions;
+ }
+
+ /**
+ * Gets the minimal supported margins.
+ *
+ * @return The minimal margins.
+ */
+ public Margins getMinMargins() {
+ return mMinMargins;
+ }
+
+ /**
+ * Gets the available input trays.
+ *
+ * @return The input trays.
+ */
+ public List<Tray> getInputTrays() {
+ return mInputTrays;
+ }
+
+ /**
+ * Gets the available output trays.
+ *
+ * @return The output trays.
+ */
+ public List<Tray> getOutputTrays() {
+ return mOutputTrays;
+ }
+
+ /**
+ * Gets the supported duplex modes.
+ *
+ * @return The duplex modes.
+ *
+ * @see PrintAttributes#DUPLEX_MODE_NONE
+ * @see PrintAttributes#DUPLEX_MODE_LONG_EDGE
+ * @see PrintAttributes#DUPLEX_MODE_SHORT_EDGE
+ */
+ public int getDuplexModes() {
+ return mDuplexModes;
+ }
+
+ /**
+ * Gets the supported color modes.
+ *
+ * @return The color modes.
+ *
+ * @see PrintAttributes#COLOR_MODE_COLOR
+ * @see PrintAttributes#COLOR_MODE_MONOCHROME
+ */
+ public int getColorModes() {
+ return mColorModes;
+ }
+
+ /**
+ * Gets the supported fitting modes.
+ *
+ * @return The fitting modes.
+ *
+ * @see PrintAttributes#FITTING_MODE_NONE
+ * @see PrintAttributes#FITTING_MODE_FIT_TO_PAGE
+ */
+ public int getFittingModes() {
+ return mFittingModes;
+ }
+
+ /**
+ * Gets the supported orientations.
+ *
+ * @return The orientations.
+ *
+ * @see PrintAttributes#ORIENTATION_PORTRAIT
+ * @see PrintAttributes#ORIENTATION_LANDSCAPE
+ */
+ public int getOrientations() {
+ return mOrientations;
+ }
+
+ /**
+ * Gets the default print attributes.
+ *
+ * @param outAttributes The attributes to populated.
+ */
+ public void getDefaults(PrintAttributes outAttributes) {
+ outAttributes.clear();
+
+ outAttributes.setMargins(mDefaultMargins);
+
+ final int mediaSizeIndex = mDefaults[PROPERTY_MEDIA_SIZE];
+ if (mediaSizeIndex >= 0) {
+ outAttributes.setMediaSize(mMediaSizes.get(mediaSizeIndex));
+ }
+
+ final int resolutionIndex = mDefaults[PROPERTY_RESOLUTION];
+ if (resolutionIndex >= 0) {
+ outAttributes.setResolution(mResolutions.get(resolutionIndex));
+ }
+
+ final int inputTrayIndex = mDefaults[PROPERTY_INPUT_TRAY];
+ if (inputTrayIndex >= 0) {
+ outAttributes.setInputTray(mInputTrays.get(inputTrayIndex));
+ }
+
+ final int outputTrayIndex = mDefaults[PROPERTY_OUTPUT_TRAY];
+ if (outputTrayIndex >= 0) {
+ outAttributes.setOutputTray(mOutputTrays.get(outputTrayIndex));
+ }
+
+ final int duplexMode = mDefaults[PROPERTY_DUPLEX_MODE];
+ if (duplexMode > 0) {
+ outAttributes.setDuplexMode(duplexMode);
+ }
+
+ final int colorMode = mDefaults[PROPERTY_COLOR_MODE];
+ if (colorMode > 0) {
+ outAttributes.setColorMode(colorMode);
+ }
+
+ final int fittingMode = mDefaults[PROPERTY_FITTING_MODE];
+ if (fittingMode > 0) {
+ outAttributes.setFittingMode(fittingMode);
+ }
+
+ final int orientation = mDefaults[PROPERTY_ORIENTATION];
+ if (orientation > 0) {
+ outAttributes.setOrientation(orientation);
+ }
+ }
+
+ private PrinterCapabilitiesInfo(Parcel parcel) {
+ mMinMargins = readMargins(parcel);
+ readMediaSizes(parcel);
+ readResolutions(parcel);
+ mInputTrays = readInputTrays(parcel);
+ mOutputTrays = readOutputTrays(parcel);
+
+ mColorModes = parcel.readInt();
+ mDuplexModes = parcel.readInt();
+ mFittingModes = parcel.readInt();
+ mOrientations = parcel.readInt();
+
+ readDefaults(parcel);
+ mDefaultMargins = readMargins(parcel);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ writeMargins(mMinMargins, parcel);
+ writeMediaSizes(parcel);
+ writeResolutions(parcel);
+ writeInputTrays(parcel);
+ writeOutputTrays(parcel);
+
+ parcel.writeInt(mColorModes);
+ parcel.writeInt(mDuplexModes);
+ parcel.writeInt(mFittingModes);
+ parcel.writeInt(mOrientations);
+
+ writeDefaults(parcel);
+ writeMargins(mDefaultMargins, parcel);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((mMinMargins == null) ? 0 : mMinMargins.hashCode());
+ result = prime * result + ((mMediaSizes == null) ? 0 : mMediaSizes.hashCode());
+ result = prime * result + ((mResolutions == null) ? 0 : mResolutions.hashCode());
+ result = prime * result + ((mInputTrays == null) ? 0 : mInputTrays.hashCode());
+ result = prime * result + ((mOutputTrays == null) ? 0 : mOutputTrays.hashCode());
+ result = prime * result + mColorModes;
+ result = prime * result + mDuplexModes;
+ result = prime * result + mFittingModes;
+ result = prime * result + mOrientations;
+ result = prime * result + Arrays.hashCode(mDefaults);
+ result = prime * result + ((mDefaultMargins == null) ? 0 : mDefaultMargins.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ PrinterCapabilitiesInfo other = (PrinterCapabilitiesInfo) obj;
+ if (mMinMargins == null) {
+ if (other.mMinMargins != null) {
+ return false;
+ }
+ } else if (!mMinMargins.equals(other.mMinMargins)) {
+ return false;
+ }
+ if (mMediaSizes == null) {
+ if (other.mMediaSizes != null) {
+ return false;
+ }
+ } else if (!mMediaSizes.equals(other.mMediaSizes)) {
+ return false;
+ }
+ if (mResolutions == null) {
+ if (other.mResolutions != null) {
+ return false;
+ }
+ } else if (!mResolutions.equals(other.mResolutions)) {
+ return false;
+ }
+ if (mInputTrays == null) {
+ if (other.mInputTrays != null) {
+ return false;
+ }
+ } else if (!mInputTrays.equals(other.mInputTrays)) {
+ return false;
+ }
+ if (mOutputTrays == null) {
+ if (other.mOutputTrays != null) {
+ return false;
+ }
+ } else if (!mOutputTrays.equals(other.mOutputTrays)) {
+ return false;
+ }
+ if (mDuplexModes != other.mDuplexModes) {
+ return false;
+ }
+ if (mColorModes != other.mColorModes) {
+ return false;
+ }
+ if (mFittingModes != other.mFittingModes) {
+ return false;
+ }
+ if (mOrientations != other.mOrientations) {
+ return false;
+ }
+ if (!Arrays.equals(mDefaults, other.mDefaults)) {
+ return false;
+ }
+ if (mDefaultMargins == null) {
+ if (other.mDefaultMargins != null) {
+ return false;
+ }
+ } else if (!mDefaultMargins.equals(other.mDefaultMargins)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("PrinterInfo{");
+ builder.append("minMargins=").append(mMinMargins);
+ builder.append(", mediaSizes=").append(mMediaSizes);
+ builder.append(", resolutions=").append(mResolutions);
+ builder.append(", inputTrays=").append(mInputTrays);
+ builder.append(", outputTrays=").append(mOutputTrays);
+ builder.append(", duplexModes=").append(duplexModesToString());
+ builder.append(", colorModes=").append(colorModesToString());
+ builder.append(", fittingModes=").append(fittingModesToString());
+ builder.append(", orientations=").append(orientationsToString());
+ builder.append("\"}");
+ return builder.toString();
+ }
+
+ private String duplexModesToString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append('[');
+ int duplexModes = mDuplexModes;
+ while (duplexModes != 0) {
+ final int duplexMode = 1 << Integer.numberOfTrailingZeros(duplexModes);
+ duplexModes &= ~duplexMode;
+ if (builder.length() > 0) {
+ builder.append(", ");
+ }
+ builder.append(PrintAttributes.duplexModeToString(duplexMode));
+ }
+ builder.append(']');
+ return builder.toString();
+ }
+
+ private String colorModesToString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append('[');
+ int colorModes = mColorModes;
+ while (colorModes != 0) {
+ final int colorMode = 1 << Integer.numberOfTrailingZeros(colorModes);
+ colorModes &= ~colorMode;
+ if (builder.length() > 0) {
+ builder.append(", ");
+ }
+ builder.append(PrintAttributes.colorModeToString(colorMode));
+ }
+ builder.append(']');
+ return builder.toString();
+ }
+
+ private String fittingModesToString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append('[');
+ int fittingModes = mFittingModes;
+ while (fittingModes != 0) {
+ final int fittingMode = 1 << Integer.numberOfTrailingZeros(fittingModes);
+ fittingModes &= ~fittingMode;
+ if (builder.length() > 0) {
+ builder.append(", ");
+ }
+ builder.append(PrintAttributes.fittingModeToString(fittingMode));
+ }
+ builder.append(']');
+ return builder.toString();
+ }
+
+ private String orientationsToString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append('[');
+ int orientations = mOrientations;
+ while (orientations != 0) {
+ final int orientation = 1 << Integer.numberOfTrailingZeros(orientations);
+ orientations &= ~orientation;
+ if (builder.length() > 0) {
+ builder.append(", ");
+ }
+ builder.append(PrintAttributes.orientationToString(orientation));
+ }
+ builder.append(']');
+ return builder.toString();
+ }
+
+ private void writeMediaSizes(Parcel parcel) {
+ if (mMediaSizes == null) {
+ parcel.writeInt(0);
+ return;
+ }
+ final int mediaSizeCount = mMediaSizes.size();
+ parcel.writeInt(mediaSizeCount);
+ for (int i = 0; i < mediaSizeCount; i++) {
+ mMediaSizes.get(i).writeToParcel(parcel);
+ }
+ }
+
+ private void readMediaSizes(Parcel parcel) {
+ final int mediaSizeCount = parcel.readInt();
+ if (mediaSizeCount > 0 && mMediaSizes == null) {
+ mMediaSizes = new ArrayList<MediaSize>();
+ }
+ for (int i = 0; i < mediaSizeCount; i++) {
+ mMediaSizes.add(MediaSize.createFromParcel(parcel));
+ }
+ }
+
+ private void writeResolutions(Parcel parcel) {
+ if (mResolutions == null) {
+ parcel.writeInt(0);
+ return;
+ }
+ final int resolutionCount = mResolutions.size();
+ parcel.writeInt(resolutionCount);
+ for (int i = 0; i < resolutionCount; i++) {
+ mResolutions.get(i).writeToParcel(parcel);
+ }
+ }
+
+ private void readResolutions(Parcel parcel) {
+ final int resolutionCount = parcel.readInt();
+ if (resolutionCount > 0 && mResolutions == null) {
+ mResolutions = new ArrayList<Resolution>();
+ }
+ for (int i = 0; i < resolutionCount; i++) {
+ mResolutions.add(Resolution.createFromParcel(parcel));
+ }
+ }
+
+ private void writeMargins(Margins margins, Parcel parcel) {
+ if (margins == null) {
+ parcel.writeInt(0);
+ } else {
+ parcel.writeInt(1);
+ margins.writeToParcel(parcel);
+ }
+ }
+
+ private Margins readMargins(Parcel parcel) {
+ return (parcel.readInt() == 1) ? Margins.createFromParcel(parcel) : null;
+ }
+
+ private void writeInputTrays(Parcel parcel) {
+ if (mInputTrays == null) {
+ parcel.writeInt(0);
+ return;
+ }
+ final int inputTrayCount = mInputTrays.size();
+ parcel.writeInt(inputTrayCount);
+ for (int i = 0; i < inputTrayCount; i++) {
+ mInputTrays.get(i).writeToParcel(parcel);
+ }
+ }
+
+ private List<Tray> readInputTrays(Parcel parcel) {
+ final int inputTrayCount = parcel.readInt();
+ if (inputTrayCount <= 0) {
+ return null;
+ }
+ List<Tray> inputTrays = new ArrayList<Tray>(inputTrayCount);
+ for (int i = 0; i < inputTrayCount; i++) {
+ inputTrays.add(Tray.createFromParcel(parcel));
+ }
+ return inputTrays;
+ }
+
+ private void writeOutputTrays(Parcel parcel) {
+ if (mOutputTrays == null) {
+ parcel.writeInt(0);
+ return;
+ }
+ final int outputTrayCount = mOutputTrays.size();
+ parcel.writeInt(outputTrayCount);
+ for (int i = 0; i < outputTrayCount; i++) {
+ mOutputTrays.get(i).writeToParcel(parcel);
+ }
+ }
+
+ private List<Tray> readOutputTrays(Parcel parcel) {
+ final int outputTrayCount = parcel.readInt();
+ if (outputTrayCount <= 0) {
+ return null;
+ }
+ List<Tray> outputTrays = new ArrayList<Tray>(outputTrayCount);
+ for (int i = 0; i < outputTrayCount; i++) {
+ outputTrays.add(Tray.createFromParcel(parcel));
+ }
+ return outputTrays;
+ }
+
+ private void readDefaults(Parcel parcel) {
+ final int defaultCount = parcel.readInt();
+ for (int i = 0; i < defaultCount; i++) {
+ mDefaults[i] = parcel.readInt();
+ }
+ }
+
+ private void writeDefaults(Parcel parcel) {
+ final int defaultCount = mDefaults.length;
+ parcel.writeInt(defaultCount);
+ for (int i = 0; i < defaultCount; i++) {
+ parcel.writeInt(mDefaults[i]);
+ }
+ }
+
+ /**
+ * Builder for creating of a {@link PrinterInfo}. This class is responsible
+ * to enforce that all required attributes have at least one default value.
+ * In other words, this class creates only well-formed {@link PrinterInfo}s.
+ * <p>
+ * Look at the individual methods for a reference whether a property is
+ * required or if it is optional.
+ * </p>
+ */
+ public static final class Builder {
+ private final PrinterCapabilitiesInfo mPrototype;
+
+ /**
+ * Creates a new instance.
+ *
+ * @param printerId The printer id. Cannot be null.
+ *
+ * @throws IllegalArgumentException If the printer id is null.
+ */
+ public Builder(PrinterId printerId) {
+ if (printerId == null) {
+ throw new IllegalArgumentException("printerId cannot be null.");
+ }
+ mPrototype = new PrinterCapabilitiesInfo();
+ }
+
+ /**
+ * Adds a supported media size.
+ * <p>
+ * <strong>Required:</strong> Yes
+ * </p>
+ *
+ * @param mediaSize A media size.
+ * @param isDefault Whether this is the default.
+ * @return This builder.
+ * @throws IllegalArgumentException If set as default and there
+ * is already a default.
+ *
+ * @see PrintAttributes.MediaSize
+ */
+ public Builder addMediaSize(MediaSize mediaSize, boolean isDefault) {
+ if (mPrototype.mMediaSizes == null) {
+ mPrototype.mMediaSizes = new ArrayList<MediaSize>();
+ }
+ final int insertionIndex = mPrototype.mMediaSizes.size();
+ mPrototype.mMediaSizes.add(mediaSize);
+ if (isDefault) {
+ throwIfDefaultAlreadySpecified(PROPERTY_MEDIA_SIZE);
+ mPrototype.mDefaults[PROPERTY_MEDIA_SIZE] = insertionIndex;
+ }
+ return this;
+ }
+
+ /**
+ * Adds a supported resolution.
+ * <p>
+ * <strong>Required:</strong> Yes
+ * </p>
+ *
+ * @param resolution A resolution.
+ * @param isDefault Whether this is the default.
+ * @return This builder.
+ *
+ * @throws IllegalArgumentException If set as default and there
+ * is already a default.
+ *
+ * @see PrintAttributes.Resolution
+ */
+ public Builder addResolution(Resolution resolution, boolean isDefault) {
+ if (mPrototype.mResolutions == null) {
+ mPrototype.mResolutions = new ArrayList<Resolution>();
+ }
+ final int insertionIndex = mPrototype.mResolutions.size();
+ mPrototype.mResolutions.add(resolution);
+ if (isDefault) {
+ throwIfDefaultAlreadySpecified(PROPERTY_RESOLUTION);
+ mPrototype.mDefaults[PROPERTY_RESOLUTION] = insertionIndex;
+ }
+ return this;
+ }
+
+ /**
+ * Sets the minimal margins.
+ * <p>
+ * <strong>Required:</strong> No
+ * </p>
+ *
+ * @param margins The margins.
+ * @param defaultMargins The default margins.
+ * @return This builder.
+ *
+ * @see PrintAttributes.Margins
+ */
+ public Builder setMinMargins(Margins margins, Margins defaultMargins) {
+ if (margins.getLeftMils() > defaultMargins.getLeftMils()
+ || margins.getTopMils() > defaultMargins.getTopMils()
+ || margins.getRightMils() < defaultMargins.getRightMils()
+ || margins.getBottomMils() < defaultMargins.getBottomMils()) {
+ throw new IllegalArgumentException("Default margins"
+ + " cannot be outside of the min margins.");
+ }
+ mPrototype.mMinMargins = margins;
+ mPrototype.mDefaultMargins = defaultMargins;
+ return this;
+ }
+
+ /**
+ * Adds an input tray.
+ * <p>
+ * <strong>Required:</strong> No
+ * </p>
+ *
+ * @param inputTray A tray.
+ * @param isDefault Whether this is the default.
+ * @return This builder.
+ *
+ * @throws IllegalArgumentException If set as default and there
+ * is already a default.
+ *
+ * @see PrintAttributes.Tray
+ */
+ public Builder addInputTray(Tray inputTray, boolean isDefault) {
+ if (mPrototype.mInputTrays == null) {
+ mPrototype.mInputTrays = new ArrayList<Tray>();
+ }
+ final int insertionIndex = mPrototype.mInputTrays.size();
+ mPrototype.mInputTrays.add(inputTray);
+ if (isDefault) {
+ throwIfDefaultAlreadySpecified(PROPERTY_INPUT_TRAY);
+ mPrototype.mDefaults[PROPERTY_INPUT_TRAY] = insertionIndex;
+ }
+ return this;
+ }
+
+ /**
+ * Adds an output tray.
+ * <p>
+ * <strong>Required:</strong> No
+ * </p>
+ *
+ * @param outputTray A tray.
+ * @param isDefault Whether this is the default.
+ * @return This builder.
+ *
+ * @throws IllegalArgumentException If set as default and there
+ * is already a default.
+ *
+ * @see PrintAttributes.Tray
+ */
+ public Builder addOutputTray(Tray outputTray, boolean isDefault) {
+ if (mPrototype.mOutputTrays == null) {
+ mPrototype.mOutputTrays = new ArrayList<Tray>();
+ }
+ final int insertionIndex = mPrototype.mOutputTrays.size();
+ mPrototype.mOutputTrays.add(outputTray);
+ if (isDefault) {
+ throwIfDefaultAlreadySpecified(PROPERTY_OUTPUT_TRAY);
+ mPrototype.mDefaults[PROPERTY_OUTPUT_TRAY] = insertionIndex;
+ }
+ return this;
+ }
+
+ /**
+ * Sets the color modes.
+ * <p>
+ * <strong>Required:</strong> Yes
+ * </p>
+ *
+ * @param colorModes The color mode bit mask.
+ * @param defaultColorMode The default color mode.
+ * @return This builder.
+ *
+ * @throws IllegalArgumentException If color modes contains an invalid
+ * mode bit or if the default color mode is invalid.
+ *
+ * @see PrintAttributes#COLOR_MODE_COLOR
+ * @see PrintAttributes#COLOR_MODE_MONOCHROME
+ */
+ public Builder setColorModes(int colorModes, int defaultColorMode) {
+ int currentModes = colorModes;
+ while (currentModes > 0) {
+ final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes));
+ currentModes &= ~currentMode;
+ PrintAttributes.enforceValidColorMode(currentMode);
+ }
+ if ((colorModes & defaultColorMode) == 0) {
+ throw new IllegalArgumentException("Default color mode not in color modes.");
+ }
+ PrintAttributes.enforceValidColorMode(colorModes);
+ mPrototype.mColorModes = colorModes;
+ mPrototype.mDefaults[PROPERTY_COLOR_MODE] = defaultColorMode;
+ return this;
+ }
+
+ /**
+ * Set the duplex modes.
+ * <p>
+ * <strong>Required:</strong> No
+ * </p>
+ *
+ * @param duplexModes The duplex mode bit mask.
+ * @param defaultDuplexMode The default duplex mode.
+ * @return This builder.
+ *
+ * @throws IllegalArgumentException If duplex modes contains an invalid
+ * mode bit or if the default duplex mode is invalid.
+ *
+ * @see PrintAttributes#DUPLEX_MODE_NONE
+ * @see PrintAttributes#DUPLEX_MODE_LONG_EDGE
+ * @see PrintAttributes#DUPLEX_MODE_SHORT_EDGE
+ */
+ public Builder setDuplexModes(int duplexModes, int defaultDuplexMode) {
+ int currentModes = duplexModes;
+ while (currentModes > 0) {
+ final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes));
+ currentModes &= ~currentMode;
+ PrintAttributes.enforceValidDuplexMode(currentMode);
+ }
+ if ((duplexModes & defaultDuplexMode) == 0) {
+ throw new IllegalArgumentException("Default duplex mode not in duplex modes.");
+ }
+ PrintAttributes.enforceValidDuplexMode(defaultDuplexMode);
+ mPrototype.mDuplexModes = duplexModes;
+ mPrototype.mDefaults[PROPERTY_DUPLEX_MODE] = defaultDuplexMode;
+ return this;
+ }
+
+ /**
+ * Sets the fitting modes.
+ * <p>
+ * <strong>Required:</strong> No
+ * </p>
+ *
+ * @param fittingModes The fitting mode bit mask.
+ * @param defaultFittingMode The default fitting mode.
+ * @return This builder.
+ *
+ * @throws IllegalArgumentException If fitting modes contains an invalid
+ * mode bit or if the default fitting mode is invalid.
+ *
+ * @see PrintAttributes#FITTING_MODE_NONE
+ * @see PrintAttributes#FITTING_MODE_FIT_TO_PAGE
+ */
+ public Builder setFittingModes(int fittingModes, int defaultFittingMode) {
+ int currentModes = fittingModes;
+ while (currentModes > 0) {
+ final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes));
+ currentModes &= ~currentMode;
+ PrintAttributes.enfoceValidFittingMode(currentMode);
+ }
+ if ((fittingModes & defaultFittingMode) == 0) {
+ throw new IllegalArgumentException("Default fitting mode not in fiting modes.");
+ }
+ PrintAttributes.enfoceValidFittingMode(defaultFittingMode);
+ mPrototype.mFittingModes = fittingModes;
+ mPrototype.mDefaults[PROPERTY_FITTING_MODE] = defaultFittingMode;
+ return this;
+ }
+
+ /**
+ * Sets the orientations.
+ * <p>
+ * <strong>Required:</strong> Yes
+ * </p>
+ *
+ * @param orientations The orientation bit mask.
+ * @param defaultOrientation The default orientation.
+ * @return This builder.
+ *
+ * @throws IllegalArgumentException If orientations contains an invalid
+ * mode bit or if the default orientation is invalid.
+ *
+ * @see PrintAttributes#ORIENTATION_PORTRAIT
+ * @see PrintAttributes#ORIENTATION_LANDSCAPE
+ */
+ public Builder setOrientations(int orientations, int defaultOrientation) {
+ int currentOrientaions = orientations;
+ while (currentOrientaions > 0) {
+ final int currentOrnt = (1 << Integer.numberOfTrailingZeros(currentOrientaions));
+ currentOrientaions &= ~currentOrnt;
+ PrintAttributes.enforceValidOrientation(currentOrnt);
+ }
+ if ((orientations & defaultOrientation) == 0) {
+ throw new IllegalArgumentException("Default orientation not in orientations.");
+ }
+ PrintAttributes.enforceValidOrientation(defaultOrientation);
+ mPrototype.mOrientations = orientations;
+ mPrototype.mDefaults[PROPERTY_ORIENTATION] = defaultOrientation;
+ return this;
+ }
+
+ /**
+ * Crates a new {@link PrinterCapabilitiesInfo} enforcing that all
+ * required properties have need specified. See individual methods
+ * in this class for reference about required attributes.
+ *
+ * @return A new {@link PrinterCapabilitiesInfo}.
+ *
+ * @throws IllegalStateException If a required attribute was not specified.
+ */
+ public PrinterCapabilitiesInfo create() {
+ if (mPrototype.mMediaSizes == null || mPrototype.mMediaSizes.isEmpty()) {
+ throw new IllegalStateException("No media size specified.");
+ }
+ if (mPrototype.mDefaults[PROPERTY_MEDIA_SIZE] == DEFAULT_UNDEFINED) {
+ throw new IllegalStateException("No default media size specified.");
+ }
+ if (mPrototype.mResolutions == null || mPrototype.mResolutions.isEmpty()) {
+ throw new IllegalStateException("No resolution specified.");
+ }
+ if (mPrototype.mDefaults[PROPERTY_RESOLUTION] == DEFAULT_UNDEFINED) {
+ throw new IllegalStateException("No default resolution specified.");
+ }
+ if (mPrototype.mColorModes == 0) {
+ throw new IllegalStateException("No color mode specified.");
+ }
+ if (mPrototype.mDefaults[PROPERTY_COLOR_MODE] == DEFAULT_UNDEFINED) {
+ throw new IllegalStateException("No default color mode specified.");
+ }
+ if (mPrototype.mOrientations == 0) {
+ throw new IllegalStateException("No oprientation specified.");
+ }
+ if (mPrototype.mDefaults[PROPERTY_ORIENTATION] == DEFAULT_UNDEFINED) {
+ throw new IllegalStateException("No default orientation specified.");
+ }
+ if (mPrototype.mMinMargins == null) {
+ mPrototype.mMinMargins = new Margins(0, 0, 0, 0);
+ }
+ if (mPrototype.mDefaultMargins == null) {
+ mPrototype.mDefaultMargins = mPrototype.mMinMargins;
+ }
+ return new PrinterCapabilitiesInfo(mPrototype);
+ }
+
+ private void throwIfDefaultAlreadySpecified(int propertyIndex) {
+ if (mPrototype.mDefaults[propertyIndex] != DEFAULT_UNDEFINED) {
+ throw new IllegalArgumentException("Default already specified.");
+ }
+ }
+ }
+
+ public static final Parcelable.Creator<PrinterCapabilitiesInfo> CREATOR =
+ new Parcelable.Creator<PrinterCapabilitiesInfo>() {
+ @Override
+ public PrinterCapabilitiesInfo createFromParcel(Parcel parcel) {
+ return new PrinterCapabilitiesInfo(parcel);
+ }
+
+ @Override
+ public PrinterCapabilitiesInfo[] newArray(int size) {
+ return new PrinterCapabilitiesInfo[size];
+ }
+ };
+}
+
diff --git a/core/java/android/print/PrinterId.java b/core/java/android/print/PrinterId.java
index 846273671f80..a3f3b2bfee11 100644
--- a/core/java/android/print/PrinterId.java
+++ b/core/java/android/print/PrinterId.java
@@ -28,24 +28,24 @@ public final class PrinterId implements Parcelable {
private final ComponentName mServiceName;
- private final String mPrinterName;
+ private final String mLocalId;
/**
* Creates a new instance.
*
* @param serviceName The managing print service.
- * @param printerName The unique name within the managing service.
+ * @param localId The locally unique id within the managing service.
*
* @hide
*/
- public PrinterId(ComponentName serviceName, String printerName) {
+ public PrinterId(ComponentName serviceName, String localId) {
mServiceName = serviceName;
- mPrinterName = printerName;
+ mLocalId = localId;
}
private PrinterId(Parcel parcel) {
mServiceName = parcel.readParcelable(null);
- mPrinterName = parcel.readString();
+ mLocalId = parcel.readString();
}
/**
@@ -60,13 +60,13 @@ public final class PrinterId implements Parcelable {
}
/**
- * Gets the name of this printer which is unique in the context
+ * Gets the id of this printer which is unique in the context
* of the print service that manages it.
*
* @return The printer name.
*/
- public String getPrinterName() {
- return mPrinterName;
+ public String getLocalId() {
+ return mLocalId;
}
@Override
@@ -77,7 +77,7 @@ public final class PrinterId implements Parcelable {
@Override
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeParcelable(mServiceName, flags);
- parcel.writeString(mPrinterName);
+ parcel.writeString(mLocalId);
}
@Override
@@ -99,7 +99,7 @@ public final class PrinterId implements Parcelable {
} else if (!mServiceName.equals(other.mServiceName)) {
return false;
}
- if (!TextUtils.equals(mPrinterName, other.mPrinterName)) {
+ if (!TextUtils.equals(mLocalId, other.mLocalId)) {
return false;
}
return true;
@@ -111,7 +111,7 @@ public final class PrinterId implements Parcelable {
int hashCode = 1;
hashCode = prime * hashCode + ((mServiceName != null)
? mServiceName.hashCode() : 1);
- hashCode = prime * hashCode + mPrinterName.hashCode();
+ hashCode = prime * hashCode + mLocalId.hashCode();
return hashCode;
}
@@ -119,9 +119,8 @@ public final class PrinterId implements Parcelable {
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("PrinterId{");
- builder.append(mServiceName.flattenToString());
- builder.append(":");
- builder.append(mPrinterName);
+ builder.append("serviceName=").append(mServiceName.flattenToString());
+ builder.append(", localId=").append(mLocalId);
builder.append('}');
return builder.toString();
}
diff --git a/core/java/android/print/PrinterInfo.java b/core/java/android/print/PrinterInfo.java
index 10cecca9e73f..ac782a83927f 100644
--- a/core/java/android/print/PrinterInfo.java
+++ b/core/java/android/print/PrinterInfo.java
@@ -18,67 +18,30 @@ package android.print;
import android.os.Parcel;
import android.os.Parcelable;
-import android.print.PrintAttributes.Margins;
-import android.print.PrintAttributes.MediaSize;
-import android.print.PrintAttributes.Resolution;
-import android.print.PrintAttributes.Tray;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
+import android.text.TextUtils;
/**
- * This class represents the description of a printer. A description
- * contains the printer id, human readable name, status, and available
- * options for various printer capabilities, such as media size, etc.
+ * This class represents the description of a printer.
*/
public final class PrinterInfo implements Parcelable {
- /**
- * Undefined default value.
- *
- * @hide
- */
- public static final int DEFAULT_UNDEFINED = -1;
-
- private static final int PROPERTY_MEDIA_SIZE = 0;
- private static final int PROPERTY_RESOLUTION = 1;
- private static final int PROPERTY_INPUT_TRAY = 2;
- private static final int PROPERTY_OUTPUT_TRAY = 3;
- private static final int PROPERTY_DUPLEX_MODE = 4;
- private static final int PROPERTY_COLOR_MODE = 5;
- private static final int PROPERTY_FITTING_MODE = 6;
- private static final int PROPERTY_ORIENTATION = 7;
- private static final int PROPERTY_COUNT = 8;
/** Printer status: the printer is ready to print. */
public static final int STATUS_READY = 1;
- private static final Margins DEFAULT_MARGINS = new Margins(0, 0, 0, 0);
-
// TODO: Add printer status constants.
private PrinterId mId;
- private int mStatus;
- private Margins mMinMargins = DEFAULT_MARGINS;
- private List<MediaSize> mMediaSizes;
- private List<Resolution> mResolutions;
- private List<Tray> mInputTrays;
- private List<Tray> mOutputTrays;
+ private String mName;
- private int mDuplexModes;
- private int mColorModes;
- private int mFittingModes;
- private int mOrientations;
+ private int mStatus;
- private final int[] mDefaults = new int[PROPERTY_COUNT];
- private Margins mDefaultMargins = DEFAULT_MARGINS;
+ private String mDescription;
- /**
- * @hide
- */
- public PrinterInfo() {
- Arrays.fill(mDefaults, DEFAULT_UNDEFINED);
+ private PrinterCapabilitiesInfo mCapabilities;
+
+ private PrinterInfo() {
+ /* do nothing */
}
private PrinterInfo(PrinterInfo prototype) {
@@ -90,63 +53,18 @@ public final class PrinterInfo implements Parcelable {
*/
public void copyFrom(PrinterInfo other) {
mId = other.mId;
+ mName = other.mName;
mStatus = other.mStatus;
-
- mMinMargins = other.mMinMargins;
- if (other.mMediaSizes != null) {
- if (mMediaSizes != null) {
- mMediaSizes.clear();
- mMediaSizes.addAll(other.mMediaSizes);
+ mDescription = other.mDescription;
+ if (other.mCapabilities != null) {
+ if (mCapabilities != null) {
+ mCapabilities.copyFrom(other.mCapabilities);
} else {
- mMediaSizes = new ArrayList<MediaSize>(other.mMediaSizes);
+ mCapabilities = new PrinterCapabilitiesInfo(other.mCapabilities);
}
} else {
- mMediaSizes = null;
+ mCapabilities = null;
}
-
- if (other.mResolutions != null) {
- if (mResolutions != null) {
- mResolutions.clear();
- mResolutions.addAll(other.mResolutions);
- } else {
- mResolutions = new ArrayList<Resolution>(other.mResolutions);
- }
- } else {
- mResolutions = null;
- }
-
- if (other.mInputTrays != null) {
- if (mInputTrays != null) {
- mInputTrays.clear();
- mInputTrays.addAll(other.mInputTrays);
- } else {
- mInputTrays = new ArrayList<Tray>(other.mInputTrays);
- }
- } else {
- mInputTrays = null;
- }
-
- if (other.mOutputTrays != null) {
- if (mOutputTrays != null) {
- mOutputTrays.clear();
- mOutputTrays.addAll(other.mOutputTrays);
- } else {
- mOutputTrays = new ArrayList<Tray>(other.mOutputTrays);
- }
- } else {
- mOutputTrays = null;
- }
-
- mDuplexModes = other.mDuplexModes;
- mColorModes = other.mColorModes;
- mFittingModes = other.mFittingModes;
- mOrientations = other.mOrientations;
-
- final int defaultCount = other.mDefaults.length;
- for (int i = 0; i < defaultCount; i++) {
- mDefaults[i] = other.mDefaults[i];
- }
- mDefaultMargins = other.mDefaultMargins;
}
/**
@@ -159,193 +77,47 @@ public final class PrinterInfo implements Parcelable {
}
/**
- * Gets the status of the printer.
- *
- * @return The status.
- */
- public int getStatus() {
- return mStatus;
- }
-
- /**
- * Gets the supported media sizes.
- *
- * @return The supported media sizes.
- */
- public List<MediaSize> getMediaSizes() {
- return mMediaSizes;
- }
-
- /**
- * Gets the supported resolutions.
- *
- * @return The supported resolutions.
- */
- public List<Resolution> getResolutions() {
- return mResolutions;
- }
-
- /**
- * Gets the minimal supported margins.
- *
- * @return The minimal margins.
- */
- public Margins getMinMargins() {
- return mMinMargins;
- }
-
- /**
- * Gets the available input trays.
- *
- * @return The input trays.
- */
- public List<Tray> getInputTrays() {
- return mInputTrays;
- }
-
- /**
- * Gets the available output trays.
- *
- * @return The output trays.
- */
- public List<Tray> getOutputTrays() {
- return mOutputTrays;
- }
-
- /**
- * Gets the supported duplex modes.
- *
- * @return The duplex modes.
+ * Get the printer name.
*
- * @see PrintAttributes#DUPLEX_MODE_NONE
- * @see PrintAttributes#DUPLEX_MODE_LONG_EDGE
- * @see PrintAttributes#DUPLEX_MODE_SHORT_EDGE
+ * @return The printer name.
*/
- public int getDuplexModes() {
- return mDuplexModes;
+ public String getName() {
+ return mName;
}
/**
- * Gets the supported color modes.
+ * Gets the printer status.
*
- * @return The color modes.
- *
- * @see PrintAttributes#COLOR_MODE_COLOR
- * @see PrintAttributes#COLOR_MODE_MONOCHROME
- */
- public int getColorModes() {
- return mColorModes;
- }
-
- /**
- * Gets the supported fitting modes.
- *
- * @return The fitting modes.
- *
- * @see PrintAttributes#FITTING_MODE_NONE
- * @see PrintAttributes#FITTING_MODE_FIT_TO_PAGE
- */
- public int getFittingModes() {
- return mFittingModes;
- }
-
- /**
- * Gets the supported orientations.
- *
- * @return The orientations.
- *
- * @see PrintAttributes#ORIENTATION_PORTRAIT
- * @see PrintAttributes#ORIENTATION_LANDSCAPE
+ * @return The status.
*/
- public int getOrientations() {
- return mOrientations;
+ public int getStatus() {
+ return mStatus;
}
/**
- * Gets the default print attributes.
+ * Gets the printer description.
*
- * @param outAttributes The attributes to populated.
+ * @return The description.
*/
- public void getDefaults(PrintAttributes outAttributes) {
- outAttributes.clear();
-
- outAttributes.setMargins(mDefaultMargins);
-
- final int mediaSizeIndex = mDefaults[PROPERTY_MEDIA_SIZE];
- if (mediaSizeIndex >= 0) {
- outAttributes.setMediaSize(mMediaSizes.get(mediaSizeIndex));
- }
-
- final int resolutionIndex = mDefaults[PROPERTY_RESOLUTION];
- if (resolutionIndex >= 0) {
- outAttributes.setResolution(mResolutions.get(resolutionIndex));
- }
-
- final int inputTrayIndex = mDefaults[PROPERTY_INPUT_TRAY];
- if (inputTrayIndex >= 0) {
- outAttributes.setInputTray(mInputTrays.get(inputTrayIndex));
- }
-
- final int outputTrayIndex = mDefaults[PROPERTY_OUTPUT_TRAY];
- if (outputTrayIndex >= 0) {
- outAttributes.setOutputTray(mOutputTrays.get(outputTrayIndex));
- }
-
- final int duplexMode = mDefaults[PROPERTY_DUPLEX_MODE];
- if (duplexMode > 0) {
- outAttributes.setDuplexMode(duplexMode);
- }
-
- final int colorMode = mDefaults[PROPERTY_COLOR_MODE];
- if (colorMode > 0) {
- outAttributes.setColorMode(mColorModes & colorMode);
- }
-
- final int fittingMode = mDefaults[PROPERTY_FITTING_MODE];
- if (fittingMode > 0) {
- outAttributes.setFittingMode(fittingMode);
- }
-
- final int orientation = mDefaults[PROPERTY_ORIENTATION];
- if (orientation > 0) {
- outAttributes.setOrientation(orientation);
- }
+ public String getDescription() {
+ return mDescription;
}
/**
- * Gets whether this printer info is fully-populated, i.e. whether
- * all required attributes are specified. See the {@link Builder}
- * documentation for which attributes are required.
+ * Gets the printer capabilities.
*
- * @return Whether this info has all required attributes.
+ * @return The capabilities.
*/
- public boolean hasAllRequiredAttributes() {
- return (mMediaSizes != null && !mMediaSizes.isEmpty()
- && mResolutions != null && !mResolutions.isEmpty()
- && mColorModes != 0 || mOrientations != 0
- && mDefaults[PROPERTY_MEDIA_SIZE] != DEFAULT_UNDEFINED
- && mDefaults[PROPERTY_RESOLUTION] != DEFAULT_UNDEFINED
- && mDefaults[PROPERTY_COLOR_MODE] != DEFAULT_UNDEFINED
- && mDefaults[PROPERTY_ORIENTATION] != DEFAULT_UNDEFINED);
+ public PrinterCapabilitiesInfo getCapabilities() {
+ return mCapabilities;
}
private PrinterInfo(Parcel parcel) {
mId = parcel.readParcelable(null);
+ mName = parcel.readString();
mStatus = parcel.readInt();
-
- mMinMargins = readMargins(parcel);
- readMediaSizes(parcel);
- readResolutions(parcel);
- mInputTrays = readInputTrays(parcel);
- mOutputTrays = readOutputTrays(parcel);
-
- mColorModes = parcel.readInt();
- mDuplexModes = parcel.readInt();
- mFittingModes = parcel.readInt();
- mOrientations = parcel.readInt();
-
- readDefaults(parcel);
- mDefaultMargins = readMargins(parcel);
+ mDescription = parcel.readString();
+ mCapabilities = parcel.readParcelable(null);
}
@Override
@@ -356,40 +128,21 @@ public final class PrinterInfo implements Parcelable {
@Override
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeParcelable(mId, flags);
+ parcel.writeString(mName);
parcel.writeInt(mStatus);
-
- writeMargins(mMinMargins, parcel);
- writeMediaSizes(parcel);
- writeResolutions(parcel);
- writeInputTrays(parcel);
- writeOutputTrays(parcel);
-
- parcel.writeInt(mColorModes);
- parcel.writeInt(mDuplexModes);
- parcel.writeInt(mFittingModes);
- parcel.writeInt(mOrientations);
-
- writeDefaults(parcel);
- writeMargins(mDefaultMargins, parcel);
+ parcel.writeString(mDescription);
+ parcel.writeParcelable(mCapabilities, flags);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
- result = prime * result + ((mId == null) ? 0 : mId.hashCode());
+ result = prime * result + ((mId != null) ? mId.hashCode() : 0);
+ result = prime * result + ((mName != null) ? mName.hashCode() : 0);
result = prime * result + mStatus;
- result = prime * result + ((mMinMargins == null) ? 0 : mMinMargins.hashCode());
- result = prime * result + ((mMediaSizes == null) ? 0 : mMediaSizes.hashCode());
- result = prime * result + ((mResolutions == null) ? 0 : mResolutions.hashCode());
- result = prime * result + ((mInputTrays == null) ? 0 : mInputTrays.hashCode());
- result = prime * result + ((mOutputTrays == null) ? 0 : mOutputTrays.hashCode());
- result = prime * result + mDuplexModes;
- result = prime * result + mColorModes;
- result = prime * result + mFittingModes;
- result = prime * result + mOrientations;
- result = prime * result + Arrays.hashCode(mDefaults);
- result = prime * result + ((mDefaultMargins == null) ? 0 : mDefaultMargins.hashCode());
+ result = prime * result + ((mDescription != null) ? mDescription.hashCode() : 0);
+ result = prime * result + ((mCapabilities != null) ? mCapabilities.hashCode() : 0);
return result;
}
@@ -412,64 +165,20 @@ public final class PrinterInfo implements Parcelable {
} else if (!mId.equals(other.mId)) {
return false;
}
- if (mStatus != other.mStatus) {
- return false;
- }
- if (mMinMargins == null) {
- if (other.mMinMargins != null) {
- return false;
- }
- } else if (!mMinMargins.equals(other.mMinMargins)) {
- return false;
- }
- if (mMediaSizes == null) {
- if (other.mMediaSizes != null) {
- return false;
- }
- } else if (!mMediaSizes.equals(other.mMediaSizes)) {
- return false;
- }
- if (mResolutions == null) {
- if (other.mResolutions != null) {
- return false;
- }
- } else if (!mResolutions.equals(other.mResolutions)) {
- return false;
- }
- if (mInputTrays == null) {
- if (other.mInputTrays != null) {
- return false;
- }
- } else if (!mInputTrays.equals(other.mInputTrays)) {
- return false;
- }
- if (mOutputTrays == null) {
- if (other.mOutputTrays != null) {
- return false;
- }
- } else if (!mOutputTrays.equals(other.mOutputTrays)) {
- return false;
- }
- if (mDuplexModes != other.mDuplexModes) {
- return false;
- }
- if (mColorModes != other.mColorModes) {
+ if (!TextUtils.equals(mName, other.mName)) {
return false;
}
- if (mFittingModes != other.mFittingModes) {
- return false;
- }
- if (mOrientations != other.mOrientations) {
+ if (mStatus != other.mStatus) {
return false;
}
- if (!Arrays.equals(mDefaults, other.mDefaults)) {
+ if (!TextUtils.equals(mDescription, other.mDescription)) {
return false;
}
- if (mDefaultMargins == null) {
- if (other.mDefaultMargins != null) {
+ if (mCapabilities == null) {
+ if (other.mCapabilities != null) {
return false;
}
- } else if (!mDefaultMargins.equals(other.mDefaultMargins)) {
+ } else if (!mCapabilities.equals(other.mCapabilities)) {
return false;
}
return true;
@@ -479,434 +188,83 @@ public final class PrinterInfo implements Parcelable {
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("PrinterInfo{");
- builder.append(mId).append(", \"");
+ builder.append("id=").append(mId);
+ builder.append(", name=").append(mName);
+ builder.append(", status=").append(mStatus);
+ builder.append(", description=").append(mDescription);
+ builder.append(", capabilities=").append(mCapabilities);
builder.append("\"}");
return builder.toString();
}
- private void writeMediaSizes(Parcel parcel) {
- if (mMediaSizes == null) {
- parcel.writeInt(0);
- return;
- }
- final int mediaSizeCount = mMediaSizes.size();
- parcel.writeInt(mediaSizeCount);
- for (int i = 0; i < mediaSizeCount; i++) {
- mMediaSizes.get(i).writeToParcel(parcel);
- }
- }
-
- private void readMediaSizes(Parcel parcel) {
- final int mediaSizeCount = parcel.readInt();
- if (mediaSizeCount > 0 && mMediaSizes == null) {
- mMediaSizes = new ArrayList<MediaSize>();
- }
- for (int i = 0; i < mediaSizeCount; i++) {
- mMediaSizes.add(MediaSize.createFromParcel(parcel));
- }
- }
-
- private void writeResolutions(Parcel parcel) {
- if (mResolutions == null) {
- parcel.writeInt(0);
- return;
- }
- final int resolutionCount = mResolutions.size();
- parcel.writeInt(resolutionCount);
- for (int i = 0; i < resolutionCount; i++) {
- mResolutions.get(i).writeToParcel(parcel);
- }
- }
-
- private void readResolutions(Parcel parcel) {
- final int resolutionCount = parcel.readInt();
- if (resolutionCount > 0 && mResolutions == null) {
- mResolutions = new ArrayList<Resolution>();
- }
- for (int i = 0; i < resolutionCount; i++) {
- mResolutions.add(Resolution.createFromParcel(parcel));
- }
- }
-
- private void writeMargins(Margins margins, Parcel parcel) {
- if (margins == null) {
- parcel.writeInt(0);
- } else {
- parcel.writeInt(1);
- margins.writeToParcel(parcel);
- }
- }
-
- private Margins readMargins(Parcel parcel) {
- return (parcel.readInt() == 1) ? Margins.createFromParcel(parcel) : null;
- }
-
- private void writeInputTrays(Parcel parcel) {
- if (mInputTrays == null) {
- parcel.writeInt(0);
- return;
- }
- final int inputTrayCount = mInputTrays.size();
- parcel.writeInt(inputTrayCount);
- for (int i = 0; i < inputTrayCount; i++) {
- mInputTrays.get(i).writeToParcel(parcel);
- }
- }
-
- private List<Tray> readInputTrays(Parcel parcel) {
- final int inputTrayCount = parcel.readInt();
- if (inputTrayCount <= 0) {
- return null;
- }
- List<Tray> inputTrays = new ArrayList<Tray>(inputTrayCount);
- for (int i = 0; i < inputTrayCount; i++) {
- inputTrays.add(Tray.createFromParcel(parcel));
- }
- return inputTrays;
- }
-
- private void writeOutputTrays(Parcel parcel) {
- if (mOutputTrays == null) {
- parcel.writeInt(0);
- return;
- }
- final int outputTrayCount = mOutputTrays.size();
- parcel.writeInt(outputTrayCount);
- for (int i = 0; i < outputTrayCount; i++) {
- mOutputTrays.get(i).writeToParcel(parcel);
- }
- }
-
- private List<Tray> readOutputTrays(Parcel parcel) {
- final int outputTrayCount = parcel.readInt();
- if (outputTrayCount <= 0) {
- return null;
- }
- List<Tray> outputTrays = new ArrayList<Tray>(outputTrayCount);
- for (int i = 0; i < outputTrayCount; i++) {
- outputTrays.add(Tray.createFromParcel(parcel));
- }
- return outputTrays;
- }
-
- private void readDefaults(Parcel parcel) {
- final int defaultCount = parcel.readInt();
- for (int i = 0; i < defaultCount; i++) {
- mDefaults[i] = parcel.readInt();
- }
- }
-
- private void writeDefaults(Parcel parcel) {
- final int defaultCount = mDefaults.length;
- parcel.writeInt(defaultCount);
- for (int i = 0; i < defaultCount; i++) {
- parcel.writeInt(mDefaults[i]);
- }
- }
-
/**
- * Builder for creating of a {@link PrinterInfo}. This class is responsible
- * to enforce that all required attributes have at least one default value.
- * In other words, this class creates only well-formed {@link PrinterInfo}s.
- * <p>
- * Look at the individual methods for a reference whether a property is
- * required or if it is optional.
- * </p>
+ * Builder for creating of a {@link PrinterInfo}.
*/
public static final class Builder {
private final PrinterInfo mPrototype;
/**
- * Creates a new instance.
+ * Constructor.
*
* @param printerId The printer id. Cannot be null.
- *
- * @throws IllegalArgumentException If the printer id is null.
+ * @param name The printer name. Cannot be empty.
+ * @param status The printer status. Must be a valid status.
*/
- public Builder(PrinterId printerId) {
+ public Builder(PrinterId printerId, String name, int status) {
if (printerId == null) {
throw new IllegalArgumentException("printerId cannot be null.");
}
+ if (TextUtils.isEmpty(name)) {
+ throw new IllegalArgumentException("name cannot be empty.");
+ }
+ if (!isValidStatus(status)) {
+ throw new IllegalArgumentException("status is invalid.");
+ }
mPrototype = new PrinterInfo();
mPrototype.mId = printerId;
- }
-
- /**
- * Sets the printer status.
- * <p>
- * <strong>Required:</strong> Yes
- * </p>
- *
- * @param status The status.
- * @return This builder.
- */
- public Builder setStatus(int status) {
+ mPrototype.mName = name;
mPrototype.mStatus = status;
- return this;
- }
-
- /**
- * Adds a supported media size.
- * <p>
- * <strong>Required:</strong> Yes
- * </p>
- *
- * @param mediaSize A media size.
- * @param isDefault Whether this is the default.
- * @return This builder.
- * @throws IllegalArgumentException If set as default and there
- * is already a default.
- *
- * @see PrintAttributes.MediaSize
- */
- public Builder addMediaSize(MediaSize mediaSize, boolean isDefault) {
- if (mPrototype.mMediaSizes == null) {
- mPrototype.mMediaSizes = new ArrayList<MediaSize>();
- }
- final int insertionIndex = mPrototype.mMediaSizes.size();
- mPrototype.mMediaSizes.add(mediaSize);
- if (isDefault) {
- throwIfDefaultAlreadySpecified(PROPERTY_MEDIA_SIZE);
- mPrototype.mDefaults[PROPERTY_MEDIA_SIZE] = insertionIndex;
- }
- return this;
- }
-
- /**
- * Adds a supported resolution.
- * <p>
- * <strong>Required:</strong> Yes
- * </p>
- *
- * @param resolution A resolution.
- * @param isDefault Whether this is the default.
- * @return This builder.
- *
- * @throws IllegalArgumentException If set as default and there
- * is already a default.
- *
- * @see PrintAttributes.Resolution
- */
- public Builder addResolution(Resolution resolution, boolean isDefault) {
- if (mPrototype.mResolutions == null) {
- mPrototype.mResolutions = new ArrayList<Resolution>();
- }
- final int insertionIndex = mPrototype.mResolutions.size();
- mPrototype.mResolutions.add(resolution);
- if (isDefault) {
- throwIfDefaultAlreadySpecified(PROPERTY_RESOLUTION);
- mPrototype.mDefaults[PROPERTY_RESOLUTION] = insertionIndex;
- }
- return this;
- }
-
- /**
- * Sets the minimal margins.
- * <p>
- * <strong>Required:</strong> No
- * </p>
- *
- * @param margins The margins.
- * @param defaultMargins The default margins.
- * @return This builder.
- *
- * @see PrintAttributes.Margins
- */
- public Builder setMinMargins(Margins margins, Margins defaultMargins) {
- if (margins.getLeftMils() > defaultMargins.getLeftMils()
- || margins.getTopMils() > defaultMargins.getTopMils()
- || margins.getRightMils() < defaultMargins.getRightMils()
- || margins.getBottomMils() < defaultMargins.getBottomMils()) {
- throw new IllegalArgumentException("Default margins"
- + " cannot be outside of the min margins.");
- }
- mPrototype.mMinMargins = margins;
- mPrototype.mDefaultMargins = defaultMargins;
- return this;
- }
-
- /**
- * Adds an input tray.
- * <p>
- * <strong>Required:</strong> No
- * </p>
- *
- * @param inputTray A tray.
- * @param isDefault Whether this is the default.
- * @return This builder.
- *
- * @throws IllegalArgumentException If set as default and there
- * is already a default.
- *
- * @see PrintAttributes.Tray
- */
- public Builder addInputTray(Tray inputTray, boolean isDefault) {
- if (mPrototype.mInputTrays == null) {
- mPrototype.mInputTrays = new ArrayList<Tray>();
- }
- final int insertionIndex = mPrototype.mInputTrays.size();
- mPrototype.mInputTrays.add(inputTray);
- if (isDefault) {
- throwIfDefaultAlreadySpecified(PROPERTY_INPUT_TRAY);
- mPrototype.mDefaults[PROPERTY_INPUT_TRAY] = insertionIndex;
- }
- return this;
- }
-
- /**
- * Adds an output tray.
- * <p>
- * <strong>Required:</strong> No
- * </p>
- *
- * @param outputTray A tray.
- * @param isDefault Whether this is the default.
- * @return This builder.
- *
- * @throws IllegalArgumentException If set as default and there
- * is already a default.
- *
- * @see PrintAttributes.Tray
- */
- public Builder addOutputTray(Tray outputTray, boolean isDefault) {
- if (mPrototype.mOutputTrays == null) {
- mPrototype.mOutputTrays = new ArrayList<Tray>();
- }
- final int insertionIndex = mPrototype.mOutputTrays.size();
- mPrototype.mOutputTrays.add(outputTray);
- if (isDefault) {
- throwIfDefaultAlreadySpecified(PROPERTY_OUTPUT_TRAY);
- mPrototype.mDefaults[PROPERTY_OUTPUT_TRAY] = insertionIndex;
- }
- return this;
}
/**
- * Sets the color modes.
- * <p>
- * <strong>Required:</strong> Yes
- * </p>
- *
- * @param colorModes The color mode bit mask.
- * @param defaultColorMode The default color mode.
- * @return This builder.
- *
- * @throws IllegalArgumentException If color modes contains an invalid
- * mode bit or if the default color mode is invalid.
+ * Constructor.
*
- * @see PrintAttributes#COLOR_MODE_COLOR
- * @see PrintAttributes#COLOR_MODE_MONOCHROME
+ * @param prototype Prototype from which to start building.
*/
- public Builder setColorModes(int colorModes, int defaultColorMode) {
- int currentModes = colorModes;
- while (currentModes > 0) {
- final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes));
- currentModes &= ~currentMode;
- PrintAttributes.enforceValidColorMode(currentMode);
- }
- if ((colorModes & defaultColorMode) == 0) {
- throw new IllegalArgumentException("Default color mode not in color modes.");
- }
- PrintAttributes.enforceValidColorMode(colorModes);
- mPrototype.mColorModes = colorModes;
- mPrototype.mDefaults[PROPERTY_COLOR_MODE] = defaultColorMode;
- return this;
+ public Builder(PrinterInfo prototype) {
+ mPrototype = prototype;
}
/**
- * Set the duplex modes.
- * <p>
- * <strong>Required:</strong> No
- * </p>
+ * Sets the printer name.
*
- * @param duplexModes The duplex mode bit mask.
- * @param defaultDuplexMode The default duplex mode.
+ * @param name The name.
* @return This builder.
- *
- * @throws IllegalArgumentException If duplex modes contains an invalid
- * mode bit or if the default duplex mode is invalid.
- *
- * @see PrintAttributes#DUPLEX_MODE_NONE
- * @see PrintAttributes#DUPLEX_MODE_LONG_EDGE
- * @see PrintAttributes#DUPLEX_MODE_SHORT_EDGE
*/
- public Builder setDuplexModes(int duplexModes, int defaultDuplexMode) {
- int currentModes = duplexModes;
- while (currentModes > 0) {
- final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes));
- currentModes &= ~currentMode;
- PrintAttributes.enforceValidDuplexMode(currentMode);
- }
- if ((duplexModes & defaultDuplexMode) == 0) {
- throw new IllegalArgumentException("Default duplex mode not in duplex modes.");
- }
- PrintAttributes.enforceValidDuplexMode(defaultDuplexMode);
- mPrototype.mDuplexModes = duplexModes;
- mPrototype.mDefaults[PROPERTY_DUPLEX_MODE] = defaultDuplexMode;
+ public Builder setName(String name) {
+ mPrototype.mName = name;
return this;
}
/**
- * Sets the fitting modes.
- * <p>
- * <strong>Required:</strong> No
- * </p>
+ * Sets the printer description.
*
- * @param fittingModes The fitting mode bit mask.
- * @param defaultFittingMode The default fitting mode.
+ * @param description The description.
* @return This builder.
- *
- * @throws IllegalArgumentException If fitting modes contains an invalid
- * mode bit or if the default fitting mode is invalid.
- *
- * @see PrintAttributes#FITTING_MODE_NONE
- * @see PrintAttributes#FITTING_MODE_FIT_TO_PAGE
*/
- public Builder setFittingModes(int fittingModes, int defaultFittingMode) {
- int currentModes = fittingModes;
- while (currentModes > 0) {
- final int currentMode = (1 << Integer.numberOfTrailingZeros(currentModes));
- currentModes &= ~currentMode;
- PrintAttributes.enfoceValidFittingMode(currentMode);
- }
- if ((fittingModes & defaultFittingMode) == 0) {
- throw new IllegalArgumentException("Default fitting mode not in fiting modes.");
- }
- PrintAttributes.enfoceValidFittingMode(defaultFittingMode);
- mPrototype.mFittingModes = fittingModes;
- mPrototype.mDefaults[PROPERTY_FITTING_MODE] = defaultFittingMode;
+ public Builder setDescription(String description) {
+ mPrototype.mDescription = description;
return this;
}
/**
- * Sets the orientations.
- * <p>
- * <strong>Required:</strong> Yes
- * </p>
+ * Sets the printer capabilities.
*
- * @param orientations The orientation bit mask.
- * @param defaultOrientation The default orientation.
+ * @param capabilities The capabilities.
* @return This builder.
- *
- * @throws IllegalArgumentException If orientations contains an invalid
- * mode bit or if the default orientation is invalid.
- *
- * @see PrintAttributes#ORIENTATION_PORTRAIT
- * @see PrintAttributes#ORIENTATION_LANDSCAPE
*/
- public Builder setOrientations(int orientations, int defaultOrientation) {
- int currentOrientaions = orientations;
- while (currentOrientaions > 0) {
- final int currentOrnt = (1 << Integer.numberOfTrailingZeros(currentOrientaions));
- currentOrientaions &= ~currentOrnt;
- PrintAttributes.enforceValidOrientation(currentOrnt);
- }
- if ((orientations & defaultOrientation) == 0) {
- throw new IllegalArgumentException("Default orientation not in orientations.");
- }
- PrintAttributes.enforceValidOrientation(defaultOrientation);
- mPrototype.mOrientations = orientations;
- mPrototype.mDefaults[PROPERTY_ORIENTATION] = defaultOrientation;
+ public Builder setCapabilities(PrinterCapabilitiesInfo capabilities) {
+ mPrototype.mCapabilities = capabilities;
return this;
}
@@ -919,10 +277,8 @@ public final class PrinterInfo implements Parcelable {
return new PrinterInfo(mPrototype);
}
- private void throwIfDefaultAlreadySpecified(int propertyIndex) {
- if (mPrototype.mDefaults[propertyIndex] != DEFAULT_UNDEFINED) {
- throw new IllegalArgumentException("Default already specified.");
- }
+ private boolean isValidStatus(int status) {
+ return (status == PrinterInfo.STATUS_READY);
}
}
diff --git a/core/java/android/printservice/IPrintService.aidl b/core/java/android/printservice/IPrintService.aidl
index e6fdbf999a35..16b7a26868ef 100644
--- a/core/java/android/printservice/IPrintService.aidl
+++ b/core/java/android/printservice/IPrintService.aidl
@@ -10,16 +10,14 @@
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
+ * See the License for the specific languagÿe governing permissions and
* limitations under the License.
*/
package android.printservice;
-import android.os.ICancellationSignal;
-import android.print.IPrinterDiscoveryObserver;
+import android.print.IPrinterDiscoverySessionObserver;
import android.print.PrintJobInfo;
-import android.print.PrinterId;
import android.printservice.IPrintServiceClient;
/**
@@ -29,9 +27,7 @@ import android.printservice.IPrintServiceClient;
*/
oneway interface IPrintService {
void setClient(IPrintServiceClient client);
- void onRequestUpdatePrinters(in List<PrinterId> printerIds);
- void onRequestCancelPrintJob(in PrintJobInfo printJobInfo);
+ void requestCancelPrintJob(in PrintJobInfo printJobInfo);
void onPrintJobQueued(in PrintJobInfo printJobInfo);
- void onStartPrinterDiscovery(IPrinterDiscoveryObserver observer);
- void onStopPrinterDiscovery();
+ void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer);
}
diff --git a/core/java/android/printservice/PrintDocument.java b/core/java/android/printservice/PrintDocument.java
index 2a1581a602d5..7437dc57d34b 100644
--- a/core/java/android/printservice/PrintDocument.java
+++ b/core/java/android/printservice/PrintDocument.java
@@ -55,14 +55,14 @@ public final class PrintDocument {
}
/**
- * Gets the data associated with this document. It is a responsibility of the
- * client to open a stream to the returned file descriptor and fully read the
- * data.
+ * Gets the data associated with this document.
* <p>
- * <strong>Note:</strong> It is your responsibility to close the file descriptor.
+ * <strong>Note: </strong> It is a responsibility of the client to open a
+ * stream to the returned file descriptor, fully read the data, and close
+ * the file descriptor.
* </p>
*
- * @return A file descriptor for reading the data or <code>null</code>.
+ * @return A file descriptor for reading the data.
*/
public FileDescriptor getData() {
ParcelFileDescriptor source = null;
diff --git a/core/java/android/printservice/PrintJob.java b/core/java/android/printservice/PrintJob.java
index 64c079e0055b..5f9a730f3f4a 100644
--- a/core/java/android/printservice/PrintJob.java
+++ b/core/java/android/printservice/PrintJob.java
@@ -21,9 +21,9 @@ import android.print.PrintJobInfo;
import android.util.Log;
/**
- * This class represents a print job from the perspective of a
- * print service. It provides APIs for observing the print job
- * state and performing operations on the print job.
+ * This class represents a print job from the perspective of a print
+ * service. It provides APIs for observing the print job state and
+ * performing operations on the print job.
*/
public final class PrintJob {
@@ -38,7 +38,8 @@ public final class PrintJob {
PrintJob(PrintJobInfo jobInfo, IPrintServiceClient client) {
mCachedInfo = jobInfo;
mPrintServiceClient = client;
- mDocument = new PrintDocument(mCachedInfo.getId(), client, jobInfo.getDocumentInfo());
+ mDocument = new PrintDocument(mCachedInfo.getId(), client,
+ jobInfo.getDocumentInfo());
}
/**
@@ -77,7 +78,7 @@ public final class PrintJob {
}
/**
- * Gets the document of this print job.
+ * Gets the printed document.
*
* @return The document.
*/
@@ -87,11 +88,12 @@ public final class PrintJob {
/**
* Gets whether this print job is queued. Such a print job is
- * ready to be printed and can be started.
+ * ready to be printed and can be started or cancelled.
*
* @return Whether the print job is queued.
*
* @see #start()
+ * @see #cancel()
*/
public boolean isQueued() {
return getInfo().getState() == PrintJobInfo.STATE_QUEUED;
@@ -112,6 +114,42 @@ public final class PrintJob {
}
/**
+ * Gets whether this print job is completed. Such a print job
+ * is successfully printed. This is a final state.
+ *
+ * @return Whether the print job is completed.
+ *
+ * @see #complete()
+ */
+ public boolean isCompleted() {
+ return getInfo().getState() == PrintJobInfo.STATE_COMPLETED;
+ }
+
+ /**
+ * Gets whether this print job is failed. Such a print job is
+ * not successfully printed due to an error. This is a final state.
+ *
+ * @return Whether the print job is failed.
+ *
+ * @see #fail(CharSequence)
+ */
+ public boolean isFailed() {
+ return getInfo().getState() == PrintJobInfo.STATE_FAILED;
+ }
+
+ /**
+ * Gets whether this print job is cancelled. Such a print job was
+ * cancelled as a result of a user request. This is a final state.
+ *
+ * @return Whether the print job is cancelled.
+ *
+ * @see #cancel()
+ */
+ public boolean isCancelled() {
+ return getInfo().getState() == PrintJobInfo.STATE_FAILED;
+ }
+
+ /**
* Starts the print job. You should call this method if {@link
* #isQueued()} returns true and you started printing.
*
@@ -163,12 +201,13 @@ public final class PrintJob {
/**
* Cancels the print job. You should call this method if {@link
* #isQueued()} or {@link #isStarted()} returns true and you canceled
- * the print job as a response to a call to {@link PrintService
- * #onRequestCancelPrintJob(PrintJob)}.
+ * the print job as a response to a call to {@link
+ * PrintService#onRequestCancelPrintJob(PrintJob)}.
*
- * @return Whether the job as canceled.
+ * @return Whether the job is canceled.
*
* @see #isStarted()
+ * @see #isQueued()
*/
public boolean cancel() {
if (isQueued() || isStarted()) {
diff --git a/core/java/android/printservice/PrintService.java b/core/java/android/printservice/PrintService.java
index 49384db2fabd..92bccd4e480d 100644
--- a/core/java/android/printservice/PrintService.java
+++ b/core/java/android/printservice/PrintService.java
@@ -25,10 +25,9 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
-import android.print.IPrinterDiscoveryObserver;
+import android.print.IPrinterDiscoverySessionObserver;
import android.print.PrintJobInfo;
import android.print.PrinterId;
-import android.print.PrinterInfo;
import android.util.Log;
import java.util.ArrayList;
@@ -37,84 +36,82 @@ import java.util.List;
/**
* <p>
- * This is the base class for implementing print services. A print service
- * knows how to discover and interact one or more printers via one or more
- * protocols.
+ * This is the base class for implementing print services. A print service knows
+ * how to discover and interact one or more printers via one or more protocols.
* </p>
* <h3>Printer discovery</h3>
* <p>
- * A print service is responsible for discovering and reporting printers.
- * A printer discovery period starts with a call to
- * {@link #onStartPrinterDiscovery()} and ends with a call to
- * {@link #onStopPrinterDiscovery()}. During a printer discovery
- * period the print service reports newly discovered printers by
- * calling {@link #addDiscoveredPrinters(List)} and reports added printers
- * that disappeared by calling {@link #removeDiscoveredPrinters(List)}.
- * Calls to {@link #addDiscoveredPrinters(List)} and
- * {@link #removeDiscoveredPrinters(List)} before a call to
- * {@link #onStartPrinterDiscovery()} and after a call to
- * {@link #onStopPrinterDiscovery()} are a no-op.
+ * A print service is responsible for discovering printers, adding discovered printers,
+ * removing added printers, and updating added printers. When the system is interested
+ * in printers managed by your service it will call {@link
+ * #onCreatePrinterDiscoverySession()} from which you must return a new {@link
+ * PrinterDiscoverySession} instance. The returned session encapsulates the interaction
+ * between the system and your service during printer discovery. For description of this
+ * interaction refer to the documentation for {@link PrinterDiscoverySession}.
* </p>
* <p>
- * For every printer discovery period all printers have to be added. Each
- * printer known to this print service should be added only once during a
- * discovery period, unless it was added and then removed before that.
- * Only an already added printer can be removed.
+ * For every printer discovery session all printers have to be added since system does
+ * not retain printers across sessions. Hence, each printer known to this print service
+ * should be added only once during a discovery session. Only an already added printer
+ * can be removed or updated. Removed printers can be added again.
* </p>
* <h3>Print jobs</h3>
* <p>
- * When a new print job targeted to the printers managed by this print
- * service is queued, i.e. ready for processing by the print service,
- * a call to {@link #onPrintJobQueued(PrintJob)} is made and the print
- * service may handle it immediately or schedule that for an appropriate
- * time in the future. The list of all print jobs for this service
- * are be available by calling {@link #getPrintJobs()}.
+ * When a new print job targeted to a printer managed by this print service is is queued,
+ * i.e. ready for processing by the print service, you will receive a call to {@link
+ * #onPrintJobQueued(PrintJob)}. The print service may handle the print job immediately
+ * or schedule that for an appropriate time in the future. The list of all active print
+ * jobs for this service is obtained by calling {@link #getActivePrintJobs()}. Active
+ * print jobs are ones that are queued or started.
* </p>
* <p>
- * A print service is responsible for setting the print job state as
- * appropriate while processing it. Initially, a print job is in a
- * {@link PrintJobInfo#STATE_QUEUED} state which means that the data to
- * be printed is spooled by the system and the print service can obtain
- * that data by calling {@link PrintJob#getDocument()}. A queued print
- * job's {@link PrintJob#isQueued()} method returns true.
+ * A print service is responsible for setting a print job's state as appropriate
+ * while processing it. Initially, a print job is queued, i.e. {@link PrintJob#isQueued()
+ * PrintJob.isQueued()} returns true, which means that the document to be printed is
+ * spooled by the system and the print service can begin processing it. You can obtain
+ * the printed document by calling {@link PrintJob#getDocument() PrintJob.getDocument()}
+ * whose data is accessed via {@link PrintDocument#getData() PrintDocument.getData()}.
+ * After the print service starts printing the data it should set the print job's
+ * state to started by calling {@link PrintJob#start()} after which
+ * {@link PrintJob#isStarted() PrintJob.isStarted()} would return true. Upon successful
+ * completion, the print job should be marked as completed by calling {@link
+ * PrintJob#complete() PrintJob.complete()} after which {@link PrintJob#isCompleted()
+ * PrintJob.isCompleted()} would return true. In case of a failure, the print job should
+ * be marked as failed by calling {@link PrintJob#fail(CharSequence) PrintJob.fail(
+ * CharSequence)} after which {@link PrintJob#isFailed() PrintJob.isFailed()} would
+ * return true.
* </p>
* <p>
- * After the print service starts printing the data it should set the
- * print job state to {@link PrintJobInfo#STATE_STARTED} by calling
- * {@link PrintJob#start()}. Upon successful completion, the print job
- * state has to be set to {@link PrintJobInfo#STATE_COMPLETED} by calling
- * {@link PrintJob#complete()}. In case of a failure, the print job
- * state should be set to {@link PrintJobInfo#STATE_FAILED} by calling
- * {@link PrintJob#fail(CharSequence)}. If a print job is in a
- * {@link PrintJobInfo#STATE_STARTED} state, i.e. {@link PrintJob#isStarted()}
- * return true, and the user requests to cancel it, the print service will
- * receive a call to {@link #onRequestCancelPrintJob(PrintJob)} which
- * requests from the service to do a best effort in canceling the job. In
- * case the job is successfully canceled, its state has to be set to
- * {@link PrintJobInfo#STATE_CANCELED}. by calling {@link PrintJob#cancel()}.
+ * If a print job is queued or started and the user requests to cancel it, the print
+ * service will receive a call to {@link #onRequestCancelPrintJob(PrintJob)} which
+ * requests from the service to do best effort in canceling the job. In case the job
+ * is successfully canceled, its state has to be marked as cancelled by calling {@link
+ * PrintJob#cancel() PrintJob.cancel()} after which {@link PrintJob#isCancelled()
+ * PrintJob.isCacnelled()} would return true.
* </p>
* <h3>Lifecycle</h3>
* <p>
- * The lifecycle of a print service is managed exclusively by the system
- * and follows the established service lifecycle. Additionally, starting
- * or stopping a print service is triggered exclusively by an explicit
- * user action through enabling or disabling it in the device settings.
- * After the system binds to a print service, it calls {@link #onConnected()}.
- * This method can be overriden by clients to perform post binding setup.
- * Also after the system unbinds from a print service, it calls
- * {@link #onDisconnected()}. This method can be overriden by clients to
- * perform post unbinding cleanup.
+ * The lifecycle of a print service is managed exclusively by the system and follows
+ * the established service lifecycle. Additionally, starting or stopping a print service
+ * is triggered exclusively by an explicit user action through enabling or disabling it
+ * in the device settings. After the system binds to a print service, it calls {@link
+ * #onConnected()}. This method can be overriden by clients to perform post binding setup.
+ * Also after the system unbinds from a print service, it calls {@link #onDisconnected()}.
+ * This method can be overriden by clients to perform post unbinding cleanup. Your should
+ * not do any work after the system disconnected from your print service since the
+ * service can be killed at any time to reclaim memory. The system will not disconnect
+ * from a print service if there are active print jobs for the printers managed by it.
* </p>
* <h3>Declaration</h3>
* <p>
- * A print service is declared as any other service in an AndroidManifest.xml
- * but it must also specify that it handles the {@link android.content.Intent}
- * with action {@link #SERVICE_INTERFACE}. Failure to declare this intent
- * will cause the system to ignore the print service. Additionally, a print
- * service must request the {@link android.Manifest.permission#BIND_PRINT_SERVICE}
- * permission to ensure that only the system can bind to it. Failure to
- * declare this intent will cause the system to ignore the print service.
- * Following is an example declaration:
+ * A print service is declared as any other service in an AndroidManifest.xml but it must
+ * also specify that it handles the {@link android.content.Intent} with action {@link
+ * #SERVICE_INTERFACE android.printservice.PrintService}. Failure to declare this intent
+ * will cause the system to ignore the print service. Additionally, a print service must
+ * request the {@link android.Manifest.permission#BIND_PRINT_SERVICE
+ * android.permission.BIND_PRINT_SERVICE} permission to ensure that only the system can
+ * bind to it. Failure to declare this intent will cause the system to ignore the print
+ * service. Following is an example declaration:
* </p>
* <pre>
* &lt;service android:name=".MyPrintService"
@@ -127,17 +124,15 @@ import java.util.List;
* </pre>
* <h3>Configuration</h3>
* <p>
- * A print service can be configured by specifying an optional settings
- * activity which exposes service specific options, an optional add
- * prints activity which is used for manual addition of printers, vendor
- * name ,etc. It is a responsibility of the system to launch the settings
- * and add printers activities when appropriate.
+ * A print service can be configured by specifying an optional settings activity which
+ * exposes service specific settings, an optional add printers activity which is used for
+ * manual addition of printers, vendor name ,etc. It is a responsibility of the system
+ * to launch the settings and add printers activities when appropriate.
* </p>
* <p>
- * A print service is configured by providing a
- * {@link #SERVICE_META_DATA meta-data} entry in the manifest when declaring
- * the service. A service declaration with a meta-data tag is presented
- * below:
+ * A print service is configured by providing a {@link #SERVICE_META_DATA meta-data}
+ * entry in the manifest when declaring the service. A service declaration with a meta-data
+ * tag is presented below:
* <pre> &lt;service android:name=".MyPrintService"
* android:permission="android.permission.BIND_PRINT_SERVICE"&gt;
* &lt;intent-filter&gt;
@@ -147,8 +142,9 @@ import java.util.List;
* &lt;/service&gt;</pre>
* </p>
* <p>
- * For more details refer to {@link #SERVICE_META_DATA} and
- * <code>&lt;{@link android.R.styleable#PrintService print-service}&gt;</code>.
+ * For more details for how to configure your print service via the meta-data refer to
+ * {@link #SERVICE_META_DATA} and <code>&lt;{@link android.R.styleable#PrintService
+ * print-service}&gt;</code>.
* </p>
*/
public abstract class PrintService extends Service {
@@ -157,21 +153,25 @@ public abstract class PrintService extends Service {
/**
* The {@link Intent} action that must be declared as handled by a service
- * in its manifest to allow the system to recognize it as a print service.
+ * in its manifest for the system to recognize it as a print service.
*/
public static final String SERVICE_INTERFACE = "android.printservice.PrintService";
/**
- * Name under which a PrintService component publishes additional information
- * about itself. This meta-data must reference an XML resource containing a
- * <code>&lt;{@link android.R.styleable#PrintService print-service}&gt;</code>
- * tag. This is a a sample XML file configuring a print service:
+ * Name under which a {@link PrintService} component publishes additional information
+ * about itself. This meta-data must reference a XML resource containing a <code>
+ * &lt;{@link android.R.styleable#PrintService print-service}&gt;</code> tag. This is
+ * a sample XML file configuring a print service:
* <pre> &lt;print-service
* android:vendor="SomeVendor"
* android:settingsActivity="foo.bar.MySettingsActivity"
* andorid:addPrintersActivity="foo.bar.MyAddPrintersActivity."
* . . .
* /&gt;</pre>
+ * <p>
+ * For detailed configuration options that can be specified via the meta-data
+ * refer to {@link android.R.styleable#PrintService android.R.styleable.PrintService}.
+ * </p>
*/
public static final String SERVICE_META_DATA = "android.printservice";
@@ -181,12 +181,12 @@ public abstract class PrintService extends Service {
private IPrintServiceClient mClient;
- private IPrinterDiscoveryObserver mDiscoveryObserver;
+ private int mLastSessionId = -1;
@Override
- protected void attachBaseContext(Context base) {
+ protected final void attachBaseContext(Context base) {
super.attachBaseContext(base);
- mHandler = new MyHandler(base.getMainLooper());
+ mHandler = new ServiceHandler(base.getMainLooper());
}
/**
@@ -204,203 +204,47 @@ public abstract class PrintService extends Service {
}
/**
- * Callback requesting from this service to start printer discovery.
- * At the end of the printer discovery period the system will call
- * {@link #onStopPrinterDiscovery()}. Discovered printers should be
- * reported by calling {@link #addDiscoveredPrinters(List)} and reported
- * ones that disappear should be reported by calling
- * {@link #removeDiscoveredPrinters(List)}.
- *
- * @see #onStopPrinterDiscovery()
- * @see #addDiscoveredPrinters(List)
- * @see #removeDiscoveredPrinters(List)
- * @see #updateDiscoveredPrinters(List)
- */
- protected abstract void onStartPrinterDiscovery();
-
- /**
- * Callback requesting from this service to stop printer discovery.
- *
- * @see #onStartPrinterDiscovery()
- * @see #addDiscoveredPrinters(List)
- * @see #removeDiscoveredPrinters(List)
- * @see #updateDiscoveredPrinters(List)
- */
- protected abstract void onStopPrinterDiscovery();
-
- /**
- * Adds discovered printers. This method should be called during a
- * printer discovery period, i.e. after a call to
- * {@link #onStartPrinterDiscovery()} and before the corresponding
- * call to {@link #onStopPrinterDiscovery()}, otherwise it does nothing.
- * <p>
- * <strong>Note:</strong> For every printer discovery period all
- * printers have to be added. You can call this method as many times as
- * necessary during the discovery period but should not pass in already
- * added printers. If a printer is already added in the same printer
- * discovery period, it will be ignored.
- * </p>
- * <p>
- * A {@link PrinterInfo} can have all of its required attributes specified,
- * or not. Whether all attributes are specified can be verified by calling
- * {@link PrinterInfo#hasAllRequiredAttributes()}. You can add printers
- * regardless if all required attributes are specified. When the system
- * (and the user) needs to interact with a printer, you will receive a
- * call to {@link #onRequestUpdatePrinters(List)}. If you fail to update
- * a printer that was added without all required attributes via calling
- * {@link #updateDiscoveredPrinters(List)}, then this printer will be
- * ignored, i.e. considered unavailable.
- * <p>
- *
- * @param printers A list with discovered printers.
- *
- * @see #updateDiscoveredPrinters(List)
- * @see #removeDiscoveredPrinters(List)
- * @see #onStartPrinterDiscovery()
- * @see #onStopPrinterDiscovery()
- */
- public final void addDiscoveredPrinters(List<PrinterInfo> printers) {
- final IPrinterDiscoveryObserver observer;
- synchronized (mLock) {
- observer = mDiscoveryObserver;
- }
- if (observer != null) {
- try {
- observer.onPrintersAdded(printers);
- } catch (RemoteException re) {
- Log.e(LOG_TAG, "Error adding discovered printers", re);
- }
- }
- }
-
- /**
- * Removes discovered printers given their ids. This method should be called
- * during a printer discovery period, i.e. after a call to
- * {@link #onStartPrinterDiscovery()} and before the corresponding
- * call to {@link #onStopPrinterDiscovery()}, otherwise it does nothing.
- * <p>
- * For every printer discovery period all printers have to be added. You
- * should remove only printers that were added in this printer discovery
- * period by a call to {@link #addDiscoveredPrinters(List)}. You can call
- * this method as many times as necessary during the discovery period
- * but should not pass in already removed printer ids. If a printer with
- * a given id is already removed, it will be ignored.
- * </p>
+ * Callback asking you to create a new {@link PrinterDiscoverySession}.
*
- * @param printerIds A list with disappeared printer ids.
- *
- * @see #addDiscoveredPrinters(List)
- * @see #updateDiscoveredPrinters(List)
- * @see #onStartPrinterDiscovery()
- * @see #onStopPrinterDiscovery()
+ * @see PrinterDiscoverySession
*/
- public final void removeDiscoveredPrinters(List<PrinterId> printerIds) {
- final IPrinterDiscoveryObserver observer;
- synchronized (mLock) {
- observer = mDiscoveryObserver;
- }
- if (observer != null) {
- try {
- observer.onPrintersRemoved(printerIds);
- } catch (RemoteException re) {
- Log.e(LOG_TAG, "Error removing discovered printers", re);
- }
- }
- }
+ protected abstract PrinterDiscoverySession onCreatePrinterDiscoverySession();
/**
- * Updates discovered printers that are already added. This method should
- * be called during a printer discovery period, i.e. after a call to
- * {@link #onStartPrinterDiscovery()} and before the corresponding
- * call to {@link #onStopPrinterDiscovery()}, otherwise it does nothing.
- * <p>
- * For every printer discovery period all printers have to be added. You
- * should update only printers that were added in this printer discovery
- * period by a call to {@link #addDiscoveredPrinters(List)}. You can call
- * this method as many times as necessary during the discovery period
- * but should not try to update already removed or never added printers.
- * If a printer is already removed or never added, it will be ignored.
- * </p>
- *
- * @param printers A list with updated printers.
- *
- * @see #addDiscoveredPrinters(List)
- * @see #removeDiscoveredPrinters(List)
- * @see #onStartPrinterDiscovery()
- * @see #onStopPrinterDiscovery()
- */
- public final void updateDiscoveredPrinters(List<PrinterInfo> printers) {
- final IPrinterDiscoveryObserver observer;
- synchronized (mLock) {
- observer = mDiscoveryObserver;
- }
- if (observer != null) {
- try {
- observer.onPrintersUpdated(printers);
- } catch (RemoteException re) {
- Log.e(LOG_TAG, "Error updating discovered printers", re);
- }
- }
- }
-
- /**
- * Called when the system will start interacting with a printer
- * giving you a change to update it in case some of its capabilities
- * have changed. For example, this method will be called when the
- * user selects a printer. Hence, it updating this printer should
- * be done as quickly as possible in order to achieve maximally
- * smooth user experience.
- * <p>
- * A {@link PrinterInfo} can have all of its required attributes specified,
- * or not. Whether all attributes are specified can be verified by calling
- * {@link PrinterInfo#hasAllRequiredAttributes()}. You can add printers
- * regardless if all required attributes are specified. When the system
- * (and the user) needs to interact with a printer, you will receive a
- * call to this method. If you fail to update a printer that was added
- * without all required attributes via calling
- * {@link #updateDiscoveredPrinters(List)}, then this printer will be
- * ignored, i.e. considered unavailable.
- * </p>
- *
- * @param printerIds The printers to be updated.
- */
- protected void onRequestUpdatePrinters(List<PrinterId> printerIds) {
- }
-
- /**
- * Called when canceling of a print job is requested. The service
+ * Called when cancellation of a print job is requested. The service
* should do best effort to fulfill the request. After the cancellation
- * is performed, the print job should be set to a cancelled state by
+ * is performed, the print job should be marked as cancelled state by
* calling {@link PrintJob#cancel()}.
*
- * @param printJob The print job to be canceled.
+ * @param printJob The print job to cancel.
+ *
+ * @see PrintJob#cancel() PrintJob.cancel()
+ * @see PrintJob#isCancelled() PrintJob.isCancelled()
*/
- protected void onRequestCancelPrintJob(PrintJob printJob) {
- }
+ protected abstract void onRequestCancelPrintJob(PrintJob printJob);
/**
* Called when there is a queued print job for one of the printers
- * managed by this print service. A queued print job is ready for
- * processing by a print service which can get the data to be printed
- * by calling {@link PrintJob#getDocument()}. This service may start
- * processing the passed in print job or schedule handling of queued
- * print jobs at a convenient time. The service can get the print
- * jobs by a call to {@link #getPrintJobs()} and examine their state
- * to find the ones with state {@link PrintJobInfo#STATE_QUEUED} by
- * calling {@link PrintJob#isQueued()}.
+ * managed by this print service.
*
* @param printJob The new queued print job.
*
- * @see #getPrintJobs()
+ * @see PrintJob#isQueued() PrintJob.isQueued()
+ * @see #getActivePrintJobs()
*/
protected abstract void onPrintJobQueued(PrintJob printJob);
/**
- * Gets the print jobs for the printers managed by this service.
+ * Gets the active print jobs for the printers managed by this service.
+ * Active print jobs are ones that are not in a final state, i.e. whose
+ * state is queued or started.
*
- * @return The print jobs.
+ * @return The active print jobs.
+ *
+ * @see PrintJob#isQueued() PrintJob.isQueued()
+ * @see PrintJob#isStarted() PrintJob.isStarted()
*/
- public final List<PrintJob> getPrintJobs() {
+ public final List<PrintJob> getActivePrintJobs() {
final IPrintServiceClient client;
synchronized (mLock) {
client = mClient;
@@ -428,14 +272,14 @@ public abstract class PrintService extends Service {
}
/**
- * Generates a global printer id given the printer's locally unique name.
+ * Generates a global printer id given the printer's locally unique one.
*
- * @param printerName The printer name.
+ * @param localId A locally unique id in the context of your print service.
* @return Global printer id.
*/
- public final PrinterId generatePrinterId(String printerName) {
+ public final PrinterId generatePrinterId(String localId) {
return new PrinterId(new ComponentName(getPackageName(),
- getClass().getName()), printerName);
+ getClass().getName()), localId);
}
@Override
@@ -443,69 +287,58 @@ public abstract class PrintService extends Service {
return new IPrintService.Stub() {
@Override
public void setClient(IPrintServiceClient client) {
- mHandler.obtainMessage(MyHandler.MSG_SET_CLEINT, client).sendToTarget();
+ mHandler.obtainMessage(ServiceHandler.MSG_SET_CLEINT, client)
+ .sendToTarget();
}
@Override
- public void onStartPrinterDiscovery(IPrinterDiscoveryObserver observer) {
- mHandler.obtainMessage(MyHandler.MSG_ON_START_PRINTER_DISCOVERY,
+ public void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer) {
+ mHandler.obtainMessage(ServiceHandler.MSG_ON_CREATE_PRINTER_DISCOVERY_SESSION,
observer).sendToTarget();
}
@Override
- public void onStopPrinterDiscovery() {
- mHandler.sendEmptyMessage(MyHandler.MSG_ON_STOP_PRINTER_DISCOVERY);
- }
-
- @Override
- public void onRequestUpdatePrinters(List<PrinterId> printerIds) {
- mHandler.obtainMessage(MyHandler.MSG_ON_REQUEST_UPDATE_PRINTERS,
- printerIds).sendToTarget();
- }
-
- @Override
- public void onRequestCancelPrintJob(PrintJobInfo printJobInfo) {
- mHandler.obtainMessage(MyHandler.MSG_ON_REQUEST_CANCEL_PRINTJOB,
+ public void requestCancelPrintJob(PrintJobInfo printJobInfo) {
+ mHandler.obtainMessage(ServiceHandler.MSG_ON_REQUEST_CANCEL_PRINTJOB,
printJobInfo).sendToTarget();
}
@Override
public void onPrintJobQueued(PrintJobInfo printJobInfo) {
- mHandler.obtainMessage(MyHandler.MSG_ON_PRINTJOB_QUEUED,
+ mHandler.obtainMessage(ServiceHandler.MSG_ON_PRINTJOB_QUEUED,
printJobInfo).sendToTarget();
}
};
}
- private final class MyHandler extends Handler {
- public static final int MSG_ON_START_PRINTER_DISCOVERY = 1;
- public static final int MSG_ON_STOP_PRINTER_DISCOVERY = 2;
+ private final class ServiceHandler extends Handler {
+ public static final int MSG_ON_CREATE_PRINTER_DISCOVERY_SESSION = 1;
+ public static final int MSG_ON_PRINTJOB_QUEUED = 2;
public static final int MSG_ON_REQUEST_CANCEL_PRINTJOB = 3;
- public static final int MSG_ON_REQUEST_UPDATE_PRINTERS = 4;
- public static final int MSG_ON_PRINTJOB_QUEUED = 5;
- public static final int MSG_SET_CLEINT = 6;
+ public static final int MSG_SET_CLEINT = 4;
- public MyHandler(Looper looper) {
+ public ServiceHandler(Looper looper) {
super(looper, null, true);
}
@Override
- @SuppressWarnings("unchecked")
public void handleMessage(Message message) {
final int action = message.what;
switch (action) {
- case MSG_ON_START_PRINTER_DISCOVERY: {
- synchronized (mLock) {
- mDiscoveryObserver = (IPrinterDiscoveryObserver) message.obj;
+ case MSG_ON_CREATE_PRINTER_DISCOVERY_SESSION: {
+ IPrinterDiscoverySessionObserver observer =
+ (IPrinterDiscoverySessionObserver) message.obj;
+ PrinterDiscoverySession session = onCreatePrinterDiscoverySession();
+ if (session == null) {
+ throw new NullPointerException("session cannot be null");
}
- onStartPrinterDiscovery();
- } break;
-
- case MSG_ON_STOP_PRINTER_DISCOVERY: {
synchronized (mLock) {
- mDiscoveryObserver = null;
+ if (session.getId() == mLastSessionId) {
+ throw new IllegalStateException("cannot reuse sessions");
+ }
+ mLastSessionId = session.getId();
}
- onStopPrinterDiscovery();
+ session.setObserver(observer);
} break;
case MSG_ON_REQUEST_CANCEL_PRINTJOB: {
@@ -513,11 +346,6 @@ public abstract class PrintService extends Service {
onRequestCancelPrintJob(new PrintJob(printJobInfo, mClient));
} break;
- case MSG_ON_REQUEST_UPDATE_PRINTERS: {
- List<PrinterId> printerIds = (List<PrinterId>) message.obj;
- onRequestUpdatePrinters(printerIds);
- } break;
-
case MSG_ON_PRINTJOB_QUEUED: {
PrintJobInfo printJobInfo = (PrintJobInfo) message.obj;
onPrintJobQueued(new PrintJob(printJobInfo, mClient));
@@ -527,9 +355,6 @@ public abstract class PrintService extends Service {
IPrintServiceClient client = (IPrintServiceClient) message.obj;
synchronized (mLock) {
mClient = client;
- if (client == null) {
- mDiscoveryObserver = null;
- }
}
if (client != null) {
onConnected();
diff --git a/core/java/android/printservice/PrinterDiscoverySession.java b/core/java/android/printservice/PrinterDiscoverySession.java
new file mode 100644
index 000000000000..5bc0f2e328a3
--- /dev/null
+++ b/core/java/android/printservice/PrinterDiscoverySession.java
@@ -0,0 +1,357 @@
+/*
+ * 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 android.printservice;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.print.IPrinterDiscoverySessionController;
+import android.print.IPrinterDiscoverySessionObserver;
+import android.print.PrinterId;
+import android.print.PrinterInfo;
+import android.util.Log;
+
+import java.lang.ref.WeakReference;
+import java.util.List;
+
+/**
+ * This class encapsulates the interaction between a print service and the
+ * system during printer discovery. During printer discovery you are responsible
+ * for adding discovered printers, removing already added printers that
+ * disappeared, and updating already added printers.
+ * <p>
+ * The opening of the session is announced by a call to {@link
+ * PrinterDiscoverySession#onOpen(List)} at which point you should start printer
+ * discovery. The closing of the session is announced by a call to {@link
+ * PrinterDiscoverySession#onClose()} at which point you should stop printer
+ * discovery. Discovered printers are added by invoking {@link
+ * PrinterDiscoverySession#addPrinters(List)}. Added printers that disappeared
+ * are removed by invoking {@link PrinterDiscoverySession#removePrinters(List)}.
+ * Added printers whose properties or capabilities changed are updated through
+ * a call to {@link PrinterDiscoverySession#updatePrinters(List)}.
+ * </p>
+ * <p>
+ * The system will make a call to
+ * {@link PrinterDiscoverySession#onRequestPrinterUpdate(PrinterId)} if you
+ * need to update a given printer. It is possible that you add a printer without
+ * specifying its capabilities. This enables you to avoid querying all
+ * discovered printers for their capabilities, rather querying the capabilities
+ * of a printer only if necessary. For example, the system will require that you
+ * update a printer if it gets selected by the user. If you did not report the
+ * printer capabilities when adding it, you must do so after the system requests
+ * a printer update. Otherwise, the printer will be ignored.
+ * </p>
+ * <p>
+ * During printer discovery all printers that are known to your print service
+ * have to be added. The system does not retain any printers from previous
+ * sessions.
+ * </p>
+ */
+public abstract class PrinterDiscoverySession {
+ private static final String LOG_TAG = "PrinterDiscoverySession";
+
+ private static int sIdCounter = 0;
+
+ private final Object mLock = new Object();
+
+ private final Handler mHandler;
+
+ private final int mId;
+
+ private IPrinterDiscoverySessionController mController;
+
+ private IPrinterDiscoverySessionObserver mObserver;
+
+ /**
+ * Constructor.
+ *
+ * @param context A context instance.
+ */
+ public PrinterDiscoverySession(Context context) {
+ mId = sIdCounter++;
+ mHandler = new SessionHandler(context.getMainLooper());
+ mController = new PrinterDiscoverySessionController(this);
+ }
+
+ void setObserver(IPrinterDiscoverySessionObserver observer) {
+ synchronized (mLock) {
+ mObserver = observer;
+ try {
+ mObserver.setController(mController);
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error setting session controller", re);
+ }
+ }
+ }
+
+ int getId() {
+ return mId;
+ }
+
+ /**
+ * Adds discovered printers. Adding an already added printer has no effect.
+ * Removed printers can be added again. You can call this method multiple
+ * times during printer discovery.
+ * <p>
+ * <strong>Note: </strong> Calling this method when the session is closed,
+ * which is if {@link #isClosed()} returns true, will throw an {@link
+ * IllegalStateException}.
+ * </p>
+ *
+ * @param printers The printers to add.
+ *
+ * @see #removePrinters(List)
+ * @see #updatePrinters(List)
+ * @see #isClosed()
+ */
+ public final void addPrinters(List<PrinterInfo> printers) {
+ final IPrinterDiscoverySessionObserver observer;
+ synchronized (mLock) {
+ throwIfClosedLocked();
+ observer = mObserver;
+ }
+ if (observer != null) {
+ try {
+ observer.onPrintersAdded(printers);
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error adding printers", re);
+ }
+ }
+ }
+
+ /**
+ * Removes added printers. Removing an already removed or never added
+ * printer has no effect. Removed printers can be added again. You
+ * can call this method multiple times during printer discovery.
+ * <p>
+ * <strong>Note: </strong> Calling this method when the session is closed,
+ * which is if {@link #isClosed()} returns true, will throw an {@link
+ * IllegalStateException}.
+ * </p>
+ *
+ * @param printerIds The ids of the removed printers.
+ *
+ * @see #addPrinters(List)
+ * @see #updatePrinters(List)
+ * @see #isClosed()
+ */
+ public final void removePrinters(List<PrinterId> printerIds) {
+ final IPrinterDiscoverySessionObserver observer;
+ synchronized (mLock) {
+ throwIfClosedLocked();
+ observer = mObserver;
+ }
+ if (observer != null) {
+ try {
+ observer.onPrintersRemoved(printerIds);
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error removing printers", re);
+ }
+ }
+ }
+
+ /**
+ * Updates added printers. Updating a printer that was not added or that
+ * was removed has no effect. You can call this method multiple times
+ * during printer discovery.
+ * <p>
+ * <strong>Note: </strong> Calling this method when the session is closed,
+ * which is if {@link #isClosed()} returns true, will throw an {@link
+ * IllegalStateException}.
+ * </p>
+ *
+ * @param printers The printers to update.
+ *
+ * @see #addPrinters(List)
+ * @see #removePrinters(List)
+ * @see #isClosed()
+ */
+ public final void updatePrinters(List<PrinterInfo> printers) {
+ final IPrinterDiscoverySessionObserver observer;
+ synchronized (mLock) {
+ throwIfClosedLocked();
+ observer = mObserver;
+ }
+ if (observer != null) {
+ try {
+ observer.onPrintersUpdated(printers);
+ } catch (RemoteException re) {
+ Log.e(LOG_TAG, "Error updating printers", re);
+ }
+ }
+ }
+
+ /**
+ * Callback notifying you that the session is open and you should start
+ * printer discovery. Discovered printers should be added via calling
+ * {@link #addPrinters(List)}. Added printers that disappeared should be
+ * removed via calling {@link #removePrinters(List)}. Added printers whose
+ * properties or capabilities changes should be updated via calling {@link
+ * #updatePrinters(List)}. When the session is closed you will receive a
+ * call to {@link #onClose()}.
+ * <p>
+ * During printer discovery all printers that are known to your print
+ * service have to be added. The system does not retain any printers from
+ * previous sessions.
+ * </p>
+ * <p>
+ * <strong>Note: </strong>You are also given a list of printers whose
+ * availability has to be checked first. For example, these printers could
+ * be the user's favorite ones, therefore they have to be verified first.
+ * </p>
+ *
+ * @see #onClose()
+ * @see #isClosed()
+ * @see #addPrinters(List)
+ * @see #removePrinters(List)
+ * @see #updatePrinters(List)
+ */
+ public abstract void onOpen(List<PrinterId> priorityList);
+
+ /**
+ * Callback notifying you that the session is closed and you should stop
+ * printer discovery. After the session is closed and any attempt to call
+ * any of its methods will throw an exception. Whether a session is closed
+ * can be checked by calling {@link #isClosed()}. Once the session is closed
+ * it will never be opened again.
+ *
+ * @see #onOpen(List)
+ * @see #isClosed()
+ * @see #addPrinters(List)
+ * @see #removePrinters(List)
+ * @see #updatePrinters(List)
+ */
+ public abstract void onClose();
+
+ /**
+ * Requests that you update a printer. You are responsible for updating
+ * the printer by also reporting its capabilities via calling {@link
+ * #updatePrinters(List)}.
+ * <p>
+ * <strong>Note: </strong> A printer can be initially added without its
+ * capabilities to avoid polling printers that the user will not select.
+ * However, after this method is called you are expected to update the
+ * printer <strong>including</strong> its capabilities. Otherwise, the
+ * printer will be ignored.
+ * <p>
+ * A scenario when you may be requested to update a printer is if the user
+ * selects it and the system has to present print options UI based on the
+ * printer's capabilities.
+ * </p>
+ *
+ * @param printerId The printer id.
+ *
+ * @see #updatePrinters(List)
+ * @see PrinterInfo.Builder#setCapabilities(PrinterCapabilitiesInfo)
+ * PrinterInfo.Builder.setCapabilities(PrinterCapabilitiesInfo)
+ */
+ public abstract void onRequestPrinterUpdate(PrinterId printerId);
+
+ /**
+ * Gets whether this session is closed.
+ *
+ * @return Whether the session is closed.
+ */
+ public final boolean isClosed() {
+ synchronized (mLock) {
+ return (mController == null && mObserver == null);
+ }
+ }
+
+ void close() {
+ synchronized (mLock) {
+ throwIfClosedLocked();
+ mController = null;
+ mObserver = null;
+ }
+ }
+
+ private void throwIfClosedLocked() {
+ if (isClosed()) {
+ throw new IllegalStateException("Session is closed");
+ }
+ }
+
+ private final class SessionHandler extends Handler {
+ public static final int MSG_OPEN = 1;
+ public static final int MSG_CLOSE = 2;
+ public static final int MSG_REQUEST_PRINTER_UPDATE = 3;
+
+ public SessionHandler(Looper looper) {
+ super(looper, null, true);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public void handleMessage(Message message) {
+ switch (message.what) {
+ case MSG_OPEN: {
+ List<PrinterId> priorityList = (List<PrinterId>) message.obj;
+ onOpen(priorityList);
+ } break;
+
+ case MSG_CLOSE: {
+ onClose();
+ close();
+ } break;
+
+ case MSG_REQUEST_PRINTER_UPDATE: {
+ PrinterId printerId = (PrinterId) message.obj;
+ onRequestPrinterUpdate(printerId);
+ } break;
+ }
+ }
+ }
+
+ private static final class PrinterDiscoverySessionController extends
+ IPrinterDiscoverySessionController.Stub {
+ private final WeakReference<PrinterDiscoverySession> mWeakSession;
+
+ public PrinterDiscoverySessionController(PrinterDiscoverySession session) {
+ mWeakSession = new WeakReference<PrinterDiscoverySession>(session);
+ }
+
+ @Override
+ public void open(List<PrinterId> priorityList) {
+ PrinterDiscoverySession session = mWeakSession.get();
+ if (session != null) {
+ session.mHandler.obtainMessage(SessionHandler.MSG_OPEN,
+ priorityList).sendToTarget();
+ }
+ }
+
+ @Override
+ public void close() {
+ PrinterDiscoverySession session = mWeakSession.get();
+ if (session != null) {
+ session.mHandler.sendEmptyMessage(SessionHandler.MSG_CLOSE);
+ }
+ }
+
+ @Override
+ public void requestPrinterUpdate(PrinterId printerId) {
+ PrinterDiscoverySession session = mWeakSession.get();
+ if (session != null) {
+ session.mHandler.obtainMessage(
+ SessionHandler.MSG_REQUEST_PRINTER_UPDATE,
+ printerId).sendToTarget();
+ }
+ }
+ };
+}
diff --git a/core/java/android/printservice/package.html b/core/java/android/printservice/package.html
new file mode 100644
index 000000000000..6b0327cc1ae3
--- /dev/null
+++ b/core/java/android/printservice/package.html
@@ -0,0 +1,24 @@
+<HTML>
+<BODY>
+<p>
+Provides classes for implementing print services. Print services are plug-in components
+that know how to talk to printers via some standard protocols. These services serve as a
+bridge between the system and the printers. Hence, the printer and print protocol specific
+implementation is factored out of the system and can by independently developed and updated.
+</p>
+<p>
+A print service implementation should extend {@link android.printservice.PrintService}
+and implement its abstract methods. Also the print service has to follow the contract for
+managing print {@link android.printservice.PrintJob}s to ensure correct interaction with
+the system and consistent user experience.
+<p/>
+<p>
+The system is responsible for starting and stopping a print service depending on whether
+there are active print jobs for the printers managed by the service. The print service
+should also perform printer discovery in a timely fashion to ensure good user experience.
+The interaction between the system and the print service during printer discovery is
+encapsulated by a {@link android.printservice.PrinterDiscoverySession} instance created
+by the print service when requested by the system.
+</p>
+</BODY>
+</HTML>
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 4865fd0df3bd..585115a2c936 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -644,6 +644,23 @@ public final class Settings {
"android.settings.NFCSHARING_SETTINGS";
/**
+ * Activity Action: Show NFC Tap & Pay settings
+ * <p>
+ * This shows UI that allows the user to configure Tap&Pay
+ * settings.
+ * <p>
+ * In some cases, a matching Activity may not exist, so ensure you
+ * safeguard against this.
+ * <p>
+ * Input: Nothing.
+ * <p>
+ * Output: Nothing
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_NFC_PAYMENT_SETTINGS =
+ "android.settings.NFC_PAYMENT_SETTINGS";
+
+ /**
* Activity Action: Show Daydream settings.
* <p>
* In some cases, a matching Activity may not exist, so ensure you
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 20938f512733..7a8289276ea4 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -12062,7 +12062,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
- * Resolve padding depending on layout direction.
+ * Resolves padding depending on layout direction, if applicable, and
+ * recomputes internal padding values to adjust for scroll bars.
*
* @hide
*/
@@ -12102,11 +12103,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
- internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight,
- mUserPaddingBottom);
onRtlPropertiesChanged(resolvedLayoutDirection);
}
+ internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
+
mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
}
@@ -14012,10 +14013,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
if (more && hardwareAccelerated) {
- // invalidation is the trigger to recreate display lists, so if we're using
- // display lists to render, force an invalidate to allow the animation to
- // continue drawing another frame
- parent.invalidate(true);
if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
// alpha animations should cause the child to recreate its display list
invalidate(true);
@@ -14659,13 +14656,26 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @hide
*/
protected void resolveDrawables() {
- if (canResolveLayoutDirection()) {
- if (mBackground != null) {
- mBackground.setLayoutDirection(getLayoutDirection());
- }
- mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
- onResolveDrawables(getLayoutDirection());
+ // Drawables resolution may need to happen before resolving the layout direction (which is
+ // done only during the measure() call).
+ // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
+ // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
+ // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
+ // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
+ // direction to be resolved as its resolved value will be the same as its raw value.
+ if (!isLayoutDirectionResolved() &&
+ getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
+ return;
+ }
+
+ final int layoutDirection = isLayoutDirectionResolved() ?
+ getLayoutDirection() : getRawLayoutDirection();
+
+ if (mBackground != null) {
+ mBackground.setLayoutDirection(layoutDirection);
}
+ mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
+ onResolveDrawables(layoutDirection);
}
/**
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 1f7ff9b7abf9..3977a33f3197 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -608,6 +608,11 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ /** Whether the window is in local focus mode or not */
+ private boolean isInLocalFocusMode() {
+ return (mWindowAttributes.flags & WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE) != 0;
+ }
+
void destroyHardwareResources() {
if (mAttachInfo.mHardwareRenderer != null) {
if (mAttachInfo.mHardwareRenderer.isEnabled()) {
@@ -1818,7 +1823,7 @@ public final class ViewRootImpl implements ViewParent,
mNewSurfaceNeeded = false;
mViewVisibility = viewVisibility;
- if (mAttachInfo.mHasWindowFocus) {
+ if (mAttachInfo.mHasWindowFocus && !isInLocalFocusMode()) {
final boolean imTarget = WindowManager.LayoutParams
.mayUseInputMethod(mWindowAttributes.flags);
if (imTarget != mLastWasImTarget) {
@@ -2906,7 +2911,7 @@ public final class ViewRootImpl implements ViewParent,
private final static int MSG_RESIZED = 4;
private final static int MSG_RESIZED_REPORT = 5;
private final static int MSG_WINDOW_FOCUS_CHANGED = 6;
- private final static int MSG_DISPATCH_KEY = 7;
+ private final static int MSG_DISPATCH_INPUT_EVENT = 7;
private final static int MSG_DISPATCH_APP_VISIBILITY = 8;
private final static int MSG_DISPATCH_GET_NEW_SURFACE = 9;
private final static int MSG_DISPATCH_KEY_FROM_IME = 11;
@@ -2941,8 +2946,8 @@ public final class ViewRootImpl implements ViewParent,
return "MSG_RESIZED_REPORT";
case MSG_WINDOW_FOCUS_CHANGED:
return "MSG_WINDOW_FOCUS_CHANGED";
- case MSG_DISPATCH_KEY:
- return "MSG_DISPATCH_KEY";
+ case MSG_DISPATCH_INPUT_EVENT:
+ return "MSG_DISPATCH_INPUT_EVENT";
case MSG_DISPATCH_APP_VISIBILITY:
return "MSG_DISPATCH_APP_VISIBILITY";
case MSG_DISPATCH_GET_NEW_SURFACE:
@@ -3092,7 +3097,8 @@ public final class ViewRootImpl implements ViewParent,
InputMethodManager imm = InputMethodManager.peekInstance();
if (mView != null) {
- if (hasWindowFocus && imm != null && mLastWasImTarget) {
+ if (hasWindowFocus && imm != null && mLastWasImTarget &&
+ !isInLocalFocusMode()) {
imm.startGettingWindowFocus(mView);
}
mAttachInfo.mKeyDispatchState.reset();
@@ -3103,7 +3109,7 @@ public final class ViewRootImpl implements ViewParent,
// Note: must be done after the focus change callbacks,
// so all of the view state is set up correctly.
if (hasWindowFocus) {
- if (imm != null && mLastWasImTarget) {
+ if (imm != null && mLastWasImTarget && !isInLocalFocusMode()) {
imm.onWindowFocus(mView, mView.findFocus(),
mWindowAttributes.softInputMode,
!mHasHadWindowFocus, mWindowAttributes.flags);
@@ -3131,8 +3137,8 @@ public final class ViewRootImpl implements ViewParent,
case MSG_DIE:
doDie();
break;
- case MSG_DISPATCH_KEY: {
- KeyEvent event = (KeyEvent)msg.obj;
+ case MSG_DISPATCH_INPUT_EVENT: {
+ InputEvent event = (InputEvent)msg.obj;
enqueueInputEvent(event, null, 0, true);
} break;
case MSG_DISPATCH_KEY_FROM_IME: {
@@ -3222,7 +3228,9 @@ public final class ViewRootImpl implements ViewParent,
// tell the window manager
try {
- mWindowSession.setInTouchMode(inTouchMode);
+ if (!isInLocalFocusMode()) {
+ mWindowSession.setInTouchMode(inTouchMode);
+ }
} catch (RemoteException e) {
throw new RuntimeException(e);
}
@@ -3624,7 +3632,7 @@ public final class ViewRootImpl implements ViewParent,
@Override
protected int onProcess(QueuedInputEvent q) {
- if (mLastWasImTarget) {
+ if (mLastWasImTarget && !isInLocalFocusMode()) {
InputMethodManager imm = InputMethodManager.peekInstance();
if (imm != null) {
final InputEvent event = q.mEvent;
@@ -5666,8 +5674,8 @@ public final class ViewRootImpl implements ViewParent,
mInvalidateOnAnimationRunnable.removeView(view);
}
- public void dispatchKey(KeyEvent event) {
- Message msg = mHandler.obtainMessage(MSG_DISPATCH_KEY, event);
+ public void dispatchInputEvent(InputEvent event) {
+ Message msg = mHandler.obtainMessage(MSG_DISPATCH_INPUT_EVENT, event);
msg.setAsynchronous(true);
mHandler.sendMessage(msg);
}
@@ -5697,7 +5705,7 @@ public final class ViewRootImpl implements ViewParent,
flags, event.getSource(), null);
fallbackAction.recycle();
- dispatchKey(fallbackEvent);
+ dispatchInputEvent(fallbackEvent);
}
}
}
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 39d48a7d8de3..7a2424371724 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1290,4 +1290,18 @@ public abstract class Window {
* @hide
*/
public void setDefaultLogo(int resId) { }
+
+ /**
+ * Set focus locally. The window should have the
+ * {@link WindowManager.LayoutParams#FLAG_LOCAL_FOCUS_MODE} flag set already.
+ * @param hasFocus Whether this window has focus or not.
+ * @param inTouchMode Whether this window is in touch mode or not.
+ */
+ public void setLocalFocus(boolean hasFocus, boolean inTouchMode) { }
+
+ /**
+ * Inject an event to window locally.
+ * @param event A key or touch event to inject to this window.
+ */
+ public void injectInputEvent(InputEvent event) { }
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 83a58be04e4b..c9c74e7603e0 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -866,6 +866,15 @@ public interface WindowManager extends ViewManager {
*/
public static final int FLAG_NEEDS_MENU_KEY = 0x08000000;
+ /**
+ * Flag for a window in local focus mode.
+ * Window in local focus mode can control focus independent of window manager using
+ * {@link Window#setLocalFocus(boolean, boolean)}.
+ * Usually window in this mode will not get touch/key events from window manager, but will
+ * get events only via local injection using {@link Window#injectInputEvent(InputEvent)}.
+ */
+ public static final int FLAG_LOCAL_FOCUS_MODE = 0x10000000;
+
/** Window flag: special flag to limit the size of the window to be
* original size ([320x480] x density). Used to create window for applications
* running under compatibility mode.
@@ -905,6 +914,7 @@ public interface WindowManager extends ViewManager {
* @see #FLAG_DISMISS_KEYGUARD
* @see #FLAG_SPLIT_TOUCH
* @see #FLAG_HARDWARE_ACCELERATED
+ * @see #FLAG_LOCAL_FOCUS_MODE
*/
@ViewDebug.ExportedProperty(flagMapping = {
@ViewDebug.FlagToString(mask = FLAG_ALLOW_LOCK_WHILE_SCREEN_ON, equals = FLAG_ALLOW_LOCK_WHILE_SCREEN_ON,
@@ -956,7 +966,9 @@ public interface WindowManager extends ViewManager {
@ViewDebug.FlagToString(mask = FLAG_SPLIT_TOUCH, equals = FLAG_SPLIT_TOUCH,
name = "FLAG_SPLIT_TOUCH"),
@ViewDebug.FlagToString(mask = FLAG_HARDWARE_ACCELERATED, equals = FLAG_HARDWARE_ACCELERATED,
- name = "FLAG_HARDWARE_ACCELERATED")
+ name = "FLAG_HARDWARE_ACCELERATED"),
+ @ViewDebug.FlagToString(mask = FLAG_LOCAL_FOCUS_MODE, equals = FLAG_LOCAL_FOCUS_MODE,
+ name = "FLAG_LOCAL_FOCUS_MODE")
})
public int flags;
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 3f391ad89f87..0ed846bd71bd 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -1243,6 +1243,12 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
mFastScroller = new FastScroller(this);
mFastScroller.setEnabled(true);
}
+
+ recomputePadding();
+
+ if (mFastScroller != null) {
+ mFastScroller.updateLayout();
+ }
}
/**
@@ -1303,7 +1309,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
@Override
public int getVerticalScrollbarWidth() {
- if (isFastScrollAlwaysVisible() && mFastScroller != null) {
+ if (mFastScroller != null && mFastScroller.isEnabled()) {
return Math.max(super.getVerticalScrollbarWidth(), mFastScroller.getWidth());
}
return super.getVerticalScrollbarWidth();
@@ -1327,6 +1333,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
}
+ @Override
+ public void setScrollBarStyle(int style) {
+ super.setScrollBarStyle(style);
+ if (mFastScroller != null) {
+ mFastScroller.setScrollBarStyle(style);
+ }
+ }
+
/**
* If fast scroll is enabled, then don't draw the vertical scrollbar.
* @hide
@@ -2787,7 +2801,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
@Override
public void onRtlPropertiesChanged(int layoutDirection) {
super.onRtlPropertiesChanged(layoutDirection);
-
if (mFastScroller != null) {
mFastScroller.setScrollbarPosition(getVerticalScrollbarPosition());
}
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index 393720fc743c..c48955f625b0 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -131,6 +131,9 @@ class FastScroller {
/** Whether there is a track image to display. */
private final boolean mHasTrackImage;
+ /** Total width of decorations. */
+ private final int mWidth;
+
/** Set containing decoration transition animations. */
private AnimatorSet mDecorAnimation;
@@ -155,6 +158,9 @@ class FastScroller {
/** The index of the current section. */
private int mCurrentSection = -1;
+ /** The current scrollbar position. */
+ private int mScrollbarPosition = -1;
+
/** Whether the list is long enough to need a fast scroller. */
private boolean mLongList;
@@ -194,6 +200,9 @@ class FastScroller {
*/
private int mOverlayPosition;
+ /** Current scrollbar style, including inset and overlay properties. */
+ private int mScrollBarStyle;
+
/** Whether to precisely match the thumb position to the list. */
private boolean mMatchDragPosition;
@@ -245,34 +254,44 @@ class FastScroller {
final Resources res = context.getResources();
final TypedArray ta = context.getTheme().obtainStyledAttributes(ATTRS);
- mTrackImage = new ImageView(context);
+ final ImageView trackImage = new ImageView(context);
+ mTrackImage = trackImage;
+
+ int width = 0;
// Add track to overlay if it has an image.
- final int trackResId = ta.getResourceId(TRACK_DRAWABLE, 0);
- if (trackResId != 0) {
+ final Drawable trackDrawable = ta.getDrawable(TRACK_DRAWABLE);
+ if (trackDrawable != null) {
mHasTrackImage = true;
- mTrackImage.setBackgroundResource(trackResId);
- mOverlay.add(mTrackImage);
+ trackImage.setBackground(trackDrawable);
+ mOverlay.add(trackImage);
+ width = Math.max(width, trackDrawable.getIntrinsicWidth());
} else {
mHasTrackImage = false;
}
- mThumbImage = new ImageView(context);
+ final ImageView thumbImage = new ImageView(context);
+ mThumbImage = thumbImage;
// Add thumb to overlay if it has an image.
final Drawable thumbDrawable = ta.getDrawable(THUMB_DRAWABLE);
if (thumbDrawable != null) {
- mThumbImage.setImageDrawable(thumbDrawable);
- mOverlay.add(mThumbImage);
+ thumbImage.setImageDrawable(thumbDrawable);
+ mOverlay.add(thumbImage);
+ width = Math.max(width, thumbDrawable.getIntrinsicWidth());
}
// If necessary, apply minimum thumb width and height.
if (thumbDrawable.getIntrinsicWidth() <= 0 || thumbDrawable.getIntrinsicHeight() <= 0) {
- mThumbImage.setMinimumWidth(res.getDimensionPixelSize(R.dimen.fastscroll_thumb_width));
- mThumbImage.setMinimumHeight(
+ final int minWidth = res.getDimensionPixelSize(R.dimen.fastscroll_thumb_width);
+ thumbImage.setMinimumWidth(minWidth);
+ thumbImage.setMinimumHeight(
res.getDimensionPixelSize(R.dimen.fastscroll_thumb_height));
+ width = Math.max(width, minWidth);
}
+ mWidth = width;
+
final int previewSize = res.getDimensionPixelSize(R.dimen.fastscroll_overlay_size);
mPreviewImage = new ImageView(context);
mPreviewImage.setMinimumWidth(previewSize);
@@ -297,10 +316,11 @@ class FastScroller {
mOverlayPosition = ta.getInt(OVERLAY_POSITION, OVERLAY_FLOATING);
ta.recycle();
+ mScrollBarStyle = listView.getScrollBarStyle();
mScrollCompleted = true;
mState = STATE_VISIBLE;
- mMatchDragPosition =
- context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB;
+ mMatchDragPosition = context.getApplicationInfo().targetSdkVersion
+ >= Build.VERSION_CODES.HONEYCOMB;
getSectionsFromIndexer();
refreshDrawablePressedState();
@@ -362,6 +382,14 @@ class FastScroller {
return mAlwaysShow;
}
+ public void setScrollBarStyle(int style) {
+ if (mScrollBarStyle != style) {
+ mScrollBarStyle = style;
+
+ updateLayout();
+ }
+ }
+
/**
* Immediately transitions the fast scroller decorations to a hidden state.
*/
@@ -375,25 +403,29 @@ class FastScroller {
View.SCROLLBAR_POSITION_LEFT : View.SCROLLBAR_POSITION_RIGHT;
}
- mLayoutFromRight = position != View.SCROLLBAR_POSITION_LEFT;
+ if (mScrollbarPosition != position) {
+ mScrollbarPosition = position;
+ mLayoutFromRight = position != View.SCROLLBAR_POSITION_LEFT;
- final int previewResId = mPreviewResId[mLayoutFromRight ? PREVIEW_RIGHT : PREVIEW_LEFT];
- mPreviewImage.setBackgroundResource(previewResId);
+ final int previewResId = mPreviewResId[mLayoutFromRight ? PREVIEW_RIGHT : PREVIEW_LEFT];
+ mPreviewImage.setBackgroundResource(previewResId);
- // Add extra padding for text.
- final Drawable background = mPreviewImage.getBackground();
- if (background != null) {
- final Rect padding = mTempBounds;
- background.getPadding(padding);
- padding.offset(mPreviewPadding, mPreviewPadding);
- mPreviewImage.setPadding(padding.left, padding.top, padding.right, padding.bottom);
- }
+ // Add extra padding for text.
+ final Drawable background = mPreviewImage.getBackground();
+ if (background != null) {
+ final Rect padding = mTempBounds;
+ background.getPadding(padding);
+ padding.offset(mPreviewPadding, mPreviewPadding);
+ mPreviewImage.setPadding(padding.left, padding.top, padding.right, padding.bottom);
+ }
- updateLayout();
+ // Requires re-layout.
+ updateLayout();
+ }
}
public int getWidth() {
- return mThumbImage.getWidth();
+ return mWidth;
}
public void onSizeChanged(int w, int h, int oldw, int oldh) {
@@ -437,7 +469,7 @@ class FastScroller {
/**
* Measures and layouts the scrollbar and decorations.
*/
- private void updateLayout() {
+ public void updateLayout() {
// Prevent re-entry when RTL properties change as a side-effect of
// resolving padding.
if (mUpdatingLayout) {
@@ -594,21 +626,36 @@ class FastScroller {
out.set(left, top, right, bottom);
}
+ /**
+ * Updates the container rectangle used for layout.
+ */
private void updateContainerRect() {
final AbsListView list = mList;
+ list.resolvePadding();
+
final Rect container = mContainerRect;
container.left = 0;
container.top = 0;
container.right = list.getWidth();
container.bottom = list.getHeight();
- final int scrollbarStyle = list.getScrollBarStyle();
+ final int scrollbarStyle = mScrollBarStyle;
if (scrollbarStyle == View.SCROLLBARS_INSIDE_INSET
|| scrollbarStyle == View.SCROLLBARS_INSIDE_OVERLAY) {
container.left += list.getPaddingLeft();
container.top += list.getPaddingTop();
container.right -= list.getPaddingRight();
container.bottom -= list.getPaddingBottom();
+
+ // In inset mode, we need to adjust for padded scrollbar width.
+ if (scrollbarStyle == View.SCROLLBARS_INSIDE_INSET) {
+ final int width = getWidth();
+ if (mScrollbarPosition == View.SCROLLBAR_POSITION_RIGHT) {
+ container.right += width;
+ } else {
+ container.left -= width;
+ }
+ }
}
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 3181164e3528..9c21f0d821e9 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -1378,6 +1378,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
} else {
dr.mDrawableSizeEnd = dr.mDrawableHeightEnd = 0;
}
+ resetResolvedDrawables();
+ resolveDrawables();
}
}
diff --git a/core/java/android/widget/ZoomButtonsController.java b/core/java/android/widget/ZoomButtonsController.java
index a89c9c14244b..50c803bdcc5f 100644
--- a/core/java/android/widget/ZoomButtonsController.java
+++ b/core/java/android/widget/ZoomButtonsController.java
@@ -503,7 +503,7 @@ public class ZoomButtonsController implements View.OnTouchListener {
ViewRootImpl viewRoot = mOwnerView.getViewRootImpl();
if (viewRoot != null) {
- viewRoot.dispatchKey(event);
+ viewRoot.dispatchInputEvent(event);
}
// We gave the key to the owner, don't let the container handle this key
diff --git a/core/java/com/android/internal/app/IProcessStats.aidl b/core/java/com/android/internal/app/IProcessStats.aidl
index e4c8bd20dde6..047424d54eb8 100644
--- a/core/java/com/android/internal/app/IProcessStats.aidl
+++ b/core/java/com/android/internal/app/IProcessStats.aidl
@@ -22,4 +22,5 @@ import com.android.internal.app.ProcessStats;
interface IProcessStats {
byte[] getCurrentStats(out List<ParcelFileDescriptor> historic);
+ int getCurrentMemoryState();
}
diff --git a/core/java/com/android/internal/app/ProcessStats.java b/core/java/com/android/internal/app/ProcessStats.java
index 39c23cf5a0cc..ac9bf16655dc 100644
--- a/core/java/com/android/internal/app/ProcessStats.java
+++ b/core/java/com/android/internal/app/ProcessStats.java
@@ -31,6 +31,8 @@ import android.webkit.WebViewFactory;
import com.android.internal.util.ArrayUtils;
import dalvik.system.VMRuntime;
+import java.io.IOException;
+import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
@@ -212,6 +214,80 @@ public final class ProcessStats implements Parcelable {
readFromParcel(in);
}
+ public void add(ProcessStats other) {
+ ArrayMap<String, SparseArray<PackageState>> pkgMap = other.mPackages.getMap();
+ for (int ip=0; ip<pkgMap.size(); ip++) {
+ String pkgName = pkgMap.keyAt(ip);
+ SparseArray<PackageState> uids = pkgMap.valueAt(ip);
+ for (int iu=0; iu<uids.size(); iu++) {
+ int uid = uids.keyAt(iu);
+ PackageState otherState = uids.valueAt(iu);
+ final int NPROCS = otherState.mProcesses.size();
+ final int NSRVS = otherState.mServices.size();
+ for (int iproc=0; iproc<NPROCS; iproc++) {
+ ProcessState otherProc = otherState.mProcesses.valueAt(iproc);
+ if (otherProc.mCommonProcess != otherProc) {
+ if (DEBUG) Slog.d(TAG, "Adding pkg " + pkgName + " uid " + uid
+ + " proc " + otherProc.mName);
+ ProcessState thisProc = getProcessStateLocked(pkgName, uid,
+ otherProc.mName);
+ if (thisProc.mCommonProcess == thisProc) {
+ if (DEBUG) Slog.d(TAG, "Existing process is single-package, splitting");
+ thisProc.mMultiPackage = true;
+ long now = SystemClock.uptimeMillis();
+ final PackageState pkgState = getPackageStateLocked(pkgName, uid);
+ thisProc = thisProc.clone(thisProc.mPackage, now);
+ pkgState.mProcesses.put(thisProc.mName, thisProc);
+ }
+ thisProc.add(otherProc);
+ }
+ }
+ for (int isvc=0; isvc<NSRVS; isvc++) {
+ ServiceState otherSvc = otherState.mServices.valueAt(isvc);
+ if (DEBUG) Slog.d(TAG, "Adding pkg " + pkgName + " uid " + uid
+ + " service " + otherSvc.mName);
+ ServiceState thisSvc = getServiceStateLocked(pkgName, uid,
+ null, otherSvc.mName);
+ thisSvc.add(otherSvc);
+ }
+ }
+ }
+
+ ArrayMap<String, SparseArray<ProcessState>> procMap = other.mProcesses.getMap();
+ for (int ip=0; ip<procMap.size(); ip++) {
+ SparseArray<ProcessState> uids = procMap.valueAt(ip);
+ for (int iu=0; iu<uids.size(); iu++) {
+ int uid = uids.keyAt(iu);
+ ProcessState otherProc = uids.valueAt(iu);
+ ProcessState thisProc = mProcesses.get(otherProc.mName, uid);
+ if (DEBUG) Slog.d(TAG, "Adding uid " + uid + " proc " + otherProc.mName);
+ if (thisProc == null) {
+ if (DEBUG) Slog.d(TAG, "Creating new process!");
+ thisProc = new ProcessState(this, otherProc.mPackage, uid, otherProc.mName);
+ mProcesses.put(otherProc.mName, uid, thisProc);
+ PackageState thisState = getPackageStateLocked(otherProc.mPackage, uid);
+ if (!thisState.mProcesses.containsKey(otherProc.mName)) {
+ thisState.mProcesses.put(otherProc.mName, thisProc);
+ }
+ }
+ thisProc.add(otherProc);
+ }
+ }
+
+ for (int i=0; i<ADJ_COUNT; i++) {
+ if (DEBUG) Slog.d(TAG, "Total duration #" + i + " inc by "
+ + other.mMemFactorDurations[i] + " from "
+ + mMemFactorDurations[i]);
+ mMemFactorDurations[i] += other.mMemFactorDurations[i];
+ }
+
+ if (other.mTimePeriodStartClock < mTimePeriodStartClock) {
+ mTimePeriodStartClock = other.mTimePeriodStartClock;
+ mTimePeriodStartClockStr = other.mTimePeriodStartClockStr;
+ }
+ mTimePeriodEndRealtime += other.mTimePeriodEndRealtime - other.mTimePeriodStartRealtime;
+ }
+
public static final Parcelable.Creator<ProcessStats> CREATOR
= new Parcelable.Creator<ProcessStats>() {
public ProcessStats createFromParcel(Parcel in) {
@@ -1098,6 +1174,43 @@ public final class ProcessStats implements Parcelable {
return true;
}
+ static byte[] readFully(InputStream stream) throws IOException {
+ int pos = 0;
+ int avail = stream.available();
+ byte[] data = new byte[avail];
+ while (true) {
+ int amt = stream.read(data, pos, data.length-pos);
+ //Log.i("foo", "Read " + amt + " bytes at " + pos
+ // + " of avail " + data.length);
+ if (amt <= 0) {
+ //Log.i("foo", "**** FINISHED READING: pos=" + pos
+ // + " len=" + data.length);
+ return data;
+ }
+ pos += amt;
+ avail = stream.available();
+ if (avail > data.length-pos) {
+ byte[] newData = new byte[pos+avail];
+ System.arraycopy(data, 0, newData, 0, pos);
+ data = newData;
+ }
+ }
+ }
+
+ public void read(InputStream stream) {
+ try {
+ byte[] raw = readFully(stream);
+ Parcel in = Parcel.obtain();
+ in.unmarshall(raw, 0, raw.length);
+ in.setDataPosition(0);
+ stream.close();
+
+ readFromParcel(in);
+ } catch (IOException e) {
+ mReadError = "caught exception: " + e;
+ }
+ }
+
public void readFromParcel(Parcel in) {
final boolean hadData = mPackages.getMap().size() > 0
|| mProcesses.getMap().size() > 0;
@@ -1289,7 +1402,7 @@ public final class ProcessStats implements Parcelable {
}
ServiceState serv = hadData ? pkgState.mServices.get(serviceName) : null;
if (serv == null) {
- serv = new ServiceState(this, pkgName, null);
+ serv = new ServiceState(this, pkgName, serviceName, null);
}
if (!serv.readFromParcel(in)) {
return;
@@ -1437,6 +1550,21 @@ public final class ProcessStats implements Parcelable {
return ps;
}
+ public ProcessStats.ServiceState getServiceStateLocked(String packageName, int uid,
+ String processName, String className) {
+ final ProcessStats.PackageState as = getPackageStateLocked(packageName, uid);
+ ProcessStats.ServiceState ss = as.mServices.get(className);
+ if (ss != null) {
+ ss.makeActive();
+ return ss;
+ }
+ final ProcessStats.ProcessState ps = processName != null
+ ? getProcessStateLocked(packageName, uid, processName) : null;
+ ss = new ProcessStats.ServiceState(this, packageName, className, ps);
+ as.mServices.put(className, ss);
+ return ss;
+ }
+
public void dumpLocked(PrintWriter pw, String reqPackage, long now, boolean dumpAll) {
long totalTime = dumpSingleTime(null, null, mMemFactorDurations, mMemFactor,
mStartTime, now);
@@ -1554,7 +1682,7 @@ public final class ProcessStats implements Parcelable {
}
}
- static long dumpSingleServiceTime(PrintWriter pw, String prefix, ServiceState service,
+ public static long dumpSingleServiceTime(PrintWriter pw, String prefix, ServiceState service,
int serviceType, int curState, long curStartTime, long now) {
long totalTime = 0;
int printedScreen = -1;
@@ -1947,6 +2075,29 @@ public final class ProcessStats implements Parcelable {
return pnew;
}
+ void add(ProcessState other) {
+ for (int i=0; i<other.mDurationsTableSize; i++) {
+ int ent = other.mDurationsTable[i];
+ int state = (ent>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
+ if (DEBUG) Slog.d(TAG, "Adding state " + state + " duration "
+ + other.mStats.getLong(ent, 0));
+ addDuration(state, other.mStats.getLong(ent, 0));
+ }
+ for (int i=0; i<other.mPssTableSize; i++) {
+ int ent = other.mPssTable[i];
+ int state = (ent>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
+ addPss(state, (int) other.mStats.getLong(ent, PSS_SAMPLE_COUNT),
+ other.mStats.getLong(ent, PSS_MINIMUM),
+ other.mStats.getLong(ent, PSS_AVERAGE),
+ other.mStats.getLong(ent, PSS_MAXIMUM),
+ other.mStats.getLong(ent, PSS_USS_MINIMUM),
+ other.mStats.getLong(ent, PSS_USS_AVERAGE),
+ other.mStats.getLong(ent, PSS_USS_MAXIMUM));
+ }
+ mNumExcessiveWake += other.mNumExcessiveWake;
+ mNumExcessiveCpu += other.mNumExcessiveCpu;
+ }
+
void resetSafely(long now) {
mDurationsTable = null;
mDurationsTableSize = 0;
@@ -2043,24 +2194,30 @@ public final class ProcessStats implements Parcelable {
if (mCurState != STATE_NOTHING) {
long dur = now - mStartTime;
if (dur > 0) {
- int idx = binarySearch(mDurationsTable, mDurationsTableSize, mCurState);
- int off;
- if (idx >= 0) {
- off = mDurationsTable[idx];
- } else {
- mStats.mAddLongTable = mDurationsTable;
- mStats.mAddLongTableSize = mDurationsTableSize;
- off = mStats.addLongData(~idx, mCurState, 1);
- mDurationsTable = mStats.mAddLongTable;
- mDurationsTableSize = mStats.mAddLongTableSize;
- }
- long[] longs = mStats.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
- longs[(off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK] += dur;
+ addDuration(mCurState, dur);
}
}
mStartTime = now;
}
+ void addDuration(int state, long dur) {
+ int idx = binarySearch(mDurationsTable, mDurationsTableSize, state);
+ int off;
+ if (idx >= 0) {
+ off = mDurationsTable[idx];
+ } else {
+ mStats.mAddLongTable = mDurationsTable;
+ mStats.mAddLongTableSize = mDurationsTableSize;
+ off = mStats.addLongData(~idx, state, 1);
+ mDurationsTable = mStats.mAddLongTable;
+ mDurationsTableSize = mStats.mAddLongTableSize;
+ }
+ long[] longs = mStats.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
+ if (DEBUG) Slog.d(TAG, "Duration of " + mName + " state " + state + " inc by " + dur
+ + " from " + longs[(off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK]);
+ longs[(off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK] += dur;
+ }
+
void incStartedServices(int memFactor, long now) {
if (mCommonProcess != this) {
mCommonProcess.incStartedServices(memFactor, now);
@@ -2094,46 +2251,53 @@ public final class ProcessStats implements Parcelable {
mLastPssState = mCurState;
mLastPssTime = SystemClock.uptimeMillis();
if (mCurState != STATE_NOTHING) {
- int idx = binarySearch(mPssTable, mPssTableSize, mCurState);
- int off;
- if (idx >= 0) {
- off = mPssTable[idx];
- } else {
- mStats.mAddLongTable = mPssTable;
- mStats.mAddLongTableSize = mPssTableSize;
- off = mStats.addLongData(~idx, mCurState, PSS_COUNT);
- mPssTable = mStats.mAddLongTable;
- mPssTableSize = mStats.mAddLongTableSize;
+ addPss(mCurState, 1, pss, pss, pss, uss, uss, uss);
+ }
+ }
+
+ void addPss(int state, int inCount, long minPss, long avgPss, long maxPss, long minUss,
+ long avgUss, long maxUss) {
+ int idx = binarySearch(mPssTable, mPssTableSize, state);
+ int off;
+ if (idx >= 0) {
+ off = mPssTable[idx];
+ } else {
+ mStats.mAddLongTable = mPssTable;
+ mStats.mAddLongTableSize = mPssTableSize;
+ off = mStats.addLongData(~idx, state, PSS_COUNT);
+ mPssTable = mStats.mAddLongTable;
+ mPssTableSize = mStats.mAddLongTableSize;
+ }
+ long[] longs = mStats.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
+ idx = (off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK;
+ long count = longs[idx+PSS_SAMPLE_COUNT];
+ if (count == 0) {
+ longs[idx+PSS_SAMPLE_COUNT] = inCount;
+ longs[idx+PSS_MINIMUM] = minPss;
+ longs[idx+PSS_AVERAGE] = avgPss;
+ longs[idx+PSS_MAXIMUM] = maxPss;
+ longs[idx+PSS_USS_MINIMUM] = minUss;
+ longs[idx+PSS_USS_AVERAGE] = avgUss;
+ longs[idx+PSS_USS_MAXIMUM] = maxUss;
+ } else {
+ longs[idx+PSS_SAMPLE_COUNT] = count+inCount;
+ if (longs[idx+PSS_MINIMUM] > minPss) {
+ longs[idx+PSS_MINIMUM] = minPss;
}
- long[] longs = mStats.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
- idx = (off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK;
- long count = longs[idx+PSS_SAMPLE_COUNT];
- if (count == 0) {
- longs[idx+PSS_SAMPLE_COUNT] = 1;
- longs[idx+PSS_MINIMUM] = pss;
- longs[idx+PSS_AVERAGE] = pss;
- longs[idx+PSS_MAXIMUM] = pss;
- longs[idx+PSS_USS_MINIMUM] = uss;
- longs[idx+PSS_USS_AVERAGE] = uss;
- longs[idx+PSS_USS_MAXIMUM] = uss;
- } else {
- longs[idx+PSS_SAMPLE_COUNT] = count+1;
- if (longs[idx+PSS_MINIMUM] > pss) {
- longs[idx+PSS_MINIMUM] = pss;
- }
- longs[idx+PSS_AVERAGE] = (long)(
- ((longs[idx+PSS_AVERAGE]*(double)count)+pss) / (count+1) );
- if (longs[idx+PSS_MAXIMUM] < pss) {
- longs[idx+PSS_MAXIMUM] = pss;
- }
- if (longs[idx+PSS_USS_MINIMUM] > uss) {
- longs[idx+PSS_USS_MINIMUM] = uss;
- }
- longs[idx+PSS_USS_AVERAGE] = (long)(
- ((longs[idx+PSS_USS_AVERAGE]*(double)count)+uss) / (count+1) );
- if (longs[idx+PSS_USS_MAXIMUM] < uss) {
- longs[idx+PSS_USS_MAXIMUM] = uss;
- }
+ longs[idx+PSS_AVERAGE] = (long)(
+ ((longs[idx+PSS_AVERAGE]*(double)count)+(avgPss*(double)inCount))
+ / (count+inCount) );
+ if (longs[idx+PSS_MAXIMUM] < maxPss) {
+ longs[idx+PSS_MAXIMUM] = maxPss;
+ }
+ if (longs[idx+PSS_USS_MINIMUM] > minUss) {
+ longs[idx+PSS_USS_MINIMUM] = minUss;
+ }
+ longs[idx+PSS_USS_AVERAGE] = (long)(
+ ((longs[idx+PSS_USS_AVERAGE]*(double)count)+(avgUss*(double)inCount))
+ / (count+inCount) );
+ if (longs[idx+PSS_USS_MAXIMUM] < maxUss) {
+ longs[idx+PSS_USS_MAXIMUM] = maxUss;
}
}
}
@@ -2239,14 +2403,15 @@ public final class ProcessStats implements Parcelable {
public static final class ServiceState {
final ProcessStats mStats;
- final String mPackage;
+ public final String mPackage;
+ public final String mName;
ProcessState mProc;
int mActive = 1;
- static final int SERVICE_STARTED = 0;
- static final int SERVICE_BOUND = 1;
- static final int SERVICE_EXEC = 2;
+ public static final int SERVICE_STARTED = 0;
+ public static final int SERVICE_BOUND = 1;
+ public static final int SERVICE_EXEC = 2;
static final int SERVICE_COUNT = 3;
int[] mDurationsTable;
@@ -2264,9 +2429,10 @@ public final class ProcessStats implements Parcelable {
public int mExecState = STATE_NOTHING;
long mExecStartTime;
- public ServiceState(ProcessStats processStats, String pkg, ProcessState proc) {
+ public ServiceState(ProcessStats processStats, String pkg, String name, ProcessState proc) {
mStats = processStats;
mPackage = pkg;
+ mName = name;
mProc = proc;
}
@@ -2287,6 +2453,17 @@ public final class ProcessStats implements Parcelable {
return mActive > 0;
}
+ void add(ServiceState other) {
+ for (int i=0; i<other.mDurationsTableSize; i++) {
+ int ent = other.mDurationsTable[i];
+ int state = (ent>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
+ addStateTime(state, other.mStats.getLong(ent, 0));
+ }
+ mStartedCount += other.mStartedCount;
+ mBoundCount += other.mBoundCount;
+ mExecCount += other.mExecCount;
+ }
+
void resetSafely(long now) {
mDurationsTable = null;
mDurationsTableSize = 0;
@@ -2321,9 +2498,8 @@ public final class ProcessStats implements Parcelable {
return true;
}
- void addStateTime(int opType, int memFactor, long time) {
+ void addStateTime(int state, long time) {
if (time > 0) {
- int state = opType + (memFactor*SERVICE_COUNT);
int idx = binarySearch(mDurationsTable, mDurationsTableSize, state);
int off;
if (idx >= 0) {
@@ -2342,15 +2518,16 @@ public final class ProcessStats implements Parcelable {
void commitStateTime(long now) {
if (mStartedState != STATE_NOTHING) {
- addStateTime(SERVICE_STARTED, mStartedState, now - mStartedStartTime);
+ addStateTime(SERVICE_STARTED + (mStartedState*SERVICE_COUNT),
+ now - mStartedStartTime);
mStartedStartTime = now;
}
if (mBoundState != STATE_NOTHING) {
- addStateTime(SERVICE_BOUND, mBoundState, now - mBoundStartTime);
+ addStateTime(SERVICE_BOUND + (mBoundState*SERVICE_COUNT), now - mBoundStartTime);
mBoundStartTime = now;
}
if (mExecState != STATE_NOTHING) {
- addStateTime(SERVICE_EXEC, mExecState, now - mExecStartTime);
+ addStateTime(SERVICE_EXEC + (mExecState*SERVICE_COUNT), now - mExecStartTime);
mExecStartTime = now;
}
}
@@ -2362,7 +2539,8 @@ public final class ProcessStats implements Parcelable {
int state = started ? memFactor : STATE_NOTHING;
if (mStartedState != state) {
if (mStartedState != STATE_NOTHING) {
- addStateTime(SERVICE_STARTED, mStartedState, now - mStartedStartTime);
+ addStateTime(SERVICE_STARTED + (mStartedState*SERVICE_COUNT),
+ now - mStartedStartTime);
} else if (started) {
mStartedCount++;
}
@@ -2386,7 +2564,8 @@ public final class ProcessStats implements Parcelable {
int state = bound ? memFactor : STATE_NOTHING;
if (mBoundState != state) {
if (mBoundState != STATE_NOTHING) {
- addStateTime(SERVICE_BOUND, mBoundState, now - mBoundStartTime);
+ addStateTime(SERVICE_BOUND + (mBoundState*SERVICE_COUNT),
+ now - mBoundStartTime);
} else if (bound) {
mBoundCount++;
}
@@ -2402,7 +2581,7 @@ public final class ProcessStats implements Parcelable {
int state = executing ? memFactor : STATE_NOTHING;
if (mExecState != state) {
if (mExecState != STATE_NOTHING) {
- addStateTime(SERVICE_EXEC, mExecState, now - mExecStartTime);
+ addStateTime(SERVICE_EXEC + (mExecState*SERVICE_COUNT), now - mExecStartTime);
} else if (executing) {
mExecCount++;
}
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index ccc0089cb0c0..04351da6dff7 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -499,7 +499,7 @@ public class ZygoteInit {
String args[] = {
"--setuid=1000",
"--setgid=1000",
- "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003,3006,3007",
+ "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",
"--capabilities=" + capabilities + "," + capabilities,
"--runtime-init",
"--nice-name=system_server",
diff --git a/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java b/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java
index f8332c48783a..a3df29199fb7 100644
--- a/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java
+++ b/core/java/com/android/internal/widget/PasswordEntryKeyboardHelper.java
@@ -184,7 +184,7 @@ public class PasswordEntryKeyboardHelper implements OnKeyboardActionListener {
KeyEvent event = events[i];
event = KeyEvent.changeFlags(event, event.getFlags()
| KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE);
- viewRootImpl.dispatchKey(event);
+ viewRootImpl.dispatchInputEvent(event);
}
}
}
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index 330806463ecc..6c4526eccfdf 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -35,8 +35,6 @@
#include <utils/Log.h>
-#define TIME_DRAWx
-
static uint32_t get_thread_msec() {
#if defined(HAVE_POSIX_CLOCKS)
struct timespec tm;
@@ -463,20 +461,6 @@ public:
canvas->drawPath(*path, *paint);
}
- static void drawPicture(JNIEnv* env, jobject, SkCanvas* canvas,
- SkPicture* picture) {
- SkASSERT(canvas);
- SkASSERT(picture);
-
-#ifdef TIME_DRAW
- SkMSec now = get_thread_msec(); //SkTime::GetMSecs();
-#endif
- canvas->drawPicture(*picture);
-#ifdef TIME_DRAW
- ALOGD("---- picture playback %d ms\n", get_thread_msec() - now);
-#endif
- }
-
static void drawBitmap__BitmapFFPaint(JNIEnv* env, jobject jcanvas,
SkCanvas* canvas, SkBitmap* bitmap,
jfloat left, jfloat top,
@@ -1103,7 +1087,6 @@ static JNINativeMethod gCanvasMethods[] = {
(void*) SkCanvasGlue::drawTextOnPath___CIIPathFFPaint},
{"native_drawTextOnPath","(ILjava/lang/String;IFFII)V",
(void*) SkCanvasGlue::drawTextOnPath__StringPathFFPaint},
- {"native_drawPicture", "(II)V", (void*) SkCanvasGlue::drawPicture},
{"freeCaches", "()V", (void*) SkCanvasGlue::freeCaches},
diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
index 2c482ea975d6..bacfdf6ae8d1 100644
--- a/core/jni/android/graphics/SurfaceTexture.cpp
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -18,6 +18,9 @@
#include <stdio.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
#include <gui/GLConsumer.h>
#include <gui/Surface.h>
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 61ace4a19bc5..f5eb38988ef2 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -220,6 +220,8 @@ static void read_mapinfo(FILE *fp, stats_t* stats)
} else {
whichHeap = HEAP_ASHMEM;
}
+ } else if (strncmp(name, "[anon:libc_malloc]", 18) == 0) {
+ whichHeap = HEAP_NATIVE;
} else if (strncmp(name, "[stack", 6) == 0) {
whichHeap = HEAP_STACK;
} else if (strncmp(name, "/dev/", 5) == 0) {
@@ -246,6 +248,8 @@ static void read_mapinfo(FILE *fp, stats_t* stats)
} else if (nameLen > 4 && strcmp(name+nameLen-4, ".art") == 0) {
whichHeap = HEAP_ART;
is_swappable = true;
+ } else if (strncmp(name, "[anon:", 6) == 0) {
+ whichHeap = HEAP_UNKNOWN;
} else if (nameLen > 0) {
whichHeap = HEAP_UNKNOWN_MAP;
} else if (start == prevEnd && prevHeap == HEAP_SO) {
diff --git a/core/jni/android_os_FileUtils.cpp b/core/jni/android_os_FileUtils.cpp
index 0aaa2b158da8..d1245da24777 100644
--- a/core/jni/android_os_FileUtils.cpp
+++ b/core/jni/android_os_FileUtils.cpp
@@ -33,46 +33,6 @@
namespace android {
-jint android_os_FileUtils_setPermissions(JNIEnv* env, jobject clazz,
- jstring file, jint mode,
- jint uid, jint gid)
-{
- const jchar* str = env->GetStringCritical(file, 0);
- String8 file8;
- if (str) {
- file8 = String8(str, env->GetStringLength(file));
- env->ReleaseStringCritical(file, str);
- }
- if (file8.size() <= 0) {
- return ENOENT;
- }
- if (uid >= 0 || gid >= 0) {
- int res = chown(file8.string(), uid, gid);
- if (res != 0) {
- return errno;
- }
- }
- return chmod(file8.string(), mode) == 0 ? 0 : errno;
-}
-
-jint android_os_FileUtils_getUid(JNIEnv* env, jobject clazz, jstring file)
-{
- struct stat stats;
- const jchar* str = env->GetStringCritical(file, 0);
- String8 file8;
- if (str) {
- file8 = String8(str, env->GetStringLength(file));
- env->ReleaseStringCritical(file, str);
- }
- if (file8.size() <= 0) {
- return ENOENT;
- }
- if (stat(file8.string(), &stats) < 0) {
- return -1;
- }
- return stats.st_uid;
-}
-
jint android_os_FileUtils_getFatVolumeId(JNIEnv* env, jobject clazz, jstring path)
{
if (path == NULL) {
@@ -95,8 +55,6 @@ jint android_os_FileUtils_getFatVolumeId(JNIEnv* env, jobject clazz, jstring pat
}
static const JNINativeMethod methods[] = {
- {"setPermissions", "(Ljava/lang/String;III)I", (void*)android_os_FileUtils_setPermissions},
- {"getUid", "(Ljava/lang/String;)I", (void*)android_os_FileUtils_getUid},
{"getFatVolumeId", "(Ljava/lang/String;)I", (void*)android_os_FileUtils_getFatVolumeId},
};
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 06d6895252cd..848c58588418 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"verhoed program-oorskakelings"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Verhoed dat die gebruiker na \'n ander program oorskakel."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"kry huidige program-inligting"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Laat die houer toe om private inligting oor die huidige program op die voorgrond van die skerm te herwin."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"monitor en beheer alle programlaaiery"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Laat die program toe om te monitor en te beheer hoe die stelsel aktiwiteite laai. Kwaadwillige programme kan dalk die stelsel heeltemal in gevaar stel. Hierdie toestemming is net nodig vir ontwikkeling, en nooit vir normale gebruik nie."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"stuur uitsending met pakket verwyder"</string>
@@ -362,8 +363,8 @@
<string name="permdesc_bindPrintService" msgid="7960067623209111135">"Laat die houer toe om aan die top-koppelvlak van \'n drukdiens te verbind. Behoort nooit vir gewone programme nodig te wees nie."</string>
<string name="permlab_accessAllPrintJobs" msgid="1120792468465711159">"kry toegang tot alle druktake"</string>
<string name="permdesc_accessAllPrintJobs" msgid="2978185311041864762">"Gee die houer toegang tot druktake wat deur \'n ander program geskep is. Behoort nooit vir normale programme nodig te wees nie."</string>
- <string name="permlab_bindNfcService" msgid="2752731300419410724">"bind aan NFC-diens"</string>
- <string name="permdesc_bindNfcService" msgid="6120647629174066862">"Laat die houer toe om die programme wat NFC-kaarte nastrewe, te bind. Behoort nooit vir normale programme nodig te wees nie."</string>
+ <string name="permlab_bindNfcService" msgid="2752731300419410724">"verbind aan NFC-diens"</string>
+ <string name="permdesc_bindNfcService" msgid="6120647629174066862">"Laat die houer toe om te verbind aan programme wat NFC-kaarte nastrewe. Behoort nooit vir normale programme nodig te wees nie."</string>
<string name="permlab_bindTextService" msgid="7358378401915287938">"bind aan \'n teksdiens"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Dit laat die houer toe om aan die topvlak-koppelvlak van \'n teksdiens (bv SpellCheckerService) te bind. Dit moet nooit vir normale programme nodig wees nie."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"bind aan \'n VPN-diens"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Laat die program toe om Wi-Fi-skerms op te stel en daaraan te koppel."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"beheer Wi-Fi-skerms"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Laat die program toe om laevlak-kenmerke van Wi-Fi-skerms te beheer."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"vang oudio-uitset vas"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Laat die program oudio-uitset vasvang en herlei."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"vang video-uitset vas"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Laat die program video-uitset vasvang en herlei."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"vang sekure video-uitset vas"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Laat die program sekure video-uitset vasvang en herlei."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"verander jou klankinstellings"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Laat die program toe om globale klankinstellings soos volume en watter luidspreker vir uitvoer gebruik word, te verander."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"neem klank op"</string>
@@ -659,6 +654,8 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Laat die houer toe om aan die top-koppelvlak van \'n kennisgewingluisteraardiens te bind. Behoort nooit vir gewone programme nodig te wees nie."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"roep die opstellingprogram op wat deur die diensverskaffer voorsien is"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Laat die houer toe om die opstellingsprogram wat deur die diensverskaffer voorsien word, op te roep. Behoort nooit vir gewone programme nodig te wees nie."</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"luister vir waarnemings oor netwerktoestande"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Laat \'n program luister vir waarnemings oor netwerktoestande. Behoort nooit nodig te wees vir normale programme nie."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Stel wagwoordreëls"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Beheer lengte en watter karakters wat in die skermontsluit-wagwoorde gebruik word."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Monitor pogings om skerm te ontsluit"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index d554d54a9759..b2ecd52fc9f5 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"የትáŒá‰ áˆ« መቀያየርን ተከላከáˆ"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"ተጠቃሚዠከሌላ መተáŒá‰ áˆªá‹« ከመቀየር ይከላከላáˆá¢"</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"የአáˆáŠ‘ የመተáŒá‰ áˆªá‹« መረጃ á‹«áŒáŠ™"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"ያዢዠበማያ ገጹ áŠá‰µ ላይ ስላለዠየአáˆáŠ‘ መተáŒá‰ áˆªá‹« የáŒáˆ መረጃ እንዲያመጣ ያስችለዋáˆá¢"</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"áˆáˆ‰áŠ•áˆ áˆ˜á‰°áŒá‰ áˆªá‹« ማስáŠáˆ» አሳይ እና ተቆጣጠር"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"እንቅስቃሴዎችን ስርዓቱ እንዴት እንደሚያስጀáˆáˆ­ ለመከታተሠእና ለመቆጣጠር ለመተáŒá‰ áˆªá‹«á‹ á‹­áˆá‰…ዳሉá¡á¡ ተንኮሠአዘሠመተáŒá‰ áˆªá‹«á‹Žá‰½ የስርዓቱን ክብረ ገመና ሙሉለሙሉ ሊያጋáˆáŒ¡ ይችላሉá¡á¡ ይህ áቃድ የሚያስáˆáˆáŒˆá‹ ለáŒáŠ•á‰£á‰³ ብቻ áŠá‹á¤ ለመደበኛ አጠቃቀሠáˆáŒ½áˆž አይደለáˆá¡á¡"</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"አካታች የተወገደለት ስርጭት ላክ"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"መተáŒá‰ áˆªá‹«á‹ የWifi ማሳያዎችን እንዲያዋቅርና ከእáŠáˆ± ጋር እንዲገናአይáˆá‰…ድለታáˆá¢"</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"የWifi ማሳያዎችን ተቆጣጠር"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"መተáŒá‰ áˆªá‹«á‹ በá‹á‰…ተኛ ደረጃ ላይ ያሉ የWifi ማሳያዎችን እንዲቆጣጠር á‹­áˆá‰…ድለታáˆá¢"</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"የድáˆáŒ½ á‹áŒ½á‹“ት ይቅረጹ"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"መተáŒá‰ áˆªá‹«á‹ የድáˆáŒ½ á‹áŒ½á‹“ት እንዲቀርጽ እና አቅጣጫá‹áŠ• እንዲያዞር ያስችለዋáˆá¢"</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"የቪዲዮ á‹áŒ½á‹“ት ይቅረጹ"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"መተáŒá‰ áˆªá‹«á‹ የቪዲዮ á‹áŒ½á‹“ት እንዲቀርጽ እና አቅጣጫá‹áŠ• እንዲያዞር ያስችለዋáˆá¢"</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"ደህንáŠá‰± የተጠበቀ የቪዲዮ á‹áŒ½á‹“ት ይቅረጹ"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"መተáŒá‰ áˆªá‹«á‹ ደህንáŠá‰± የተጠበቀ የቪዲዮ á‹áŒ½á‹“ት እንዲቀርጽ እና አቅጣጫá‹áŠ• እንዲያዞር ያስችለዋáˆá¢"</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"የድáˆá… ቅንብሮችን ለá‹áŒ¥"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"መተáŒá‰ áˆªá‹«á‹ አንደ የድáˆáŒ½ መጠን እና ለá‹áŒ½áŠ á‰µ የትኛá‹áŠ• የድáˆáŒ½ ማጉያ ጥቅሠላይ እንደዋለ የመሳሰሉ áˆáˆˆáŠ•á‰°áŠ“á‹Š የድáˆáŒ½ ቅንብሮችን እንዲያስተካክሠይáˆá‰…ድለታáˆá¢"</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"ኦዲዮ ቅዳ"</string>
@@ -659,6 +654,8 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"ያዢዠየማሳወቂያ አዳማጭ አገáˆáŒáˆŽá‰±áŠ• ከከáተኛ-ደረጃ በይáŠáŒˆáŒ¹ ጋር እንዲያስር ያስችለዋáˆá¢ ለመደበኛ መተáŒá‰ áˆªá‹«á‹Žá‰½ በጭራሽ አያስáˆáˆáŒáˆá¢"</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"በድáˆáŒ¸-ተያያዥ ሞደሠየቀረበዠየá‹á‰…ር መተáŒá‰ áˆªá‹«á‹áŠ• መጥራት"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"ያዢዠበድáˆáŒ¸-ተያያዥ ሞደሠየቀረበዠየá‹á‰…ር መተáŒá‰ áˆªá‹«á‹áŠ• እንዲጠራዠያስችለዋáˆá¢ ለመደበኛ መተáŒá‰ áˆªá‹«á‹Žá‰½ በጭራሽ አያስáˆáˆáŒáˆá¢"</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"በአá‹á‰³áˆ¨ መረብ áˆáŠ”á‰³á‹Žá‰½ ላይ የተስተዋሉ áŠáŒˆáˆ®á‰½áŠ• ያዳáˆáŒ£áˆ"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"አንድ መተáŒá‰ áˆªá‹« በአá‹á‰³áˆ¨ መረብ áˆáŠ”á‰³á‹Žá‰½ ላይ የተስተዋሉ áŠáŒˆáˆ®á‰½áŠ• እንዲያዳáˆáŒ¥ ያስችለዋáˆá¢ ለመደበኛ መተáŒá‰ áˆªá‹«á‹Žá‰½ በጭራሽ አስáˆáˆ‹áŒŠ ሊሆን አይገባáˆá¢"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"የይለá ቃሠድንቦች አዘጋጅ"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"በማያ-መክáˆá‰µ የተáˆá‰€á‹± የይለá ቃሠርá‹áˆ˜á‰µ እና á‰áˆáŠá‹Žá‰½ ተቆጣጠርá¢"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"የማሳያ-ክáˆá‰µ ሙከራዎችን አሳይ"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 60dc57e44dd7..bc22b8089e27 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"منع التبديل بين التطبيقات"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"لمنع المستخدم من التبديل إلى تطبيق آخر."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"الحصول على معلومات عن التطبيق الحالي"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"للسماح للمالك باسترداد معلومات خاصة عن التطبيق الحالي ÙÙŠ مقدمة الشاشة."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"مراقبة بدء تشغيل جميع التطبيقات والتحكم Ùيها"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"للسماح للتطبيق بمراقبة كيÙية بدء النظام للأنشطة والتحكم Ùيها. قد ØªÙØ¹Ø±Ùّض التطبيقات الضارة النظام للضرر بشكل كامل. لن تكون هناك حاجة لهذا الإذن سوى للتطوير Ùقط، وليس للاستخدام العادي على الإطلاق."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"إرسال بث الحزمة الذي تمت إزالته"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"للسماح للتطبيق بتهيئة شاشات Wi-Fi والاتصال بها."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"التحكم ÙÙŠ شاشات Wi-Fi"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"للسماح للتطبيق بالتحكم ÙÙŠ الميزات ذات المستوى Ø§Ù„Ù…Ù†Ø®ÙØ¶ ÙÙŠ شاشات Wi-Fi."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"التقاط إخراج الصوت"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"السماح للتطبيق بالتقاط إخراج الصوت وإعادة توجيهه."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"التقاط إخراج الÙيديو"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"السماح للتطبيق بالتقاط إخراج الÙيديو وإعادة توجيهه."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"التقاط إخراج الÙيديو الآمن"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"السماح للتطبيق بالتقاط إخراج الÙيديو الآمن وإعادة توجيهه."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"تغيير إعداداتك الصوتية"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"للسماح للتطبيق بتعديل إعدادات الصوت العامة مثل مستوى الصوت وأي السماعات يتم استخدامها للاستماع."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"تسجيل الصوت"</string>
@@ -659,6 +654,10 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"يتيح للمالك الربط بواجهة المستوى العلوي لخدمة تلقّي الإشعارات الصوتية. ولن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"استدعاء تطبيق التهيئة الذي ÙŠÙˆÙØ±Ù‡ مشغل شبكة الجوال"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"للسماح للمالك باستدعاء تطبيق التهيئة الذي ÙŠÙˆÙØ±Ù‡Â Ù…شغل شبكة الجوال. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
+ <!-- no translation found for permlab_accessNetworkConditions (8206077447838909516) -->
+ <skip />
+ <!-- no translation found for permdesc_accessNetworkConditions (6899102075825272211) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"تعيين قواعد كلمة المرور"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"يمكنك التحكم ÙÙŠ الطول والأحر٠المسموح بها ÙÙŠ كلمات مرور إلغاء تأمين الشاشة."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"مراقبة محاولات إلغاء Ù‚ÙÙ„ الشاشة"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 86bb7662108c..83a54b660ae0 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -316,7 +316,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"прадухілÑць пераключÑнне прыкладаннÑÑž"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Ðе дазвалÑе карыÑтальніку пераходзіць да іншага прыкладаннÑ."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"атрымаць бÑгучую інфармацыю прыкладаннÑ"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"ДазвалÑе ўладальніку атрымлiваць аÑабіÑтую інфармацыю аб бÑгучым прыкладаннi на пÑÑ€Ñднім плане Ñкрана."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"адÑочваць Ñ– кантралÑваць запуÑк уÑÑ–Ñ… прыкладаннÑÑž"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"ДазвалÑе прыкладанню Ñачыць Ñ– кантралÑваць, Ñк ÑÑ–ÑÑ‚Ñма запуÑкае працÑÑÑ‹. ШкоднаÑÐ½Ñ‹Ñ Ð¿Ñ€Ñ‹ÐºÐ»Ð°Ð´Ð°Ð½Ð½Ñ– могуць цалкам парушыць працу ÑÑ–ÑÑ‚Ñмы. ГÑты дазвол патрÑбны толькі Ð´Ð»Ñ Ñ€Ð°Ñпрацоўкі, ніколі Ð´Ð»Ñ Ð·Ð²Ñ‹Ñ‡Ð°Ð¹Ð½Ð°Ð³Ð° выкарыÑтаннÑ."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"транÑлÑваць паведамленні аб выдаленні пакетаў"</string>
@@ -675,6 +676,10 @@
<skip />
<!-- no translation found for permdesc_invokeCarrierSetup (4159549152529111920) -->
<skip />
+ <!-- no translation found for permlab_accessNetworkConditions (8206077447838909516) -->
+ <skip />
+ <!-- no translation found for permdesc_accessNetworkConditions (6899102075825272211) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"УÑтанавіць правілы паролю"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Кіраванне даўжынёй Ñ– колькаÑцю знакаў у паролі разблакоўкі Ñкрана."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Сачыць за Ñпробамі разблакоўкі Ñкрана"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 1452ecfaa553..21b4d950fbc8 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"предотвратÑване на превключването между приложениÑ"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Ðе позволÑва на Ð¿Ð¾Ñ‚Ñ€ÐµÐ±Ð¸Ñ‚ÐµÐ»Ñ Ð´Ð° превключва към друго приложение."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"извличане на Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° текущото приложение"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Разрешава на ÑобÑтвеника да извлича чаÑтна Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð·Ð° текущото приложение на преден план на екрана."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"наблюдение и контрол на Ñтартирането на вÑички приложениÑ"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Разрешава на приложението да наблюдава и контролира как ÑиÑтемата Ñтартира дейноÑти. Злонамерените Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¼Ð¾Ð³Ð°Ñ‚ изцÑло да компрометират ÑиÑтемата. Това разрешение е нужно Ñамо за програмиране, никога за нормална употреба."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"изпращане на излъчване при премахнат пакет"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Разрешава на приложението да конфигурира и да Ñе Ñвързва Ñ Ð´Ð¸Ñплеите през WiFi."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"контролиране на диÑплеите през WiFi"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Разрешава на приложението да контролира функциите от ниÑко ниво на диÑплеите през WiFi."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"запиÑване на Ð²ÑŠÐ·Ð¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ¶Ð´Ð°Ð½Ð¸Ñ Ð·Ð²ÑƒÐº"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Разрешава на приложението да запиÑва и пренаÑочва Ð²ÑŠÐ·Ð¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ¶Ð´Ð°Ð½Ð¸Ñ Ð·Ð²ÑƒÐº."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"запиÑване на Ð²ÑŠÐ·Ð¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ¶Ð´Ð°Ð½Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð·"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Разрешава на приложението да запиÑва и пренаÑочва Ð²ÑŠÐ·Ð¿Ñ€Ð¾Ð¸Ð·Ð²ÐµÐ¶Ð´Ð°Ð½Ð¸Ñ Ð¾Ð±Ñ€Ð°Ð·."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"запиÑване на защитеното възпроизвеждане на образ"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Разрешава на приложението да запиÑва и пренаÑочва защитеното възпроизвеждане на образ."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"промÑна на наÑтройките ви за звука"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Разрешава на приложението да Ð¿Ñ€Ð¾Ð¼ÐµÐ½Ñ Ð³Ð»Ð¾Ð±Ð°Ð»Ð½Ð¸Ñ‚Ðµ наÑтройки за звука, като например Ñилата и това, кой виÑокоговорител Ñе използва за изход."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"Ð·Ð°Ð¿Ð¸Ñ Ð½Ð° звук"</string>
@@ -659,6 +654,8 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Разрешава на Ð¿Ñ€Ð¸Ñ‚ÐµÐ¶Ð°Ñ‚ÐµÐ»Ñ Ð´Ð° Ñе обвърже Ñ Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñа от първо ниво на уÑлуга за Ñлушател на извеÑтиÑ. Ðормалните Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð½Ðµ би трÑбвало никога да Ñе нуждаÑÑ‚ от това."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"извикване на предоÑтавеното от оператора приложение за конфигуриране"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Разрешава на Ð¿Ñ€Ð¸Ñ‚ÐµÐ¶Ð°Ñ‚ÐµÐ»Ñ Ð´Ð° извиква предоÑтавеното от оператора приложение за конфигуриране. Ðормалните Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð±Ð¸ трÑбвало никога да не Ñе нуждаÑÑ‚ от това."</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"Ñлушане за Ð½Ð°Ð±Ð»ÑŽÐ´ÐµÐ½Ð¸Ñ Ð½Ð° мрежовите уÑловиÑ"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Разрешава на приложението да Ñлуша за Ð½Ð°Ð±Ð»ÑŽÐ´ÐµÐ½Ð¸Ñ Ð½Ð° мрежовите уÑловиÑ. Ðормалните Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð±Ð¸ трÑбвало никога да не Ñе нуждаÑÑ‚ от това."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Задаване на правила за паролата"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Контролирайте дължината и разрешените знаци за паролите за отключване на екрана."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Ðаблюдаване на опитите за отключване на екрана"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 96a35d03d66c..73794989ab73 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"impedir els canvis d\'aplicació"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Impedeix que l\'usuari canviï a una altra aplicació."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"obtenció d\'informació de l\'aplicació actual"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Permet que el titular recuperi informació privada sobre l\'aplicació actual al primer pla de la pantalla."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"supervisa i controla tots els inicis d\'aplicacions"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Permet que l\'aplicació supervisi i controli com el sistema inicia activitats. Les aplicacions malicioses poden comprometre totalment el sistema. Aquest permís només és necessari per al desenvolupament, mai per a l\'ús normal."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"enviar difusió d\'eliminació de paquet"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Permet a l\'aplicació configurar-se i connectar-se a les pantalles Wi-Fi."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"control de les pantalles Wi-Fi"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Permet a l\'aplicació controlar les funcions de baix nivell de les pantalles Wi-Fi."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"captura la sortida d\'àudio"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Permet que l\'aplicació capturi i redirigeixi la sortida d\'àudio."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"captura la sortida de vídeo"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Permet que l\'aplicació capturi i redirigeixi la sortida de vídeo."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"captura la sortida de vídeo segur"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Permet que l\'aplicació capturi i redirigeixi la sortida de vídeo segur."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"canviar la configuració d\'àudio"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Permet que l\'aplicació modifiqui la configuració d\'àudio general, com ara el volum i l\'altaveu de sortida que es fa servir."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"enregistrar àudio"</string>
@@ -659,6 +654,8 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permet que el titular vinculi la interfície de nivell superior d\'un servei de processament de notificacions. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"invoca l\'aplicació de configuració proporcionada per l\'operador"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permet que el titular invoqui l\'aplicació de configuració proporcionada per l\'operador. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"conèixer les observacions sobre les condicions de la xarxa"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Permet que una aplicació conegui les observacions sobre les condicions de la xarxa. No s\'ha de necessitar mai per a aplicacions normals."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Defineix les normes de contrasenya"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Controla la longitud i els caràcters permesos a les contrasenyes de desbloqueig de pantalla."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Control d\'intents de desbloqueig de pantalla"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index e9d65f803173..5a3bdf8c672a 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"zabránění přepínání aplikací"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Zabrání uživateli přepnout na jinou aplikaci."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"získat informace o aktuální aplikaci"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Umožňuje držiteli získat soukromé informace o aktuální aplikaci na popředí obrazovky."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"sledování a řízení spouštění všech aplikací"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Umožňuje aplikaci sledovat a řídit spouÅ¡tÄ›ní Äinností systémem. Å kodlivé aplikace mohou systém zcela ovládnout. Toto oprávnÄ›ní je požadováno pouze pro úÄely vývoje, nikdy pro běžné použití."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"odeslání vysílání o odstranÄ›ní balíÄku"</string>
@@ -362,10 +363,8 @@
<string name="permdesc_bindPrintService" msgid="7960067623209111135">"Umožňuje navázání na nejvyšší úroveň tiskové služby. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
<string name="permlab_accessAllPrintJobs" msgid="1120792468465711159">"přístup ke všem tiskovým úlohám"</string>
<string name="permdesc_accessAllPrintJobs" msgid="2978185311041864762">"Umožňuje přístup k tiskovým úlohám vytvořeným jinou aplikací. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
- <!-- no translation found for permlab_bindNfcService (2752731300419410724) -->
- <skip />
- <!-- no translation found for permdesc_bindNfcService (6120647629174066862) -->
- <skip />
+ <string name="permlab_bindNfcService" msgid="2752731300419410724">"navázat se na službu NFC"</string>
+ <string name="permdesc_bindNfcService" msgid="6120647629174066862">"Umožňuje držiteli navázat se na aplikace, které emulují karty NFC. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
<string name="permlab_bindTextService" msgid="7358378401915287938">"navázat se na textovou službu"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Umožňuje držiteli připojit se k nejvyšší úrovni rozhraní textové služby (např. SpellCheckerService). Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"navázat se na službu VPN"</string>
@@ -476,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Povoluje aplikaci připojit a konfigurovat displeje přes Wi-Fi."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"ovládat displeje přes Wi-Fi"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Povoluje aplikaci ovládat základní funkce displejů přes Wi-Fi."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"zachytit výstup zvuku"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Umožní aplikaci zachytit a přesměrovat výstup zvuku."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"zachytit výstup videa"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Umožní aplikaci zachytit a přesměrovat výstup videa."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"zachytit zabezpeÄený výstup videa"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Umožní aplikaci zachytit a pÅ™esmÄ›rovat zabezpeÄený výstup videa."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"změna nastavení zvuku"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Umožňuje aplikaci zmÄ›nit globální nastavení zvuku, například hlasitost Äi reproduktor pro výstup zvuku."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"nahrávání zvuku"</string>
@@ -661,6 +654,8 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Umožňuje držiteli navázat se na nejvyšší úroveň služby pro poslouchání oznámení. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"vyvolat konfiguraÄní aplikaci poskytnutou operátorem"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Umožňuje vyvolání konfiguraÄní aplikace poskytnuté operátorem. Běžné aplikace by toto oprávnÄ›ní nemÄ›ly nikdy požadovat."</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"naslouchat informacím o stavu sítě"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Umožňuje aplikaci naslouchat informacím o stavu sítě. Běžné aplikace by toto oprávnění neměly nikdy potřebovat."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Nastavit pravidla pro heslo"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Řídit délku hesel pro odemÄení obrazovky a povolené znaky."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Sledovat pokusy o odemÄení obrazovky"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index c97c7e73a5cd..56022e647a26 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"undgå programskift"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Forhindrer brugeren i at skifte til en anden app."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"få aktuelle app-oplysninger"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Tillader, at brugeren henter private oplysninger om den aktuelle applikation i forgrunden på ​​skærmen."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"overvåge og kontrollere åbning af alle apps"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Tillader, at appen kan overvåge og kontrollere, hvordan systemet starter aktiviteter. Ondsindede apps kan fuldstændig kompromittere systemet. Denne tilladelse er kun nødvendig til udvikling, aldrig til normal brug."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"send udsendelse om fjernet pakke"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Tillader, at appen konfigurerer og opretter forbindelse til Wi-Fi-skærme."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"kontrollér Wi-Fi-skærme"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Tillader, at appen kontrollerer Wi-Fi-skærmfunktioner på lavt niveau."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"opfang et lydoutput"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Tillader, at appen opfanger og omdirigerer et lydoutput."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"opfang et videooutput"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Tillader, at appen opfanger og omdirigerer et videooutput."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"opfang et sikkert videooutput"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Tillader, at appen opfanger og omdirigerer et sikkert videooutput."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"skift dine lydindstillinger"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Tillader, at appen kan ændre globale lydindstillinger, som f.eks. lydstyrke og hvilken højttaler der bruges til output."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"optage lyd"</string>
@@ -659,6 +654,8 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Tillader brugeren at forpligte sig til en underretningslyttertjenestes grænseflade på øverste niveau. Bør aldrig være nødvendigt til almindelige apps."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"aktivere konfigurationsappen, der leveres af mobilselskabet"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Tillader, at brugeren aktiverer konfigurationsappen, der er forsynet af mobilselskabet. Dette bør aldrig være nødvendigt for almindelige apps."</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"observer netværksforhold"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Tillader, at en applikation observerer netværksforhold. Bør aldrig være nødvendigt for almindelige apps."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Indstil regler for adgangskode"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontroller længden samt tilladte tegn i adgangskoder til oplåsning af skærmen."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Overvåg forsøg på oplåsning af skærm"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index b26f65b211d5..c0006dd2fa24 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -236,7 +236,7 @@
<string name="capability_title_canRequestEnhancedWebAccessibility" msgid="1739881766522594073">"Verbesserte Web-Bedienung aktivieren"</string>
<string name="capability_desc_canRequestEnhancedWebAccessibility" msgid="7881063961507511765">"Skripts können installiert werden, um den Zugriff auf App-Inhalte zu erleichtern."</string>
<string name="capability_title_canRequestFilterKeyEvents" msgid="2103440391902412174">"Text bei der Eingabe beobachten"</string>
- <string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Einschließlich persönlicher Daten wie Kreditkartennummern und Passwörter."</string>
+ <string name="capability_desc_canRequestFilterKeyEvents" msgid="7463135292204152818">"Einschließlich personenbezogener Daten wie Kreditkartennummern und Passwörter."</string>
<string name="permlab_statusBar" msgid="7417192629601890791">"Statusleiste deaktivieren oder ändern"</string>
<string name="permdesc_statusBar" msgid="8434669549504290975">"Ermöglicht der App, die Statusleiste zu deaktivieren oder Systemsymbole hinzuzufügen oder zu entfernen"</string>
<string name="permlab_statusBarService" msgid="7247281911387931485">"Statusleiste"</string>
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"App-Wechsel verhindern"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Hindert den Nutzer daran, zu einer anderen App zu wechseln"</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"Informationen zur aktuellen App abrufen"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Ermöglicht es dem Inhaber, private Informationen zur aktuellen App im Vordergrund des Bildschirms abzurufen"</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"Start von Apps überwachen und steuern"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Ermöglicht der App, den Start von Systemaktivitäten zu überwachen und zu steuern. Schädliche Apps können so das gesamte System beeinträchtigen. Diese Berechtigung wird nur zu Entwicklungszwecken und nie für die normale Nutzung benötigt."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"Broadcast ohne Paket senden"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Erlaubt der App, WLAN-Anzeigen zu konfigurieren und eine Verbindung zu diesen herzustellen"</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"WLAN-Anzeigen steuern"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Erlaubt der App, untergeordnete Funktionen von WLAN-Anzeigen zu steuern"</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"Audioausgabe erfassen"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Ermöglicht der App das Erfassen und Weiterleiten von Audioausgaben"</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"Videoausgabe erfassen"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Ermöglicht der App das Erfassen und Weiterleiten von Videoausgaben"</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"Sichere Videoausgabe erfassen"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Ermöglicht der App das Erfassen und Weiterleiten von sicheren Videoausgaben"</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"Audio-Einstellungen ändern"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Ermöglicht der App, globale Audio-Einstellungen zu ändern, etwa die Lautstärke und den Lautsprecher für die Ausgabe."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"Audio aufnehmen"</string>
@@ -659,6 +654,8 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Ermöglicht dem Inhaber, sich an die Oberfläche der obersten Ebene eines Benachrichtigungs-Listener-Dienstes zu binden. Sollte nie für normale Apps benötigt werden."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"Vom Mobilfunkanbieter bereitgestellte Konfigurations-App aufrufen"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Ermöglicht dem Inhaber, die vom Mobilfunkanbieter bereitgestellte Konfigurations-App aufzurufen. Sollte für normale Apps nie benötigt werden."</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"Informationen zu den Netzwerkbedingungen erfassen"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Ermöglicht der App, Informationen zu den Netzwerkbedingungen zu erfassen. Sollte für normale Apps nie benötigt werden."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Passwortregeln festlegen"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Zulässige Länge und Zeichen für Passwörter zum Entsperren des Bildschirms festlegen"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Versuche zum Entsperren des Displays überwachen"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 571f155ca0d7..c762d6f1cd7d 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"αποτÏοπή εναλλαγών εφαÏμογών"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Δεν επιτÏέπει στο χÏήστη να μεταβεί σε άλλη εφαÏμογή."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"λήψη πληÏοφοÏιών σχετικά με την Ï„Ïέχουσα εφαÏμογή"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Δίνει στον κάτοχο τη δυνατότητα ανάκτησης απόÏÏητων πληÏοφοÏιών σχετικά με την Ï„Ïέχουσα εφαÏμογή στο Ï€Ïοσκήνιο της οθόνης."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"παÏακολοÏθηση και έλεγχος όλων των εκκινήσεων εφαÏμογών"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"ΕπιτÏέπει στην εφαÏμογή να παÏακολουθεί και να ελέγχει τον Ï„Ïόπο με τον οποίο το σÏστημα εκκινεί δÏαστηÏιότητες. Τυχόν κακόβουλες εφαÏμογές ενδέχεται να θέσουν σε κίνδυνο το σÏστημα. Αυτή η άδεια είναι απαÏαίτητη μόνο για σκοποÏÏ‚ ανάπτυξης και ποτέ για συνήθη χÏήση."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"αποστολή εκπομπής χωÏίς πακέτο"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"ΕπιτÏέπει τη διαμόÏφωση της εφαÏμογής και τη σÏνδεσης σε οθόνες Wifi."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"έλεγχος οθονών Wifi"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"ΕπιτÏέπει στην εφαÏμογή τον έλεγχο των λειτουÏγιών Ï‡Î±Î¼Î·Î»Î¿Ï ÎµÏ€Î¹Ï€Î­Î´Î¿Ï… των οθονών Wifi."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"έγγÏαφή εξόδου ήχου"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Δίνει στην εφαÏμογή τη δυνατότητα εγγÏαφής και ανακατεÏθυνσης εξόδου ήχου."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"έγγÏαφή εξόδου βίντεο"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Δίνει στην εφαÏμογή τη δυνατότητα εγγÏαφής και ανακατεÏθυνσης εξόδου βίντεο."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"έγγÏαφή ασφαλοÏÏ‚ εξόδου βίντεο"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Δίνει στην εφαÏμογή τη δυνατότητα εγγÏαφής και ανακατεÏθυνσης ασφαλοÏÏ‚ εξόδου βίντεο."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"αλλαγή των Ïυθμίσεων ήχου"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"ΕπιτÏέπει στην εφαÏμογή την Ï„Ïοποποίηση καθολικών Ïυθμίσεων ήχου, όπως η ένταση και ποιο ηχείο χÏησιμοποιείται για έξοδο."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"εγγÏαφή ήχου"</string>
@@ -659,6 +654,8 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"ΕπιτÏέπει στον κάτοχο τη δέσμευση στη διεπαφή ανωτάτου επιπέδου μιας υπηÏεσίας ακÏόασης ειδοποιήσεων. Δεν απαιτείται σε κανονικές εφαÏμογές."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"κλήση της εφαÏμογής διαμόÏφωσης που παÏέχεται από την εταιÏεία κινητής τηλεφωνίας"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"ΕπιτÏέπει στον κάτοχο την κλήση της εφαÏμογής διαμόÏφωσης που παÏέχεται από την εταιÏεία κινητής τηλεφωνίας. Δεν απαιτείται για κανονικές εφαÏμογές."</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"λήψη παÏατηÏήσεων σχετικά με την κατάσταση δικτÏου"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"ΕπιτÏέπει σε μια εφαÏμογή να λαμβάνει παÏατηÏήσεις σχετικά με την κατάσταση δικτÏου. Δεν θα Ï€Ïέπει να απαιτείται ποτέ για κανονικές εφαÏμογές."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"ΟÏισμός κανόνων ÎºÏ‰Î´Î¹ÎºÎ¿Ï Ï€Ïόσβασης"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Έλεγχος του μεγέθους και των χαÏακτήÏων που επιτÏέπονται στους κωδικοÏÏ‚ Ï€Ïόσβασης ξεκλειδώματος οθόνης."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"ΠαÏακολοÏθηση Ï€Ïοσπαθειών ξεκλειδώματος οθόνης"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 3a08f9854cf3..ff26cf470a5c 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"prevent app switches"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Prevents the user from switching to another app."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"get current app info"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Allows the holder to retrieve private information about the current application in the foreground of the screen."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"monitor and control all app launching"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Allows the app to monitor and control how the system launches activities. Malicious apps may completely compromise the system. This permission is only needed for development, never for normal use."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"send package removed broadcast"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Allows the app to configure and connect to Wi-Fi displays."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"control Wi-Fi displays"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Allows the app to control low-level features of Wi-Fi displays."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"capture audio output"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Allows the app to capture and redirect audio output."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"capture video output"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Allows the app to capture and redirect video output."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"capture secure video output"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Allows the app to capture and redirect secure video output."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"change your audio settings"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Allows the app to modify global audio settings such as volume and which speaker is used for output."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"record audio"</string>
@@ -659,6 +654,8 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Allows the holder to bind to the top-level interface of a notification listener service. Should never be needed for normal apps."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"invoke the carrier-provided configuration app"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Allows the holder to invoke the carrier-provided configuration app. Should never be needed for normal apps."</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"listen for observations on network conditions"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Allows an application to listen for observations on network conditions. Should never be needed for normal apps."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Set password rules"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Control the length and the characters allowed in screen-unlock passwords."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Monitor screen-unlock attempts"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 959729baf108..e477ae809a69 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"impedir conmutadores de aplicación"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Evita que el usuario cambie a otra aplicación."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"obtener información de aplicación actual"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Permite que el titular recupere información privada sobre la aplicación actual en el primer plano de la pantalla."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"supervisar y controlar la ejecución de todas las aplicaciones"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Permite que la aplicación supervise y controle la manera en la que el sistema inicia actividades. Las aplicaciones maliciosas pueden comprometer el sistema por completo. Este permiso es necesario solo para el desarrollo, nunca para el uso habitual."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"enviar emisión de paquete eliminado"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Permite que la aplicación configure y se conecte a pantallas Wi-Fi."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"controlar pantallas Wi-Fi"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Permite que la aplicación controle funciones de bajo nivel de las pantallas Wi-Fi."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"Capturar salida de audio"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Permite que la aplicación capture y redirija la salida de audio."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"Capturar salida de video"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Permite que la aplicación capture y redirija la salida de video."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"Capturar salida de video segura"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Permite que la aplicación capture y redirija la salida de video segura."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"cambiar tu configuración de audio"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Permite que la aplicación modifique la configuración de audio global, por ejemplo, el volumen y el altavoz de salida."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"grabar audio"</string>
@@ -659,6 +654,8 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permite al propietario vincularse a la interfaz de nivel superior de un servicio de agente de escucha de notificaciones. Las aplicaciones normales no deberían necesitar este permiso."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"ejecutar la aplicación de configuración proporcionada por el proveedor"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permite al propietario ejecutar la aplicación de configuración proporcionada por el proveedor. Las aplicaciones normales no deberían necesitar este permiso."</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"Detectar cambios en el estado de la red"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Permite que una aplicación detecte cambios en el estado de la red. Las aplicaciones normales no deberían necesitar este permiso."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Establecer reglas de contraseña"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Controlar la longitud y los caracteres permitidos en las contraseñas para desbloquear la pantalla"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Supervisa los intentos para desbloquear la pantalla"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index c12cb76c519a..f3c990346e82 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"evitar cambios de aplicación"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Evita que el usuario cambie a otra aplicación."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"obtener información de la aplicación actual"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Permite que el titular recupere información privada sobre la aplicación actual en el primer plano de la pantalla."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"supervisar y controlar la ejecución de todas las aplicaciones"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Permite que la aplicación supervise y controle la ejecución de las actividades del sistema. Las aplicaciones malintencionadas pueden vulnerar la seguridad del sistema. Este permiso es necesario únicamente para tareas de desarrollo, nunca para el uso habitual."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"enviar emisión eliminada de paquete"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Permite que la aplicación configure pantallas Wi-Fi y se conecte a ellas."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"controlar pantallas Wi-Fi"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Permite que la aplicación controle funciones de bajo nivel de pantallas Wi-Fi."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"capturar salida de audio"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Permite que la aplicación capture y redirija la salida de audio."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"capturar salida de vídeo"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Permite que la aplicación capture y redirija la salida de vídeo."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"capturar salida de vídeo segura"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Permite que la aplicación capture y redirija la salida de vídeo segura."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"cambiar la configuración de audio"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Permite que la aplicación modifique la configuración de audio global (por ejemplo, el volumen y el altavoz de salida)."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"grabar sonido"</string>
@@ -659,6 +654,8 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permite enlazar con la interfaz de nivel superior de un servicio de detector de notificaciones. No debe ser necesario para las aplicaciones normales."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"ejecutar la aplicación de configuración proporcionada por el operador"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permite ejecutar la aplicación de configuración proporcionada por el operador. No debe ser necesario para aplicaciones normales."</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"detectar cambios en el estado de la red"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Permite que una aplicación detecte cambios en el estado de la red. No debe ser necesario para aplicaciones normales."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Establecimiento de reglas de contraseña"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Controlar la longitud y los caracteres permitidos en las contraseñas de bloqueo de pantalla"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Control de intentos de bloqueo de pantalla"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 82243c1a802d..bf71a02f8efa 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"väldi rakenduste ümberlülitamist"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Takistab kasutaja lülitumist teisele rakendusele."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"aktiivse rakenduse teabe hankimine"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Lubab õiguste saajal hankida privaatset teavet ekraanil esiplaanil oleva aktiivse rakenduse kohta."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"Kõigi rakenduste käivitumise jälgimine ja juhtimine"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Võimaldab rakendusel jälgida ja juhtida, kuidas süsteem tegevusi käivitab. Pahatahtlikud rakendused võivad süsteemi täielikult rikkuda. Seda õigust on vaja ainult arenduseks, mitte tavakasutuse korral."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"saada paketist eemaldatud saade"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Lubab rakendusel seadistada WiFi-ekraane ja nendega ühendus luua."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"WiFi-ekraanide juhtimine"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Lubab rakendusel juhtida WiFi-ekraanide madala taseme funktsioone."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"heliväljundi jäädvustamine"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Lubab rakendusel jäädvustada ja ümber suunata heliväljundit."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"videoväljundi jäädvustamine"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Lubab rakendusel jäädvustada ja ümber suunata videoväljundit."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"kaitstud videoväljundi jäädvustamine"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Lubab rakendusel jäädvustada ja ümber suunata kaitstud videoväljundit."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"muuda heliseadeid"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Võimaldab rakendusel muuta üldiseid heliseadeid, näiteks helitugevust ja seda, millist kõlarit kasutatakse väljundiks."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"salvesta heli"</string>
@@ -659,6 +654,10 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Võimaldab omanikul siduda märguannete kuulamisteenuse ülemise taseme kasutajaliidese. Seda ei tohiks tavarakenduste puhul kunagi vaja olla."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"operaatoripoolse konfiguratsioonirakenduse aktiveerimine"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Lubab omanikul aktiveerida operaatoripoolse konfiguratsioonirakenduse. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
+ <!-- no translation found for permlab_accessNetworkConditions (8206077447838909516) -->
+ <skip />
+ <!-- no translation found for permdesc_accessNetworkConditions (6899102075825272211) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Parooli reeglite määramine"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontrollige ekraaniluku avamise paroolide pikkust ja tähemärke."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Ekraani avamiskatsed"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 3216d9907b31..8aa97cdf071d 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"ممانعت از جابجایی برنامه"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"اجازه نمی‎دهد کاربر به برنامه دیگری برود."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"Ø¯Ø±ÛŒØ§ÙØª اطلاعات برنامه ÙØ¹Ù„ÛŒ"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"به دارنده اجازه می‌دهد اطلاعات خصوصی مربوط به برنامه ÙØ¹Ù„ÛŒ را در پیش زمینه ØµÙØ­Ù‡ بازیابی کند."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"نظارت و کنترل راه‌اندازی همه برنامه"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"به برنامه اجازه می‎دهد تا نحوه راه‌اندازی ÙØ¹Ø§Ù„یت‌های سیستم را کنترل کند. برنامه‎های مخرب می‎توانند کاملا با سیستم سازگار شوند. این مجوز Ùقط برای توسعه نیاز است Ùˆ برای Ø§Ø³ØªÙØ§Ø¯Ù‡ عادی نیست."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"ارسال پخش بسته حذ٠شده"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"به برنامه اجازه می‌دهد تا اتصال به ØµÙØ­Ø§Øª نمایش Wi‑Fi را پیکربندی کند."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"کنترل ØµÙØ­Ù‡ نمایش‌های Wi‑Fi"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"به برنامه اجازه می‌دهد Ú©Ù‡ ویژگی‌های سطح پایین ØµÙØ­Ù‡â€ŒÙ‡Ø§ÛŒ نمایش Wi‑Fi را کنترل کند."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"ضبط خروجی صدا"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"به برنامه امکان می‌دهد خروجی صدا را ضبط و هدایت کند."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"ضبط خروجی ویدیو"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"به برنامه امکان می‌دهد خروجی ویدیو را ضبط و هدایت کند."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"ضبط خروجی ویدیوی ایمن"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"به برنامه امکان می‌دهد خروجی ویدیوی ایمن را ضبط و هدایت کند."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"تغییر تنظیمات صوتی"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"به برنامه امکان می‌دهد تنظیمات صوتی Ú©Ù„ÛŒ مانند میزان صدا Ùˆ بلندگوی مورد Ø§Ø³ØªÙØ§Ø¯Ù‡ برای پخش صدا را اصلاح کند."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"ضبط صدا"</string>
@@ -659,6 +654,10 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"به دارنده اجازه می‌دهد به یک رابط سطح بالای سرویس شنونده اعلان متصل شود. هرگز نباید برای برنامه‌های عادی لازم شود."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"لغو برنامه پیکربندی ارائه شده توسط شرکت مخابراتی"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"به دارنده اجازه می‌دهد که تنظیمات برنامه شرکت مخابراتی را لغو کند. هرگز برای برنامه‌های معمولی مورد نیاز نیست."</string>
+ <!-- no translation found for permlab_accessNetworkConditions (8206077447838909516) -->
+ <skip />
+ <!-- no translation found for permdesc_accessNetworkConditions (6899102075825272211) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"تنظیم قوانین رمز ورود"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"طول Ùˆ نویسه‎های مجاز در گذرواژه‌های بازکردن Ù‚ÙÙ„ ØµÙØ­Ù‡ را کنترل کنید."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"نمایش تلاش‌های Ù‚ÙÙ„ گشایی ØµÙØ­Ù‡"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 86a793f5bc68..bdc87974e1f5 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"estä sovellusten vaihto"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Estää käyttäjää siirtymästä toiseen sovellukseen."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"hae nykyisen sovelluksen tiedot"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Antaa sovellukselle luvan noutaa nykyistä sovellusta koskevia yksityisiä tietoja ruudun etualalla."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"kaikkien sovellusten käynnistämisen valvonta ja hallinta"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Antaa sovelluksen valvoa ja hallita sitä, miten laite käynnistää toimintoja. Haitalliset sovellukset voivat vaarantaa laitteen käytön. Tätä oikeutta tarvitaan vain kehityskäyttöön eikä koskaan tavalliseen käyttöön."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"lähetä paketeista poistettuja lähetyksiä"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Antaa sovelluksen määrittää wifi-näyttöjä ja muodostaa yhteyden niihin."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"hallitse wifi-näyttöjä"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Antaa sovelluksen hallita wifi-näyttöjen matalan tason ominaisuuksia."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"äänentoiston kaappaus"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Antaa sovellukselle luvan äänentoiston kaappaamiseen ja uudelleenohjaamiseen."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"videokuvan kaappaus"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Antaa sovellukselle luvan videokuvan kaappaamiseen ja uudelleenohjaamiseen"</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"suojatun videokuvan kaappaus"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Antaa sovellukselle luvan suojatun videokuvan kaappaamiseen ja uudelleenohjaamiseen."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"muuta ääniasetuksia"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Antaa sovelluksen muokata yleisiä ääniasetuksia, kuten äänenvoimakkuutta ja käytettävää kaiutinta."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"tallentaa ääntä"</string>
@@ -659,6 +654,8 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Antaa sovelluksen sitoutua ilmoituskuuntelijan ylimmän tason käyttöliittymään. Ei tavallisten sovelluksien käyttöön."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"Palveluntarjoajan määrityssovelluksen käynnistäminen"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Antaa luvanhaltijan käynnistää palveluntarjoajan määrityssovelluksen. Ei tavallisten sovelluksien käyttöön."</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"verkon tilahavaintojen kuunteleminen"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Antaa sovellukselle luvan kuunnella verkon tilahavaintoja. Ei tavallisten sovellusten käyttöön."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Aseta salasanasäännöt"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Hallinnoi ruudun lukituksenpoistosalasanoissa sallittuja merkkejä ja salasanan pituutta."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Tarkkaile ruudun lukituksen poistoyrityksiä"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index f71be9461fdb..bca53e1f370b 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"empêcher les changements d\'applications"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Empêche l\'utilisateur de changer d\'application."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"Récupérer des informations sur l\'application actuelle"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Permet à l\'application autorisée de récupérer des informations confidentielles à propos de l\'application exécutée au premier plan sur l\'écran."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"suivre et contrôler le lancement de toutes les applications"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Permet à l\'application de surveiller et de contrôler la façon dont le système lance les activités. Des applications malveillantes peuvent exploiter cette fonctionnalité pour totalement compromettre le système. Cette autorisation est uniquement destinée aux développeurs. Elle ne doit jamais être activée dans le cadre d\'une utilisation standard."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"Envoyer une diffusion sans paquet"</string>
@@ -362,10 +363,8 @@
<string name="permdesc_bindPrintService" msgid="7960067623209111135">"Permet à l\'application autorisée de s\'associer à l\'interface de niveau supérieur d\'un service d\'impression. Cette fonctionnalité ne devrait pas être nécessaire pour les applications standards."</string>
<string name="permlab_accessAllPrintJobs" msgid="1120792468465711159">"accéder à l\'ensemble des tâches d\'impression"</string>
<string name="permdesc_accessAllPrintJobs" msgid="2978185311041864762">"Permet à l\'application autorisée d\'accéder aux tâches d\'impression créées via une autre application. Cette fonctionnalité ne devrait pas être nécessaire pour les applications standards."</string>
- <!-- no translation found for permlab_bindNfcService (2752731300419410724) -->
- <skip />
- <!-- no translation found for permdesc_bindNfcService (6120647629174066862) -->
- <skip />
+ <string name="permlab_bindNfcService" msgid="2752731300419410724">"s\'associer au service NFC"</string>
+ <string name="permdesc_bindNfcService" msgid="6120647629174066862">"Permet à l\'application autorisée de s\'associer aux applications qui reproduisent le fonctionnement des cartes NFC. Cette fonctionnalité ne devrait pas être nécessaire pour les applications standards."</string>
<string name="permlab_bindTextService" msgid="7358378401915287938">"associer à un service de texte"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Permet à l\'application de s\'associer à l\'interface de haut niveau d\'un service de texte (par exemple, SpellCheckerService). Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"associer à un service VPN"</string>
@@ -476,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Permet à l\'application de configurer des écrans Wi-Fi et de s\'y connecter."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"contrôler les écrans Wi-Fi"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Permet à l\'application de contrôler les fonctionnalités de base des écrans Wi-Fi."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"enregistrer les sorties audio"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Autoriser l\'application à enregistrer et à rediriger les sorties audio"</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"enregistrer les sorties vidéo"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Autoriser l\'application à enregistrer et à rediriger les sorties vidéo"</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"enregistrer les sorties vidéo sécurisées"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Autoriser l\'application à enregistrer et à rediriger les sorties vidéo sécurisées"</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"modifier vos paramètres audio"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Permet à l\'application de modifier les paramètres audio généraux, tels que le volume et la sortie audio utilisée."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"Enregistrer des fichiers audio"</string>
@@ -661,6 +654,8 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permet à l\'application de s\'associer à l\'interface de niveau supérieur d\'un service d\'écoute des notifications. Ne devrait jamais être nécessaire pour les applications normales."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"faire appel à l\'application de configuration fournie par l\'opérateur"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permet à l\'application autorisée de faire appel à l\'application de configuration fournie par l\'opérateur. Cette fonctionnalité ne devrait pas être nécessaire pour les applications standards."</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"détecter des observations sur les conditions du réseau"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Permet à une application de détecter des observations sur les conditions du réseau. Les applications standards ne devraient pas nécessiter cette autorisation."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Définir les règles du mot de passe"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Choisir le nombre et le type de caractères autorisés dans les mots de passe de déverrouillage de l\'écran"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Gérer les tentatives de déverrouillage de l\'écran"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 31f4cb6a0f23..d4f10f1ff59f 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"à¤à¤ªà¥â€à¤²à¤¿à¤•ेशन सà¥â€à¤µà¤¿à¤š करने से रोकता है"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"उपयोगकरà¥à¤¤à¤¾ को दूसरे à¤à¤ªà¥â€à¤²à¤¿à¤•ेशन पर सà¥â€à¤µà¤¿à¤š करने से रोकता है."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"वरà¥à¤¤à¤®à¤¾à¤¨ à¤à¤ªà¥à¤²à¤¿à¤•ेशन की जानकारी पà¥à¤°à¤¾à¤ªà¥à¤¤ करें"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"धारक को सà¥à¤•à¥à¤°à¥€à¤¨ के अगà¥à¤°à¤­à¤¾à¤— में सà¥à¤¥à¤¿à¤¤ वरà¥à¤¤à¤®à¤¾à¤¨ à¤à¤ªà¥à¤²à¤¿à¤•ेशन के बारे में निजी जानकारी पà¥à¤°à¤¾à¤ªà¥à¤¤ करने देती है."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"सभी à¤à¤ªà¥â€à¤²à¤¿à¤•ेशन की लॉनà¥â€à¤šà¤¿à¤‚ग की निगरानी करें और उसे नियंतà¥à¤°à¤¿à¤¤ करें"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"à¤à¤ªà¥à¤²à¤¿à¤•ेशन को यह निगरानी और नियंतà¥à¤°à¤¿à¤¤ करने देता है कि सिसà¥à¤Ÿà¤® कैसे गतिविधियां लॉनà¥à¤š करता है. दà¥à¤°à¥à¤­à¤¾à¤µà¤¨à¤¾à¤ªà¥‚रà¥à¤£ à¤à¤ªà¥à¤²à¤¿à¤•ेशन सिसà¥à¤Ÿà¤® को पूरी तरह से जोखिम में डाल सकते हैं. इस अनà¥à¤®à¤¤à¤¿ की आवशà¥à¤¯à¤•ता केवल विकास के लिठहै, सामानà¥à¤¯ उपयोग के लिठकभी नहीं."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"पैकेज निकाले गठपà¥à¤°à¤¸à¤¾à¤°à¤£ भेजें"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"à¤à¤ªà¥à¤²à¤¿à¤•ेशन को कॉनà¥à¤«à¤¼à¤¿à¤—र करने देता है और Wifi डिसà¥à¤ªà¥à¤²à¥‡ से कनेकà¥à¤Ÿ करता है."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"Wifi डिसà¥à¤ªà¥à¤²à¥‡ को नियंतà¥à¤°à¤¿à¤¤ करें"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"à¤à¤ªà¥à¤²à¤¿à¤•ेशन को Wifi डिसà¥à¤ªà¥à¤²à¥‡ की निमà¥à¤¨-सà¥à¤¤à¤° की सà¥à¤µà¤¿à¤§à¤¾à¤à¤‚ नियंतà¥à¤°à¤¿à¤¤ करने देता है."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"ऑडियो आउटपà¥à¤Ÿ को कैपà¥â€à¤šà¤° करें"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"à¤à¤ªà¥â€à¤²à¤¿à¤•ेशन को ऑडियो आउटपà¥à¤Ÿ को कैपà¥â€à¤šà¤° और रीडायरेकà¥â€à¤Ÿ करने देता है."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"वीडियो आउटपà¥à¤Ÿ को कैपà¥â€à¤šà¤° करें"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"à¤à¤ªà¥â€à¤²à¤¿à¤•ेशन को वीडियो आउटपà¥à¤Ÿ को कैपà¥â€à¤šà¤° और रीडायरेकà¥â€à¤Ÿ करने देता है."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ वीडियो आउटपà¥à¤Ÿ को कैपà¥â€à¤šà¤° करें"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"à¤à¤ªà¥â€à¤²à¤¿à¤•ेशन को सà¥à¤°à¤•à¥à¤·à¤¿à¤¤ वीडियो आउटपà¥à¤Ÿ को कैपà¥â€à¤šà¤° और रीडायरेकà¥â€à¤Ÿ करने देता है."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"अपनी ऑडियो सेटिंग बदलें"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"à¤à¤ªà¥à¤²à¤¿à¤•ेशन को वैशà¥à¤µà¤¿à¤• ऑडियो सेटिंग, जैसे वॉलà¥â€à¤¯à¥‚म और कौन-सा सà¥à¤ªà¥€à¤•र आउटपà¥à¤Ÿ के लिठउपयोग किया गया, संशोधित करने देता है."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"ऑडियो रिकॉरà¥à¤¡ करें"</string>
@@ -659,6 +654,8 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"धारक को सूचना शà¥à¤°à¤µà¤£à¤•रà¥à¤¤à¤¾ सेवा के शीरà¥à¤· सà¥à¤¤à¤°à¥€à¤¯ इंटरफ़ेस से जà¥à¤¡à¤¼à¤¨à¥‡ देती है. सामानà¥à¤¯ à¤à¤ªà¥à¤²à¤¿à¤•ेशन के लिठकभी भी आवशà¥à¤¯à¤• नहीं होनी चाहिà¤."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"वाहक के दà¥à¤µà¤¾à¤°à¤¾ उपलबà¥à¤§ कराया गया कॉनà¥à¤«à¤¼à¤¿à¤—रेशन à¤à¤ªà¥à¤²à¤¿à¤•ेशन पà¥à¤°à¤¾à¤°à¤‚भ करें"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"धारक को वाहक के दà¥à¤µà¤¾à¤°à¤¾ उपलबà¥à¤§ कराया गया कॉनà¥à¤«à¤¼à¤¿à¤—रेशन à¤à¤ªà¥à¤²à¤¿à¤•ेशन पà¥à¤°à¤¾à¤°à¤‚भ करने देता है. सामानà¥â€à¤¯ à¤à¤ªà¥â€à¤²à¤¿à¤•ेशन के लिठकभी भी आवशà¥â€à¤¯à¤• नहीं होना चाहिà¤."</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"नेटवरà¥à¤• सà¥à¤¥à¤¿à¤¤à¤¿à¤¯à¥‹à¤‚ के अवलोकनों को सà¥à¤¨à¥‡à¤‚"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"à¤à¤ªà¥à¤²à¤¿à¤•ेशन को नेटवरà¥à¤• सà¥à¤¥à¤¿à¤¤à¤¿à¤¯à¥‹à¤‚ के अवलोकनों को सà¥à¤¨à¤¨à¥‡Â à¤¦à¥‡à¤¤à¤¾ है. सामानà¥à¤¯ à¤à¤ªà¥à¤²à¤¿à¤•ेशन के लिठकभी भी आवशà¥à¤¯à¤• नहीं होना चाहिà¤."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"पासवरà¥à¤¡ नियम सेट करें"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"सà¥â€à¤•à¥à¤°à¥€à¤¨-अनलॉक पासवरà¥à¤¡ में अनà¥à¤®à¤¤à¤¿ पà¥à¤°à¤¾à¤ªà¥à¤¤ लंबाई और वरà¥à¤£à¥‹à¤‚ को नियंतà¥à¤°à¤¿à¤¤ करें."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"सà¥â€à¤•à¥à¤°à¥€à¤¨-अनलॉक के पà¥à¤°à¤¯à¤¾à¤¸à¥‹à¤‚ पर निगरानी रखें"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 88e6a91b50dd..0d7d9bf74953 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"spreÄavanje promjene aplikacije"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"SprjeÄava korisnika u prebacivanju na drugu aplikaciju."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"dohvaćanje informacija o trenutaÄnoj aplikaciji"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Omogućuje nositelju dohvaćanje privatnih informacija o trenutaÄnoj aplikaciji u prednjem planu na zaslonu."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"praćenje i nadzor svih pokretanja aplikacija"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Omogućuje aplikaciji nadzor i upravljanje naÄinom na koji sustav pokreće aktivnosti. Zlonamjerne aplikacije mogu posve ugroziti sustav. Ta je dozvola potrebna samo za razvoj, nikada za uobiÄajenu upotrebu."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"slanje paketno uklonjenog prijenosa"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Omogućuje aplikaciji konfiguriranje i povezivanje s Wi-Fi zaslonima."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"upravljaj Wifi zaslonima"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Omogućuje aplikaciji upravljanje znaÄajkama Wi-Fi zaslona niske razine."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"primanje audioizlaza"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Omogućuje aplikaciji primanje i preusmjeravanje audioizlaza."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"primanje videoizlaza"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Omogućuje aplikaciji primanje i preusmjeravanje videoizlaza."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"primanje sigurnog videoizlaza"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Omogućuje aplikaciji primanje i preusmjeravanje sigurnog videoizlaza."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"promjena postavki zvuka"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Aplikaciji omogućuje izmjenu globalnih postavki zvuka, primjerice glasnoće i zvuÄnika koji se upotrebljava za izlaz."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"snimanje zvuka"</string>
@@ -659,6 +654,10 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Nositelju omogućuje vezanje uz suÄelje najviÅ¡e razine usluge sluÅ¡atelja obavijesti. Ne bi smjelo biti potrebno za uobiÄajene aplikacije."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"pozovi operaterovu aplikaciju za konfiguraciju"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"DopuÅ¡ta nositelju pozivanje operaterove aplikacije za konfiguraciju. Ne bi smjelo biti potrebno za uobiÄajene aplikacije."</string>
+ <!-- no translation found for permlab_accessNetworkConditions (8206077447838909516) -->
+ <skip />
+ <!-- no translation found for permdesc_accessNetworkConditions (6899102075825272211) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Postavi pravila zaporke"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Upravljajte duljinom zaporki za otkljuÄavanje zaslona i dopuÅ¡tenim znakovima u tim zaporkama."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Nadgledaj pokuÅ¡aje otkljuÄavanja zaslona"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index ee458b87fee8..d9d570c77ddc 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"alkalmazásváltás megakadályozása"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Megakadályozza, hogy a felhasználó átváltson egy másik alkalmazásra."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"az alkalmazás aktuális információinak lekérése"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Lehetővé teszi, hogy a felhasználó privát adatokat kérjen le az aktuális alkalmazásról a képernyő előterében."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"alkalmazásindítások nyomon követése és vezérlése"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Lehetővé teszi az alkalmazás számára, hogy figyelje és vezérelje, hogy a rendszer hogyan indít el tevékenységeket. A rosszindulatú alkalmazások teljesen tönkretehetik a rendszert. Ez az engedély csak fejlesztéshez szükséges, normál használathoz sosem."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"eltávolított csomagú üzenetek küldése"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Lehetővé teszi, hogy az alkalmazás Wi-Fi kijelzőket konfiguráljon, és csatlakozzon hozzájuk."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"Wi-Fi kijelzők irányítása"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Lehetővé teszi, hogy az alkalmazás irányítsa a Wi-Fi kijelzők alacsonyabb szintű funkcióit."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"audiokimenet rögzítése"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Engedélyezi az alkalmazásnak a hangkimenet rögzítését és átirányítását."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"videokimenet rögzítése"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Engedélyezi az alkalmazásnak a videokimenet rögzítését és átirányítását."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"biztonságos videokimenet rögzítése"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Engedélyezi az alkalmazásnak a biztonságos videokimenet rögzítését és átirányítását."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"hangbeállítások módosítása"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Lehetővé teszi az alkalmazás számára az általános hangbeállítások, például a hangerő és a használni kívánt kimeneti hangszóró módosítását."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"hanganyag rögzítése"</string>
@@ -659,6 +654,8 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Lehetővé teszi a használó számára, hogy csatlakozzon egy értesítésfigyelő szolgáltatás legfelső szintű felületéhez. A normál alkalmazásoknak erre soha nincs szükségük."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"a szolgáltatói konfigurációs alkalmazás hívása"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Lehetővé teszi a használó számára a szolgáltató által biztosított konfigurációs alkalmazás hívását. A normál alkalmazásoknak erre soha nincs szükségük."</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"hálózati körülményekkel kapcsolatos észrevételek figyelemmel kísérése"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Lehetővé teszi egy alkalmazás számára, hogy figyelemmel kísérje a hálózati körülményekkel kapcsolatos észrevételeket. A normál alkalmazásoknak erre soha nincs szükségük."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Jelszavakkal kapcsolatos szabályok beállítása"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"A képernyőzár-feloldási jelszavakban engedélyezett karakterek és hosszúság vezérlése."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Képernyőzár-feloldási kísérletek figyelése"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index bc8517c2bd21..9892d105519e 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"cegah pergantian aplikasi"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Mencegah pengguna beralih ke apl lain."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"dapatkan info tentang aplikasi yang aktif"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Memungkinkan pemegang mengambil informasi pribadi tentang aplikasi yang aktif di latar depan layar."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"memantau dan mengontrol semua peluncuran apl"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Mengizinkan apl memantau dan mengontrol cara sistem meluncurkan kegiatan. Apl berbahaya dapat meretas sistem sepenuhnya. Izin ini hanya diperlukan untuk pengembangan, tidak pernah diperlukan untuk penggunaan normal."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"kirim siaran paket dihapus"</string>
@@ -362,10 +363,8 @@
<string name="permdesc_bindPrintService" msgid="7960067623209111135">"Memungkinkan pemegang mengikat antarmuka tingkat tinggi dari suatu layanan pencetakan. Tidak pernah diperlukan oleh aplikasi normal."</string>
<string name="permlab_accessAllPrintJobs" msgid="1120792468465711159">"mengakses semua tugas pencetakan"</string>
<string name="permdesc_accessAllPrintJobs" msgid="2978185311041864762">"Memungkinkan pemegang mengakses tugas pencetakan yang dibuat oleh aplikasi lain. Tidak pernah diperlukan aplikasi normal."</string>
- <!-- no translation found for permlab_bindNfcService (2752731300419410724) -->
- <skip />
- <!-- no translation found for permdesc_bindNfcService (6120647629174066862) -->
- <skip />
+ <string name="permlab_bindNfcService" msgid="2752731300419410724">"mengikat ke layanan NFC"</string>
+ <string name="permdesc_bindNfcService" msgid="6120647629174066862">"Memungkinkan pemegang mengikat ke aplikasi yang meniru kartu NFC. Tidak pernah dibutuhkan untuk aplikasi normal."</string>
<string name="permlab_bindTextService" msgid="7358378401915287938">"mengikat ke layanan SMS"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Mengizinkan pemegang mengikat antarmuka tingkat tinggi dari suatu layanan teks (misal: SpellCheckerService). Tidak pernah diperlukan oleh apl normal."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"mengikat ke layanan VPN"</string>
@@ -476,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Izinkan aplikasi mengonfigurasi dan terhubung ke tampilan Wi-Fi."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"mengontrol tampilan Wi-Fi"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Izinkan aplikasi mengontrol fitur tingkat rendah dari tampilan Wi-Fi."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"tangkap keluaran audio"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Memungkinkan aplikasi menangkap dan mengalihkan keluaran audio."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"tangkap keluaran video"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Memungkinkan aplikasi menangkap dan mengalihkan keluaran video."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"tangkap keluaran video aman"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Memungkinkan aplikasi menangkap dan mengalihkan keluaran video aman."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"ubah setelan audio Anda"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Memungkinkan aplikasi mengubah setelan audio global, misalnya volume dan pengeras suara mana yang digunakan untuk keluaran."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"rekam audio"</string>
@@ -661,6 +654,10 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Memungkinkan pemegang mengikat antarmuka tingkat teratas dari suatu layanan pendengar pemberitahuan. Tidak pernah diperlukan oleh aplikasi normal."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"memanggil aplikasi konfigurasi yang disediakan operator"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Memungkinkan pemegang meminta aplikasi konfigurasi yang disediakan operator. Tidak pernah diperlukan aplikasi normal."</string>
+ <!-- no translation found for permlab_accessNetworkConditions (8206077447838909516) -->
+ <skip />
+ <!-- no translation found for permdesc_accessNetworkConditions (6899102075825272211) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Setel aturan sandi"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontrol panjang dan karakter yang diizinkan dalam sandi pembuka layar."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Upaya pembukaan kunci layar monitor"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 60f40ae00065..4a5c12b69b24 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"impedire commutazione applicazione"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Impedisce all\'utente di passare a un\'altra applicazione."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"recupero di informazioni sull\'app corrente"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Consente al titolare di recuperare le informazioni private sull\'app correntemente in primo piano sullo schermo."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"monitoraggio e controllo avvio di tutte le applicazioni"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Consente all\'applicazione di monitorare e controllare l\'avvio delle attività da parte del sistema. Le applicazioni dannose potrebbero compromettere completamente il sistema. Questa autorizzazione è necessaria solo per lo sviluppo, mai per l\'utilizzo normale."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"invio broadcast rimossi dal pacchetto"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Consente all\'applicazione di configurare schermi Wi-Fi e di collegarsi a essi."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"controllo di schermi Wi-Fi"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Consente all\'applicazione di controllare le funzioni di basso livello di schermi Wi-Fi."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"acquisizione dell\'uscita audio"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Consente all\'app di acquisire e reindirizzare l\'uscita audio."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"acquisizione dell\'uscita video"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Consente all\'app di acquisire e reindirizzare l\'uscita video."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"acquisizione dell\'uscita video sicura"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Consente all\'app di acquisire e reindirizzare l\'uscita video sicura."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"modifica impostazioni audio"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Consente all\'applicazione di modificare le impostazioni audio globali, come il volume e quale altoparlante viene utilizzato per l\'uscita."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"registrazione audio"</string>
@@ -659,6 +654,8 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Consente al titolare di vincolarsi all\'interfaccia di primo livello di un servizio listener di notifica. Non dovrebbe mai essere necessaria per le normali applicazioni."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"richiamo dell\'app di configurazione operatore-provider"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Consente al titolare di richiamare l\'app di configurazione dell\'operatore-provider. Non dovrebbe essere mai necessaria per le normali applicazioni."</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"ascolto delle osservazioni sulle condizioni di rete"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Consente a un\'applicazione di ascoltare le osservazioni sulle condizioni di rete. Da non utilizzare mai con app normali."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Imposta regole password"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Controlla la lunghezza e i caratteri ammessi nelle password di sblocco dello schermo."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Monitora tentativi di sblocco dello schermo"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 2c8406079021..2c052b7d171b 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"מנע החלפת יישומי×"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"מניעת מעבר ×œ×™×™×©×•× ×חר על ידי המשתמש."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"קבל ×¤×¨×˜×™× ×¢×œ ×”×™×™×©×•× ×”× ×•×›×—×™"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"מ×פשר ×œ×‘×¢×œ×™× ×œ×חזר מידע פרטי לגבי ×”×™×™×©×•× ×”× ×•×›×—×™ שבקדמת המסך."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"ניהול מעקב ושליטה על כל הפעלות היישומי×"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"מ×פשר ×œ×™×™×©×•× ×œ× ×”×œ מעקב ×חר ×”×ופן שבו המערכת מפעילה פעילויות, ולשלוט בו. ×™×™×©×•×ž×™× ×–×“×•× ×™×™× ×¢×œ×•×œ×™× ×œ×¡×›×Ÿ ×ת המערכת כולה. הרש××” זו ××™× ×” נחוצה לשימוש רגיל, ××œ× ×œ×¤×™×ª×•×— בלבד."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"שלח שידור שהוסר מחבילה"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"מ×פשר ל×פליקציה להגדיר ולהתחבר לתצוגות Wi-Fi."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"שלוט בתצוגות Wi-Fi"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"מ×פשר ל×פליקציה לשלוט בתכונות ברמה נמוכה של תצוגות Wi-Fi."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"קליטת פלט ×ודיו"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"מ×פשרת ל×פליקציה לקלוט ולהפנות מחדש פלט ×ודיו."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"קליטת פלט ויד×ו"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"מ×פשרת ל×פליקציה לקלוט ולהפנות מחדש פלט ויד×ו."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"קליטת פלט ויד×ו מ×ובטח"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"מ×פשרת ל×פליקציה לקלוט ולהפנות מחדש פלט ויד×ו מ×ובטח."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"שנה ×ת הגדרות ×”×ודיו שלך"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"מ×פשר ×œ×™×™×©×•× ×œ×©× ×•×ª הגדרות ×ודיו גלובליות כמו עוצמת קול ובחירת הרמקול המשמש לפלט."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"הקלט ×ודיו"</string>
@@ -659,6 +654,8 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"הרש××” זו מ×פשרת למשתמש לבצע ×יגוד לממשק הרמה העליונה של שירות מ×זין להתר×ות. הרש××” זו ××£ ×¤×¢× ××™× ×” נחוצה ×œ×™×™×©×•×ž×™× ×¨×’×™×œ×™×."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"הפעלה של ×פליקציית תצורה שסופקה על ידי ספק"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"ההרש××” הזו מ×פשרת ×œ×‘×¢×œ×™× ×œ×”×¤×¢×™×œ ×ת ×פליקציית התצורה שסופקה על ידי ספק. ×œ×¢×•×œ× ×œ× ×מורה להיות נחוצה עבור ×פליקציות רגילות."</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"קליטת מעקב ×חר תנ××™ רשת"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"מ×פשרת ל×פליקציה לקלוט מעקב ×חר תנ××™ רשת. ×œ×¢×•×œ× ×œ× ×מורה להיות נחוצה עבור ×פליקציות רגילות."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"הגדר כללי סיסמה"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"שלוט ב×ורך ×•×‘×ª×•×•×™× ×”×ž×•×ª×¨×™× ×‘×¡×™×¡×ž×ות לביטול נעילת מסך."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"עקוב ×חר ניסיונות לביטול נעילת מסך"</string>
@@ -1125,7 +1122,7 @@
<string name="screen_compat_mode_hint" msgid="1064524084543304459">"×פשר תכונה זו מחדש ב\'הגדרות מערכת\' &lt;†Google Apps†&lt; \'הורדות\'."</string>
<string name="smv_application" msgid="3307209192155442829">"×”×™×™×©×•× <xliff:g id="APPLICATION">%1$s</xliff:g> (תהליך <xliff:g id="PROCESS">%2$s</xliff:g>) הפר ×ת מדיניות StrictMode ב×כיפה עצמית שלו."</string>
<string name="smv_process" msgid="5120397012047462446">"התהליך <xliff:g id="PROCESS">%1$s</xliff:g> הפר ×ת מדיניות StrictMode ב×כיפה עצמית."</string>
- <string name="android_upgrading_title" msgid="1584192285441405746">"Android מבצע שדרוג..."</string>
+ <string name="android_upgrading_title" msgid="1584192285441405746">"â€Android מבצע שדרוג…"</string>
<string name="android_upgrading_apk" msgid="7904042682111526169">"מבצע ×ופטימיזציה של ×™×™×©×•× <xliff:g id="NUMBER_0">%1$d</xliff:g> מתוך <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"מפעיל יישומי×."</string>
<string name="android_upgrading_complete" msgid="1405954754112999229">"×ž×¡×™×™× ×תחול."</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index d94a978f7a8b..031d7f1400fd 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"アプリケーションã®åˆ‡ã‚Šæ›¿ãˆã‚’ç¦æ­¢ã™ã‚‹"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"ユーザーãŒåˆ¥ã®ã‚¢ãƒ—リã«åˆ‡ã‚Šæ›¿ãˆã‚‰ã‚Œãªã„よã†ã«ã—ã¾ã™ã€‚"</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"ç¾åœ¨ã®ã‚¢ãƒ—リ情報ã®å–å¾—"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"ç”»é¢ã®ãƒ•ォアグラウンドã§ç¾åœ¨ã®ã‚¢ãƒ—リã«é–¢ã™ã‚‹éžå…¬é–‹æƒ…報をå–å¾—ã™ã‚‹ã“ã¨ã‚’所有者ã«è¨±å¯ã—ã¾ã™ã€‚"</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"ã™ã¹ã¦ã®ã‚¢ãƒ—リ起動ã®ç›£è¦–ã¨åˆ¶å¾¡"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"システムã«ã‚ˆã‚‹ã‚¢ã‚¯ãƒ†ã‚£ãƒ“ティ起動方法を監視ã—制御ã™ã‚‹ã“ã¨ã‚’アプリã«è¨±å¯ã—ã¾ã™ã€‚ã“ã®è¨±å¯ã‚’悪æ„ã®ã‚るアプリã«åˆ©ç”¨ã•れるã¨ã€ã‚·ã‚¹ãƒ†ãƒ å…¨ä½“ã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãŒä¾µå®³ã•れるæã‚ŒãŒã‚りã¾ã™ã€‚ã“ã®è¨±å¯ã¯é–‹ç™ºæ™‚ã«ã®ã¿å¿…è¦ã§ã€é€šå¸¸ã®ä½¿ç”¨ã§ã¯ä¸è¦ã§ã™ã€‚"</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"パッケージ削除ブロードキャストã®é€ä¿¡"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Wi-Fiディスプレイを設定ã—ã¦æŽ¥ç¶šã™ã‚‹ã“ã¨ã‚’アプリã«è¨±å¯ã—ã¾ã™ã€‚"</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"Wi-Fiディスプレイã®åˆ¶å¾¡"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Wi-Fiディスプレイã®ä½Žãƒ¬ãƒ™ãƒ«æ©Ÿèƒ½ã‚’制御ã™ã‚‹ã“ã¨ã‚’アプリã«è¨±å¯ã—ã¾ã™ã€‚"</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"音声出力ã®ã‚­ãƒ£ãƒ—ãƒãƒ£"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"音声出力ã®ã‚­ãƒ£ãƒ—ãƒãƒ£ã¨ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆã‚’アプリã«è¨±å¯ã—ã¾ã™ã€‚"</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"動画出力ã®ã‚­ãƒ£ãƒ—ãƒãƒ£"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"動画出力ã®ã‚­ãƒ£ãƒ—ãƒãƒ£ã¨ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆã‚’アプリã«è¨±å¯ã—ã¾ã™ã€‚"</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"セキュリティä¿è­·ã•れãŸå‹•画出力ã®ã‚­ãƒ£ãƒ—ãƒãƒ£"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"セキュリティä¿è­·ã•れãŸå‹•画出力ã®ã‚­ãƒ£ãƒ—ãƒãƒ£ã¨ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆã‚’アプリã«è¨±å¯ã—ã¾ã™ã€‚"</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"音声設定ã®å¤‰æ›´"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"音声全般ã®è¨­å®šï¼ˆéŸ³é‡ã€å‡ºåŠ›ã«ä½¿ç”¨ã™ã‚‹ã‚¹ãƒ”ーカーãªã©ï¼‰ã®å¤‰æ›´ã‚’アプリã«è¨±å¯ã—ã¾ã™ã€‚"</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"録音"</string>
@@ -659,6 +654,8 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"通知リスナーサービスã®ãƒˆãƒƒãƒ—レベルインターフェースã«ãƒã‚¤ãƒ³ãƒ‰ã™ã‚‹ã“ã¨ã‚’所有者ã«è¨±å¯ã—ã¾ã™ã€‚通常ã®ã‚¢ãƒ—リã§ã¯ä¸è¦ã§ã™ã€‚"</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"æºå¸¯é€šä¿¡ä¼šç¤¾ãŒæä¾›ã™ã‚‹è¨­å®šã‚¢ãƒ—リã®å‘¼ã³å‡ºã—"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"æºå¸¯é€šä¿¡ä¼šç¤¾ãŒæä¾›ã™ã‚‹è¨­å®šã‚¢ãƒ—リを呼ã³å‡ºã™ã“ã¨ã‚’所有者ã«è¨±å¯ã—ã¾ã™ã€‚通常ã®ã‚¢ãƒ—リã§ã¯ä¸è¦ã§ã™ã€‚"</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯çжæ³ç›£è¦–ã®ãŸã‚ã®ãƒªãƒƒã‚¹ãƒ³"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯çжæ³ã‚’監視ã™ã‚‹ãŸã‚リッスンã™ã‚‹ã“ã¨ã‚’アプリã«è¨±å¯ã—ã¾ã™ã€‚通常ã®ã‚¢ãƒ—リã§å¿…è¦ã«ãªã‚‹ã“ã¨ã¯ã‚りã¾ã›ã‚“。"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"パスワードルールã®è¨­å®š"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"ç”»é¢ãƒ­ãƒƒã‚¯è§£é™¤ãƒ‘スワードã®é•·ã•ã¨ä½¿ç”¨ã§ãる文字を制御ã—ã¾ã™ã€‚"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"ç”»é¢ãƒ­ãƒƒã‚¯è§£é™¤è©¦è¡Œã®ç›£è¦–"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 3d46bb629e57..7d4e40774117 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"애플리케ì´ì…˜ 전환 ë°©ì§€"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"사용ìžê°€ 다른 앱으로 전환하지 못하게 합니다."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"현재 앱 정보 얻기"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"ê¶Œí•œì„ ê°€ì§„ í”„ë¡œê·¸ëž¨ì´ í™”ë©´ì˜ í¬ê·¸ë¼ìš´ë“œì—서 현재 애플리케ì´ì…˜ì— 대한 비공개 정보를 검색하ë„ë¡ í—ˆìš©í•©ë‹ˆë‹¤."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"실행 ì¤‘ì¸ ëª¨ë“  앱 ëª¨ë‹ˆí„°ë§ ë° ì œì–´"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"ì•±ì´ ì‹œìŠ¤í…œì—서 활ë™ì´ 시작ë˜ëŠ” ë°©ì‹ì„ 모니터ë§í•˜ê³  관리할 수 있ë„ë¡ í—ˆìš©í•©ë‹ˆë‹¤. ì´ ê²½ìš° 악성 ì•±ì´ ì´ ê¸°ëŠ¥ì„ ì´ìš©í•˜ì—¬ ì‹œìŠ¤í…œì„ ì™„ì „ížˆ ì†ìƒì‹œí‚¬ 수 있습니다. ì´ ê¶Œí•œì€ ê°œë°œ 과정ì—ë§Œ 필요하며 ì¼ë°˜ 사용 시ì—는 필요하지 않습니다."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"패키지 제거 브로드ìºìŠ¤íŠ¸ 보내기"</string>
@@ -362,10 +363,8 @@
<string name="permdesc_bindPrintService" msgid="7960067623209111135">"ê¶Œí•œì„ ê°€ì§„ í”„ë¡œê·¸ëž¨ì´ ì¸ì‡„ ì„œë¹„ìŠ¤ì— ëŒ€í•œ 최ìƒìœ„ ì¸í„°íŽ˜ì´ìŠ¤ë¥¼ 사용하ë„ë¡ í•©ë‹ˆë‹¤. ì¼ë°˜ 앱ì—는 필요하지 않습니다."</string>
<string name="permlab_accessAllPrintJobs" msgid="1120792468465711159">"모든 ì¸ì‡„ ìž‘ì—…ì— ì•¡ì„¸ìŠ¤"</string>
<string name="permdesc_accessAllPrintJobs" msgid="2978185311041864762">"ê¶Œí•œì„ ê°€ì§„ í”„ë¡œê·¸ëž¨ì´ ë‹¤ë¥¸ 앱ì—서 ìƒì„±í•œ ì¸ì‡„ ìž‘ì—…ì— ì•¡ì„¸ìŠ¤í•˜ë„ë¡ í•©ë‹ˆë‹¤. ì¼ë°˜ 앱ì—는 필요하지 않습니다."</string>
- <!-- no translation found for permlab_bindNfcService (2752731300419410724) -->
- <skip />
- <!-- no translation found for permdesc_bindNfcService (6120647629174066862) -->
- <skip />
+ <string name="permlab_bindNfcService" msgid="2752731300419410724">"NFC 서비스 사용"</string>
+ <string name="permdesc_bindNfcService" msgid="6120647629174066862">"ê¶Œí•œì„ ê°€ì§„ í”„ë¡œê·¸ëž¨ì´ NFC 카드를 ì—뮬레ì´ì…˜í•˜ëŠ” 애플리케ì´ì…˜ì„ 사용하ë„ë¡ í—ˆìš©í•©ë‹ˆë‹¤. ì¼ë°˜ 앱ì—는 필요하지 않습니다."</string>
<string name="permlab_bindTextService" msgid="7358378401915287938">"í…스트 서비스 ì—°ê²°"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"ê¶Œí•œì„ ê°€ì§„ í”„ë¡œê·¸ëž¨ì´ í…스트 서비스(예: SpellCheckerService)ì— ëŒ€í•œ 최ìƒìœ„ ì¸í„°íŽ˜ì´ìŠ¤ë¥¼ 사용하ë„ë¡ í—ˆìš©í•©ë‹ˆë‹¤. ì¼ë°˜ 앱ì—는 필요하지 않습니다."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"VPN 서비스와 연결"</string>
@@ -476,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"ì•±ì´ Wi-Fi 디스플레ì´ë¥¼ 설정하고 연결하ë„ë¡ í—ˆìš©í•©ë‹ˆë‹¤."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"Wi-Fi ë””ìŠ¤í”Œë ˆì´ ì œì–´"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"ì•±ì´ Wi-Fi 디스플레ì´ì˜ 하위 수준 ê¸°ëŠ¥ì„ ì œì–´í•˜ë„ë¡ í—ˆìš©í•©ë‹ˆë‹¤."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"오디오 출력 캡처"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"ì•±ì´ ì˜¤ë””ì˜¤ ì¶œë ¥ì„ ìº¡ì²˜í•˜ê³  리디렉션하ë„ë¡ í—ˆìš©í•©ë‹ˆë‹¤."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"비디오 출력 캡처"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"ì•±ì´ ë¹„ë””ì˜¤ ì¶œë ¥ì„ ìº¡ì²˜í•˜ê³  리디렉션하ë„ë¡ í—ˆìš©í•©ë‹ˆë‹¤."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"안전한 비디오 출력 캡처"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"ì•±ì´ ì•ˆì „í•œ 비디오 ì¶œë ¥ì„ ìº¡ì²˜í•˜ê³  리디렉션하ë„ë¡ í—ˆìš©í•©ë‹ˆë‹¤."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"오디오 설정 변경"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"ì•±ì´ ìŒëŸ‰ì´ë‚˜ ì¶œë ¥ì„ ìœ„í•´ 사용하는 스피커 등 ì „ì²´ 오디오 ì„¤ì •ì„ ë³€ê²½í•  수 있ë„ë¡ í—ˆìš©í•©ë‹ˆë‹¤."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"오디오 ë…¹ìŒ"</string>
@@ -661,6 +654,8 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"ê¶Œí•œì„ ê°€ì§„ í”„ë¡œê·¸ëž¨ì´ ì•Œë¦¼ 수신기 ì„œë¹„ìŠ¤ì— ëŒ€í•œ 최ìƒìœ„ ì¸í„°íŽ˜ì´ìŠ¤ë¥¼ 사용하ë„ë¡ í—ˆìš©í•©ë‹ˆë‹¤. ì¼ë°˜ 앱ì—는 필요하지 않습니다."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"ì´ë™í†µì‹ ì‚¬ì—서 제공한 구성 앱 호출"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"ê¶Œí•œì„ ê°€ì§„ í”„ë¡œê·¸ëž¨ì´ ì´ë™í†µì‹ ì‚¬ì—서 제공한 구성 ì•±ì„ í˜¸ì¶œí•˜ë„ë¡ í•©ë‹ˆë‹¤. ì¼ë°˜ 앱ì—는 필요하지 않습니다."</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"ë„¤íŠ¸ì›Œí¬ ìƒíƒœì— 대한 관측 ë³´ê³  수신"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"애플리케ì´ì…˜ì´ ë„¤íŠ¸ì›Œí¬ ìƒíƒœì— 대한 관측 보고를 수신하ë„ë¡ í—ˆìš©í•©ë‹ˆë‹¤. ì¼ë°˜ 앱ì—는 필요하지 않습니다."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"비밀번호 규칙 설정"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"화면 잠금해제 ë¹„ë°€ë²ˆí˜¸ì— í—ˆìš©ë˜ëŠ” ê¸¸ì´ ë° ë¬¸ìž ìˆ˜ë¥¼ 제어합니다."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"화면 잠금해제 ì‹œë„ ëª¨ë‹ˆí„°ë§"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index b8025042171e..544f98bd3526 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"neleisti perjungti programų"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Neleidžiama naudotojui perjungti į kitą programą."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"gauti esamos programos informacijÄ…"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Savininkui leidžiama gauti privaÄiÄ… esamos pirmaeilÄ—s ekrano programos informacijÄ…."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"stebėti ir valdyti visų programų paleidimą"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Leidžiama programai stebėti ir valdyti, kaip sistema paleidžia veiklą. Kenkėjiškos programos gali visiškai pažeisti sistemą. Šis leidimas reikalingas tik kuriant ir jo niekada nereikia naudojant įprastai."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"siųsti pašalinto paketo perdavimą"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Leidžiama programai konfigÅ«ruoti ir prisijungti prie „Wi-Fi“ pateikÄių."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"valdyti „Wi-Fi“ pateiktis"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Leidžiama programai valdyti „Wi-Fi“ pateikÄių žemo lygio funkcijas."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"fiksuoti garso įvestį"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Programai leidžiama fiksuoti ir peradresuoti garso išvestį."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"fiksuoti vaizdo išvestį"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Programai leidžiama fiksuoti ir peradresuoti vaizdo išvestį."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"fiksuoti saugią vaizdo išvestį"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Programai leidžiama fiksuoti ir peradresuoti saugią vaizdo išvestį."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"keisti garso nustatymus"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Leidžiama programai keisti visuotinius garso nustatymus, pvz., garsumÄ… ir tai, kuris garsiakalbis naudojamas iÅ¡vesÄiai."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"įrašyti garsą"</string>
@@ -659,6 +654,10 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Leidžiama turÄ—tojui susisaistyti su praneÅ¡imų skaitymo priemonÄ—s paslaugos aukÅ¡Äiausio lygio sÄ…saja. Ä®prastoms programoms to neturÄ—tų prireikti."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"iškviesti operatoriaus pateiktą konfigūravimo programą"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Turėtojui leidžiama iškviesti operatoriaus pateiktą konfigūravimo programą. Įprastoms programoms to neturėtų prireikti."</string>
+ <!-- no translation found for permlab_accessNetworkConditions (8206077447838909516) -->
+ <skip />
+ <!-- no translation found for permdesc_accessNetworkConditions (6899102075825272211) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Nustatyti slaptažodžio taisykles"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Valdyti leidžiamą ekrano atrakinimo slaptažodžių ilgį ir leidžiamus naudoti simbolius."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"StebÄ—ti bandymus atrakinti ekranÄ…"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 479a88792621..83d39623ce33 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"novÄ“rst lietojumprogrammu pÄrslÄ“gÅ¡anu"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"NovÄ“rÅ¡ lietotÄja pÄrslÄ“gÅ¡anos uz citu lietotni."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"paÅ¡reizÄ“jÄs lietotnes informÄcijas iegūšana"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Ä»auj Ä«paÅ¡niekam izgÅ«t privÄtu informÄciju par paÅ¡reizÄ“jo lietojumprogrammu ekrÄna priekÅ¡plÄnÄ."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"pÄrraudzÄ«t un kontrolÄ“t visu lietotņu atvÄ“rÅ¡anu"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Ä»auj lietotnei pÄrraudzÄ«t un kontrolÄ“t, kÄ sistÄ“mÄ tiek palaistas darbÄ«bas. Ä»aunprÄtÄ«gas lietotnes var pilnÄ«bÄ uzlauzt sistÄ“mu. Å Ä« atļauja ir nepiecieÅ¡ama tikai izstrÄdei, taÄu ne parastai lietoÅ¡anai."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"sūtīt apraidi par pakotnes noņemšanu"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Ļauj lietotnei konfigurēt Wi-Fi displejus un veidot savienojumu ar tiem."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"Wi-Fi displeju vadība"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Ļauj lietotnei kontrolēt zema līmeņa funkcijas Wi-Fi displejos."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"tvert audio izvadi"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Ļauj lietotnei tvert un novirzīt audio izvadi."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"tvert video izvadi"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Ļauj lietotnei tvert un novirzīt video izvadi."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"tvert drošu video izvadi"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Ļauj lietotnei tvert un novirzīt drošu video izvadi."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"mainīt audio iestatījumus"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Ä»auj lietotnei mainÄ«t globÄlos audio iestatÄ«jumus, piemÄ“ram, skaļumu un izejai izmantoto skaļruni."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"ierakstīt audio"</string>
@@ -659,6 +654,10 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Ä»auj Ä«paÅ¡niekam izveidot saiti ar paziņojumu uztvÄ“rÄ“ja pakalpojuma augšējÄ lÄ«meņa saskarni. ParastajÄm lietotnÄ“m tas nekad nav nepiecieÅ¡ams."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"Operatora nodroÅ¡inÄtas konfigurÄcijas lietotnes izsaukÅ¡ana"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Ä»auj Ä«paÅ¡niekam izsaukt operatora nodroÅ¡inÄto konfigurÄcijas lietotni. ParastÄm lietotnÄ“m tas nekad nav nepiecieÅ¡ams."</string>
+ <!-- no translation found for permlab_accessNetworkConditions (8206077447838909516) -->
+ <skip />
+ <!-- no translation found for permdesc_accessNetworkConditions (6899102075825272211) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Paroles kÄrtulu iestatīšana"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"KontrolÄ“ ekrÄna atbloķēšanas parolÄ“ atļautÄs rakstzÄ«mes un garumu."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"EkrÄna atbloķēšanas mēģinÄjumu pÄrraudzīšana"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 07aec806eb71..c89ffe8eb7b6 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"halang pertukaran apl"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Menghalang pengguna daripada bertukar kepada apl lain."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"dapatkan maklumat apl semasa"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Membenarkan pemegang mendapatkan maklumat peribadi tentang permohonan semasa di latar hadapan skrin"</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"pantau dan kawal semua pelancaran apl"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Membenarkan apl untuk memantau dan mengawal cara sistem melancarkan aktiviti. Apl hasad boleh menjejaskan sistem sepenuhnya. Kebenaran ini hanya diperlukan untuk pembangunan, tidak sekali-kali untuk penggunaan biasa."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"hantar siaran bahawa pakej telah dialih keluar"</string>
@@ -363,7 +364,7 @@
<string name="permlab_accessAllPrintJobs" msgid="1120792468465711159">"akses semua kerja cetakan"</string>
<string name="permdesc_accessAllPrintJobs" msgid="2978185311041864762">"Membenarkan pemegang mengakses kerja cetakan yang dibuat oleh apl lain. Tidak sekali-kali diperlukan untuk apl biasa."</string>
<string name="permlab_bindNfcService" msgid="2752731300419410724">"terikat kepada perkhidmatan NFC"</string>
- <string name="permdesc_bindNfcService" msgid="6120647629174066862">"Membenarkan pemegang untuk terikat kepada aplikasi yang mengikuti kad NFC. Tidak sekali-kali harus diperlukan untuk apl normal."</string>
+ <string name="permdesc_bindNfcService" msgid="6120647629174066862">"Membenarkan pemegang untuk terikat kepada aplikasi yang mengikut kad NFC. Tidak sekali-kali diperlukan untuk apl normal."</string>
<string name="permlab_bindTextService" msgid="7358378401915287938">"terikat kepada perkhidmatan teks"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Membenarkan pemegang mengikat kepada antara muka peringkat atasan perkhidmatan teks(mis. PerkhidmatanPenyemakEjaan). Tidak seharusnya diperlukan untuk apl biasa."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"terikat kepada perkhidmatan VPN"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Membenarkan apl mengkonfigurasi dan menyambung ke paparan Wifi."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"kawal paparan Wifi"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Membenarkan apl mengawal ciri tahap rendah paparan Wifi."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"tangkap output audio"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Membenarkan apl menangkap dan mengubah hala output audio."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"tangkap output video"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Membenarkan apl menangkap dan mengubah hala output video."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"tangkap output video selamat"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Membenarkan apl menangkap dan mengubah hala output video selamat."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"tukar tetapan audio anda"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Membenarkan apl untuk mengubah suai tetapan audio global seperti kelantangan dan pembesar suara mana digunakan untuk output."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"rakam audio"</string>
@@ -659,6 +654,8 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi perkhidmatan pendengar pemberitahuan. Tidak sekali-kali diperlukan untuk apl biasa."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"gunakan apl konfigurasi yang disediakan oleh pembawa"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Membenarkan pemegang menggunakan apl konfigurasi yang diberikan oleh pembawa. Tidak sekali-kali diperlukan untuk apl biasa."</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"dengar pemerhatian mengenai keadaan rangkaian"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Membenarkan aplikasi mendengar pemerhantian tentang keadaan rangkaian. Tidak sekali-kali diperlukan untuk apl biasa."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Tetapkan peraturan kata laluan"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Mengawal panjang dan aksara yang dibenarkan dalam kata laluan buka kunci skrin."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Memantau percubaan buka kunci skrin"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 20c47786fd76..75362a42da67 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -243,27 +243,27 @@
<string name="permdesc_statusBarService" msgid="716113660795976060">"Gir appen tillatelse til å vises i statusfeltet."</string>
<string name="permlab_expandStatusBar" msgid="1148198785937489264">"utvide/slå sammen statusfeltet"</string>
<string name="permdesc_expandStatusBar" msgid="6917549437129401132">"Lar appen utvide eller skjule statuslinjen."</string>
- <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"omdirigerer utgående anrop"</string>
+ <string name="permlab_processOutgoingCalls" msgid="3906007831192990946">"omdirigere utgående anrop"</string>
<string name="permdesc_processOutgoingCalls" msgid="5331318931937402040">"Lar appen behandle utgående anrop og endre nummeret som skal ringes opp. Denne tillatelsen lar appen overvåke, viderekoble eller hindre utgående anrop."</string>
- <string name="permlab_receiveSms" msgid="8673471768947895082">"mottar tekstmeldinger (SMS)"</string>
+ <string name="permlab_receiveSms" msgid="8673471768947895082">"motta tekstmeldinger (SMS)"</string>
<string name="permdesc_receiveSms" msgid="6424387754228766939">"Lar appen motta og behandle tekstmeldinger. Dette betyr at appen kan overvåke eller slette meldinger som er sendt til enheten din uten at du har sett dem."</string>
- <string name="permlab_receiveMms" msgid="1821317344668257098">"mottar tekstmeldinger (MMS)"</string>
+ <string name="permlab_receiveMms" msgid="1821317344668257098">"motta tekstmeldinger (MMS)"</string>
<string name="permdesc_receiveMms" msgid="533019437263212260">"Lar appen motta og behandle multimediemeldinger. Dette betyr at appen kan overvåke eller slette meldinger som er sendt til enheten din uten at du har sett dem."</string>
<string name="permlab_receiveEmergencyBroadcast" msgid="1803477660846288089">"motta nødkringkastinger"</string>
<string name="permdesc_receiveEmergencyBroadcast" msgid="848524070262431974">"Lar appen motta og behandle nødkringkastingsmeldinger. Denne tillatelsen er bare tilgjengelig for systemapper."</string>
- <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"lesing av kringkastede meldinger"</string>
+ <string name="permlab_readCellBroadcasts" msgid="1598328843619646166">"lese kringkastede meldinger"</string>
<string name="permdesc_readCellBroadcasts" msgid="6361972776080458979">"Tillater at appen kan lese kringkastede meldinger enheten din mottar. Kringkastede varsler leveres noen steder for å advare deg om nødsituasjoner. Skadelige apper kan forstyrre ytelsen eller funksjonen til enheten din når en kringkastet nødmelding mottas."</string>
<string name="permlab_sendSms" msgid="5600830612147671529">"sende SMS-meldinger"</string>
<string name="permdesc_sendSms" msgid="7094729298204937667">"Lar appen sende tekstmeldinger. Dette kan resultere i uventede kostnader. Merk at skadelige apper kan påføre deg kostnader ved å sende meldinger uten bekreftelse fra deg."</string>
<string name="permlab_sendRespondViaMessageRequest" msgid="8713889105305943200">"send svar via melding-hendelser"</string>
<string name="permdesc_sendRespondViaMessageRequest" msgid="7107648548468778734">"Lar appen sende forespørsler om håndtering av svar via melding-hendelser for innkommende anrop til andre meldingsapper."</string>
- <string name="permlab_readSms" msgid="8745086572213270480">"leser tekstmeldinger (SMS eller MMS)"</string>
+ <string name="permlab_readSms" msgid="8745086572213270480">"lese tekstmeldinger (SMS eller MMS)"</string>
<string name="permdesc_readSms" product="tablet" msgid="2467981548684735522">"Lar appen lese tekstmeldinger lagret på nettbrettet eller SIM-kortet ditt. Dette lar appen lese alle tekstmeldingene dine, uavhengig av innhold og konfidensialitet."</string>
<string name="permdesc_readSms" product="default" msgid="3695967533457240550">"Lar appen lese tekstmeldinger lagret på telefonen eller SIM-kortet ditt. Dette lar appen lese alle tekstmeldingene dine, uavhengig av innhold og konfidensialitet."</string>
<string name="permlab_writeSms" msgid="3216950472636214774">"redigerer tekstmeldingene dine (SMS eller MMS)"</string>
<string name="permdesc_writeSms" product="tablet" msgid="5160413947794501538">"Lar appen skrive til SMS-meldinger som er lagret på nettbrettet eller SIM-kortet ditt. Ondsinnede apper kan komme til å slette meldingene dine."</string>
<string name="permdesc_writeSms" product="default" msgid="7268668709052328567">"Lar appen skrive til SMS-meldinger som er lagret på telefonen eller SIM-kortet ditt. Ondsinnede apper kan komme til å slette meldingene dine."</string>
- <string name="permlab_receiveWapPush" msgid="5991398711936590410">"mottar tekstmeldinger (WAP)"</string>
+ <string name="permlab_receiveWapPush" msgid="5991398711936590410">"motta tekstmeldinger (WAP)"</string>
<string name="permdesc_receiveWapPush" msgid="748232190220583385">"Lar appen motta og behandle WAP-meldinger. Dette betyr at appen kan overvåke eller slette meldinger som er sendt til deg uten at du har sett dem."</string>
<string name="permlab_getTasks" msgid="6466095396623933906">"hente apper som kjører"</string>
<string name="permdesc_getTasks" msgid="7454215995847658102">"Lar appen hente informasjon om oppgaver som kjører og som nylig har kjørt. Dette kan tillate appen å oppdage informasjon om hvilke apper som brukes på enheten."</string>
@@ -281,17 +281,17 @@
<string name="permdesc_removeTasks" msgid="1394714352062635493">"Lar appen fjerne oppgaver og avslutte apper. Ondsinnede apper kan forstyrre atferden til andre apper."</string>
<string name="permlab_manageActivityStacks" msgid="7391191384027303065">"administrering av aktivitetsstabler"</string>
<string name="permdesc_manageActivityStacks" msgid="1615881933034084440">"Gir appen tillatelse til å legge til, fjerne og endre aktivitetsstablene som andre apper kjøres i. Skadelige apper kan skape problemer i atferden til andre apper."</string>
- <string name="permlab_startAnyActivity" msgid="2918768238045206456">"igangsetting av aktiviteter"</string>
+ <string name="permlab_startAnyActivity" msgid="2918768238045206456">"sette i gang aktiviteter"</string>
<string name="permdesc_startAnyActivity" msgid="997823695343584001">"Tillater at appen kan starte en aktivitet, uavhengig av tillatelsesbeskyttelse og eksportstatus."</string>
<string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"angi skjermkompatibilitet"</string>
<string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Lar appen kontrollere modus for skjermkompatibilitet i andre apper. Skadelige apper kan ødelegge funksjoner i andre apper."</string>
- <string name="permlab_setDebugApp" msgid="3022107198686584052">"aktivere feilsøking av app"</string>
+ <string name="permlab_setDebugApp" msgid="3022107198686584052">"aktivere feilsøking av apper"</string>
<string name="permdesc_setDebugApp" msgid="4474512416299013256">"Lar appen slå av feilsøking for andre apper. Ondsinnede apper kan bruke dette til å avslutte andre apper."</string>
<string name="permlab_changeConfiguration" msgid="4162092185124234480">"endrer systemets skjerminnstillinger"</string>
<string name="permdesc_changeConfiguration" msgid="4372223873154296076">"Lar appen endre den nåværende konfigurasjonen, som for eksempel språk eller generell skriftstørrelse."</string>
- <string name="permlab_enableCarMode" msgid="5684504058192921098">"aktiver bilmodus"</string>
+ <string name="permlab_enableCarMode" msgid="5684504058192921098">"aktivere bilmodus"</string>
<string name="permdesc_enableCarMode" msgid="4853187425751419467">"Lar appen aktivere bilmodus."</string>
- <string name="permlab_killBackgroundProcesses" msgid="3914026687420177202">"lukker andre apper"</string>
+ <string name="permlab_killBackgroundProcesses" msgid="3914026687420177202">"lukke andre apper"</string>
<string name="permdesc_killBackgroundProcesses" msgid="4593353235959733119">"Lar appen avslutte andre appers bakgrunnsprosesser. Dette kan føre til at andre apper slutter å kjøre."</string>
<string name="permlab_forceStopPackages" msgid="2329627428832067700">"tvinge andre apper til å stoppe"</string>
<string name="permdesc_forceStopPackages" msgid="5253157296183940812">"Lar appen tvinge andre apper til å stoppe."</string>
@@ -299,9 +299,9 @@
<string name="permdesc_forceBack" msgid="3892295830419513623">"Lar appen tvinge alle aktiviteter som kjører i forgrunnen til å lukkes og flyttes til bakgrunnen. Skal aldri være nødvendig for vanlige apper."</string>
<string name="permlab_dump" msgid="1681799862438954752">"hente intern systemtilstand"</string>
<string name="permdesc_dump" msgid="1778299088692290329">"Lar appen hente ut informasjon om systemets indre tilstand. Ondsinnede apper kan hente et bredt spekter av privat og sikker informasjon som de vanligvis aldri burde ha behov for."</string>
- <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"hent av skjerminnhold"</string>
+ <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"hente skjerminnhold"</string>
<string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Lar appen hente ut innholdet i det aktive vinduet. Ondsinnede apper kan hente ut hele vindusinnholdet og undersøke all teksten, med unntak av passord."</string>
- <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"Aktiver tilgjengelighet midlertidig"</string>
+ <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"aktivere tilgjengelighet midlertidig"</string>
<string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Lar en app midlertidig aktivere tilgjengelighet på enheten. Skadelige apper kan aktivere tilgjengelighet uten bekreftelse fra brukeren."</string>
<string name="permlab_retrieve_window_info" msgid="8532295199112519378">"hente vindusinformasjon"</string>
<string name="permdesc_retrieve_window_info" msgid="4998836370424186849">"Lar appen hente informasjon om vinduene fra vindusbehandleren. Skadelige apper kan hente informasjon som ikke er ment for intern systembruk."</string>
@@ -310,12 +310,13 @@
<string name="permlab_magnify_display" msgid="5973626738170618775">"forstørre visningen"</string>
<string name="permdesc_magnify_display" msgid="7121235684515003792">"Lar apper forstørre innholdet på en skjerm. Skadelige apper kan endre skjerminnhold på en måte som gjør at enheten blir ubrukelig."</string>
<string name="permlab_shutdown" msgid="7185747824038909016">"delvis avslutning"</string>
- <string name="permdesc_shutdown" msgid="7046500838746291775">"Lar applikasjonen sette aktivitetshåndtereren i avslutningstilstand. Slår ikke systemet helt av."</string>
- <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"forhindre applikasjonsbytte"</string>
+ <string name="permdesc_shutdown" msgid="7046500838746291775">"Lar appen sette aktivitetshåndtereren i avslutningstilstand. Slår ikke systemet helt av."</string>
+ <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"forhindre bytte mellom apper"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Hindrer brukeren i å bytte til en annen app."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"få informasjon om appen"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Tillater brukeren å få tilgang til privat informasjon om den aktuelle appen i forgrunnen på skjermen."</string>
- <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"avervåke og kontrollere all oppstart av apper"</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
+ <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"overvåke og kontrollere all oppstart av apper"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Lar appen overvåke og kontrollere hvordan systemet starter opp aktiviteter. Ondsinnede apper kan utsette hele systemet for sikkerhetsbrudd. Denne tillatelsen er bare nødvendig for utviklere, aldri for vanlig bruk."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"kringkaste melding om fjernet pakke"</string>
<string name="permdesc_broadcastPackageRemoved" msgid="6621901216207931089">"Lar appen kringkaste et varsel om at en app-pakke har blitt fjernet. Ondsinnede apper kan bruke dette til å avslutte alle andre apper som kjører."</string>
@@ -325,7 +326,7 @@
<string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Lar appen kringkaste et varsel om at en WAP-PUSH-melding er mottatt. Ondsinnede apper kan bruke dette til å forfalske MMS-meldingskvitteringer, eller ubemerket erstatte innholdet av alle slags nettsider med ondsinnede varianter."</string>
<string name="permlab_setProcessLimit" msgid="2451873664363662666">"begrense antallet kjørende prosesser"</string>
<string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Lar appen kontrollere det maksimale antallet prosesser som kjører. Aldri nødvendig for vanlige apper."</string>
- <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"tvinger bakgrunnsapper til å lukkes"</string>
+ <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"tvinge bakgrunnsapper til å lukkes"</string>
<string name="permdesc_setAlwaysFinish" msgid="7471310652868841499">"Lar appen kontrollere hvorvidt aktiviteter alltid er fullført så snart de flyttes til bakgrunnen. Aldri nødvendig for vanlige apper."</string>
<string name="permlab_batteryStats" msgid="2789610673514103364">"lese batteristatistikk"</string>
<string name="permdesc_batteryStats" msgid="5897346582882915114">"Lar apper lese gjeldende data på lavt nivå om batteribruk. Kan også la appen finne ut detaljert informasjon om hvilke apper du bruker."</string>
@@ -339,7 +340,7 @@
<string name="permdesc_backup" msgid="6912230525140589891">"Lar appen kontrollere systemets mekanisme for sikkerhetskopiering og gjenoppretting. Ikke beregnet på vanlige apper."</string>
<string name="permlab_confirm_full_backup" msgid="5557071325804469102">"bekrefte en fullstendig sikkerhetskopi, eller gjenopprette driften"</string>
<string name="permdesc_confirm_full_backup" msgid="1748762171637699562">"Lar appen starte det fullstendige grensesnittet for bekreftelse av sikkerhetskopiering. Skal ikke måtte brukes av noen apper."</string>
- <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"vis uautoriserte vinduer"</string>
+ <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"vise uautoriserte vinduer"</string>
<string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Lar appen opprette vinduer som er ment for å brukes av brukergrensesnittet til det interne systemet. Ikke beregnet på vanlige apper."</string>
<string name="permlab_systemAlertWindow" msgid="3543347980839518613">"overstyre andre apper"</string>
<string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Lar appen være aktiv over andre apper eller deler av brukergrensesnittet. Dette kan virke inn på bruken din av grensesnittet i andre apper, eller endre det du tror du ser i andre apper."</string>
@@ -352,7 +353,7 @@
<string name="permlab_injectEvents" msgid="1378746584023586600">"trykke taster og kontrolknapper"</string>
<string name="permdesc_injectEvents" product="tablet" msgid="206352565599968632">"Lar appen levere sine egne inndatahendelser (tastetrykk osv.) til andre apper. Ondsinnede apper kan bruke dette til å ta over nettbrettet."</string>
<string name="permdesc_injectEvents" product="default" msgid="653128057572326253">"Lar appen levere sine egne inndatahendelser (tastetrykk osv.) til andre apper. Ondsinnede apper kan bruke dette til å ta over telefonen."</string>
- <string name="permlab_readInputState" msgid="469428900041249234">"ta opp hva som skrives og gjøres"</string>
+ <string name="permlab_readInputState" msgid="469428900041249234">"ta opp det du skriver og gjør"</string>
<string name="permdesc_readInputState" msgid="8387754901688728043">"Lar appen se hvilke taster du trykker på, selv når du samhandler med en annen app (f.eks. skriver inn et passord). Skal aldri være nødvendig for vanlige apper."</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"binde til en inndatametode"</string>
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Lar innehaveren binde det øverste nivået av grensesnittet til en inndatametode. Skal aldri være nødvendig for normale apper."</string>
@@ -368,11 +369,11 @@
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Lar innehaveren binde seg til øverste grensesnittnivå for en teksttjeneste (f.eks. SpellCheckerService). Skal aldri være nødvendig for vanlige apper."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"binde deg til en VPN-tjeneste"</string>
<string name="permdesc_bindVpnService" msgid="2067845564581693905">"Lar innehaveren binde seg til det øverste nivået av grensesnittet for en VPN-tjeneste. Skal aldri være nødvendig for vanlige apper."</string>
- <string name="permlab_bindWallpaper" msgid="8716400279937856462">"bind til bakgrunnsbilde"</string>
+ <string name="permlab_bindWallpaper" msgid="8716400279937856462">"binde til bakgrunnsbilde"</string>
<string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Lar innehaveren binde det øverste nivået av grensesnittet til en bakgrunn. Skal aldri være nødvendig for vanlige apper."</string>
- <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bind til modultjenste"</string>
+ <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"binde til modultjenste"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Lar innehaveren binde seg til det øverste nivået av grensesnittet for en modultjeneste. Skal aldri være nødvendig for vanlige apper."</string>
- <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"kommuniser med enhetsadministrator"</string>
+ <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"kommunisere med enhetsadministrator"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Lar innehaveren sende hensikter til en enhetsadministrator. Skal aldri være nødvendig for normale apper."</string>
<string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"legge til eller fjerne en enhetsadministrator"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Tillater innehaveren å legge til eller fjerne aktive enhetsadministratorer. Dette skal aldri være nødvendig for vanlige apper."</string>
@@ -416,39 +417,39 @@
<string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"Lar programmer gi eller trekke tilbake spesielle tillatelser for eget bruk eller for andre programmer. Skadelige programmer kan bruke dette for å få tilgang til funksjoner de ikke skal ha tilgang til."</string>
<string name="permlab_setPreferredApplications" msgid="8463181628695396391">"angi foretrukne apper"</string>
<string name="permdesc_setPreferredApplications" msgid="4973986762241783712">"Lar appen endre de foretrukne appene dine. Ondsinnede apper kan ubemerket endre apper som kjøres, og forfalske eksisterende apper til å samle private data fra deg."</string>
- <string name="permlab_writeSettings" msgid="2226195290955224730">"endrer systeminnstillingene"</string>
+ <string name="permlab_writeSettings" msgid="2226195290955224730">"endre systeminnstillingene"</string>
<string name="permdesc_writeSettings" msgid="7775723441558907181">"Lar appen endre dataene i systeminnstillingene. Ondsinnede apper kan bruke dette til å skade systemkonfigurasjonen."</string>
<string name="permlab_writeSecureSettings" msgid="204676251876718288">"endre sikre systeminnstillinger"</string>
<string name="permdesc_writeSecureSettings" msgid="8159535613020137391">"Lar appen endre dataene for systemets sikre innstillinger. Ikke beregnet på vanlige apper."</string>
<string name="permlab_writeGservices" msgid="2149426664226152185">"redigere Google-tjenestekartet"</string>
<string name="permdesc_writeGservices" msgid="1287309437638380229">"Lar appen endre Google-tjenestekartet. Ikke beregnet på vanlige apper."</string>
- <string name="permlab_receiveBootCompleted" msgid="5312965565987800025">"kjører fra oppstart"</string>
+ <string name="permlab_receiveBootCompleted" msgid="5312965565987800025">"kjøre ved oppstart"</string>
<string name="permdesc_receiveBootCompleted" product="tablet" msgid="7390304664116880704">"Lar appen starte seg selv så snart systemet har startet opp. Dette kan føre til lengre oppstartstid for nettbrettet, i tillegg til at nettbrettet kan bli generelt tregere av at appen alltid kjører."</string>
<string name="permdesc_receiveBootCompleted" product="default" msgid="513950589102617504">"Lar appen starte seg selv så snart systemet har startet opp. Dette kan føre til lengre oppstartstid for telefonen, i tillegg til at telefonen kan bli generelt tregere av at appen alltid kjører."</string>
<string name="permlab_broadcastSticky" msgid="7919126372606881614">"sende varige kringkastinger"</string>
<string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"Lar appen sende faste kringkastinger («sticky broadcasts») som blir værende etter at kringkastingen er over. Overdreven bruk kan gjøre nettbrettet tregt eller ustabilt ved å bruke for mye minne."</string>
<string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"Lar appen sende faste kringkastinger («sticky broadcasts») som blir værende etter at kringkastingen er over. Overdreven bruk kan gjøre telefonen treg eller ustabil ved å bruke for mye minne."</string>
- <string name="permlab_readContacts" msgid="8348481131899886131">"leser kontaktene dine"</string>
+ <string name="permlab_readContacts" msgid="8348481131899886131">"lese kontaktene dine"</string>
<string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"Lar appen lese informasjon om kontaktene lagret på nettbrettet ditt, inkludert hvor ofte du har ringt, sendt e-post til, eller på andre måter kommunisert med spesifikke personer. Denne tillatelsen lar apper lagre kontaktdata. Merk at skadelige apper kan dele disse dataene uten at du vet om det."</string>
<string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"Lar appen lese informasjon om kontaktene lagret på telefonen din, inkludert hvor ofte du har ringt, sendt e-post til eller på andre måter kommunisert med spesifikke personer. Denne tillatelsen lar apper lagre kontaktdata. Merk at skadelige apper kan dele disse dataene uten at du vet om det."</string>
- <string name="permlab_writeContacts" msgid="5107492086416793544">"endrer kontaktene dine"</string>
+ <string name="permlab_writeContacts" msgid="5107492086416793544">"endre kontaktene dine"</string>
<string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"Lar appen endre informasjon om kontaktene lagret på nettbrettet ditt, inkludert hvor ofte du har ringt, sendt e-post til eller på andre måter kommunisert med bestemte kontakter. Denne tillatelsen lar apper slette kontaktdata."</string>
<string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"Lar appen endre informasjon om kontaktene lagret på telefonen din, inkludert hvor ofte du har ringt, sendt e-post til eller på andre måter kommunisert med bestemte kontakter. Denne tillatelsen lar apper slette kontaktdata."</string>
- <string name="permlab_readCallLog" msgid="3478133184624102739">"lar appen lese anropsloggen"</string>
+ <string name="permlab_readCallLog" msgid="3478133184624102739">"lese anropsloggen"</string>
<string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"Lar appen lese samtaleloggen på nettbrettet ditt. Dette omfatter informasjon om innkommende og utgående anrop. Denne tillatelsen lar apper lagre all samtaleinformasjonen din. Merk at skadelige apper kan dele informasjonen uten at du har samtykket."</string>
<string name="permdesc_readCallLog" product="default" msgid="5777725796813217244">"Lar appen lese samtaleloggen på telefonen din. Dette omfatter informasjon om innkommende og utgående anrop. Denne tillatelsen lar apper lagre all samtaleinformasjonen din. Merk at skadelige apper kan dele informasjonen uten at du har samtykket."</string>
- <string name="permlab_writeCallLog" msgid="8552045664743499354">"lar appen endre samtaleloggen"</string>
+ <string name="permlab_writeCallLog" msgid="8552045664743499354">"endre anropsloggen"</string>
<string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"Lar appen endre nettbrettets samtalelogg, inkludert data om innkommende og utgående anrop. Skadelige apper kan utnytte denne tillatelsen til å slette eller endre samtaleloggen din."</string>
<string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"Lar appen endre telefonens samtalelogg, inkludert data om innkommende og utgående anrop. Skadelige apper kan utnytte denne tillatelsen til å slette eller endre samtaleloggen din."</string>
- <string name="permlab_readProfile" msgid="4701889852612716678">"leser ditt eget kontaktkort"</string>
+ <string name="permlab_readProfile" msgid="4701889852612716678">"lese ditt eget kontaktkort"</string>
<string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Lar appen lese personlig profilinformasjon som er lagret på enheten, som for eksempel navn og kontaktinformasjon. Dette betyr at appen kan identifisere deg og sende profilinformasjonen din til andre."</string>
- <string name="permlab_writeProfile" msgid="907793628777397643">"endrer ditt eget kontaktkort"</string>
+ <string name="permlab_writeProfile" msgid="907793628777397643">"endre ditt eget kontaktkort"</string>
<string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Lar appen endre eller legge til personlig profilinformasjon som er lagret på enheten din, som for eksempel navn og kontaktinformasjon. Dette betyr at appen kan identifisere deg og sende profilinformasjonen din til andre."</string>
<string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"lese din sosiale strøm"</string>
<string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Lar appen lese og synkronisere sosiale oppdateringer fra deg selv og vennene dine. Vær forsiktig når du deler informasjon - med denne tillatelsen kan appen lese kommunikasjon mellom deg og vennene dine på sosiale nettverk, uavhengig av konfidensialitet. Vær oppmerksom på at denne tillatelsen kanskje ikke gjelder for alle sosiale nettverk."</string>
<string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"skrive i din sosiale strøm"</string>
<string name="permdesc_writeSocialStream" product="default" msgid="3086557552204114849">"Lar appen vise sosiale oppdateringer fra vennene dine. Vær forsiktig når du deler informasjon - med denne tillatelsen kan appen lage meldinger som ser ut som om de kommer fra en venn. Vær oppmerksom på at denne tillatelsen kanskje ikke gjelder på alle sosiale nettverk."</string>
- <string name="permlab_readCalendar" msgid="5972727560257612398">"les kalenderhendelser og konfidensiell informasjon"</string>
+ <string name="permlab_readCalendar" msgid="5972727560257612398">"lese kalenderhendelser og konfidensiell informasjon"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"Lar appen lese alle kalenderaktivitetene lagret på nettbrettet ditt, inkludert aktiviteter for venner eller kolleger. Dette kan gjøre at appen deler eller lagrer kalenderinformasjonen din uavhengig av konfidensialitet og sensitivitet."</string>
<string name="permdesc_readCalendar" product="default" msgid="7434548682470851583">"Lar appen lese alle kalenderaktivitetene lagret på telefonen din, inkludert aktiviteter for venner eller kolleger. Dette kan gjøre at appen deler eller lagrer kalenderinformasjonen din uavhengig av konfidensialitet og sensitivitet."</string>
<string name="permlab_writeCalendar" msgid="8438874755193825647">"legge til eller endre kalenderhendelser og sende e-post til gjester uten eiernes viten"</string>
@@ -456,7 +457,7 @@
<string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"Lar appen legge til, fjerne og endre aktiviteter du kan redigere på telefonen din, inkludert aktiviteter for venner eller kolleger. Dette kan gjøre at appen sender meldinger som ser ut som om de kommer fra kalendereiere eller endre aktiviteter uten at eierne vet om det."</string>
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"lage simulerte posisjonskilder for testing"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"Opprette fiktive posisjonskilder for testing eller installere en ny posisjonsangiver. Dette gjør at appen kan overstyre posisjonen eller statusen som rapporteres av ekte posisjonskilder, som for eksempel GPS eller posisjonsangivere."</string>
- <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"få tilgang til ekstra posisjonskommandoer"</string>
+ <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"bruke ekstra posisjonskommandoer"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"Lar appen få tilgang til flere kommandoer fra posisjonsangivere. Dette kan gjøre at appen forstyrrer GPS-funksjonen eller andre posisjonskilder."</string>
<string name="permlab_installLocationProvider" msgid="6578101199825193873">"installere posisjonskilder"</string>
<string name="permdesc_installLocationProvider" msgid="9066146120470591509">"Opprette fiktive posisjonskilder for testing eller installere en ny posisjonsangiver. Dette gjør at appen kan overstyre posisjonen eller statusen som rapporteres av ekte posisjonskilder, som for eksempel GPS eller posisjonsangivere."</string>
@@ -464,9 +465,9 @@
<string name="permdesc_accessFineLocation" msgid="5295047563564981250">"Lar appen se den nøyaktige posisjonen din ved hjelp av GPS (Global Positioning System) eller posisjonstjenester for nettverk, som for eksempel basestasjoner og Wi-Fi. Disse posisjonstjenestene må være slått på og tilgjengelig for enheten din, for at appen skal kunne bruke dem. Apper kan bruke dette til å fastslå hvor du er, og funksjonen kan medføre økt batteribruk."</string>
<string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"omtrentlig posisjon (nettverksbasert)"</string>
<string name="permdesc_accessCoarseLocation" msgid="2538200184373302295">"Lar appen se den omtrentlige posisjonen din. Denne posisjonen hentes fra posisjonstjenester som benytter posisjonskilder som for eksempel basestasjoner og Wi-Fi. Disse posisjonstjenestene må være slått på og tilgjengelig for enheten din, for at appen skal kunne bruke dem. Apper kan bruke dette til å finne ut omtrent hvor du er."</string>
- <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"få tilgang til SurfaceFlinger"</string>
+ <string name="permlab_accessSurfaceFlinger" msgid="2363969641792388947">"bruke SurfaceFlinger"</string>
<string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Lar appen bruke grunnleggende SurfaceFlinger-funksjoner."</string>
- <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"lese skjermbufferet"</string>
+ <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"lese skjermbufferen"</string>
<string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Lar appen lese innholdet i rammebufferen."</string>
<string name="permlab_accessInputFlinger" msgid="5348635270689553857">"tilgang til InputFlinger"</string>
<string name="permdesc_accessInputFlinger" msgid="2104864941201226616">"Lar appen bruke grunnleggende InputFlinger-funksjoner."</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Tillater appen å konfigurere og koble til Wi-Fi-skjermer."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"kontrollere Wi-Fi-skjermer"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Tillater appen å kontrollere lavnivåfunksjoner i Wi-Fi-skjermer."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"ta opp fra lydutdata"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Lar appen ta opp og omdirigere lydutdata."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"ta opp fra videoutdata"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Lar appen ta opp og omdirigere videoutdata."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"ta opp fra sikre videoutdata"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Lar appen ta opp og omdirigere sikre videoutdata."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"endre lydinnstillinger"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Lar appen endre globale lydinnstillinger slik som volum og hvilken høyttaler som brukes for lydavspilling."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"ta opp lyd"</string>
@@ -494,37 +489,37 @@
<string name="permdesc_camera" msgid="8497216524735535009">"Lar appen ta bilder og filme med kameraet. Denne tillatelsen gjør at appen kan bruke kameraet når som helst uten bekreftelse fra deg."</string>
<string name="permlab_cameraDisableTransmitLed" msgid="2651072630501126222">"deaktiver LED-lyset for indikering av overføring når kameraet er i bruk"</string>
<string name="permdesc_cameraDisableTransmitLed" msgid="4764585465480295341">"Tillater at forhåndsinnstallerte systemapper deaktiverer LED-indikatoren for kamerabruk."</string>
- <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"deaktiver nettbrett permanent"</string>
+ <string name="permlab_brick" product="tablet" msgid="2961292205764488304">"deaktivere nettbrettet permanent"</string>
<string name="permlab_brick" product="default" msgid="8337817093326370537">"deaktivere telefonen permanent"</string>
<string name="permdesc_brick" product="tablet" msgid="4334818808001699530">"Lar appen deaktivere hele nettbrettet permanent. Dette er svært risikabelt."</string>
<string name="permdesc_brick" product="default" msgid="5788903297627283099">"Lar appen deaktivere hele telefonen permanent. Dette er svært risikabelt."</string>
- <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"tvungen omstart av nettbrettet"</string>
+ <string name="permlab_reboot" product="tablet" msgid="3436634972561795002">"tvinge omstart av nettbrettet"</string>
<string name="permlab_reboot" product="default" msgid="2898560872462638242">"tvinge omstart av telefon"</string>
<string name="permdesc_reboot" product="tablet" msgid="8172056180063700741">"Lar appen fremtvinge omstart av nettbrettet."</string>
<string name="permdesc_reboot" product="default" msgid="5326008124289989969">"Lar appen fremtvinge omstart av telefonen."</string>
- <string name="permlab_mount_unmount_filesystems" product="nosdcard" msgid="2927361537942591841">"får tilgang til filsystemet til USB-lagring"</string>
+ <string name="permlab_mount_unmount_filesystems" product="nosdcard" msgid="2927361537942591841">"bruke filsystemet for USB-lagring"</string>
<string name="permlab_mount_unmount_filesystems" product="default" msgid="4402305049890953810">"får tilgang til filsystemet til SD-kort"</string>
<string name="permdesc_mount_unmount_filesystems" msgid="1829290701658992347">"Lar appen koble til og fra filsystemer for flyttbar lagring."</string>
- <string name="permlab_mount_format_filesystems" product="nosdcard" msgid="6227819582624904972">"tømmer USB-lagring"</string>
- <string name="permlab_mount_format_filesystems" product="default" msgid="262582698639274056">"tømmer SD-kort"</string>
+ <string name="permlab_mount_format_filesystems" product="nosdcard" msgid="6227819582624904972">"tømme USB-lagring"</string>
+ <string name="permlab_mount_format_filesystems" product="default" msgid="262582698639274056">"tømme SD-kort"</string>
<string name="permdesc_mount_format_filesystems" msgid="8784268246779198627">"Lar appen formatere flyttbare lagringsmedier."</string>
<string name="permlab_asec_access" msgid="3411338632002193846">"få informasjon om intern lagring"</string>
<string name="permdesc_asec_access" msgid="3094563844593878548">"Lar appen innhente informasjon om intern lagring."</string>
- <string name="permlab_asec_create" msgid="6414757234789336327">"opprett intern lagring"</string>
+ <string name="permlab_asec_create" msgid="6414757234789336327">"opprette intern lagring"</string>
<string name="permdesc_asec_create" msgid="4558869273585856876">"Lar appen opprette intern lagring."</string>
- <string name="permlab_asec_destroy" msgid="526928328301618022">"slett intern lagring"</string>
+ <string name="permlab_asec_destroy" msgid="526928328301618022">"ødelegge intern lagring"</string>
<string name="permdesc_asec_destroy" msgid="7218749286145526537">"Lar appen slette intern lagring."</string>
<string name="permlab_asec_mount_unmount" msgid="8877998101944999386">"koble til eller fra intern lagring"</string>
<string name="permdesc_asec_mount_unmount" msgid="3451360114902490929">"Lar appen koble intern lagring til eller fra."</string>
<string name="permlab_asec_rename" msgid="7496633954080472417">"gi nytt navn til intern lagring"</string>
<string name="permdesc_asec_rename" msgid="1794757588472127675">"Lar appen gi nytt navn til intern lagring."</string>
- <string name="permlab_vibrate" msgid="7696427026057705834">"kontrollerer vibrasjon"</string>
+ <string name="permlab_vibrate" msgid="7696427026057705834">"kontrollere vibreringen"</string>
<string name="permdesc_vibrate" msgid="6284989245902300945">"Lar appen kontrollere vibreringsfunksjonen."</string>
<string name="permlab_flashlight" msgid="2155920810121984215">"kontrollere lommelykten"</string>
<string name="permdesc_flashlight" msgid="6522284794568368310">"Lar appen kontrollere lommelykten."</string>
<string name="permlab_manageUsb" msgid="1113453430645402723">"administrere innstillinger og tillatelser for USB-enheter"</string>
<string name="permdesc_manageUsb" msgid="7776155430218239833">"Lar appen administrere innstillinger og tillatelser for USB-enheter."</string>
- <string name="permlab_accessMtp" msgid="4953468676795917042">"implementer MTP-protokoll"</string>
+ <string name="permlab_accessMtp" msgid="4953468676795917042">"implementere MTP-protokoll"</string>
<string name="permdesc_accessMtp" msgid="6532961200486791570">"Tillater tilgang til kjerne-MTP-driver for implementering av MTP USB-protokollen."</string>
<string name="permlab_hardware_test" msgid="4148290860400659146">"teste maskinvare"</string>
<string name="permdesc_hardware_test" msgid="6597964191208016605">"Lar appen styre ulike eksterne enheter for å teste maskinvare."</string>
@@ -532,18 +527,18 @@
<string name="permdesc_callPhone" msgid="3740797576113760827">"Lar appen ringe telefonnumre uten at du gjør noe. Dette kan resultere i uventede oppringninger og kostnader. Appen kan imidlertid ikke ringe nødnumre. Merk at skadelige apper kan påføre deg kostnader ved å ringe uten bekreftelse fra deg."</string>
<string name="permlab_callPrivileged" msgid="4198349211108497879">"ringe vilkårlige telefonnummer direkte"</string>
<string name="permdesc_callPrivileged" msgid="1689024901509996810">"Lar appen ringe alle slags telefonnumre, deriblant nødnumre, uten din innvirkning. Ondsinnede apper kan foreta unødvendige og ulovlige anrop til nødtjenestene."</string>
- <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"start CDMA-nettbrettoppsett direkte"</string>
+ <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"starte CDMA-nettbrettoppsett direkte"</string>
<string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"begynne CDMA-telefonoppsett direkte"</string>
<string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Lar appen starte CDMA-oppsett. Ondsinnede apper kan bruke dette til å starte CDMA-oppsett uten grunn."</string>
<string name="permlab_locationUpdates" msgid="7785408253364335740">"kontrollere varsling for plasseringsendring"</string>
<string name="permdesc_locationUpdates" msgid="1120741557891438876">"Lar appen aktivere og deaktivere varsler om posisjonsoppdatering fra radioen. Ikke beregnet på vanlige apper."</string>
- <string name="permlab_checkinProperties" msgid="7855259461268734914">"få tilgang til egenskaper for innsjekking"</string>
+ <string name="permlab_checkinProperties" msgid="7855259461268734914">"bruke innsjekking"</string>
<string name="permdesc_checkinProperties" msgid="4024526968630194128">"Gir appen lese- og skrivetilgang til egenskaper som er lastet opp av innsjekkingstjenesten. Ikke beregnet på vanlige apper."</string>
- <string name="permlab_bindGadget" msgid="776905339015863471">"velg gadgeter"</string>
+ <string name="permlab_bindGadget" msgid="776905339015863471">"velge moduler"</string>
<string name="permdesc_bindGadget" msgid="8261326938599049290">"Lar appen fortelle systemet hvilke moduler som kan brukes av hvilke apper. En app som har denne tillatelsen kan gi andre apper tilgang til personlige data. Ikke beregnet på vanlige apper."</string>
<string name="permlab_modifyPhoneState" msgid="8423923777659292228">"endre telefontilstand"</string>
<string name="permdesc_modifyPhoneState" msgid="1029877529007686732">"Lar appen kontrollere telefonfunksjonene til enheten. En app som har denne tillatelsen kan bytte nettverk, slå telefonens radio på og av og lignende, uten å varsle deg i det hele tatt."</string>
- <string name="permlab_readPhoneState" msgid="9178228524507610486">"leser telefonstatus og -identitet"</string>
+ <string name="permlab_readPhoneState" msgid="9178228524507610486">"lese telefonstatus og -identitet"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Lar appen bruke enhetens telefonfunksjoner. Med denne tillatelsen kan appen finne telefonnummer og enhets-ID-er, registrere om en samtale pågår, og se det eksterne nummeret det opprettes en forbindelse med via oppringing."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"hindre nettbrettet fra å gå over til sovemodus"</string>
<string name="permlab_wakeLock" product="default" msgid="573480187941496130">"forhindre telefonen fra å sove"</string>
@@ -558,7 +553,7 @@
<string name="permdesc_factoryTest" product="default" msgid="8136644990319244802">"Kjøre som en lavnivås produsenttest, med full tilgang til telefonens maskinvare. Kun tilgjengelig når telefonen kjører i produsenttestmodus."</string>
<string name="permlab_setWallpaper" msgid="6627192333373465143">"endre bakgrunnsbilde"</string>
<string name="permdesc_setWallpaper" msgid="7373447920977624745">"Lar appen angi systembakgrunnen."</string>
- <string name="permlab_setWallpaperHints" msgid="3278608165977736538">"endrer størrelsen på bakgrunnsbildet"</string>
+ <string name="permlab_setWallpaperHints" msgid="3278608165977736538">"endre størrelsen på bakgrunnsbildet"</string>
<string name="permdesc_setWallpaperHints" msgid="8235784384223730091">"Lar appen angi størrelsestips for systembakgrunnen."</string>
<string name="permlab_masterClear" msgid="2315750423139697397">"tilbakestille systemet til fabrikkinnstillinger"</string>
<string name="permdesc_masterClear" msgid="3665380492633910226">"Lar appen gjennomføre fullstendig tilbakestilling til fabrikkstandard, noe som sletter alle data, konfigurasjoner og installerte apper."</string>
@@ -583,7 +578,7 @@
<string name="permdesc_accessNetworkState" msgid="8318964424675960975">"Lar appen se informasjon om nettverkstilkoblinger, slik som hvilke nettverk som finnes og er tilkoblet."</string>
<string name="permlab_createNetworkSockets" msgid="8018758136404323658">"full nettverkstilgang"</string>
<string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"Lar appen opprette nettverkskontakter og bruke tilpassede nettverksprotokoller. Nettleseren og andre apper gjør det mulig å sende data til Internett, så denne tillatelsen er ikke nødvendig for å kunne sende data til Internett."</string>
- <string name="permlab_writeApnSettings" msgid="505660159675751896">"endre eller avskjær nettverksinnstillinger og -trafikk"</string>
+ <string name="permlab_writeApnSettings" msgid="505660159675751896">"endre eller avskjære nettverksinnstillinger og -trafikk"</string>
<string name="permdesc_writeApnSettings" msgid="5333798886412714193">"Lar appen endre nettverksinnstillinger og avbryte eller undersøke all nettverkstrafikk, for eksempel for å endre mellomtjener og port for alle navn på tilgangspunkt (APN). Ondsinnede apper kan overvåke, viderekoble eller endre nettverkspakker uten at du vet om det."</string>
<string name="permlab_changeNetworkState" msgid="958884291454327309">"endre nettverkskonnektivitet"</string>
<string name="permdesc_changeNetworkState" msgid="6789123912476416214">"Lar appen endre innstillingene for nettverkstilknytning."</string>
@@ -591,14 +586,14 @@
<string name="permdesc_changeTetherState" msgid="1524441344412319780">"Lar appen endre innstillingene for nettverkstilknytning via tethering."</string>
<string name="permlab_changeBackgroundDataSetting" msgid="1400666012671648741">"endre innstilling for bakgrunnsdata"</string>
<string name="permdesc_changeBackgroundDataSetting" msgid="5347729578468744379">"Lar appen endre innstillingene for bakgrunnsdatabruk."</string>
- <string name="permlab_accessWifiState" msgid="5202012949247040011">"ser Wi-Fi-tilkoblinger"</string>
+ <string name="permlab_accessWifiState" msgid="5202012949247040011">"se Wi-Fi-tilkoblinger"</string>
<string name="permdesc_accessWifiState" msgid="5002798077387803726">"Lar appen se informasjon om Wi-Fi-nettverk, f.eks. hvorvidt Wi-Fi er aktivert og navn på tilkoblede Wi-Fi-enheter."</string>
- <string name="permlab_changeWifiState" msgid="6550641188749128035">"kobler til og fra Wi-Fi"</string>
+ <string name="permlab_changeWifiState" msgid="6550641188749128035">"koble til og fra Wi-Fi"</string>
<string name="permdesc_changeWifiState" msgid="7137950297386127533">"Lar appen koble til og fra Wi-Fi-tilgangspunkter, og å gjøre endringer i enhetens konfigurasjon for Wi-Fi-nettverk."</string>
- <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"tillat multicast for trådløse nettverk"</string>
+ <string name="permlab_changeWifiMulticastState" msgid="1368253871483254784">"tillate multicast for trådløse nettverk"</string>
<string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"Lar appen motta pakker som sendes til alle enhetene på et Wi-Fi-nettverk ved hjelp av multikastingsadresser, Dette bruker mer strøm enn modusen uten multikasting."</string>
<string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"Lar appen motta pakker som sendes til alle enhetene på et Wi-Fi-nettverk ved hjelp av multikastingsadresser, Dette bruker mer strøm enn modusen uten multikasting."</string>
- <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"endrer Bluetooth-innstillinger"</string>
+ <string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"endre Bluetooth-innstillinger"</string>
<string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Lar appen konfigurere det lokale Bluetooth-nettbrettet, samt oppdage og koble sammen med eksterne enheter."</string>
<string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Lar appen konfigurere den lokale Bluetooth-telefonen, samt oppdage og koble sammen med eksterne enheter."</string>
<string name="permlab_accessWimaxState" msgid="4195907010610205703">"koble til eller fra WiMAX"</string>
@@ -606,12 +601,12 @@
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Endre WiMAX-status"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Lar appen koble nettbrettet til og fra WiMAX-nettverk."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Lar appen koble telefonen til og fra WiMAX-nettverk."</string>
- <string name="permlab_bluetooth" msgid="6127769336339276828">"kobler til Bluetooth-enheter"</string>
+ <string name="permlab_bluetooth" msgid="6127769336339276828">"koble til Bluetooth-enheter"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Lar appen se Bluetooth-konfigurasjonen på nettbrettet, samt opprette og godta tilkoblinger med sammenkoblede enheter."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Lar appen se Bluetooth-konfigurasjonen på telefonen, samt opprette og godta tilkoblinger med sammenkoblede enheter."</string>
<string name="permlab_nfc" msgid="4423351274757876953">"kontroller overføring av data med NFC-teknologi"</string>
<string name="permdesc_nfc" msgid="7120611819401789907">"Lar appen kommunisere med etiketter, kort og lesere som benytter NFC-teknologi."</string>
- <string name="permlab_disableKeyguard" msgid="3598496301486439258">"deaktiverer skjermlåsen"</string>
+ <string name="permlab_disableKeyguard" msgid="3598496301486439258">"deaktivere skjermlåsen"</string>
<string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Lar appen deaktivere tastelåsen og eventuell tilknyttet passordsikkerhet. Et eksempel er at telefonen deaktiverer tastelåsen når du mottar et innkommende anrop, og deretter aktiverer tastelåsen igjen når samtalen er ferdig."</string>
<string name="permlab_readSyncSettings" msgid="6201810008230503052">"lese synkroniseringsinnstillinger"</string>
<string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Lar appen lese synkroniseringsinnstillingene for en konto. For eksempel kan den finne ut om Personer-appen er synkronisert med en konto."</string>
@@ -623,7 +618,7 @@
<string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"Lar appen hente inn detaljer om strømmer som er synkroniserte for øyeblikket."</string>
<string name="permlab_subscribedFeedsWrite" msgid="9015246325408209296">"endre abonnement på nyhetskilder"</string>
<string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Lar appen endre strømmer som er synkronisert for øyeblikket. Ondsinnede apper kan endre de synkroniserte strømmene dine."</string>
- <string name="permlab_readDictionary" msgid="4107101525746035718">"leser uttrykkene du har lagt til i ordboken"</string>
+ <string name="permlab_readDictionary" msgid="4107101525746035718">"lese ord du har lagt til i ordboken"</string>
<string name="permdesc_readDictionary" msgid="659614600338904243">"Lar appen lese alle ord, navn og uttrykk som brukeren har lagret i brukerordlisten."</string>
<string name="permlab_writeDictionary" msgid="2183110402314441106">"legge til ord i brukerdefinert ordliste"</string>
<string name="permdesc_writeDictionary" msgid="8185385716255065291">"Lar appen skrive nye ord i brukerordlisten."</string>
@@ -641,11 +636,11 @@
<string name="permdesc_manageDocs" product="default" msgid="8704323176914121484">"Lar appen administrere dokumentlagring."</string>
<string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"Ã¥pne eksternlagring for alle brukere"</string>
<string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Tillater appen å åpne eksternlagring for alle brukere."</string>
- <string name="permlab_cache_filesystem" msgid="5656487264819669824">"tilgang til bufrede filer"</string>
+ <string name="permlab_cache_filesystem" msgid="5656487264819669824">"bruke bufrede filer"</string>
<string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Lar appen lese og skrive til det bufrede filsystemet."</string>
<string name="permlab_use_sip" msgid="5986952362795870502">"foreta/motta Internett-anrop"</string>
<string name="permdesc_use_sip" msgid="4717632000062674294">"Lar appen bruke SIP-tjenesten til å foreta og motta Internett-anrop."</string>
- <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"les tidligere nettverksbruk"</string>
+ <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"lese tidligere nettverksbruk"</string>
<string name="permdesc_readNetworkUsageHistory" msgid="7689060749819126472">"Lar appen lese tidligere nettverksbruk for bestemte nettverk og apper."</string>
<string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"administrer retningslinjene for nettverk"</string>
<string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"Lar appen administrere retningslinjene for nettverket og definere appspesifikke regler."</string>
@@ -653,12 +648,14 @@
<string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"Lar appen endre hvordan nettverksbruk regnes ut for apper. Ikke beregnet på vanlige apper."</string>
<string name="permlab_markNetworkSocket" msgid="3658527214914959749">"endring av kontaktmerker"</string>
<string name="permdesc_markNetworkSocket" msgid="7655568433696356578">"Gir appen tillatelse til å endre kontaktmerker for ruting"</string>
- <string name="permlab_accessNotifications" msgid="7673416487873432268">"varseltilgang"</string>
+ <string name="permlab_accessNotifications" msgid="7673416487873432268">"tilgang til varsler"</string>
<string name="permdesc_accessNotifications" msgid="458457742683431387">"Lar appen hente, gjennomgå og fjerne varsler, inkludert de som sendes fra andre apper."</string>
<string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"binding til en varsellyttertjeneste"</string>
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Lar innehaveren binde seg til det øverste grensesnittnivået for en varsellyttertjeneste. Skal aldri være nødvendig for vanlige apper."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"starte konfigurasjonsappen som ble levert av operatøren"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Gir innehaveren tillatelse til å kalle opp den konfigurasjonsappen som ble levert av operatøren. Dette skal ikke være nødvendig for vanlige apper."</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"lytte etter observasjoner om nettverksforhold"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Gir appen tillatelse til å lytte etter observasjoner om nettverksforhold. Dette skal ikke være nødvendig for vanlige apper."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Angi passordregler"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontroller tillatt lengde og tillatte tegn i passord for opplåsing av skjerm."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Overvåk forsøk på opplåsing av skjerm"</string>
@@ -924,22 +921,22 @@
<string name="autofill_parish" msgid="8202206105468820057">"Sogn"</string>
<string name="autofill_area" msgid="3547409050889952423">"Område"</string>
<string name="autofill_emirate" msgid="2893880978835698818">"Emirat"</string>
- <string name="permlab_readHistoryBookmarks" msgid="3775265775405106983">"leser nettbokmerkene og nettloggen din"</string>
+ <string name="permlab_readHistoryBookmarks" msgid="3775265775405106983">"lese nettbokmerkene og nettloggen din"</string>
<string name="permdesc_readHistoryBookmarks" msgid="8462378226600439658">"Lar appen lese loggen for alle nettadressene nettleseren har besøkt, og alle bokmerkene i nettleseren. Vær oppmerksom på at denne tillatelsen kanskje ikke benyttes av tredjepartsnettlesere eller andre apper med mulighet for nettsurfing."</string>
- <string name="permlab_writeHistoryBookmarks" msgid="3714785165273314490">"skriver nettbokmerker og nettlogg"</string>
+ <string name="permlab_writeHistoryBookmarks" msgid="3714785165273314490">"skrive nettbokmerker og nettlogg"</string>
<string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="6825527469145760922">"Lar appen endre nettleserens logg eller bokmerker lagret på nettbrettet ditt. Dette kan føre til at appen sletter eller endrer nettleserdata. Vær oppmerksom på at denne tillatelsen kanskje ikke benyttes av tredjepartsnettlesere eller andre apper med mulighet for nettsurfing."</string>
<string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"Lar appen endre nettleserens logg eller bokmerker lagret på telefonen din. Dette kan føre til at appen sletter eller endrer nettleserdata. Vær oppmerksom på at denne tillatelsen kanskje ikke benyttes av tredjepartsnettlesere eller andre apper med mulighet for nettsurfing."</string>
- <string name="permlab_setAlarm" msgid="1379294556362091814">"angir alarm"</string>
+ <string name="permlab_setAlarm" msgid="1379294556362091814">"stille alarm"</string>
<string name="permdesc_setAlarm" msgid="316392039157473848">"Lar appen stille inn alarmen for en installert alarmklokke-app. Enkelte alarmklokke-apper implementerer kanskje ikke denne funksjonen."</string>
- <string name="permlab_addVoicemail" msgid="5525660026090959044">"legg til talepost"</string>
+ <string name="permlab_addVoicemail" msgid="5525660026090959044">"legge til talepost"</string>
<string name="permdesc_addVoicemail" msgid="6604508651428252437">"Lar appen legge til meldinger i talepostkassen din."</string>
<string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"endre nettleserens tillatelser for geoposisjonering"</string>
<string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Lar appen endre nettleserens tillatelser for geoposisjonering. Ondsinnede apper kan bruke dette for å tillate sending av posisjonsinformasjon til vilkårlige nettsteder."</string>
- <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"bekreft pakker"</string>
+ <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"bekrefte pakker"</string>
<string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Lar appen bekrefte om en pakke kan installeres."</string>
<string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"bind til en pakkeverifikator"</string>
<string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Lar innehaveren sende forespørsler om pakkeverifikatorer. Skal aldri være nødvendig for normale apper."</string>
- <string name="permlab_serialPort" msgid="546083327654631076">"tilgang til serielle porter"</string>
+ <string name="permlab_serialPort" msgid="546083327654631076">"bruke serieporter"</string>
<string name="permdesc_serialPort" msgid="2991639985224598193">"Gir innehaveren tilgang til serielle porter ved hjelp av SerialManager API."</string>
<string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"gå til innholdsleverandører eksternt"</string>
<string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Lar innehaveren gå til innholdsleverandører fra kommandovinduet. Skal aldri være nødvendig for vanlige apper."</string>
@@ -1279,9 +1276,9 @@
<string name="ext_media_nomedia_notification_message" product="nosdcard" msgid="6921126162580574143">"USB-lagring fjernet. Sett inn et nytt medium."</string>
<string name="ext_media_nomedia_notification_message" product="default" msgid="3870120652983659641">"Minnekortet ble fjernet. Sett inn et nytt."</string>
<string name="activity_list_empty" msgid="1675388330786841066">"Finner ingen samsvarende aktiviteter."</string>
- <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"oppdater statistikk over komponentbruk"</string>
+ <string name="permlab_pkgUsageStats" msgid="8787352074326748892">"oppdatere statistikk over komponentbruk"</string>
<string name="permdesc_pkgUsageStats" msgid="1106612424254277630">"Lar appen endre innsamlet bruksstatistikk om komponenter. Ikke beregnet på vanlige apper."</string>
- <string name="permlab_copyProtectedData" msgid="4341036311211406692">"kopiére innhold"</string>
+ <string name="permlab_copyProtectedData" msgid="4341036311211406692">"kopiere innhold"</string>
<string name="permdesc_copyProtectedData" msgid="4390697124288317831">"Lar appen påkalle standard meldingsbeholdertjeneste for kopiering av innhold. Ikke beregnet på vanlige apper."</string>
<string name="permlab_route_media_output" msgid="1642024455750414694">"Videresending av medieutdata"</string>
<string name="permdesc_route_media_output" msgid="4932818749547244346">"Lar en app videresende medieutdata til andre eksterne enheter."</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 8399369f3987..9c4e2130651f 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"schakelen tussen apps voorkomen"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Hiermee wordt voorkomen dat de gebruiker overschakelt naar een andere app."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"huidige appgegevens ophalen"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"De houder kan hiermee persoonlijke gegevens ophalen over de applicatie die momenteel op de voorgrond wordt weergegeven."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"alle startende apps bijhouden en beheren"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Hiermee kan de app de manier bijhouden en beheren waarop het systeem activiteiten start. Schadelijke apps kunnen het systeem volledig in gevaar brengen. Deze machtiging is alleen voor ontwikkeling vereist, nooit voor normaal gebruik."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"melding verzenden dat pakket is verwijderd"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"De app toestaan wifi-displays te configureren en hiermee verbinding te maken."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"wifi-displays beheren"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"De app toestaan minder belangrijke functies van wifi-displays te beheren."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"audio-uitvoer vastleggen"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Hiermee kan de app audio-uitvoer vastleggen en verwerken."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"video-uitvoer vastleggen"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Hiermee kan de app video-uitvoer vastleggen en verwerken."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"beveiligde video-uitvoer vastleggen"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Hiermee kan de app beveiligde video-uitvoer vastleggen en verwerken."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"uw audio-instellingen wijzigen"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Hiermee kan de app algemene audio-instellingen wijzigen zoals het volume en welke luidspreker wordt gebruikt voor de uitvoer."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"audio opnemen"</string>
@@ -659,6 +654,8 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Hiermee kan de houder koppelen aan de hoofdinterface van een listener-service voor meldingen. Nooit vereist voor normale apps."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"de door de provider geleverde configuratie-app aanroepen"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Hiermee kan de houder de door de provider geleverde configuratie-app aanroepen. Nooit vereist voor normale apps."</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"controleren op waarnemingen met betrekking tot netwerkomstandigheden"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Hiermee kan een app controleren op waarnemingen met betrekking tot netwerkomstandigheden. Nooit vereist voor normale apps."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Wachtwoordregels instellen"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"De lengte en tekens beheren die zijn toegestaan in wachtwoorden voor schermontgrendeling."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Pogingen voor schermontgrendeling bijhouden"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 21e322802805..d4a5761d5669 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"zapobieganie przełączaniu aplikacji"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Uniemożliwia użytkownikowi przełączenie na inną aplikację."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"pobierz informacje o bieżącej aplikacji"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Zezwala posiadaczowi na pobieranie prywatnych informacji o bieżącej aplikacji i wyświetlanie ich na pierwszym planie ekranu."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"monitorowanie i kontrolowanie wszystkich uruchamianych aplikacji"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Pozwala aplikacji na monitorowanie i kontrolowanie sposobu uruchamiania działań przez system. Złośliwe aplikacje mogą całkowicie naruszyć zabezpieczenia systemu. To uprawnienie nigdy nie jest potrzebne podczas normalnego użytkowania, a jedynie podczas programowania."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"wysyłanie transmisji informującej o usuniętym pakiecie"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Zezwala aplikacji na konfigurację wyświetlaczy Wi-Fi i łączenie z nimi."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"zarządzanie wyświetlaczami Wi-Fi"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Zezwala aplikacji na zarządzanie niskopoziomowymi funkcjami wyświetlaczy Wi-Fi."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"przechwyć wyjście audio"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Zezwala aplikacji na przechwytywanie i przekierowywanie wyjścia audio."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"przechwyć wyjście wideo"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Zezwala aplikacji na przechwytywanie i przekierowywanie wyjścia wideo."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"przechwyć bezpieczne wyjście wideo"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Zezwala aplikacji na przechwytywanie i przekierowywanie bezpiecznego wyjścia wideo."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"zmienianie ustawień audio"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Pozwala aplikacji na modyfikowanie globalnych ustawień dźwięku, takich jak głośność oraz urządzenie wyjściowe."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"nagrywanie dźwięku"</string>
@@ -659,6 +654,8 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Zezwala na tworzenie powiązania z interfejsem najwyższego poziomu usługi odbiornika powiadomień. Nie powinno być nigdy potrzebne dla zwykłych aplikacji."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"wywoływanie aplikacji konfiguracyjnej udostępnionej przez operatora"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Zezwala na wywoływanie aplikacji konfiguracyjnej udostępnionej przez operatora. Nieprzeznaczone dla zwykłych aplikacji."</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"śledź stan sieci"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Pozwala aplikacji śledzić stan sieci. Nieprzeznaczone dla zwykłych aplikacji."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Określ reguły hasła"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontrolowanie długości haseł odblokowania ekranu i dozwolonych w nich znaków"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Monitoruj próby odblokowania ekranu"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 021ebac4e436..2db7a187b081 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"impedir trocas de aplicações"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Impede que o utilizador mude para outra aplicação."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"obter informações da aplicação atual"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Permite ao titular recuperar informações privadas acerca da aplicação atual no primeiro plano do ecrã."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"monitorizar e controlar a iniciação de todas as aplicações"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Permite que uma aplicação monitorize e controle a forma como o sistema inicia atividades. As aplicações maliciosas podem comprometer totalmente o sistema. Esta autorização só é necessária para programação, nunca para utilização normal."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"enviar difusão de pacote removido"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Permite que a aplicação se configure e se ligue a visores Wi-Fi."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"controlar visores Wi-Fi"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Permite que a aplicação controle funcionalidades de baixo nível em visores Wi-Fi."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"capturar saída de áudio"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Permite à aplicação capturar e redirecionar a saída de áudio."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"capturar saída de vídeo"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Permite à aplicação capturar e redirecionar a saída de vídeo."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"capturar saída de vídeo segura"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Permite à aplicação capturar e redirecionar a saída de vídeo segura."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"alterar as suas definições de áudio"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Permite que a aplicação modifique definições de áudio globais, tais como o volume e qual o altifalante utilizado para a saída de som."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"gravar áudio"</string>
@@ -659,6 +654,8 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permite que o titular vincule a interface de nível superior de um serviço de escuta de notificações. Nunca deverá ser necessário para aplicações normais."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"invocar a aplicação de configuração fornecida pela operadora"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permite que o titular invoque a aplicação de configuração fornecida pela operadora. Nunca deverá ser necessário para aplicações normais."</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"ouvir observações sobre as condições da rede"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Permite que uma aplicação ouça observações sobre as condições da rede. Nunca deverá ser necessário para aplicações normais."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Definir regras de palavra-passe"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Controlar o comprimento e os caracteres permitidos nas palavras-passe de desbloqueio do ecrã."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Monitorizar tentativas de desbloqueio do ecrã"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 9f206a675298..2fbb511056c1 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"evitar trocas de aplicativo"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Impede que o usuário alterne para outro aplicativo."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"obter informações do aplicativo atual"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Permite ao titular recuperar informações particulares sobre o aplicativo atual em primeiro plano na tela."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"monitorar e controlar todos os aplicativos que estão sendo iniciados"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Permite que o aplicativo monitore e controle a forma como o sistema inicia atividades. Aplicativos maliciosos podem comprometer completamente o sistema. Esta permissão só é necessária para o desenvolvimento, nunca para o uso normal."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"enviar transmissão removida do pacote"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Permite que o aplicativo configure e conecte a monitores Wi-Fi."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"controlar monitores Wi-Fi"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Permite que o aplicativo controle recursos de baixo nível de monitores Wi-Fi."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"capturar saída de áudio"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Permite que o aplicativo capture e redirecione a saída de áudio."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"capturar saída de vídeo"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Permite que o aplicativo capture e redirecione a saída de vídeo."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"capturar saída de vídeo segura"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Permite que o aplicativo capture e redirecione a saída de vídeo segura."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"alterar as suas configurações de áudio"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Permite que o aplicativo modifique configurações de áudio globais como volume e alto-falantes de saída."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"gravar áudio"</string>
@@ -659,6 +654,8 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permite que o proprietário sujeite a interface de nível superior a um serviço ouvinte de notificações. Não deve ser necessário para aplicativos comuns."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"invocar o aplicativo de configuração fornecido pela operadora"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permite que o proprietário invoque o aplicativo de configuração fornecido pela operadora. Não deve ser necessário para aplicativos comuns."</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"detectar observações nas condições da rede"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Permite que o aplicativo detecte observações nas condições da rede. Não deve ser necessário para aplicativos comuns."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Definir regras para senha"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Controle o tamanho e os caracteres permitidos nas senhas de desbloqueio de tela."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Monitorar tentativas de desbloqueio da tela"</string>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index e6d9783ad7f7..363fb9484a57 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -479,7 +479,7 @@
<skip />
<!-- no translation found for permlab_getTopActivityInfo (2537922311411546016) -->
<skip />
- <!-- no translation found for permdesc_getTopActivityInfo (2512448855496067131) -->
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
<skip />
<!-- no translation found for permlab_runSetActivityWatcher (892239094867182656) -->
<skip />
@@ -1104,6 +1104,10 @@
<skip />
<!-- no translation found for permdesc_invokeCarrierSetup (4159549152529111920) -->
<skip />
+ <!-- no translation found for permlab_accessNetworkConditions (8206077447838909516) -->
+ <skip />
+ <!-- no translation found for permdesc_accessNetworkConditions (6899102075825272211) -->
+ <skip />
<!-- no translation found for policylab_limitPassword (4497420728857585791) -->
<skip />
<!-- no translation found for policydesc_limitPassword (3252114203919510394) -->
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 539762a4d102..11f4b5f3b786 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"împiedicare comutare între aplicaţii"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Împiedică trecerea utilizatorului la o altă aplicaţie."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"obținere informații despre aplicația curentă"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Permite proprietarului să preia informațiile private despre aplicația curentă în prim-planul ecranului."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"monitorizare şi control asupra lansării tuturor aplicaţiilor"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Permite aplicaţiei să monitorizeze şi să controleze modul în care sistemul lansează activităţi. Aplicaţiile rău intenţionate pot să compromită sistemul în întregime. Această permisiune este necesară doar pentru dezvoltare şi niciodată pentru utilizarea normală."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"trimitere mesaj difuzat privind extragerea din pachet"</string>
@@ -362,10 +363,8 @@
<string name="permdesc_bindPrintService" msgid="7960067623209111135">"Permite proprietarului să se conecteze la interfața de nivel superior a unui serviciu de printare. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
<string name="permlab_accessAllPrintJobs" msgid="1120792468465711159">"acces la toate procesele de printare"</string>
<string name="permdesc_accessAllPrintJobs" msgid="2978185311041864762">"Permite proprietarului să acceseze procesele de printare create de o altă aplicație. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
- <!-- no translation found for permlab_bindNfcService (2752731300419410724) -->
- <skip />
- <!-- no translation found for permdesc_bindNfcService (6120647629174066862) -->
- <skip />
+ <string name="permlab_bindNfcService" msgid="2752731300419410724">"conectare la serviciul NFC"</string>
+ <string name="permdesc_bindNfcService" msgid="6120647629174066862">"Permite aplicației autorizate să se asocieze cu aplicații care emulează carduri NFC. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
<string name="permlab_bindTextService" msgid="7358378401915287938">"conectare la un serviciu text"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Permite proprietarului să se conecteze la o interfaţă de nivel superior a unui serviciu text (de ex., SpellCheckerService). Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"conectare la un serviciu VPN"</string>
@@ -476,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Permite aplicaţiei să configureze şi să se conecteze la afişaje Wi-Fi."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"controlează afişaje Wi-Fi"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Permite aplicaţiei să controleze funcţiile de nivel redus ale afişajelor Wi-Fi."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"capturați ieșirea audio"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Permite aplicației să captureze și să redirecționeze ieșirea audio."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"capturați ieșirea video"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Permite aplicației să captureze și să redirecționeze ieșirea video."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"capturați ieșirea video securizată"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Permite aplicației să captureze și să redirecționeze ieșirea video securizată."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"modificare setări audio"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Permite aplicaţiei să modifice setările audio globale, cum ar fi volumul şi difuzorul care este utilizat pentru ieşire."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"înregistrare audio"</string>
@@ -661,6 +654,8 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permite proprietarului să se conecteze la interfața de nivel superior a unui serviciu de citire a notificărilor. În mod normal aplicațiile nu ar trebui să aibă nevoie de această permisiune."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"apelarea aplicației de configurare furnizată de operator"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permite proprietarului să apeleze aplicația de configurare furnizată de operator. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"ascultați observații despre starea rețelei"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Permite unei aplicații să asculte observații despre starea rețelei. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Setaţi reguli pentru parolă"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Stabiliţi lungimea şi tipul de caractere permise în parolele pentru deblocarea ecranului."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Monitorizaţi încercările de deblocare a ecranului"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 361e9a4a2060..1629be31cdaa 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"Защита от Ð¿ÐµÑ€ÐµÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ð¹"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Запрещает пользователÑм переключатьÑÑ Ð¼ÐµÐ¶Ð´Ñƒ приложениÑми."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"Показ информации о текущем приложении"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Ðа Ñкране будут отображатьÑÑ ÑÐ²ÐµÐ´ÐµÐ½Ð¸Ñ Ð¾ текущем приложении."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"ОтÑлеживание и управление запуÑком вÑех приложений"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Приложение Ñможет отÑлеживать запуÑк ÑиÑтемных процеÑÑов и управлÑть им. ВредоноÑные программы Ñмогут получить полный контроль над ÑиÑтемой. Это разрешение необходимо только Ð´Ð»Ñ Ñ€Ð°Ð·Ñ€Ð°Ð±Ð¾Ñ‚ÐºÐ¸ и не нужно в обычном режиме."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"Отправка оповещений об удалении пакетов"</string>
@@ -362,10 +363,8 @@
<string name="permdesc_bindPrintService" msgid="7960067623209111135">"Приложение Ñможет подключатьÑÑ Ðº базовому интерфейÑу Ñлужбы печати. Это разрешение не иÑпользуетÑÑ Ð¾Ð±Ñ‹Ñ‡Ð½Ñ‹Ð¼Ð¸ приложениÑми."</string>
<string name="permlab_accessAllPrintJobs" msgid="1120792468465711159">"ДоÑтуп к заданиÑм печати"</string>
<string name="permdesc_accessAllPrintJobs" msgid="2978185311041864762">"Владелец Ñможет проÑматривать Ð·Ð°Ð´Ð°Ð½Ð¸Ñ Ð¿ÐµÑ‡Ð°Ñ‚Ð¸, Ñозданные другими приложениÑми. Это разрешение не иÑпользуетÑÑ Ð¾Ð±Ñ‹Ñ‡Ð½Ñ‹Ð¼Ð¸ приложениÑми."</string>
- <!-- no translation found for permlab_bindNfcService (2752731300419410724) -->
- <skip />
- <!-- no translation found for permdesc_bindNfcService (6120647629174066862) -->
- <skip />
+ <string name="permlab_bindNfcService" msgid="2752731300419410724">"подключатьÑÑ Ðº Ñлужбе NFC"</string>
+ <string name="permdesc_bindNfcService" msgid="6120647629174066862">"Приложение Ñможет подключатьÑÑ Ðº программам Ñ Ð¸Ð¼Ð¸Ñ‚Ð°Ñ†Ð¸ÐµÐ¹ карт NFC. Это разрешение не иÑпользуетÑÑ Ð¾Ð±Ñ‹Ñ‡Ð½Ñ‹Ð¼Ð¸ приложениÑми."</string>
<string name="permlab_bindTextService" msgid="7358378401915287938">"Подключение к Ñлужбе текÑтовых Ñообщений"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"ПозволÑет подключатьÑÑ Ðº базовому интерфейÑу Ñлужбы текÑтовых Ñообщений (например, SpellCheckerService). Это разрешение не иÑпользуетÑÑ Ð¾Ð±Ñ‹Ñ‡Ð½Ñ‹Ð¼Ð¸ приложениÑми."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"Подключение к VPN-Ñлужбе"</string>
@@ -476,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Приложение Ñможет подключатьÑÑ Ðº Ñкранам Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ Wi-Fi и наÑтраивать их."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"Управление мониторами, подключенными через Wi-Fi"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Приложение Ñможет управлÑть низкоуровневыми функциÑми Ñкранов, подключенных через Wi-Fi."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"захват аудиоÑигнала"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Приложение Ñможет захватывать и перенаправлÑть аудиоÑигнал."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"захват видеоÑигнала"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Приложение Ñможет захватывать и перенаправлÑть видеоÑигнал."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"захват защищенного видеоÑигнала"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Приложение Ñможет захватывать и перенаправлÑть защищенный видеоÑигнал."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"Изменение наÑтроек аудио"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Приложение Ñможет изменÑть ÑиÑтемные наÑтройки звука, например уровень громкоÑти и активный динамик."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"ЗапиÑÑŒ аудио"</string>
@@ -661,6 +654,10 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Приложение Ñможет подключатьÑÑ Ðº базовому интерфейÑу Ñлужбы проÑмотра уведомлений. Это разрешение не иÑпользуетÑÑ Ð¾Ð±Ñ‹Ñ‡Ð½Ñ‹Ð¼Ð¸ приложениÑми."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"ЗапуÑк Ð¿Ñ€Ð¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð½Ð°Ñтроек, предоÑтавленного оператором"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Владелец Ñможет запуÑкать приложение наÑтроек, предоÑтавленное оператором. Это разрешение не иÑпользуетÑÑ Ð¾Ð±Ñ‹Ñ‡Ð½Ñ‹Ð¼Ð¸ приложениÑми."</string>
+ <!-- no translation found for permlab_accessNetworkConditions (8206077447838909516) -->
+ <skip />
+ <!-- no translation found for permdesc_accessNetworkConditions (6899102075825272211) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Правила выбора паролей"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Контролировать длину и Ñимволы при вводе паролей Ð´Ð»Ñ ÑнÑÑ‚Ð¸Ñ Ð±Ð»Ð¾ÐºÐ¸Ñ€Ð¾Ð²ÐºÐ¸ Ñкрана."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"ОтÑлеживать попытки ÑнÑÑ‚Ð¸Ñ Ð±Ð»Ð¾ÐºÐ¸Ñ€Ð¾Ð²ÐºÐ¸ Ñкрана"</string>
@@ -1481,8 +1478,7 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Экран HDMI"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"Ðаложение â„– <xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g> х <xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> тчк/дюйм"</string>
- <!-- no translation found for display_manager_overlay_display_secure_suffix (6022119702628572080) -->
- <skip />
+ <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", безопаÑный"</string>
<string name="wifi_display_notification_title" msgid="2223050649240326557">"БеÑпроводной проектор подключен"</string>
<string name="wifi_display_notification_message" msgid="4498802012464170685">"Изображение передаетÑÑ Ð½Ð° другое уÑтройÑтво"</string>
<string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Отключить"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index de6785c7ca15..8eb65a60db05 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"zabrániť prepínaniu aplikácií"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Zabráni používateľovi prepnúť na inú aplikáciu."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"získať informácie o aktuálnej aplikácii"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Umožňuje držiteľovi povolenia naÄítaÅ¥ súkromné ​​informácie o aktuálnej aplikácii v popredí obrazovky."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"sledovať a ovládať všetky spustenia aplikácií"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Umožňuje aplikácii sledovaÅ¥ a ovládaÅ¥ spúšťanie aktivít systémom. Å kodlivé aplikácie môžu systém úplne ovládnuÅ¥. Toto povolenie je potrebné len na úÄely vývoja, nikdy nie na bežné používanie."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"odoslanie vysielania o odstránení balíÄka"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Umožňuje aplikácii konfigurovať displeje a pripojiť sa k nim cez siete Wi-Fi."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"ovládať displeje cez sieť Wi-Fi"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Umožňuje aplikácii ovládať základné funkcie displejov cez siete Wi-Fi."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"zachytiť výstup zvuku"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Umožňuje aplikácii zachytiť a presmerovať výstup zvuku."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"zachytiť výstup videa"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Umožňuje aplikácii zachytiť a presmerovať výstup videa."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"zachytiÅ¥ zabezpeÄený výstup videa"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Umožňuje aplikácii zachytiÅ¥ a presmerovaÅ¥ zabezpeÄený výstup videa."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"zmeny vašich nastavení zvuku"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Umožňuje aplikácii upraviÅ¥ globálne nastavenia zvuku, ako je hlasitosÅ¥, alebo urÄiÅ¥, z ktorého reproduktora bude zvuk vychádzaÅ¥."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"záznam zvuku"</string>
@@ -659,6 +654,8 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Umožňuje držiteľovi naviazaÅ¥ sa na najvyššiu úroveň služby na poÄúvanie upozornení. Bežné aplikácie by toto nastavenie nemali nikdy požadovaÅ¥."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"vyvolanie aplikácie pre konfiguráciu poskytnutú operátorom"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Umožňuje držiteľovi vyvolať aplikáciu pre konfiguráciu poskytnutú operátorom. Bežné aplikácie by toto povolenie nemali nikdy potrebovať."</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"zachytávať informácie o stave siete"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Umožňuje aplikácii zachytávať informácie o stave siete. Bežné aplikácie by toto povolenie nemali nikdy potrebovať."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Nastaviť pravidlá pre heslo"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Ovládanie dĺžky hesiel na odomknutie obrazovky a v nich používané znaky."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Sledovať pokusy o odomknutie obrazovky"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index a14a080f89ee..6ee87fcafe12 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"prepreÄevanje preklopa programov"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Uporabniku prepreÄuje preklop v drug program."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"pridobivanje podatkov o trenutni aplikaciji"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"OmogoÄa imetniku pridobivanje zasebnih podatkov o trenutni aplikaciji v ospredju zaslona."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"spremljanje in nadzor vseh zagonov programov"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Programu omogoÄa spremljanje in nadziranje naÄina, kako sistem zažene dejavnosti. Zlonamerni programi lahko v celoti ogrozijo varnost sistema. To dovoljenje je potrebno samo za razvoj, vendar nikoli za obiÄajno uporabo."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"pošiljanje oddaje brez paketa"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"OmogoÄa aplikaciji konfiguriranje zaslonov Wi-Fi in povezovanje z njimi."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"nadzor zaslonov Wi-Fi"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"OmogoÄa aplikaciji nadzor osnovnih funkcij zaslonov Wi-Fi."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"zajem avdioizhoda"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"OmogoÄi aplikaciji, da zajame in preusmeri avdioizhod."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"zajem videoizhoda"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"OmogoÄi aplikaciji, da zajame in preusmeri videoizhod."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"zajem varnega videoizhoda"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"OmogoÄi aplikaciji, da zajame in preusmeri varni videoizhod."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"spreminjanje nastavitev zvoka"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Aplikaciji omogoÄa spreminjanje sploÅ¡nih zvoÄnih nastavitev, na primer glasnost in kateri zvoÄnik se uporablja."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"snemanje zvoka"</string>
@@ -659,6 +654,8 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Lastniku omogoÄa povezovanje z vmesnikom storitve posluÅ¡alca obvestil najviÅ¡je ravni. Tega nikoli ni treba uporabiti za navadne aplikacije."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"sprožitev operaterjeve aplikacije za konfiguracijo"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Lastniku omogoÄa sproženje operaterjeve aplikacije za konfiguracijo. Tega nikoli ni treba uporabiti za navadne aplikacije."</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"spremljanje razmer v omrežju"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Aplikaciji omogoÄa spremljanje razmer v omrežju. Pri navadnih aplikacijah to ne bi smelo biti potrebno."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Nastavitev pravil za geslo"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Nadzor nad dolžino in znaki, ki so dovoljeni v geslih za odklepanje zaslona."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"nadzor nad poskusi odklepanja zaslona"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 1f253cfc45d8..85bac704172e 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"Ñпречавање пребацивања Ñа једне апликације на другу"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Спречава да кориÑник пређе на другу апликацију."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"преузимање информација о актуелној апликацији"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Дозвољава влаÑнику да преузима приватне информације о актуелној апликацији у првом плану екрана."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"надгледање и контрола покретања Ñвих апликација"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Дозвољава апликацији да прати начин на који ÑиÑтем покреће активноÑти и да њиме управља. Злонамерне апликације могу у потпуноÑти да угрозе ÑиÑтем. Ова дозвола је потребна Ñамо за програмирање, а никада за уобичајено коришћење."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"Ñлање емитовања уклоњеног пакета"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Дозвољава апликацији да конфигурише Wi-Fi екране и повезује Ñе Ñа њима."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"контрола Wi-Fi екрана"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Дозвољава апликацији да контролише функције Wi-Fi екрана ниÑког нивоа."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"Ñнимање аудио Ñадржаја"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Дозвољава апликацији да Ñнима и преуÑмерава аудио Ñадржај."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"Ñнимање видео Ñадржаја"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Дозвољава апликацији да Ñнима и преуÑмерава видео Ñадржај."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"Ñнимање безбедног видео Ñадржаја"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Дозвољава апликацији да Ñнима и преуÑмерава безбедан видео Ñадржај."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"промена аудио подешавања"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Дозвољава апликацији да мења глобална аудио подешавања као што Ñу јачина звука и избор звучника који Ñе кориÑти као излаз."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"Ñнимање аудио запиÑа"</string>
@@ -659,6 +654,10 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Дозвољава влаÑнику да Ñе повеже Ñа интерфејÑом уÑлуге монитора обавештења највишег нивоа. Уобичајене апликације никада не би требало да је кориÑте."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"позивање апликације Ñа конфигурацијом коју одређује оператер"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Дозвољава влаÑнику да позива апликацију Ñа конфигурацијом коју одређује оператер. Уобичајене апликације никада не би требало да је кориÑте."</string>
+ <!-- no translation found for permlab_accessNetworkConditions (8206077447838909516) -->
+ <skip />
+ <!-- no translation found for permdesc_accessNetworkConditions (6899102075825272211) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Подешавање правила за лозинку"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Контролишите дужину и знакове дозвољене у лозинкама за откључавање екрана."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Ðадгледање покушаја откључавања екрана"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 63ddfeac6b0f..763653d44c64 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"förhindrar programbyten"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Hindrar användaren från att byta till en annan app."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"hämta information om aktuell app"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Innehavaren tillåts att hämta privat information om den app som för tillfället är i förgrunden på skärmen."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"övervaka och styra alla appar som öppnas"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Tillåter att appen övervakar och styr hur systemet startar aktiviteter. Skadliga appar kan kompromettera systemet helt. Den här behörigheten behövs bara för programmering, aldrig för vanlig användning."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"skicka meddelande om borttaget paket"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Tillåter att appen konfigurerar och ansluter till Wi-Fi-skärmar."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"kontrollerar Wi-Fi-skärmar"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Tillåter att appen kontrollerar grundläggande funktioner för Wi-Fi-skärmar."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"fånga upp ljudutgång"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Tillåt att appen fångar upp och omdirigerar ljudutgången."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"fånga upp videoutgång"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Tillåt att appen fångar upp och omdirigerar videoutgången."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"fånga upp säker videoutgång"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Tillåt att appen fångar upp och omdirigerar säker videoutgång."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"ändra dina ljudinställningar"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Tillåter att appen ändrar globala ljudinställningar som volym och vilken högtalarutgång som används."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"spela in ljud"</string>
@@ -659,6 +654,8 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en meddelandelyssnare. Ska inte behövas för vanliga appar."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"anropa konfigurationsappen från operatören"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Innehavaren tillåts att anropa konfigurationsappen från operatören. Ska inte behövas för vanliga appar."</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"lyssna efter information om nätverksförhållanden"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Tillåter att appen lyssnar efter information om nätverksförhållanden. Vanliga appar bör aldrig behöva den här behörigheten."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Ange lösenordsregler"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Bestäm hur många och vilka tecken som är tillåtna i skärmlåsets lösenord."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Övervaka försök att låsa upp skärmen"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 0c36bafada9d..23ca2dd150f4 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"zuia swichi za app"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Huzuia mtumiaji dhidi ya kubadilisha na kwenda kwa programu nyingine."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"pata maelezo ya sasa kuhusu programu"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Huruhusu mmiliki kurejesha maelezo ya faragha kuhusu programu ya sasa katika mandharimbele ya skrini."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"Fuatilia na kudhibiti uzinduzi wote wa programu"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Inaruhusu programu kufuatilia na kudhibiti jinsi mfumo unazindua shughuli. Programu hasidi zinaweza kutia mfumo hatarini. Ruhusa inahitajika tu kwa usanidi, kamwe sio kwa matumizi ya kawaida."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"furushi lililotumwa limeondoa tangazo"</string>
@@ -362,8 +363,8 @@
<string name="permdesc_bindPrintService" msgid="7960067623209111135">"Inaruhusu kishikiliaji kujifungilia kiolesura cha kiwango cha juu cha huduma ya kuchapisha. Haipaswi kuhitajika kwa programu za kawaida."</string>
<string name="permlab_accessAllPrintJobs" msgid="1120792468465711159">"fikia kazi zote za kuchapisha"</string>
<string name="permdesc_accessAllPrintJobs" msgid="2978185311041864762">"Huruhusu mmiliki kufikia kazi za kuchapisha zilizoundwa na programu nyingine. Haipaswi kuhitajika kwa programu za kawaida kamwe."</string>
- <string name="permlab_bindNfcService" msgid="2752731300419410724">"funga kwa huduma ya NFC"</string>
- <string name="permdesc_bindNfcService" msgid="6120647629174066862">"Huruhusu mmiliki kufunga kwa programu zinazoiga kadi za NFC. Haipaswi kuhitaji kamwe kwa programu za kawaida."</string>
+ <string name="permlab_bindNfcService" msgid="2752731300419410724">"funga kwenye huduma za NFC"</string>
+ <string name="permdesc_bindNfcService" msgid="6120647629174066862">"Huruhusu mmiliki kufunga kwa programu zinazoiga kadi za NFC. Haipaswi kuhitajika kamwe kwa programu za kawaida."</string>
<string name="permlab_bindTextService" msgid="7358378401915287938">"Imefungwa kwa huduma ya maandishi"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Inaruhusu kishikiliaji kushurutisha kusano ya kiwango cha juu ya huduma ya matini(k.m.SpellCheckerService). Haipaswi kuhitajika kwa programu za kawaida."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"funga kwa huduma ya VPN"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Inaruhusu programu kusanidi na kuunganika kwenye maonyesho ya Wifi."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"dhibiti maonyesho ya Wifi"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Inaruhusu programu kudhibiti vipengele vya kiwango cha chini vya maonyesho ya Wifi."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"nasa sauti"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Inaruhusu programu kunasa na kuelekeza sauti kwingine."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"nasa sauti ya video"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Inaruhusu programu kunasa na kuelekeza video kwingine."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"nasa sauti ya video kwa usalama"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Inaruhusu programu kunasa na kuelekeza video kwingine kwa usalama."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"badilisha mipangilio yako ya sauti"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Inaruhusu programu kurekebisha mipangilio ya sauti kila mahali kama vile sauti na ni kipaza sauti kipi ambacho kinatumika kwa kutoa."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"rekodi sauti"</string>
@@ -659,6 +654,10 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Inaruhusu kishikilizi kuunganishwa kwenye kusano cha kiwango cha juu cha huduma ya kisikilizi cha arifa. Haipaswi kuhitajika tena kwa programu za kawaida."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"omba programu ya usakinishaji inayotolewa na mtoa huduma."</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Inaruhusu kishikiliaji kuomba programu ya usakinishaji inayotolewa na mto huduma. Haipaswi kuhitajika kwa programu za kawaida."</string>
+ <!-- no translation found for permlab_accessNetworkConditions (8206077447838909516) -->
+ <skip />
+ <!-- no translation found for permdesc_accessNetworkConditions (6899102075825272211) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Weka kanuni za nenosiri"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Dhibiti urefu na vibambo vinavyoruhusiwa katika manenosiri ya kufungua skrini."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Chunguza majaribio ya kutofun gua skrini"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index d4b08c8a3380..98b9950abdb9 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"ป้องà¸à¸±à¸™à¸à¸²à¸£à¹€à¸›à¸¥à¸µà¹ˆà¸¢à¸™à¹à¸­à¸›à¸žà¸¥à¸´à¹€à¸„ชัน"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"ป้องà¸à¸±à¸™à¹„ม่ให้ผู้ใช้สลับไปใช้à¹à¸­à¸›à¸žà¸¥à¸´à¹€à¸„ชันอื่น"</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"รับข้อมูลà¹à¸­à¸›à¸žà¸¥à¸´à¹€à¸„ชันปัจจุบัน"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"ช่วยให้เจ้าของสามารถดึงข้อมูลส่วนตัวเà¸à¸µà¹ˆà¸¢à¸§à¸à¸±à¸šà¹à¸­à¸›à¸žà¸¥à¸´à¹€à¸„ชันปัจจุบันในส่วนหน้าของหน้าจอ"</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"ตรวจสอบà¹à¸¥à¸°à¸„วบคุมà¹à¸­à¸›à¸žà¸¥à¸´à¹€à¸„ชันทั้งหมดที่เปิดใช้งาน"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"อนุà¸à¸²à¸•ให้à¹à¸­à¸›à¸žà¸¥à¸´à¹€à¸„ชันตรวจสอบà¹à¸¥à¸°à¸„วบคุมวิธีà¸à¸²à¸£à¸—ี่ระบบเปิดà¸à¸´à¸ˆà¸à¸£à¸£à¸¡à¸•่างๆ à¹à¸­à¸›à¸žà¸¥à¸´à¹€à¸„ชันที่เป็นอันตรายอาจทำอันตรายà¹à¸à¹ˆà¸£à¸°à¸šà¸šà¹„ด้อย่างสิ้นเชิง à¸à¸²à¸£à¸­à¸™à¸¸à¸à¸²à¸•นี้จำเป็นสำหรับà¸à¸²à¸£à¸žà¸±à¸’นาเท่านั้น ไม่ใช้สำหรับà¹à¸­à¸›à¸žà¸¥à¸´à¹€à¸„ชันทั่วไปโดยเด็ดขาด"</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"ส่งà¸à¸²à¸£à¸à¸£à¸°à¸ˆà¸²à¸¢à¸‚้อมูลว่ามีà¸à¸²à¸£à¸™à¸³à¹à¸žà¸„เà¸à¸ˆà¸­à¸­à¸"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"อนุà¸à¸²à¸•ให้à¹à¸­à¸›à¸à¸³à¸«à¸™à¸”ค่าà¹à¸¥à¸°à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¸•่อà¸à¸±à¸šà¸ˆà¸­à¹à¸ªà¸”งผล WiFi ได้"</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"ควบคุมà¸à¸²à¸£à¹à¸ªà¸”งผลด้วย WiFi"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"อนุà¸à¸²à¸•ให้à¹à¸­à¸›à¸„วบคุมคุณลัà¸à¸©à¸“ะต่างๆ ในระดับล่างของà¸à¸²à¸£à¹à¸ªà¸”งผลด้วย WiFi"</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"บันทึà¸à¹€à¸­à¸²à¸•์พุตเสียง"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"อนุà¸à¸²à¸•ให้à¹à¸­à¸›à¸šà¸±à¸™à¸—ึà¸à¹à¸¥à¸°à¹€à¸›à¸¥à¸µà¹ˆà¸¢à¸™à¹€à¸ªà¹‰à¸™à¸—างเอาต์พุตเสียง"</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"บันทึà¸à¹€à¸­à¸²à¸•์พุตวิดีโอ"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"อนุà¸à¸²à¸•ให้à¹à¸­à¸›à¸šà¸±à¸™à¸—ึà¸à¹à¸¥à¸°à¹€à¸›à¸¥à¸µà¹ˆà¸¢à¸™à¹€à¸ªà¹‰à¸™à¸—างเอาต์พุตวิดีโอ"</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"บันทึà¸à¹€à¸­à¸²à¸•์พุตเสียงที่ปลอดภัย"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"อนุà¸à¸²à¸•ให้à¹à¸­à¸›à¸šà¸±à¸™à¸—ึà¸à¹à¸¥à¸°à¹€à¸›à¸¥à¸µà¹ˆà¸¢à¸™à¹€à¸ªà¹‰à¸™à¸—างเอาต์พุตของวิดีโอที่ปลอดภัย"</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"เปลี่ยนà¸à¸²à¸£à¸•ั้งค่าเสียงของคุณ"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"อนุà¸à¸²à¸•ให้à¹à¸­à¸›à¸žà¸¥à¸´à¹€à¸„ชันปรับเปลี่ยนà¸à¸²à¸£à¸•ั้งค่าเสียงทั้งหมดได้ เช่น ระดับเสียงà¹à¸¥à¸°à¸¥à¸³à¹‚พงที่จะใช้งาน"</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"บันทึà¸à¹€à¸ªà¸µà¸¢à¸‡"</string>
@@ -659,6 +654,10 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"อนุà¸à¸²à¸•ให้เจ้าของเชื่อมโยงà¸à¸±à¸šà¸­à¸´à¸™à¹€à¸•อร์เฟซระดับสูงสุดของบริà¸à¸²à¸£à¸•ัวฟังà¸à¸²à¸£à¹à¸ˆà¹‰à¸‡à¹€à¸•ือน ซึ่งไม่มีความจำเป็นสำหรับà¹à¸­à¸›à¸˜à¸£à¸£à¸¡à¸”า"</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"เรียà¸à¹ƒà¸Šà¹‰à¹à¸­à¸›à¸à¸²à¸£à¸à¸³à¸«à¸™à¸”ค่าของผู้ให้บริà¸à¸²à¸£"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"อนุà¸à¸²à¸•ให้ผู้ใช้สามารถเรียà¸à¹ƒà¸Šà¹‰à¹à¸­à¸›à¸à¸²à¸£à¸à¸³à¸«à¸™à¸”ค่าของผู้ให้บริà¸à¸²à¸£ ซึ่งà¹à¸­à¸›à¸—ั่วไปไม่จำเป็นต้องใช้"</string>
+ <!-- no translation found for permlab_accessNetworkConditions (8206077447838909516) -->
+ <skip />
+ <!-- no translation found for permdesc_accessNetworkConditions (6899102075825272211) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"ตั้งค่าà¸à¸Žà¸£à¸«à¸±à¸ªà¸œà¹ˆà¸²à¸™"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"ควบคุมความยาวà¹à¸¥à¸°à¸­à¸±à¸à¸‚ระที่อนุà¸à¸²à¸•ให้ใช้ในรหัสผ่านà¸à¸²à¸£à¸›à¸¥à¸”ล็อà¸à¸«à¸™à¹‰à¸²à¸ˆà¸­"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"ตรวจสอบความพยายามในà¸à¸²à¸£à¸›à¸¥à¸”ล็อà¸à¸«à¸™à¹‰à¸²à¸ˆà¸­"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 7f33245feb83..01aab09148bb 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"pigilan ang mga paglipat ng app"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Pinipigilan ang mga user sa paglipat sa isa pang app."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"kunin ang impormasyon ng kasalukuyang app"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Pinapayagan ang may-ari na bawiin ang pribadong impormasyon tungkol sa kasalukuyang application sa foreground ng screen."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"subaybayan at kontrolin ang lahat ng paglunsad ng app"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Pinapayagan ang app na subaybayan at kontrolin kung paano naglulunsad ng mga aktibidad ang system. Maaaring ganap na ikompromiso ng nakakahamak na apps ang system. Kinakailangan lamang ang pahintulot na ito para sa pagpapabuti, hindi kailanman para sa normal na paggamit."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"magpadala ng package inalis ang broadcast"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Pinapayagan ang app na mag-configure at kumonekta sa mga Wifi display."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"magkontrol ng mga Wifi display"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Pinapayagan ang app na magkontrol ng mga tampok sa mababang antas ng mga dispay ng Wifi."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"kumuha ng audio output"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Pinapayagan ang app na kumuha at mag-redirect ng audio output."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"kumuha ng video output"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Pinapayagan ang app na kumuha at mag-redirect ng video output."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"kumuha ng secure na video output"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Pinapayagan ang app na kumuha at mag-redirect ng secure na video output."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"baguhin ang mga setting ng iyong audio"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Pinapayagan ang app na baguhin ang mga pandaigdigang setting ng audio gaya ng volume at kung aling speaker ang ginagamit para sa output."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"mag-record ng audio"</string>
@@ -659,6 +654,10 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Nagbibigay-daan sa may-ari na mapailalim sa interface sa tuktok na antas ng isang serbisyo ng notification listener. Hindi dapat kailanganin para sa karaniwang apps kahit kailan."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"paganahin ang app ng configuration na ibinigay ng carrier"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Nagbibigay-daan sa may-ari na paganahin ang app ng configuration na ibinigay ng carrier. Hindi dapat kailanganin para sa normal na apps kahit kailan."</string>
+ <!-- no translation found for permlab_accessNetworkConditions (8206077447838909516) -->
+ <skip />
+ <!-- no translation found for permdesc_accessNetworkConditions (6899102075825272211) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Magtakda ng mga panuntunan sa password"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontrolin ang haba at mga character na pinapayagan sa mga password sa pag-unlock ng screen."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Subaybayan ang mga pagsubok sa pag-unlock ng screen"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index d682d379df6d..1c8b64061693 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"uygulama deÄŸiÅŸimlerini engelle"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Kullanıcının başka bir uygulamaya geçiş yapmasını engeller."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"geçerli uygulama bilgilerini al"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"İzin sahibine, ekranın ön planındaki geçerli uygulama hakkında gizli bilgileri alma olanağı verir."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"tüm uygulama başlatma işlemlerini izle ve denetle"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Uygulamaya, sistemin etkinlikleri nasıl başlattığını izleme ve denetleme izni verir. Kötü amaçlı uygulamalar sistemi tamamen tehlikeye atabilir. Bu izin normal kullanım için değildir, sadece geliştirme süreçlerinde kullanılır."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"paket ile kaldırılan yayını gönder"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Uygulamaya kablosuz ekranları yapılandırma ve bunlara bağlanma izni verir."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"Kablosuz ekranları denetle"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Uygulamaya kablosuz ekranların alt düzey özelliklerini kontrol etme izni verir."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"ses çıkışını yakala"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Uygulamaya, ses çıkışını yakalayıp yönlendirme izni verir."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"video çıkışını yakala"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Uygulamaya, video çıkışını yakalayıp yönlendirme izni verir."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"güvenli video çıkışını yakala"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Uygulamaya, güvenli video çıkışını yakalayıp yönlendirme izni verir."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"ses ayarlarınızı değiştirin"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Uygulamaya ses düzeyi ve ses çıkışı için kullanılan hoparlör gibi genel ses ayarlarını değiştirme izni verir."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"ses kaydet"</string>
@@ -659,6 +654,8 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"İzin sahibine bir bildirim dinleyici hizmetinin en üst düzey arayüzüne bağlanma izni verir. Normal uygulamalarda hiçbir zaman gerek duyulmaz."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"operatör tarafından sağlanan yapılandırma uygulamasını çalıştır"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"İzin sahibine, operatör tarafından sağlanan yapılandırma uygulamasını çalıştırma izni verir. Normal uygulamalarda hiçbir zaman gerek duyulmaz."</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"ağ koşullarındaki gözlemleri dinle"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Bir uygulamaya, ağ koşullarındaki gözlemleri dinleme izni verir. Normal uygulamalar için hiçbir zaman gerekmez."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Şifre kuralları ayarla"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Ekran kilidini açma şifrelerinde izin verilen uzunluğu ve karakterleri denetleme."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Ekran kilidini açma denemelerini izle"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index b41171bb53ce..e87a400bd3b6 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"запобіг. зміні програм"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Запобігати переходу кориÑтувача до іншої програми."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"отримати інформацію про поточну програму"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"ДозволÑÑ” влаÑникові отримувати приватну інформацію про поточну програму на передньому плані екрана."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"відÑтежувати та контролювати запуÑки вÑÑ–Ñ… програм"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"ДозволÑÑ” програмі відÑтежувати та контролювати, Ñк Ñаме ÑиÑтема запуÑкає дії. Шкідливі програми можуть отримати повний контроль над ÑиÑтемою. Цей дозвіл потрібний лише Ð´Ð»Ñ Ñ€Ð¾Ð·Ñ€Ð¾Ð±ÐºÐ¸, а не Ð´Ð»Ñ Ð·Ð²Ð¸Ñ‡Ð°Ð¹Ð½Ð¾Ð³Ð¾ кориÑтуваннÑ."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"надÑил. Ð·Ð°Ð¿Ð¸Ñ Ð¿Ñ€Ð¾ видал. пакета"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"ДозволÑÑ” програмі налаштовувати екрани Wi-Fi Ñ– під’єднуватиÑÑ Ð´Ð¾ них."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"керувати екранами Wi-Fi"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"ДозволÑÑ” програмі керувати низькорівневими функціÑми екранів Wi-Fi."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"отримувати доÑтуп до аудіовиходу"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"ДозволÑÑ” програмі отримувати доÑтуп до аудіовиходу й переÑпрÑмовувати його."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"отримувати доÑтуп до відеовиходу"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"ДозволÑÑ” програмі отримувати доÑтуп до відеовиходу й переÑпрÑмовувати його."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"отримувати доÑтуп до захищеного відеовиходу"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"ДозволÑÑ” програмі отримувати доÑтуп до захищеного відеовиходу й переÑпрÑмовувати його."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"змінювати налаштув-Ð½Ñ Ð·Ð²ÑƒÐºÑƒ"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"ДозволÑÑ” програмі змінювати загальні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð²ÑƒÐºÑƒ, Ñк-от гучніÑть Ñ– динамік, Ñкий викориÑтовуєтьÑÑ Ð´Ð»Ñ Ð²Ð¸Ð²Ð¾Ð´Ñƒ Ñигналу."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"запиÑ-ти аудіо"</string>
@@ -659,6 +654,8 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"ДозволÑÑ” влаÑнику прив’ÑзуватиÑÑ Ð´Ð¾ інтерфейÑу верхнього Ñ€Ñ–Ð²Ð½Ñ Ñлужби Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ Ñповіщень. Ðіколи не заÑтоÑовуєтьÑÑ Ð´Ð»Ñ Ð·Ð²Ð¸Ñ‡Ð°Ð¹Ð½Ð¸Ñ… програм."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"викликати надану оператором програму конфігурації"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"ДозволÑÑ” влаÑнику викликати надану оператором програму конфігурації. Ðіколи не заÑтоÑовуєтьÑÑ Ð´Ð»Ñ Ð·Ð²Ð¸Ñ‡Ð°Ð¹Ð½Ð¸Ñ… програм."</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"проÑлуховувати дані ÑпоÑтережень за Ñтаном мережі"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"ДозволÑÑ” програмі проÑлуховувати дані ÑпоÑтережень за Ñтаном мережі. Ðіколи не заÑтоÑовуєтьÑÑ Ð´Ð»Ñ Ð·Ð²Ð¸Ñ‡Ð°Ð¹Ð½Ð¸Ñ… програм."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"УÑтан. правила паролÑ"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Контролювати довжину паролів Ð´Ð»Ñ Ñ€Ð¾Ð·Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ ÐµÐºÑ€Ð°Ð½Ð° та дозволені в них Ñимволи."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"ВідÑтежув. Ñпроби розблок. екрана"</string>
@@ -1479,7 +1476,7 @@
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"Екран HDMI"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"ÐÐ°ÐºÐ»Ð°Ð´Ð°Ð½Ð½Ñ â„–<xliff:g id="ID">%1$d</xliff:g>"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>Ñ…<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
- <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", фікÑована"</string>
+ <string name="display_manager_overlay_display_secure_suffix" msgid="6022119702628572080">", безпечний"</string>
<string name="wifi_display_notification_title" msgid="2223050649240326557">"Бездротовий екран під’єднано"</string>
<string name="wifi_display_notification_message" msgid="4498802012464170685">"Цей екран відображаєтьÑÑ Ð½Ð° іншому приÑтрої"</string>
<string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"Від’єднати"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 9e5b36c32e2b..2e95cd188f90 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"ngăn chuyển đổi ứng dụng"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Ngăn ngưá»i dùng chuyển sang ứng dụng khác."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"truy cập thông tin ứng dụng hiện tại"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Cho phép chá»§ sở hữu truy xuất thông tin cá nhân vỠứng dụng hiện tại ở ná»n trước cá»§a màn hình."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"giám sát và kiểm soát tất cả hoạt động khởi chạy ứng dụng"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Cho phép ứng dụng giám sát và kiểm soát cách hệ thống khởi chạy các hoạt động. Ứng dụng độc hại hoàn toàn có thể làm tổn hại hệ thống. Quyá»n này chỉ cần cho mục đích phát triển, không dành cho mục đích sá»­ dụng thông thưá»ng."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"gá»­i truyá»n phát đã xóa cá»§a gói"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Cho phép ứng dụng định cấu hình và kết nối với màn hình Wi-Fi."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"kiểm soát màn hình Wi-Fi"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Cho phép ứng dụng kiểm soát các tính năng cấp thấp của màn hình Wi-Fi."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"thu thập dữ liệu đầu ra âm thanh"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Cho phép ứng dụng thu thập và chuyển hướng dữ liệu đầu ra âm thanh."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"thu thập dữ liệu đầu ra video"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Cho phép ứng dụng thu thập và chuyển hướng dữ liệu đầu ra video."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"thu thập dữ liệu đầu ra video an toàn"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Cho phép ứng dụng thu thập và chuyển hướng dữ liệu đầu ra video an toàn."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"thay đổi cài đặt âm thanh của bạn"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Cho phép ứng dụng sửa đổi cài đặt âm thanh chung chẳng hạn như âm lượng và loa nào được sử dụng cho thiết bị ra."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"ghi âm"</string>
@@ -659,6 +654,10 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Cho phép chá»§ sở hữu liên kết vá»›i giao diện cấp cao nhất cá»§a dịch vụ trình xá»­ lý thông báo. Không cần thiết cho các ứng dụng thông thưá»ng."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"gá»i ra ứng dụng cấu hình do nhà cung cấp dịch vụ cung cấp"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Cho phép chá»§ sở hữu gá»i ra ứng dụng cấu hình do nhà cung cấp dịch vụ cung cấp. Không cần thiết cho các ứng dụng thông thưá»ng."</string>
+ <!-- no translation found for permlab_accessNetworkConditions (8206077447838909516) -->
+ <skip />
+ <!-- no translation found for permdesc_accessNetworkConditions (6899102075825272211) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Äặt quy tắc mật khẩu"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Kiểm soát độ dài và ký tự được phép trong mật khẩu mở khóa màn hình."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Giám sát những lần thử mở khóa màn hình"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index a60b088c8307..a2267a6750cd 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"ç¦æ­¢åˆ‡æ¢åº”用"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"阻止用户切æ¢åˆ°å…¶ä»–应用。"</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"获å–当å‰åº”用的信æ¯"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"å…许应用检索目å‰åœ¨å±å¹•å‰å°è¿è¡Œçš„应用专有的信æ¯ã€‚"</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"监控所有应用的å¯åЍ"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"å…许应用监视和控制系统是如何å¯åŠ¨æ´»åŠ¨çš„ã€‚æ¶æ„应用å¯èƒ½ä¼šå®Œå…¨ç ´å系统。此æƒé™åªæœ‰åœ¨è¿›è¡Œå¼€å‘æ—¶æ‰éœ€è¦ï¼Œæ­£å¸¸ä½¿ç”¨æƒ…况下ç»ä¸éœ€è¦ã€‚"</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"å‘é€åŒ…删除的广播"</string>
@@ -362,10 +363,8 @@
<string name="permdesc_bindPrintService" msgid="7960067623209111135">"å…è®¸åº”ç”¨ç»‘å®šè‡³æ‰“å°æœåŠ¡çš„é¡¶çº§æŽ¥å£ã€‚普通应用ç»ä¸éœ€è¦æ­¤æƒé™ã€‚"</string>
<string name="permlab_accessAllPrintJobs" msgid="1120792468465711159">"查看或修改所有打å°ä½œä¸š"</string>
<string name="permdesc_accessAllPrintJobs" msgid="2978185311041864762">"å…许应用查看或修改其他应用创建的打å°ä½œä¸šã€‚普通应用ç»ä¸éœ€è¦æ­¤æƒé™ã€‚"</string>
- <!-- no translation found for permlab_bindNfcService (2752731300419410724) -->
- <skip />
- <!-- no translation found for permdesc_bindNfcService (6120647629174066862) -->
- <skip />
+ <string name="permlab_bindNfcService" msgid="2752731300419410724">"绑定到 NFC æœåŠ¡"</string>
+ <string name="permdesc_bindNfcService" msgid="6120647629174066862">"å…许应用绑定到模拟 NFC å¡çš„应用。普通应用ç»ä¸éœ€è¦æ­¤æƒé™ã€‚"</string>
<string name="permlab_bindTextService" msgid="7358378401915287938">"绑定至文字æœåŠ¡"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"å…许用户绑定至文字æœåŠ¡ï¼ˆå¦‚ SpellCheckerService)的顶级接å£ã€‚普通应用ç»ä¸éœ€è¦æ­¤æƒé™ã€‚"</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"绑定到 VPN æœåŠ¡"</string>
@@ -476,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"å…许应用é…置并连接到 WLAN 显示设备。"</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"控制 WLAN 显示设备"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"å…许应用控制 WLAN 显示设备的基础功能。"</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"æ•获音频输出"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"å…许该应用æ•获和é‡å®šå‘音频输出。"</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"æ•获视频输出"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"å…许该应用æ•获和é‡å®šå‘视频输出。"</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"æ•获安全视频输出"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"å…许该应用æ•获和é‡å®šå‘安全视频输出。"</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"更改您的音频设置"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"å…许该应用修改全局音频设置,例如音é‡å’Œç”¨äºŽè¾“出的扬声器。"</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"录音"</string>
@@ -661,6 +654,8 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"å…许应用绑定到通知侦å¬å™¨æœåŠ¡çš„é¡¶çº§æŽ¥å£ï¼ˆæ™®é€šåº”用ç»ä¸éœ€è¦æ­¤æƒé™ï¼‰ã€‚"</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"调用è¿è¥å•†æä¾›çš„é…置应用"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"å…许应用调用è¿è¥å•†æä¾›çš„é…置应用。普通应用ç»ä¸éœ€è¦æ­¤æƒé™ã€‚"</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"监å¬ç½‘络状况的观测信æ¯"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"å…许应用监å¬ç½‘络状况的观测信æ¯ã€‚普通应用ç»ä¸éœ€è¦æ­¤æƒé™ã€‚"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"设置密ç è§„则"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"控制å±å¹•è§£é”å¯†ç æ‰€å…许的长度和字符。"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"监视å±å¹•è§£é”å°è¯•次数"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 2ea03d729d73..9558319f03d3 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"é˜²æ­¢åˆ‡æ›æ‡‰ç”¨ç¨‹å¼"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"防止使用者切æ›åˆ°å…¶ä»–應用程å¼ã€‚"</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"å–å¾—ç›®å‰çš„æ‡‰ç”¨ç¨‹å¼è³‡è¨Š"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"å…許應用程å¼é‡å°ç›®å‰åœ¨èž¢å¹•剿™¯é‹ä½œçš„æ‡‰ç”¨ç¨‹å¼æ“·å–ç§äººè³‡è¨Šã€‚"</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"ç›£è¦–åŠæŽ§åˆ¶æ‰€æœ‰æ‡‰ç”¨ç¨‹å¼çš„啟動程åº"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"å…許應用程å¼ç›£è¦–和控制系統啟動活動的方å¼ã€‚請注æ„ï¼Œæƒ¡æ„æ‡‰ç”¨ç¨‹å¼å¯èƒ½åˆ©ç”¨æ­¤åŠŸèƒ½ç ´å£žæ•´å€‹ç³»çµ±ã€‚é€™å€‹æ¬Šé™åªæœ‰é–‹ç™¼äººå“¡æ‰éœ€è¦ï¼Œä¸€èˆ¬ä½¿ç”¨è€…ä¸éœ€ä½¿ç”¨é€™å€‹æ¬Šé™ã€‚"</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"傳é€ç¨‹å¼å·²ç§»é™¤å»£æ’­"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"å…許應用程å¼è¨­å®šåŠé€£æŽ¥ Wi-Fi 顯示è£ç½®ã€‚"</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"控制 Wi-Fi 顯示è£ç½®"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"å…è¨±æ‡‰ç”¨ç¨‹å¼æŽ§åˆ¶ Wi-Fi 顯示è£ç½®çš„低階功能。"</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"æ“·å–音訊輸出"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"å…è¨±æ‡‰ç”¨ç¨‹å¼æ“·å–åŠé‡æ–°å°Žå‘音訊輸出。"</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"æ“·å–視訊輸出"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"å…è¨±æ‡‰ç”¨ç¨‹å¼æ“·å–åŠé‡æ–°å°Žå‘視訊輸出。"</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"æ“·å–安全視訊輸出"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"å…è¨±æ‡‰ç”¨ç¨‹å¼æ“·å–åŠé‡æ–°å°Žå‘安全視訊輸出。"</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"變更音訊設定"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"å…許應用程å¼ä¿®æ”¹å…¨åŸŸéŸ³è¨Šè¨­å®šï¼Œä¾‹å¦‚音é‡å’Œç”¨ä¾†è¼¸å‡ºçš„å–‡å­ã€‚"</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"錄製音訊"</string>
@@ -659,6 +654,10 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"å…許應用程å¼ç¹«çµè‡³é€šçŸ¥æŽ¥è½å™¨æœå‹™çš„é ‚å±¤ä»‹é¢ (一般應用程å¼ä¸éœ€ä½¿ç”¨)。"</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"å«ç”¨è¡Œå‹•通訊業者æä¾›çš„設定應用程å¼"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"å…許應用程å¼å«ç”¨è¡Œå‹•通訊業者æä¾›çš„è¨­å®šæ‡‰ç”¨ç¨‹å¼ (一般應用程å¼ä¸¦ä¸éœ€è¦)。"</string>
+ <!-- no translation found for permlab_accessNetworkConditions (8206077447838909516) -->
+ <skip />
+ <!-- no translation found for permdesc_accessNetworkConditions (6899102075825272211) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"設定密碼è¦å‰‡"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"控制螢幕解鎖密碼所å…許的長度和字元。"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"監視螢幕解鎖嘗試次數"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 2e027e16265b..575ff5952e4a 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -314,7 +314,8 @@
<string name="permlab_stopAppSwitches" msgid="4138608610717425573">"gwema ukushintsha kohlelo lokusebenza"</string>
<string name="permdesc_stopAppSwitches" msgid="8262195802582255021">"Igwema umsebenzisi ukuthi ashintshele kolunye uhlelo lokusebenza."</string>
<string name="permlab_getTopActivityInfo" msgid="2537922311411546016">"thola ulwazi lohlelo lokusebenza lwamanje"</string>
- <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"Ivumela umphathi ukuthi athole ulwazi oluyimfihlo mayelana nohlelo lokusebenza lwamanje ngaphambili kwesikrini."</string>
+ <!-- no translation found for permdesc_getTopActivityInfo (8153651434145132505) -->
+ <skip />
<string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"qapha futhi ulawule ukuqaliswa kwazo zonke izinsiza"</string>
<string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"Ivumela uhlelo lokusebebenza ukuthi luhlole futhi lulawule ukuthi isistimu iziqalisa kanjani imisebenzi. Izinhlelo zokusebenza ezinobungozi zingensa isistimu ibe sebungozini. Le mvume idingakalela intuthuku kuphela hhayi ukusetshenziswa okwejwayelekile."</string>
<string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"thumela iphakheji yomsakazo okhishiwe"</string>
@@ -474,18 +475,12 @@
<string name="permdesc_configureWifiDisplay" msgid="7916815158690218065">"Ivumela uhlelo lokusebenza ukulungisa nokuxhuma ekubukisweni kwe-Wi-Fi."</string>
<string name="permlab_controlWifiDisplay" msgid="393641276723695496">"lawula ukubukwa kwe-Wi-Fi"</string>
<string name="permdesc_controlWifiDisplay" msgid="4543912292681826986">"Uvumela uhlelo lokusebenza ukulawula izici zeleveli ephansi zokuboniswa kwe-Wi-Fi."</string>
- <!-- no translation found for permlab_captureAudioOutput (6857134498402346708) -->
- <skip />
- <!-- no translation found for permdesc_captureAudioOutput (6210597754212208853) -->
- <skip />
- <!-- no translation found for permlab_captureVideoOutput (2246828773589094023) -->
- <skip />
- <!-- no translation found for permdesc_captureVideoOutput (359481658034149860) -->
- <skip />
- <!-- no translation found for permlab_captureSecureVideoOutput (7815398969303382016) -->
- <skip />
- <!-- no translation found for permdesc_captureSecureVideoOutput (2779793064709350289) -->
- <skip />
+ <string name="permlab_captureAudioOutput" msgid="6857134498402346708">"shutha okukhipha umsindo"</string>
+ <string name="permdesc_captureAudioOutput" msgid="6210597754212208853">"Kuvumela uhlelo lokusebenza ukuba lushuthe futhi luqondise kabusha okukhipha umsindo."</string>
+ <string name="permlab_captureVideoOutput" msgid="2246828773589094023">"shutha okokukhipha ividiyo"</string>
+ <string name="permdesc_captureVideoOutput" msgid="359481658034149860">"Kuvumela uhlelo lokusebenza ukuba lushuthe futhi luqondise kabusha okukhipha ividiyo."</string>
+ <string name="permlab_captureSecureVideoOutput" msgid="7815398969303382016">"shutha okukhipha ividiyo ephephile"</string>
+ <string name="permdesc_captureSecureVideoOutput" msgid="2779793064709350289">"Kuvumela uhlelo lokusebenza ukuba lushuthe futhi luqondise kabusha okukhipa ividiyo ephephile."</string>
<string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"shintsha izilungiselelo zakho zomsindo"</string>
<string name="permdesc_modifyAudioSettings" msgid="3522565366806248517">"Ivumela uhlelo lokusebenza ukushintsha izilungiselelo zomsindo we-global njengevolomu nokuthi isiphi isipika esisetshenziselwa okukhiphayo."</string>
<string name="permlab_recordAudio" msgid="3876049771427466323">"qopha umsindo"</string>
@@ -659,6 +654,8 @@
<string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Ivumela umbambi ukubophezela kwisixhumi esibonakalayo sezinga eliphezulu lesevisi yomlaleli wesaziso. Akusoze kwadingeka kwizinhlelo zokusebenza ezivamile."</string>
<string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"buyisela uhlelo lokusebenza lokulungiselelwa okunikezwe yinkampani yenethiwekhi"</string>
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Ivumela umnikazi ukuthi abuyisele uhlelo lokusebenza lokulungiselelwa. Akumele idingelwe izinhlelo zokusebenza ezijwayelekile."</string>
+ <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"Lalela okubonwayo kuzimo zenethiwekhi"</string>
+ <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Ivumela uhlelo lokusebenza ukuthi lulalele okubonwa kuzimo zenethiwekhi. Akumele idingelwe izinhlelo zokusebenza ezijwayelekile."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Misa imithetho yephasiwedi"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Lawula ubude nezinhlamvu ezivunyelwe kumaphasiwedi okuvula isikrini"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Gaka imizamo yokuvula isikrini"</string>
diff --git a/docs/html/google/gcm/adv.jd b/docs/html/google/gcm/adv.jd
index 136062408e9f..567b12cbb60c 100644
--- a/docs/html/google/gcm/adv.jd
+++ b/docs/html/google/gcm/adv.jd
@@ -22,7 +22,12 @@ page.title=GCM Advanced Topics
</ol>
</li>
<li><a href="#retry">Automatic Retry Using Exponential Back-Off</a></li>
-<li><a href="#unreg">How Unregistration Works</a></li>
+<li><a href="#unreg">Unregistration</a>
+ <ol>
+ <li><a href="#unreg-why">Why you should rarely unregister</a></li>
+ <li><a href="#unreg-how">How unregistration works</a></li>
+ </ol>
+</li>
<li><a href="#collapsible">Send-to-Sync vs. Messages with Payload</a>
<ol>
<li><a href="#s2s">Send-to-sync messages</a></li>
@@ -31,7 +36,8 @@ page.title=GCM Advanced Topics
</ol>
</li>
<li><a href="#ttl">Setting an Expiration Date for a Message</a> </li>
-<li><a href="#throttling"></a><a href="#multi-senders">Receiving Messages from Multiple Senders</a></li>
+<li><a href="#throttling"></a><a href="#multi-senders">Receiving Messages from
+Multiple Senders</a></li>
</ol>
</div>
@@ -42,17 +48,56 @@ page.title=GCM Advanced Topics
<h2 id="msg-lifetime">Lifetime of a Message</h2>
-<p>When a 3rd-party server posts a message to GCM and receives a message ID back, it does not mean that the message was already delivered to the device. Rather, it means that it was accepted for delivery. What happens to the message after it is accepted depends on many factors.</p>
-<p>In the best-case scenario, if the device is connected to GCM, the screen is on, and there are no throttling restrictions (see <a href="#throttling">Throttling</a>), the message will be delivered right away.</p>
-<p>If the device is connected but idle, the message will still be
-delivered right away unless the <code>delay_while_idle</code> flag is set to true. Otherwise, it will be stored in the GCM servers until the device is awake. And that's where the <code>collapse_key</code> flag plays a role: if there is already a message with the same collapse key (and registration ID) stored and waiting for delivery, the old message will be discarded and the new message will take its place (that is, the old message will be collapsed by the new one). However, if the collapse key is not set, both the new and old messages are stored for future delivery.</p>
+<p>When a 3rd-party server posts a message to GCM and receives a message ID back,
+it does not mean that the message was already delivered to the device. Rather, it
+means that it was accepted for delivery. What happens to the message after it is
+accepted depends on many factors.</p>
-<p class="note"><strong>Note:</strong> There is a limit on how many messages can be stored without collapsing. That limit is currently 100. If the limit is reached, all stored messages are discarded. Then when the device is back online, it receives a special message indicating that the limit was reached. The application can then handle the situation properly, typically by requesting a full sync.</p>
+<p>In the best-case scenario, if the device is connected to GCM, the screen is on,
+and there are no throttling restrictions (see <a href="#throttling">Throttling</a>),
+the message will be delivered right away.</p>
-<p>If the device is not connected to GCM, the message will be stored until a connection is established (again respecting the collapse key rules). When a connection is established, GCM will deliver all pending messages to the device, regardless of the <code>delay_while_idle</code> flag. If the device never gets connected again (for instance, if it was factory reset), the message will eventually time out and be discarded from GCM storage. The default timeout is 4 weeks, unless the <code>time_to_live</code> flag is set.</p>
-
-<p>Finally, when GCM attempts to deliver a message to the device and the application was uninstalled, GCM will discard that message right away and invalidate the registration ID. Future attempts to send a message to that device will get a <code>NotRegistered</code> error. See <a href="#unreg">How Unregistration Works</a> for more information.</p>
-<p>Although is not possible to track the status of each individual message, the Google APIs Console stats are broken down by messages sent to device, messages collapsed, and messages waiting for delivery.</p>
+<p>If the device is connected but idle, the message will still be
+delivered right away unless the <code>delay_while_idle</code> flag is set to true.
+Otherwise, it will be stored in the GCM servers until the device is awake. And
+that's where the <code>collapse_key</code> flag plays a role: if there is already
+a message with the same collapse key (and registration ID) stored and waiting for
+delivery, the old message will be discarded and the new message will take its place
+(that is, the old message will be collapsed by the new one). However, if the collapse
+key is not set, both the new and old messages are stored for future delivery.
+Collapsible messages are also called <a href="#s2s">send-to-sync messages</a>.</p>
+
+<p class="note"><strong>Note:</strong> There is a limit on how many messages can
+be stored without collapsing. That limit is currently 100. If the limit is reached,
+all stored messages are discarded. Then when the device is back online, it receives
+a special message indicating that the limit was reached. The application can then
+handle the situation properly, typically by requesting a full sync.
+<br><br>
+Likewise, there is a limit on how many <code>collapse_key</code>s you can have for
+a particular device. GCM allows a maximum of 4 different collapse keys to be used
+by the GCM server per device
+any given time. In other words, the GCM server can simultaneously store 4 different
+send-to-sync messages, each with a different collapse key. If you exceed this number
+GCM will only keep 4 collapse keys, with no guarantees about which ones they will be.
+See <a href="#s2s">Send-to-sync messages</a> for more information.
+</p>
+
+<p>If the device is not connected to GCM, the message will be stored until a
+connection is established (again respecting the collapse key rules). When a connection
+is established, GCM will deliver all pending messages to the device, regardless of
+the <code>delay_while_idle</code> flag. If the device never gets connected again
+(for instance, if it was factory reset), the message will eventually time out and
+be discarded from GCM storage. The default timeout is 4 weeks, unless the
+<code>time_to_live</code> flag is set.</p>
+
+<p>Finally, when GCM attempts to deliver a message to the device and the
+application was uninstalled, GCM will discard that message right away and
+invalidate the registration ID. Future attempts to send a message to that device
+will get a <code>NotRegistered</code> error. See <a href="#unreg">
+How Unregistration Works</a> for more information.</p>
+<p>Although is not possible to track the status of each individual message, the
+Google APIs Console stats are broken down by messages sent to device, messages
+collapsed, and messages waiting for delivery.</p>
<h2 id="throttling">Throttling</h2>
<p>To prevent abuse (such as sending a flood of messages to a device) and
@@ -74,107 +119,112 @@ belonging to a non-throttled category by GCM for network and battery
efficiency reasons.</p>
<h2 id="reg-state">Keeping the Registration State in Sync</h2>
-<p>Whenever the application receives a <code>com.google.android.c2dm.intent.REGISTRATION</code> intent with a <code>registration_id</code> extra, it should save the ID for future use, pass it to the 3rd-party server to complete the registration, and keep track of whether the server completed the registration. If the server fails to complete the registration, it should try again or unregister from GCM.</p>
+<p>Whenever the application registers as described in
+<a href="{@docRoot}google/gcm/client.html">Implementing GCM Client</a>,
+it should save the registration ID for future use, pass it to the
+3rd-party server to complete the registration, and keep track of
+whether the server completed the registration. If the server fails
+to complete the registration, it should try again or unregister from GCM.</p>
+
<p>There are also two other scenarios that require special care:</p>
<ul>
<li>Application update</li>
<li>Backup and restore
</li>
</ul>
-<p>When an application is updated, it should invalidate its existing registration ID, as it is not guaranteed to work with the new version. Because there is no lifecycle method called when the application is updated, the best way to achieve this validation is by storing the current application version when a registration ID is stored. Then when the application is started, compare the stored value with the current application version. If they do not match, invalidate the stored data and start the registration process again.</p>
-
-<p>Similarly, you should not save the registration ID when an application is backed up. This is because the registration ID could become invalid by the time the application is restored, which would put the application in an invalid state (that is, the application thinks it is registered, but the server and GCM do not store that registration ID anymore&mdash;thus the application will not get more messages).</p>
+<p>When an application is updated, it should invalidate its existing registration
+ID, as it is not guaranteed to work with the new version. Because there is no
+lifecycle method called when the application is updated, the best way to achieve
+this validation is by storing the current application version when a registration
+ID is stored. Then when the application is started, compare the stored value with
+the current application version. If they do not match, invalidate the stored data
+and start the registration process again.</p>
+
+<p>Similarly, you should not save the registration ID when an application is
+backed up. This is because the registration ID could become invalid by the time
+the application is restored, which would put the application in an invalid state
+(that is, the application thinks it is registered, but the server and GCM do not
+store that registration ID anymore&mdash;thus the application will not get more
+messages).</p>
<h3 id="canonical">Canonical IDs</h3>
-<p>On the server side, as long as the application is behaving well, everything should work normally. However, if a bug in the application triggers multiple registrations for the same device, it can be hard to reconcile state and you might end up with duplicate messages.</p>
-<p>GCM provides a facility called &quot;canonical registration IDs&quot; to easily recover from these situations. A canonical registration ID is defined to be the ID of the last registration requested by your application. This is the ID that the server should use when sending messages to the device.</p>
-<p>If later on you try to send a message using a different registration ID, GCM will process the request as usual, but it will include the canonical registration ID in the <code>registration_id</code> field of the response. Make sure to replace the registration ID stored in your server with this canonical ID, as eventually the ID you're using will stop working.</p>
+<p>On the server side, as long as the application is behaving well, everything
+should work normally. However, if a bug in the application triggers multiple
+registrations for the same device, it can be hard to reconcile state and you might
+end up with duplicate messages.</p>
+<p>GCM provides a facility called &quot;canonical registration IDs&quot; to easily
+recover from these situations. A canonical registration ID is defined to be the ID
+of the last registration requested by your application. This is the ID that the
+server should use when sending messages to the device.</p>
+<p>If later on you try to send a message using a different registration ID, GCM
+will process the request as usual, but it will include the canonical registration
+ID in the <code>registration_id</code> field of the response. Make sure to replace
+the registration ID stored in your server with this canonical ID, as eventually
+the ID you're using will stop working.</p>
<h2 id="retry">Automatic Retry Using Exponential Back-Off</h2>
-<p>When the application receives a <code>com.google.android.c2dm.intent.REGISTRATION</code> intent with the <code>error</code> extra set as <code>SERVICE_NOT_AVAILABLE</code>, it should retry the failed operation (register or unregister).</p>
-<p>In the simplest case, if your application just calls <code>register</code> and GCM is not a fundamental part of the application, the application could simply ignore the error and try to register again the next time it starts. Otherwise, it should retry the previous operation using exponential back-off. In exponential back-off, each time there is a failure, it should wait twice the previous amount of time before trying again. If the register (or unregister) operation was synchronous, it could be retried in a simple loop. However, since it is asynchronous, the best approach is to schedule a pending intent to retry the operation. The following steps describe how to implement this in the <code>MyIntentService</code> example used above:</p>
-<ol>
- <li> Create a random token to verify the origin of the retry intent:
+<p>When registration or unregistration fails, the app should retry the failed operation.</p>
+<p>In the simplest case, if your application attempts to register and GCM is not a
+fundamental part of the application, the application could simply ignore the error
+and try to register again the next time it starts. Otherwise, it should retry the
+previous operation using exponential back-off. In exponential back-off, each time
+there is a failure, it should wait twice the previous amount of time before trying
+again. If the register (or unregister) operation was synchronous, it could be retried
+in a simple loop. However, since it is asynchronous, the best approach is to schedule
+a {@link android.app.PendingIntent} to retry the operation.
-<pre class="prettyprint pretty-java">private static final String TOKEN =
- Long.toBinaryString(new Random().nextLong());
-</pre>
+<h2 id="unreg">Unregistration</h2>
- <li> Change the <code>handleRegistration()</code> method so it creates the pending intent when appropriate:</li>
-
-<pre class="prettyprint pretty-java">...
-if (error != null) {
- if ("SERVICE_NOT_AVAILABLE".equals(error)) {
- long backoffTimeMs = // get back-off time from shared preferences
- long nextAttempt = SystemClock.elapsedRealtime() + backoffTimeMs;
- Intent retryIntent = new Intent("com.example.gcm.intent.RETRY");
- retryIntent.putExtra("token", TOKEN);
- PendingIntent retryPendingIntent =
- PendingIntent.getBroadcast(context, 0, retryIntent, 0);
- AlarmManager am = (AlarmManager)
- context.getSystemService(Context.ALARM_SERVICE);
- am.set(AlarmManager.ELAPSED_REALTIME, nextAttempt, retryPendingIntent);
- backoffTimeMs *= 2; // Next retry should wait longer.
- // update back-off time on shared preferences
- } else {
- // Unrecoverable error, log it
- Log.i(TAG, "Received error: " + error);
-}
-...</pre>
-<p> The back-off time is stored in a shared preference. This ensures that it is persistent across multiple activity launches. The name of the intent does not matter, as long as the same intent is used in the following steps.</p></li>
-
- <li> Change the <code>onHandleIntent()</code> method adding an <code>else if</code> case for the retry intent:</li>
-
-<pre class="prettyprint pretty-java">...
-} else if (action.equals("com.example.gcm.intent.RETRY")) {
- String token = intent.getStringExtra("token");
- // make sure intent was generated by this class, not by a malicious app
- if (TOKEN.equals(token)) {
- String registrationId = // get from shared properties
- if (registrationId != null) {
- // last operation was attempt to unregister; send UNREGISTER intent again
- } else {
- // last operation was attempt to register; send REGISTER intent again
- }
-}
-...</pre>
-
- <li> Create a new instance of <code>MyReceiver</code> in your activity:</li>
-
-<pre class="prettyprint pretty-java">private final MyBroadcastReceiver mRetryReceiver = new MyBroadcastReceiver();
-</pre>
+<p>This section explains when you should unregister in GCM and what happens
+when you do.</p>
- <li>In the activity's <code>onCreate()</code> method, register the new instance to receive the <code>com.example.gcm.intent.RETRY</code> intent:
- <pre class="prettyprint pretty-java">...
-IntentFilter filter = new IntentFilter(&quot;com.example.gcm.intent.RETRY&quot;);
-filter.addCategory(getPackageName());
-registerReceiver(mRetryReceiver, filter);
-...</pre>
+<h3 id="unreg-why">Why you should rarely unregister</h3>
-<p class="note"><strong>Note:</strong> You must dynamically create a new instance of the broadcast receiver since the one defined by the manifest can only receive intents with the <code>com.google.android.c2dm.permission.SEND</code> permission. The permission <code>com.google.android.c2dm.permission.SEND</code> is a system permission and as such it cannot be granted to a regular application.</p>
+<p>A registration ID (regID) represents a particular Android application running
+on a particular device. You should only need to unregister in rare cases, such as
+if you want an app to stop receiving messages, or if you suspect that the regID has
+been compromised. In general, though, once an app has a regID, you shouldn't need
+to change it.</p>
-</li>
+<p>In particular, you should never unregister your app as a mechanism for
+logout or for switching between users, for the following reasons:</p>
- <li>In the activity's <code>onDestroy()</code> method, unregister the broadcast receiver:</li>
+<ul>
+ <li>A regID maps an app to a device. It isn't associated with a particular
+ logged in user. If you unregister and then re-register, GCM may return the same
+ ID or a different ID&mdash;there's no guarantee either way.</li>
+
+ <li>Unregistration may take up to 5 minutes to propagate.</li>
+ <li>After unregistration, re-registration may again take up to 5 minutes to
+propagate. During this time messages may be rejected due to the state of being
+unregistered, and after all this, messages may still go to the wrong user.</li>
+</ul>
-<pre class="prettyprint pretty-java">unregisterReceiver(mRetryReceiver);</pre>
-</ol>
-<h2 id="unreg">How Unregistration Works</h2>
-<p>There are two ways to unregister a device from GCM: manually and automatically.</p>
-<p>An Android application can manually unregister itself by issuing a <code>com.google.android.c2dm.intent.UNREGISTER</code> intent, which is useful when the application offers a logoff feature (so it can unregister on logoff and register again on logon). See the <a href="gcm.html#unregistering">Architectural Overview</a> for more discussion of this topic. This is the sequence of events when an application unregisters itself:</p>
-<ol>
- <li> The application issues a <code>com.google.android.c2dm.intent.UNREGISTER</code> intent, passing the package name as an extra.</li>
- <li>When the GCM server is done with the unregistration, it sends a <code>com.google.android.c2dm.intent.REGISTRATION</code> intent with the <code>unregistered</code> extra set.</li>
- <li>The application then must contact the 3rd-party server so it can remove the registration ID.</li>
- <li>The application should also clear its registration ID.
- </li>
-</ol>
-<p>An application can be automatically unregistered after it is uninstalled from the device. However, this process does not happens right away, as Android does not provide an uninstall callback. What happens in this scenario is as follows:</p>
+
+<p>The solution is to manage your own mapping between users, the regID, and
+individual messages:</p>
+
+<ul>
+ <li>Your app server should maintain a mapping between the current user
+and the regID. This should include information about which user is supposed to
+receive a particular message.</li>
+ <li>The app running on the device should check to ensure that messages it
+receives match the logged in user.</li>
+</ul>
+
+
+<h3 id="unreg-how">How unregistration works</h3>
+
+<p>An application can be automatically unregistered after it is uninstalled from
+the device. However, this process does not happens right away, as Android does not
+provide an uninstall callback. What happens in this scenario is as follows:</p>
<ol>
<li>The end user uninstalls the application.</li>
<li>The 3rd-party server sends a message to GCM server.</li>
<li>The GCM server sends the message to the device.</li>
- <li>The GCM client receives the message and queries Package Manager about whether there are broadcast receivers configured to receive it, which returns <code>false</code>.
+ <li>The GCM client receives the message and queries Package Manager about
+whether there are broadcast receivers configured to receive it, which returns
+<code>false</code>.
</li>
<li>The GCM client informs the GCM server that the application was uninstalled.</li>
<li>The GCM server marks the registration ID for deletion.</li>
@@ -184,9 +234,16 @@ registerReceiver(mRetryReceiver, filter);
</li>
</ol>
-<p class ="note"><strong>Note:</strong> The GCM client is the Google Cloud Messaging framework present on the device.</p>
+<p class ="note"><strong>Note:</strong> The GCM client is the Google Cloud
+Messaging framework present on the device.</p>
-<p>Note that it might take a while for the registration ID be completely removed from GCM. Thus it is possible that messages sent during step 7 above gets a valid message ID as response, even though the message will not be delivered to the device. Eventually, the registration ID will be removed and the server will get a <code>NotRegistered</code> error, without any further action being required from the 3rd-party server (this scenario happens frequently while an application is being developed and tested).</p>
+<p>Note that it might take a while for the registration ID be completely removed
+from GCM. Thus it is possible that messages sent during step 7 above gets a valid
+message ID as response, even though the message will not be delivered to the device.
+Eventually, the registration ID will be removed and the server will get a
+<code>NotRegistered</code> error, without any further action being required from
+the 3rd-party server (this scenario happens frequently while an application is
+being developed and tested).</p>
<h2 id="collapsible">Send-to-Sync vs. Messages with Payload</h2>
@@ -196,17 +253,45 @@ registerReceiver(mRetryReceiver, filter);
<li>By default, it is stored by GCM for 4 weeks.</li>
</ul>
-<p>But despite these similarities, messages can behave very differently depending on their particular settings. One major distinction between messages is whether they are collapsed (where each new message replaces the preceding message) or not collapsed (where each individual message is delivered). Every message sent in GCM is either a &quot;send-to-sync&quot; (collapsible) message or a &quot;message with payload&quot; (non-collapsible message). These concepts are described in more detail in the following sections.</p>
+<p>But despite these similarities, messages can behave very differently depending
+on their particular settings. One major distinction between messages is whether
+they are collapsed (where each new message replaces the preceding message) or not
+collapsed (where each individual message is delivered). Every message sent in GCM
+is either a &quot;send-to-sync&quot; (collapsible) message or a &quot;message with
+payload&quot; (non-collapsible message). These concepts are described in more
+detail in the following sections.</p>
<h3 id="s2s"><strong>Send-to-sync messages</strong></h3>
-<p>A send-to-sync (collapsible) message is often a &quot;tickle&quot; that tells a mobile application to sync data from the server. For example, suppose you have an email application. When a user receives new email on the server, the server pings the mobile application with a &quot;New mail&quot; message. This tells the application to sync to the server to pick up the new email. The server might send this message multiple times as new mail continues to accumulate, before the application has had a chance to sync. But if the user has received 25 new emails, there's no need to preserve every &quot;New mail&quot; message. One is sufficient. Another example would be a sports application that updates users with the latest score. Only the most recent message is relevant, so it makes sense to have each new message replace the preceding message. </p>
-
-<p>The email and sports applications are cases where you would probably use the GCM <code>collapse_key</code> parameter. A <em>collapse key</em> is an arbitrary string that is used to collapse a group of like messages when the device is offline, so that only the most recent message gets sent to the client. For example, &quot;New mail,&quot; &quot;Updates available,&quot; and so on</p>
-<p>GCM allows a maximum of 4 different collapse keys to be used by the GCM server at any given time. In other words, the GCM server can simultaneously store 4 different send-to-sync messages, each with a different collapse key. If you exceed this number GCM will only keep 4 collapse keys, with no guarantees about which ones they will be.</p>
+<p>A send-to-sync (collapsible) message is often a &quot;tickle&quot; that tells
+a mobile application to sync data from the server. For example, suppose you have
+an email application. When a user receives new email on the server, the server
+pings the mobile application with a &quot;New mail&quot; message. This tells the
+application to sync to the server to pick up the new email. The server might send
+this message multiple times as new mail continues to accumulate, before the application
+has had a chance to sync. But if the user has received 25 new emails, there's no
+need to preserve every &quot;New mail&quot; message. One is sufficient. Another
+example would be a sports application that updates users with the latest score.
+Only the most recent message is relevant, so it makes sense to have each new
+message replace the preceding message. </p>
+
+<p>The email and sports applications are cases where you would probably use the
+GCM <code>collapse_key</code> parameter. A <em>collapse key</em> is an arbitrary
+string that is used to collapse a group of like messages when the device is offline,
+so that only the most recent message gets sent to the client. For example,
+&quot;New mail,&quot; &quot;Updates available,&quot; and so on</p>
+<p>GCM allows a maximum of 4 different collapse keys to be used by the GCM server
+at any given time. In other words, the GCM server can simultaneously store 4
+different send-to-sync messages per device, each with a different collapse key.
+For example, Device A can have A1, A2, A3, and A4. Device B can have B1, B2, B3,
+and B4, and so on. If you exceed this number GCM will only keep 4 collapse keys, with no
+guarantees about which ones they will be.</p>
<h3 id="payload">Messages with payload</h3>
-<p>Unlike a send-to-sync message, every &quot;message with payload&quot; (non-collapsible message) is delivered. The payload the message contains can be up to 4kb. For example, here is a JSON-formatted message in an IM application in which spectators are discussing a sporting event:</p>
+<p>Unlike a send-to-sync message, every &quot;message with payload&quot;
+(non-collapsible message) is delivered. The payload the message contains can be
+up to 4kb. For example, here is a JSON-formatted message in an IM application in
+which spectators are discussing a sporting event:</p>
<pre class="prettyprint pretty-json">{
"registration_id" : "APA91bHun4MxP5egoKMwt2KZFBaFUH-1RYqx...",
@@ -217,19 +302,42 @@ registerReceiver(mRetryReceiver, filter);
},
}</pre>
-<p>A &quot;message with payload&quot; is not simply a &quot;ping&quot; to the mobile application to contact the server to fetch data. In the aforementioned IM application, for example, you would want to deliver every message, because every message has different content. To specify a non-collapsible message, you simply omit the <code>collapse_key</code> parameter. Thus GCM will send each message individually. Note that the order of delivery is not guaranteed.</p>
-<p>GCM will store up to 100 non-collapsible messages. After that, all messages are discarded from GCM, and a new message is created that tells the client how far behind it is. The message is delivered through a regular <code>com.google.android.c2dm.intent.RECEIVE</code> intent, with the following extras:</p>
+<p>A &quot;message with payload&quot; is not simply a &quot;ping&quot; to the
+mobile application to contact the server to fetch data. In the aforementioned IM
+application, for example, you would want to deliver every message, because every
+message has different content. To specify a non-collapsible message, you simply
+omit the <code>collapse_key</code> parameter. Thus GCM will send each message
+individually. Note that the order of delivery is not guaranteed.</p>
+
+<p>GCM will store up to 100 non-collapsible messages. After that, all messages
+are discarded from GCM, and a new message is created that tells the client how
+far behind it is. The message is delivered through a regular
+<code>com.google.android.c2dm.intent.RECEIVE</code> intent, with the following
+extras:</p>
<ul>
- <li> <code>message_type</code>&mdash;The value is always the string &quot;deleted_messages&quot;.</li>
- <li><code>total_deleted</code>&mdash;The value is a string with the number of deleted messages.</li>
+ <li> <code>message_type</code>&mdash;The value is always the string
+&quot;deleted_messages&quot;.</li>
+ <li><code>total_deleted</code>&mdash;The value is a string with the number of
+deleted messages.</li>
</ul>
-<p>The application should respond by syncing with the server to recover the discarded messages. </p>
+<p>The application should respond by syncing with the server to recover the
+discarded messages. </p>
<h3 id="which">Which should I use?</h3>
- <p>If your application does not need to use non-collapsible messages, collapsible messages are a better choice from a performance standpoint, because they put less of a burden on the device battery.</p>
+ <p>If your application does not need to use non-collapsible messages, collapsible
+messages are a better choice from a performance standpoint, because they put less
+of a burden on the device battery. However, if you use collapsible messages, remember that
+<strong>GCM only allows a maximum of 4 different collapse keys to be used by the GCM server
+per device at any given time</strong>. You must not exceed this number, or it could cause
+unpredictable consequences.</p>
<h2 dir="ltr" id="ttl">Setting an Expiration Date for a Message</h2>
-<p>The Time to Live (TTL) feature lets the sender specify the maximum lifespan of a message using the <code>time_to_live</code> parameter in the send request. The value of this parameter must be a duration from 0 to 2,419,200 seconds, and it corresponds to the maximum period of time for which GCM will store and try to deliver the message. Requests that don't contain this field default to the maximum period of 4 weeks.</p>
+<p>The Time to Live (TTL) feature lets the sender specify the maximum lifespan
+of a message using the <code>time_to_live</code> parameter in the send request.
+The value of this parameter must be a duration from 0 to 2,419,200 seconds, and
+it corresponds to the maximum period of time for which GCM will store and try to
+deliver the message. Requests that don't contain this field default to the maximum
+period of 4 weeks.</p>
<p>Here are some possible uses for this feature:</p>
<ul>
<li>Video chat incoming calls</li>
@@ -237,9 +345,29 @@ registerReceiver(mRetryReceiver, filter);
<li>Calendar events</li>
</ul>
<h3 id="bg">Background </h3>
-<p>GCM will usually deliver messages immediately after they are sent. However, this might not always be possible. For example, the device could be turned off, offline, or otherwise unavailable. In other cases, the sender itself might request that messages not be delivered until the device becomes active by using the <code>delay_while_idle</code> flag. Finally, GCM might intentionally delay messages to prevent an application from consuming excessive resources and negatively impacting battery life.</p>
-<p>When this happens, GCM will store the message and deliver it as soon as it's feasible. While this is fine in most cases, there are some applications for which a late message might as well never be delivered. For example, if the message is an incoming call or video chat notification, it will only be meaningful for a small period of time before the call is terminated. Or if the message is an invitation to an event, it will be useless if received after the event has ended.</p>
-<p>Another advantage of specifying the expiration date for a message is that GCM will never throttle messages with a <code>time_to_live</code> value of 0 seconds. In other words, GCM will guarantee best effort for messages that must be delivered &quot;now or never.&quot; Keep in mind that a <code>time_to_live</code> value of 0 means messages that can't be delivered immediately will be discarded. However, because such messages are never stored, this provides the best latency for sending notifications.</p>
+<p>GCM will usually deliver messages immediately after they are sent. However,
+this might not always be possible. For example, the device could be turned off,
+offline, or otherwise unavailable. In other cases, the sender itself might request
+that messages not be delivered until the device becomes active by using the
+<code>delay_while_idle</code> flag. Finally, GCM might intentionally delay messages
+to prevent an application from consuming excessive resources and negatively
+impacting battery life.</p>
+
+<p>When this happens, GCM will store the message and deliver it as soon as it's
+feasible. While this is fine in most cases, there are some applications for which
+a late message might as well never be delivered. For example, if the message is
+an incoming call or video chat notification, it will only be meaningful for a
+small period of time before the call is terminated. Or if the message is an
+invitation to an event, it will be useless if received after the event has ended.</p>
+
+<p>Another advantage of specifying the expiration date for a message is that GCM
+will never throttle messages with a <code>time_to_live</code> value of 0 seconds.
+In other words, GCM will guarantee best effort for messages that must be delivered
+&quot;now or never.&quot; Keep in mind that a <code>time_to_live</code> value of
+0 means messages that can't be delivered immediately will be discarded. However,
+because such messages are never stored, this provides the best latency for
+sending notifications.</p>
+
<p>Here is an example of a JSON-formatted request that includes TTL:</p>
<pre class="prettyprint pretty-json">
{
@@ -256,9 +384,23 @@ registerReceiver(mRetryReceiver, filter);
<h2 id="multi-senders">Receiving Messages from Multiple Senders</h2>
-<p>GCM allows multiple parties to send messages to the same application. For example, suppose your application is an articles aggregator with multiple contributors, and you want each of them to be able to send a message when they publish a new article. This message might contain a URL so that the application can download the article. Instead of having to centralize all sending activity in one location, GCM gives you the ability to let each of these contributors send its own messages.</p>
-<p>To make this possible, all you need to do is have each sender generate its own project number. Then include those IDs in the sender field, separated by commas, when requesting a registration. Finally, share the registration ID with your partners, and they'll be able to send messages to your application using their own authentication keys.</p>
-<p>This code snippet illustrates this feature. Senders are passed as an intent extra in a comma-separated list:</p>
+
+<p>GCM allows multiple parties to send messages to the same application. For
+example, suppose your application is an articles aggregator with multiple
+contributors, and you want each of them to be able to send a message when they
+publish a new article. This message might contain a URL so that the application
+can download the article. Instead of having to centralize all sending activity in
+one location, GCM gives you the ability to let each of these contributors send
+its own messages.</p>
+
+<p>To make this possible, all you need to do is have each sender generate its own
+project number. Then include those IDs in the sender field, separated by commas,
+when requesting a registration. Finally, share the registration ID with your
+partners, and they'll be able to send messages to your application using their
+own authentication keys.</p>
+<p>This code snippet illustrates this feature. Senders are passed as an intent
+extra in a comma-separated list:</p>
+
<pre class="prettyprint pretty-java">Intent intent = new Intent(GCMConstants.INTENT_TO_GCM_REGISTRATION);
intent.setPackage(GSF_PACKAGE);
intent.putExtra(GCMConstants.EXTRA_APPLICATION_PENDING_INTENT,
@@ -269,4 +411,3 @@ ontext.startService(intent);
</pre>
<p>Note that there is limit of 100 multiple senders.</p>
-
diff --git a/docs/html/google/gcm/ccs.jd b/docs/html/google/gcm/ccs.jd
index 9c5961c55ab2..244278eba72d 100644
--- a/docs/html/google/gcm/ccs.jd
+++ b/docs/html/google/gcm/ccs.jd
@@ -1,93 +1,96 @@
-page.title=GCM Cloud Connection Server
+page.title=GCM Cloud Connection Server (XMPP)
@jd:body
<div id="qv-wrapper">
<div id="qv">
-<h2>Quickview</h2>
-
-<ul>
-<li>Get an introduction to key CCS terms and concepts.</li>
-<li>Learn how to send and receive both upstream and downstream messages in CCS.</li>
-</ul>
-
<h2>In this document</h2>
<ol class="toc">
- <li><a href="#gcm">CCS vs. GCM HTTP</a> </li>
<li><a href="#usage">How to Use CCS</a>
- <ol>
- <li><a href="#send_msg">Sending Messages</a></li>
- <li><a href="#format">Message Format</a></li>
- <li><a href="#msg_examples">Message Examples</a></li>
+ <ol class="toc">
+ <li><a href="#auth">Authentication</a></li>
+ </ol>
+ </li>
+ <li><a href="#format">Message Format</a>
+ <ol class="toc">
+ <li><a href="#request">Request format</a></li>
+ <li><a href="#response">Response format</a></li>
+ </ol>
+ </li>
+ <li><a href="#upstream">Upstream Messages</a> </li>
+ <li><a href="#flow">Flow Control</a> </li>
+ <li><a href="#implement">Implementing an XMPP-based App Server</a>
+ <ol class="toc">
+ <li><a href="#smack">Java sample using the Smack library</a></li>
+ <li><a href="#python">Python sample</a></li>
</ol>
</li>
- <li><a href="#flow">Flow Control</a> </li>
</ol>
<h2>See Also</h2>
<ol class="toc">
-<li><a href="{@docRoot}google/gcm/gs.html">Getting Started</a></li>
-<li><a href="https://services.google.com/fb/forms/gcm/" class="external-link" target="_android">CCS and User Notifications Signup Form</a></li>
+<li><a href="{@docRoot}google/play-services/gcm/http.html">HTTP</a></li>
+<li><a href="{@docRoot}google/play-services/gcm/gs.html">Getting Started</a></li>
+<li><a href="{@docRoot}google/play-services/gcm/server.html">Implementing GCM Server</a></li>
+<li><a href="{@docRoot}google/play-services/gcm/client.html">Implementing GCM Client</a></li>
+<li><a href="https://services.google.com/fb/forms/gcm/" class="external-link"
+target="_android">CCS and User Notifications Signup Form</a></li>
</ol>
</div>
</div>
-<p class="note"><strong>Note:</strong> To try out this feature, sign up using <a href="https://services.google.com/fb/forms/gcm/">this form</a>.</p>
+<p class="note"><strong>Note:</strong> To try out this feature, sign up using
+<a href="https://services.google.com/fb/forms/gcm/">this form</a>.</p>
-<p>The GCM Cloud Connection Server (CCS) allows third party servers to communicate with Android devices by establishing a persistent TCP connection with Google servers using the XMPP protocol. This communication is asynchronous and bidirectional.</p>
-<p>You can continue to use the HTTP request mechanism to send messages to GCM servers, side-by-side with CCS which uses XMPP. Some of the benefits of CCS include:</p>
+<p>The GCM Cloud Connection Server (CCS) is a connection server based on XMPP.
+CCS allows 3rd-party app servers (which you're
+responsible for implementing) to communicate
+with Android devices by establishing a persistent TCP connection with Google
+servers using the XMPP protocol. This communication is asynchronous and bidirectional.</p>
+<p>You can continue to use the HTTP request mechanism to send messages to GCM
+servers, side-by-side with CCS which uses XMPP. Some of the benefits of CCS include:</p>
<ul>
- <li>The asynchronous nature of XMPP allows you to send more messages with fewer resources.</li>
- <li>Communication is bidirectional&mdash;not only can the server send messages to the device, but the device can send messages back to the server.</li>
-<li>You can send messages back using the same connection used for receiving, thereby improving battery life.</li>
+ <li>The asynchronous nature of XMPP allows you to send more messages with fewer
+resources.</li>
+ <li>Communication is bidirectional&mdash;not only can the server send messages
+to the device, but the device can send messages back to the server.</li>
+<li>You can send messages back using the same connection used for receiving,
+thereby improving battery life.</li>
</ul>
-<p>The upstream messaging (device-to-cloud) feature of CCS is part of the Google Play services platform. Upstream messaging is available through the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> APIs. To use upstream messaging and the new streamlined registration process, you must <a href="{@docRoot}google/play-services/setup.html">set up</a> the Google Play services SDK.</p>
+<p>The upstream messaging (device-to-cloud) feature of CCS is part of the Google
+Play services platform. Upstream messaging is available through the
+<a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">
+{@code GoogleCloudMessaging}</a>
+APIs. For examples, see
+<a href="#implement">Implementing an XMPP-based App Server</a>.</p>
-<p class="note"><strong>Note:</strong> For an example of an XMPP server, see <a href="server.html#xmpp">GCM Server</a>.
-
-<h2 id="gcm">CCS vs. GCM HTTP</h2>
-
-<p>CCS messaging differs from GCM HTTP messaging in the following ways:</p>
-<ul>
- <li>Upstream/Downstream messages
- <ul>
- <li>GCM HTTP: Downstream only: cloud-to-device. </li>
- <li>CCS: Upstream and downstream (device-to-cloud, cloud-to-device). </li>
- </ul>
- </li>
- <li>Asynchronous messaging
- <ul>
- <li>GCM HTTP: 3rd-party servers send messages as HTTP POST requests and wait for a response. This mechanism is synchronous and causes the sender to block before sending another message.</li>
- <li>CCS: 3rd-party servers connect to Google infrastructure using a persistent XMPP connection and send/receive messages to/from all their devices at full line speed. CCS sends acknowledgements or failure notifications (in the form of special ACK and NACK JSON-encoded XMPP messages) asynchronously.</li>
- </ul>
- </li>
+<p class="note"><strong>Note:</strong> See
+<a href="server.html#params">Implementing GCM Server</a> for a list of all the message
+parameters and which connection server(s) supports them.</p>
- <li>JSON
- <ul>
- <li>GCM HTTP: JSON messages sent as HTTP POST.</li>
- <li>CCS: JSON messages encapsulated in XMPP messages.</li>
- </ul>
- </li>
-</ul>
-<p>This document describes how to use CCS. For general concepts and information on how to use GCM HTTP, see the <a href="gcm.html">GCM Architectural Overview</a>.</p>
<h2 id="usage">How to Use CCS</h2>
-<p>GCM Cloud Connection Server (CCS) is an XMPP endpoint, running on {@code http://gcm.googleapis.com} port 5235.</p>
+<p>GCM Cloud Connection Server (CCS) is an XMPP endpoint, running on
+{@code http://gcm.googleapis.com} port 5235.</p>
-<p>CCS requires a Transport Layer Security (TLS) connection. That means the XMPP client must initiate a TLS connection.
-For example in smack, you would call {@code setSocketFactory(SSLSocketFactory)}, similar to “old style SSL†XMPP connections and https.</p>
+<p>CCS requires a Transport Layer Security (TLS) connection. That means the XMPP
+client must initiate a TLS connection.
+For example in Java, you would call {@code setSocketFactory(SSLSocketFactory)}.</p>
-<p>CCS requires a SASL PLAIN authentication mechanism using {@code &lt;your_GCM_Sender_Id&gt;&#64;gcm.googleapis.com} (GCM sender ID) and the API key as the password, where the sender ID and API key are the same as described in <a href="gs.html">Getting Started</a>.</p>
+<p>CCS requires a SASL PLAIN authentication mechanism using
+{@code &lt;your_GCM_Sender_Id&gt;&#64;gcm.googleapis.com} (GCM sender ID) and the
+API key as the password, where the sender ID and API key are the same as described
+in <a href="gs.html">Getting Started</a>.</p>
<p> You can use most XMPP libraries to interact with CCS.</p>
-<h3 id="send_msg">Sending messages</h3>
+<h3 id="auth">Authentication</h3>
<p>The following snippets illustrate how to perform authentication in CCS.</p>
<h4>Client</h4>
@@ -108,13 +111,13 @@ For example in smack, you would call {@code setSocketFactory(SSLSocketFactory)},
<h4>Client</h4>
<pre>&lt;auth mechanism=&quot;PLAIN&quot;
xmlns=&quot;urn:ietf:params:xml:ns:xmpp-sasl&quot;&gt;MTI2MjAwMzQ3OTMzQHByb2plY3RzLmdjbS5hb
-mRyb2lkLmNvbQAxMjYyMDAzNDc5FzNAcHJvamVjdHMtZ2EtLmFuZHJvaWQuY29tAEFJe
mFTeUIzcmNaTmtmbnFLZEZiOW1oekNCaVlwT1JEQTJKV1d0dw==&lt;/auth&gt;
</pre>
+
<h4>Server</h4>
<pre>&lt;success xmlns=&quot;urn:ietf:params:xml:ns:xmpp-sasl&quot;/&gt;</pre>
-<h3 id="format">Message Format</h3>
+<h2 id="format">Message Format</h2>
<p>CCS uses normal XMPP <code>&lt;message&gt;</code> stanzas. The body of the message must be:
</p>
<pre>
@@ -123,25 +126,42 @@ mFTeUIzcmNaTmtmbnFLZEZiOW1oekNCaVlwT1JEQTJKV1d0dw==&lt;/auth&gt;
&lt;/gcm&gt;
</pre>
-<p>The JSON payload for server-to-device is similar to what the GCM http endpoint uses, with these exceptions:</p>
+<p>The JSON payload for server-to-device is similar to what the GCM http endpoint
+uses, with these exceptions:</p>
<ul>
<li>There is no support for multiple recipients.</li>
<li>{@code to} is used instead of {@code registration_ids}.</li>
- <li>CCS adds the field {@code message_id}, which is required. This ID uniquely identifies the message in an XMPP connection. The ACK or NACK from CCS uses the {@code message_id} to identify a message sent from 3rd-party servers to CCS. Therefore, it's important that this {@code message_id} not only be unique, but always present.</li>
+ <li>CCS adds the field {@code message_id}, which is required. This ID uniquely
+identifies the message in an XMPP connection. The ACK or NACK from CCS uses the
+{@code message_id} to identify a message sent from 3rd-party app servers to CCS.
+Therefore, it's important that this {@code message_id} not only be unique, but
+always present.</li>
- <li>For ACK/NACK messages that are special control messages, you also need to include a {@code message_type} field in the JSON message. For example:
+<li>For ACK/NACK messages that are special control messages, you also need to
+include a {@code message_type} field in the JSON message. The value can be either
+'ack' or 'nack'. For example:
-<pre>message_type = ('ack' OR 'nack');</pre>
+<pre>message_type = ('ack');</pre>
</li>
</ul>
-<p>For each message a device sends to the server, you need to send an ACK message. You never need to send a NACK message. If you don't send an ACK for a message, CCS will just resend it.
+<p>For each device message your app server receives from CCS, it needs to send
+an ACK message.
+It never needs to send a NACK message. If you don't send an ACK for a message,
+CCS will just resend it.
</p>
-<p>CCS also sends an ACK or NACK for each server-to-device message. If you do not receive either, it means that the TCP connection was closed in the middle of the operation and your server needs to resend the messages.
+<p>CCS also sends an ACK or NACK for each server-to-device message. If you do not
+receive either, it means that the TCP connection was closed in the middle of the
+operation and your server needs to resend the messages. See
+<a href="#flow">Flow Control</a> for details.
</p>
-<h3 id="msg_examples">Message Examples</h3>
+<p class="note"><strong>Note:</strong> See
+<a href="server.html#params">Implementing GCM Server</a> for a list of all the message
+parameters and which connection server(s) supports them.</p>
-<p>Here is an XMPP stanza containing the JSON message from a 3rd-party server to CCS:
+<h3 id="request">Request format</h3>
+
+<p>Here is an XMPP stanza containing the JSON message from a 3rd-party app server to CCS:
</p>
<pre>&lt;message id=&quot;&quot;&gt;
@@ -160,7 +180,15 @@ mFTeUIzcmNaTmtmbnFLZEZiOW1oekNCaVlwT1JEQTJKV1d0dw==&lt;/auth&gt;
&lt;/message&gt;
</pre>
-<p>Here is an XMPP stanza containing the ACK/NACK message from CCS to 3rd-party server:
+<h3 id="response">Response format</h3>
+
+<p>A CCS response can have 3 possible forms. The first one is a regular 'ack'
+message. But when the response contains an error, there are 2
+different forms the message can take, described below.</p>
+
+<h4 id="ack">ACK message</h4>
+
+<p>Here is an XMPP stanza containing the ACK/NACK message from CCS to 3rd-party app server:
</p>
<pre>&lt;message id=&quot;&quot;&gt;
&lt;gcm xmlns=&quot;google:mobile:data&quot;&gt;
@@ -171,24 +199,138 @@ mFTeUIzcmNaTmtmbnFLZEZiOW1oekNCaVlwT1JEQTJKV1d0dw==&lt;/auth&gt;
}
&lt;/gcm&gt;
&lt;/message&gt;
+</pre>
-&lt;message id=&quot;&quot;&gt;
- &lt;gcm xmlns=&quot;google:mobile:data&quot;&gt;
+<h4 id="nack">NACK message</h4>
+
+<p>A NACK error is a regular XMPP message in which the {@code message_type} status
+message is &quot;nack&quot;. A NACK message contains:</p>
+<ul>
+<li>Nack error code.</li>
+<li>Nack error description.</li>
+</ul>
+
+<p>Below are some examples.</p>
+
+<p>Bad registration:</p>
+<pre>&lt;message&gt;
+ &lt;data:gcm xmlns:data=&quot;google:mobile:data&quot;&gt;
{
- &quot;from&quot;:&quot;REGID&quot;,
- &quot;message_id&quot;:&quot;m-1366082849205&quot;
- &quot;error&quot;: ERROR_CODE,
- &quot;message_type&quot;:&quot;nack&quot;
+ &quot;error&quot;:&quot;BAD_REGISTRATION&quot;, // error code
+ &quot;message_id&quot;:&quot;msgId1&quot;,
+ &quot;from&quot;:&quot;PA91bHFOtaQGSwupt5l1og&quot;,
+ &quot;message_type&quot;:&quot;nack&quot;
+ }
+ &lt;/data:gcm&gt;
+&lt;/message&gt;</pre>
+
+<p>Invalid "time to live":</p>
+
+<pre>&lt;message&gt;
+ &lt;data:gcm xmlns:data=&quot;google:mobile:data&quot;&gt;
+ {
+ &quot;error&quot;:&quot;InvalidJson : INVALID_TTL : Invalid value (-1) for \&quot;time_to_live\&quot;: must be between 0 and \&quot;2419200\&quot;\n&quot;,
+ &quot;message_id&quot;:&quot;msgId1&quot;,
+ &quot;from&quot;:&quot;APA91bHFOtaQGSwupt5l1og&quot;,
+ &quot;message_type&quot;:&quot;nack&quot;
+ }
+ &lt;/data:gcm&gt;
+&lt;/message&gt;</pre>
+
+<p>JSON type error:</p>
+
+<pre>&lt;message&gt;
+ &lt;data:gcm xmlns:data=&quot;google:mobile:data&quot;&gt;
+ {
+ &quot;error&quot;:&quot;InvalidJson : JSON_TYPE_ERROR : Field \&quot;delay_while_idle\&quot; must be a JSON java.lang.Boolean: not-boolean-user-supplied-value\n&quot;,
+ &quot;message_id&quot;:&quot;msgId1&quot;,
+ &quot;from&quot;:&quot;APA91bHFOtaQGSwupt5l1og&quot;,
+ &quot;message_type&quot;:&quot;nack&quot;
}
+ &lt;/data:gcm&gt;
+&lt;/message&gt;</pre>
+
+
+<p>The following table lists some of the more common NACK error codes.</p>
+
+<p class="table-caption" id="table1">
+ <strong>Table 1.</strong> NACK error codes.</p>
+
+<table border="1">
+<tr>
+<th>Error Code</th>
+<th>Description</th>
+</tr>
+<tr>
+<td>{@code BAD_REGISTRATION}</td>
+<td>The device has a registration ID, but it's invalid.</td>
+</tr>
+<tr>
+<td>{@code DEVICE_UNREGISTERED}</td>
+<td>The device is not registered.</td>
+</tr>
+<tr>
+<td>{@code INTERNAL_SERVER_ERROR}</td>
+<td>The server encountered an error while trying to process the request.</td>
+</tr>
+<tr>
+<td>{@code SERVICE_UNAVAILABLE}</td>
+<td>The CCS connection server is temporarily unavailable, try again later
+(using exponential backoff, etc.).</td>
+</tr>
+<tr>
+<td>{@code BAD_ACK}</td>
+<td>The ACK message is improperly formed.</td>
+</tr>
+<tr>
+<td>{@code AUTHENTICATION_FAILED}</td>
+<td>This is a 401 error indicating that there was an error authenticating the sender account.</td>
+</tr>
+<tr>
+<td>{@code INVALID_TTL}</td>
+<td>There was an error in the supplied "time to live" value.</td>
+</tr>
+<tr>
+<td>{@code JSON_TYPE_ERROR}</td>
+<td>There was an error in the supplied JSON data type.</td>
+</tr>
+</table>
+
+<h4 id="stanza">Stanza error</h4>
+
+<p>You can also get a stanza error in certain cases.
+A stanza error contains:</p>
+<ul>
+<li>Stanza error code.</li>
+<li>Stanza error description (free text).</li>
+</ul>
+<p>For example:</p>
+
+<pre>&lt;message id=&quot;3&quot; type=&quot;error&quot; to=&quot;123456789@gcm.googleapis.com/ABC&quot;&gt;
+ &lt;gcm xmlns=&quot;google:mobile:data&quot;&gt;
+ {&quot;random&quot;: &quot;text&quot;}
&lt;/gcm&gt;
+ &lt;error code=&quot;400&quot; type=&quot;modify&quot;&gt;
+ &lt;bad-request xmlns=&quot;urn:ietf:params:xml:ns:xmpp-stanzas&quot;/&gt;
+ &lt;text xmlns=&quot;urn:ietf:params:xml:ns:xmpp-stanzas&quot;&gt;
+ InvalidJson: JSON_PARSING_ERROR : Missing Required Field: message_id\n
+ &lt;/text&gt;
+ &lt;/error&gt;
&lt;/message&gt;
</pre>
-<h4>Upstream Messages</h4>
-<p>Using CCS and the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">GoogleCloudMessaging</a> API, you can send messages from a user's device to the cloud.</p>
+<h2 id="upstream">Upstream Messages</h2>
-<p>Here is how you send an upstream message using the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">GoogleCloudMessaging</a> API. For a complete example, see <a href="gs.html#gs_example">Getting Started</a>:</p>
+<p>Using CCS and the
+<a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">
+{@code GoogleCloudMessaging}</a>
+API, you can send messages from a user's device to the cloud.</p>
+
+<p>Here is how you send an upstream message using the
+<a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">
+{@code GoogleCloudMessaging}</a>
+API. For a complete example, see <a href="client.html">Implementing GCM Client</a>:</p>
<pre>GoogleCloudMessaging gcm = GoogleCloudMessaging.get(context);
String GCM_SENDER_ID = "Your-Sender-ID";
@@ -198,12 +340,15 @@ Bundle data = new Bundle();
// Bundle data consists of a key-value pair
data.putString("hello", "world");
// "time to live" parameter
+// This is optional. It specifies a value in seconds up to 4 weeks.
int ttl = [0 seconds, 4 weeks]
gcm.send(GCM_SENDER_ID + "&#64;gcm.googleapis.com", id, ttl, data);
</pre>
-<p>This call generates the necessary XMPP stanza for sending the upstream message. The message goes from the app on the device to CCS to the 3rd-party server. The stanza has the following format:</p>
+<p>This call generates the necessary XMPP stanza for sending the upstream message.
+The message goes from the app on the device to CCS to the 3rd-party app server.
+The stanza has the following format:</p>
<pre>&lt;message id=&quot;&quot;&gt;
&lt;gcm xmlns=&quot;google:mobile:data&quot;&gt;
@@ -219,7 +364,8 @@ gcm.send(GCM_SENDER_ID + "&#64;gcm.googleapis.com", id, ttl, data);
&lt;/gcm&gt;
&lt;/message&gt;</pre>
-<p>Here is the format of the ACK expected by CCS from 3rd-party servers in response to the above message:</p>
+<p>Here is the format of the ACK expected by CCS from 3rd-party app servers in
+response to the above message:</p>
<pre>&lt;message id=&quot;&quot;&gt;
&lt;gcm xmlns=&quot;google:mobile:data&quot;&gt;
@@ -231,13 +377,478 @@ gcm.send(GCM_SENDER_ID + "&#64;gcm.googleapis.com", id, ttl, data);
&lt;/gcm&gt;
&lt;/message&gt;</pre>
-
<h2 id="flow">Flow Control</h2>
-<p>Every message sent to CCS receives either an ACK or a NACK response. Messages that haven't received one of these responses are considered pending. If the pending message count reaches 1000, the 3rd-party server should stop sending new messages and wait for CCS to acknowledge some of the existing pending messages.</p>
+<p>Every message sent to CCS receives either an ACK or a NACK response. Messages
+that haven't received one of these responses are considered pending. If the pending
+message count reaches 1000, the 3rd-party app server should stop sending new messages
+and wait for CCS to acknowledge some of the existing pending messages as illustrated in
+figure 1:</p>
+
+<img src="{@docRoot}images/gcm/CCS-ack.png">
-<p>Conversely, to avoid overloading the 3rd-party server, CCS will stop sending if there are too many unacknowledged messages. Therefore, the 3rd-party server should "ACK" received messages as soon as possible to maintain a constant flow of incoming messages. The aforementioned pending message limit doesn't apply to these ACKs. Even if the pending message count reaches 1000, the 3rd-party server should continue sending ACKs to avoid blocking delivery of new messages.</p>
+<p class="img-caption">
+ <strong>Figure 1.</strong> Message/ack flow.
+</p>
-<p>ACKs are only valid within the context of one connection. If the connection is closed before a message can be ACKed, the 3rd-party server should wait for CCS to resend the message before ACKing it again.
+<p>Conversely, to avoid overloading the 3rd-party app server, CCS will stop sending
+if there are too many unacknowledged messages. Therefore, the 3rd-party app server
+should "ACK" upstream messages, received from the client application via CCS, as soon as possible
+to maintain a constant flow of incoming messages. The aforementioned pending message limit doesn't
+apply to these ACKs. Even if the pending message count reaches 1000, the 3rd-party app server
+should continue sending ACKs for messages received from CCS to avoid blocking delivery of new
+upstream messages.</p>
+
+<p>ACKs are only valid within the context of one connection. If the connection is
+closed before a message can be ACKed, the 3rd-party app server should wait for CCS
+to resend the upstream message before ACKing it again. Similarly, all pending messages for which an
+ACK/NACK was not received from CCS before the connection was closed should be sent again.
</p>
+<h2 id="implement">Implementing an XMPP-based App Server</h2>
+
+<p>This section gives examples of implementing an app server that works with CCS.
+Note that a full GCM implementation requires a client-side implementation, in
+addition to the server. For more information, see <a href="client.html">
+Implementing GCM Client</a>.</a>
+
+<h3 id="smack">Java sample using the Smack library</h3>
+
+<p>Here is a sample app server written in Java, using the
+<a href="http://www.igniterealtime.org/projects/smack/">Smack</a> library.</p>
+
+<pre>import org.jivesoftware.smack.ConnectionConfiguration;
+import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode;
+import org.jivesoftware.smack.ConnectionListener;
+import org.jivesoftware.smack.PacketInterceptor;
+import org.jivesoftware.smack.PacketListener;
+import org.jivesoftware.smack.XMPPConnection;
+import org.jivesoftware.smack.XMPPException;
+import org.jivesoftware.smack.filter.PacketTypeFilter;
+import org.jivesoftware.smack.packet.DefaultPacketExtension;
+import org.jivesoftware.smack.packet.Message;
+import org.jivesoftware.smack.packet.Packet;
+import org.jivesoftware.smack.packet.PacketExtension;
+import org.jivesoftware.smack.provider.PacketExtensionProvider;
+import org.jivesoftware.smack.provider.ProviderManager;
+import org.jivesoftware.smack.util.StringUtils;
+import org.json.simple.JSONValue;
+import org.json.simple.parser.ParseException;
+import org.xmlpull.v1.XmlPullParser;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.net.ssl.SSLSocketFactory;
+/**
+ * Sample Smack implementation of a client for GCM Cloud Connection Server.
+ *
+ * &lt;p&gt;For illustration purposes only.
+ */
+public class SmackCcsClient {
+
+ Logger logger = Logger.getLogger(&quot;SmackCcsClient&quot;);
+
+ public static final String GCM_SERVER = &quot;gcm.googleapis.com&quot;;
+ public static final int GCM_PORT = 5235;
+
+ public static final String GCM_ELEMENT_NAME = &quot;gcm&quot;;
+ public static final String GCM_NAMESPACE = &quot;google:mobile:data&quot;;
+
+ static Random random = new Random();
+ XMPPConnection connection;
+ ConnectionConfiguration config;
+
+ /**
+ * XMPP Packet Extension for GCM Cloud Connection Server.
+ */
+ class GcmPacketExtension extends DefaultPacketExtension {
+ String json;
+
+ public GcmPacketExtension(String json) {
+ super(GCM_ELEMENT_NAME, GCM_NAMESPACE);
+ this.json = json;
+ }
+
+ public String getJson() {
+ return json;
+ }
+
+ &#64;Override
+ public String toXML() {
+ return String.format(&quot;&lt;%s xmlns=\&quot;%s\&quot;&gt;%s&lt;/%s&gt;&quot;, GCM_ELEMENT_NAME,
+ GCM_NAMESPACE, json, GCM_ELEMENT_NAME);
+ }
+
+ &#64;SuppressWarnings(&quot;unused&quot;)
+ public Packet toPacket() {
+ return new Message() {
+ // Must override toXML() because it includes a &lt;body&gt;
+ &#64;Override
+ public String toXML() {
+
+ StringBuilder buf = new StringBuilder();
+ buf.append(&quot;&lt;message&quot;);
+ if (getXmlns() != null) {
+ buf.append(&quot; xmlns=\&quot;&quot;).append(getXmlns()).append(&quot;\&quot;&quot;);
+ }
+ if (getLanguage() != null) {
+ buf.append(&quot; xml:lang=\&quot;&quot;).append(getLanguage()).append(&quot;\&quot;&quot;);
+ }
+ if (getPacketID() != null) {
+ buf.append(&quot; id=\&quot;&quot;).append(getPacketID()).append(&quot;\&quot;&quot;);
+ }
+ if (getTo() != null) {
+ buf.append(&quot; to=\&quot;&quot;).append(StringUtils.escapeForXML(getTo())).append(&quot;\&quot;&quot;);
+ }
+ if (getFrom() != null) {
+ buf.append(&quot; from=\&quot;&quot;).append(StringUtils.escapeForXML(getFrom())).append(&quot;\&quot;&quot;);
+ }
+ buf.append(&quot;&gt;&quot;);
+ buf.append(GcmPacketExtension.this.toXML());
+ buf.append(&quot;&lt;/message&gt;&quot;);
+ return buf.toString();
+ }
+ };
+ }
+ }
+
+ public SmackCcsClient() {
+ // Add GcmPacketExtension
+ ProviderManager.getInstance().addExtensionProvider(GCM_ELEMENT_NAME,
+ GCM_NAMESPACE, new PacketExtensionProvider() {
+
+ &#64;Override
+ public PacketExtension parseExtension(XmlPullParser parser)
+ throws Exception {
+ String json = parser.nextText();
+ GcmPacketExtension packet = new GcmPacketExtension(json);
+ return packet;
+ }
+ });
+ }
+
+ /**
+ * Returns a random message id to uniquely identify a message.
+ *
+ * &lt;p&gt;Note:
+ * This is generated by a pseudo random number generator for illustration purpose,
+ * and is not guaranteed to be unique.
+ *
+ */
+ public String getRandomMessageId() {
+ return &quot;m-&quot; + Long.toString(random.nextLong());
+ }
+
+ /**
+ * Sends a downstream GCM message.
+ */
+ public void send(String jsonRequest) {
+ Packet request = new GcmPacketExtension(jsonRequest).toPacket();
+ connection.sendPacket(request);
+ }
+
+ /**
+ * Handles an upstream data message from a device application.
+ *
+ * &lt;p&gt;This sample echo server sends an echo message back to the device.
+ * Subclasses should override this method to process an upstream message.
+ */
+ public void handleIncomingDataMessage(Map&lt;String, Object&gt; jsonObject) {
+ String from = jsonObject.get(&quot;from&quot;).toString();
+
+ // PackageName of the application that sent this message.
+ String category = jsonObject.get(&quot;category&quot;).toString();
+
+ // Use the packageName as the collapseKey in the echo packet
+ String collapseKey = &quot;echo:CollapseKey&quot;;
+ &#64;SuppressWarnings(&quot;unchecked&quot;)
+ Map&lt;String, String&gt; payload = (Map&lt;String, String&gt;) jsonObject.get(&quot;data&quot;);
+ payload.put(&quot;ECHO&quot;, &quot;Application: &quot; + category);
+
+ // Send an ECHO response back
+ String echo = createJsonMessage(from, getRandomMessageId(), payload, collapseKey, null, false);
+ send(echo);
+ }
+
+ /**
+ * Handles an ACK.
+ *
+ * &lt;p&gt;By default, it only logs a {@code INFO} message, but subclasses could override it to
+ * properly handle ACKS.
+ */
+ public void handleAckReceipt(Map&lt;String, Object&gt; jsonObject) {
+ String messageId = jsonObject.get(&quot;message_id&quot;).toString();
+ String from = jsonObject.get(&quot;from&quot;).toString();
+ logger.log(Level.INFO, &quot;handleAckReceipt() from: &quot; + from + &quot;, messageId: &quot; + messageId);
+ }
+
+ /**
+ * Handles a NACK.
+ *
+ * &lt;p&gt;By default, it only logs a {@code INFO} message, but subclasses could override it to
+ * properly handle NACKS.
+ */
+ public void handleNackReceipt(Map&lt;String, Object&gt; jsonObject) {
+ String messageId = jsonObject.get(&quot;message_id&quot;).toString();
+ String from = jsonObject.get(&quot;from&quot;).toString();
+ logger.log(Level.INFO, &quot;handleNackReceipt() from: &quot; + from + &quot;, messageId: &quot; + messageId);
+ }
+
+ /**
+ * Creates a JSON encoded GCM message.
+ *
+ * &#64;param to RegistrationId of the target device (Required).
+ * &#64;param messageId Unique messageId for which CCS will send an &quot;ack/nack&quot; (Required).
+ * &#64;param payload Message content intended for the application. (Optional).
+ * &#64;param collapseKey GCM collapse_key parameter (Optional).
+ * &#64;param timeToLive GCM time_to_live parameter (Optional).
+ * &#64;param delayWhileIdle GCM delay_while_idle parameter (Optional).
+ * &#64;return JSON encoded GCM message.
+ */
+ public static String createJsonMessage(String to, String messageId, Map&lt;String, String&gt; payload,
+ String collapseKey, Long timeToLive, Boolean delayWhileIdle) {
+ Map&lt;String, Object&gt; message = new HashMap&lt;String, Object&gt;();
+ message.put(&quot;to&quot;, to);
+ if (collapseKey != null) {
+ message.put(&quot;collapse_key&quot;, collapseKey);
+ }
+ if (timeToLive != null) {
+ message.put(&quot;time_to_live&quot;, timeToLive);
+ }
+ if (delayWhileIdle != null &amp;&amp; delayWhileIdle) {
+ message.put(&quot;delay_while_idle&quot;, true);
+ }
+ message.put(&quot;message_id&quot;, messageId);
+ message.put(&quot;data&quot;, payload);
+ return JSONValue.toJSONString(message);
+ }
+
+ /**
+ * Creates a JSON encoded ACK message for an upstream message received from an application.
+ *
+ * &#64;param to RegistrationId of the device who sent the upstream message.
+ * &#64;param messageId messageId of the upstream message to be acknowledged to CCS.
+ * &#64;return JSON encoded ack.
+ */
+ public static String createJsonAck(String to, String messageId) {
+ Map&lt;String, Object&gt; message = new HashMap&lt;String, Object&gt;();
+ message.put(&quot;message_type&quot;, &quot;ack&quot;);
+ message.put(&quot;to&quot;, to);
+ message.put(&quot;message_id&quot;, messageId);
+ return JSONValue.toJSONString(message);
+ }
+
+ /**
+ * Connects to GCM Cloud Connection Server using the supplied credentials.
+ *
+ * &#64;param username GCM_SENDER_ID&#64;gcm.googleapis.com
+ * &#64;param password API Key
+ * &#64;throws XMPPException
+ */
+ public void connect(String username, String password) throws XMPPException {
+ config = new ConnectionConfiguration(GCM_SERVER, GCM_PORT);
+ config.setSecurityMode(SecurityMode.enabled);
+ config.setReconnectionAllowed(true);
+ config.setRosterLoadedAtLogin(false);
+ config.setSendPresence(false);
+ config.setSocketFactory(SSLSocketFactory.getDefault());
+
+ // NOTE: Set to true to launch a window with information about packets sent and received
+ config.setDebuggerEnabled(true);
+
+ // -Dsmack.debugEnabled=true
+ XMPPConnection.DEBUG_ENABLED = true;
+
+ connection = new XMPPConnection(config);
+ connection.connect();
+
+ connection.addConnectionListener(new ConnectionListener() {
+
+ &#64;Override
+ public void reconnectionSuccessful() {
+ logger.info(&quot;Reconnecting..&quot;);
+ }
+
+ &#64;Override
+ public void reconnectionFailed(Exception e) {
+ logger.log(Level.INFO, &quot;Reconnection failed.. &quot;, e);
+ }
+
+ &#64;Override
+ public void reconnectingIn(int seconds) {
+ logger.log(Level.INFO, &quot;Reconnecting in %d secs&quot;, seconds);
+ }
+
+ &#64;Override
+ public void connectionClosedOnError(Exception e) {
+ logger.log(Level.INFO, &quot;Connection closed on error.&quot;);
+ }
+
+ &#64;Override
+ public void connectionClosed() {
+ logger.info(&quot;Connection closed.&quot;);
+ }
+ });
+
+ // Handle incoming packets
+ connection.addPacketListener(new PacketListener() {
+
+ &#64;Override
+ public void processPacket(Packet packet) {
+ logger.log(Level.INFO, &quot;Received: &quot; + packet.toXML());
+ Message incomingMessage = (Message) packet;
+ GcmPacketExtension gcmPacket =
+ (GcmPacketExtension) incomingMessage.getExtension(GCM_NAMESPACE);
+ String json = gcmPacket.getJson();
+ try {
+ &#64;SuppressWarnings(&quot;unchecked&quot;)
+ Map&lt;String, Object&gt; jsonObject =
+ (Map&lt;String, Object&gt;) JSONValue.parseWithException(json);
+
+ // present for &quot;ack&quot;/&quot;nack&quot;, null otherwise
+ Object messageType = jsonObject.get(&quot;message_type&quot;);
+
+ if (messageType == null) {
+ // Normal upstream data message
+ handleIncomingDataMessage(jsonObject);
+
+ // Send ACK to CCS
+ String messageId = jsonObject.get(&quot;message_id&quot;).toString();
+ String from = jsonObject.get(&quot;from&quot;).toString();
+ String ack = createJsonAck(from, messageId);
+ send(ack);
+ } else if (&quot;ack&quot;.equals(messageType.toString())) {
+ // Process Ack
+ handleAckReceipt(jsonObject);
+ } else if (&quot;nack&quot;.equals(messageType.toString())) {
+ // Process Nack
+ handleNackReceipt(jsonObject);
+ } else {
+ logger.log(Level.WARNING, &quot;Unrecognized message type (%s)&quot;,
+ messageType.toString());
+ }
+ } catch (ParseException e) {
+ logger.log(Level.SEVERE, &quot;Error parsing JSON &quot; + json, e);
+ } catch (Exception e) {
+ logger.log(Level.SEVERE, &quot;Couldn't send echo.&quot;, e);
+ }
+ }
+ }, new PacketTypeFilter(Message.class));
+
+
+ // Log all outgoing packets
+ connection.addPacketInterceptor(new PacketInterceptor() {
+ &#64;Override
+ public void interceptPacket(Packet packet) {
+ logger.log(Level.INFO, &quot;Sent: {0}&quot;, packet.toXML());
+ }
+ }, new PacketTypeFilter(Message.class));
+
+ connection.login(username, password);
+ }
+
+ public static void main(String [] args) {
+ final String userName = &quot;Your GCM Sender Id&quot; + &quot;&#64;gcm.googleapis.com&quot;;
+ final String password = &quot;API Key&quot;;
+
+ SmackCcsClient ccsClient = new SmackCcsClient();
+
+ try {
+ ccsClient.connect(userName, password);
+ } catch (XMPPException e) {
+ e.printStackTrace();
+ }
+
+ // Send a sample hello downstream message to a device.
+ String toRegId = &quot;RegistrationIdOfTheTargetDevice&quot;;
+ String messageId = ccsClient.getRandomMessageId();
+ Map&lt;String, String&gt; payload = new HashMap&lt;String, String&gt;();
+ payload.put(&quot;Hello&quot;, &quot;World&quot;);
+ payload.put(&quot;CCS&quot;, &quot;Dummy Message&quot;);
+ payload.put(&quot;EmbeddedMessageId&quot;, messageId);
+ String collapseKey = &quot;sample&quot;;
+ Long timeToLive = 10000L;
+ Boolean delayWhileIdle = true;
+ ccsClient.send(createJsonMessage(toRegId, messageId, payload, collapseKey,
+ timeToLive, delayWhileIdle));
+ }
+}</pre>
+<h3 id="python">Python sample</h3>
+
+<p>Here is an example of a CCS app server written in Python. This sample echo
+server sends an initial message, and for every upstream message received, it sends
+a dummy response back to the application that sent the upstream message. This
+example illustrates how to connect, send, and receive GCM messages using XMPP. It
+shouldn't be used as-is on a production deployment.</p>
+
+<pre>
+#!/usr/bin/python
+import sys, json, xmpp, random, string
+
+SERVER = 'gcm.googleapis.com'
+PORT = 5235
+USERNAME = "Your GCM Sender Id"
+PASSWORD = "API Key"
+REGISTRATION_ID = "Registration Id of the target device"
+
+unacked_messages_quota = 1000
+send_queue = []
+
+# Return a random alphanumerical id
+def random_id():
+ rid = ''
+ for x in range(8): rid += random.choice(string.ascii_letters + string.digits)
+ return rid
+
+def message_callback(session, message):
+ global unacked_messages_quota
+ gcm = message.getTags('gcm')
+ if gcm:
+ gcm_json = gcm[0].getData()
+ msg = json.loads(gcm_json)
+ if not msg.has_key('message_type'):
+ # Acknowledge the incoming message immediately.
+ send({'to': msg['from'],
+ 'message_type': 'ack',
+ 'message_id': msg['message_id']})
+ # Queue a response back to the server.
+ if msg.has_key('from'):
+ # Send a dummy echo response back to the app that sent the upstream message.
+ send_queue.append({'to': msg['from'],
+ 'message_id': random_id(),
+ 'data': {'pong': 1}})
+ elif msg['message_type'] == 'ack' or msg['message_type'] == 'nack':
+ unacked_messages_quota += 1
+
+def send(json_dict):
+ template = (&quot;&lt;message&gt;&lt;gcm xmlns='google:mobile:data'&gt;{1}&lt;/gcm&gt;&lt;/message&gt;&quot;)
+ client.send(xmpp.protocol.Message(
+ node=template.format(client.Bind.bound[0], json.dumps(json_dict))))
+
+def flush_queued_messages():
+ global unacked_messages_quota
+ while len(send_queue) and unacked_messages_quota &gt; 0:
+ send(send_queue.pop(0))
+ unacked_messages_quota -= 1
+
+client = xmpp.Client('gcm.googleapis.com', debug=['socket'])
+client.connect(server=(SERVER,PORT), secure=1, use_srv=False)
+auth = client.auth(USERNAME, PASSWORD)
+if not auth:
+ print 'Authentication failed!'
+ sys.exit(1)
+
+client.RegisterHandler('message', message_callback)
+
+send_queue.append({'to': REGISTRATION_ID,
+ 'message_id': 'reg_id',
+ 'data': {'message_destination': 'RegId',
+ 'message_id': random_id()}})
+
+while True:
+ client.Process(1)
+ flush_queued_messages()</pre>
diff --git a/docs/html/google/gcm/client.jd b/docs/html/google/gcm/client.jd
index 7604932aa383..df357a270309 100644
--- a/docs/html/google/gcm/client.jd
+++ b/docs/html/google/gcm/client.jd
@@ -1,24 +1,663 @@
-page.title=GCM Client
+page.title=Implementing GCM Client
page.tags="cloud","push","messaging"
@jd:body
<div id="qv-wrapper">
<div id="qv">
+
+<h2>In this document</h2>
+
+<ol class="toc">
+<li><a href="#play-services">Set Up Google Play Services</a></li>
+<li><a href="#manifest">Edit Your Application's Manifest</a></li>
+<li><a href="#app">Write Your Application</a>
+ <ol class="toc">
+ <li><a href="#sample-play">Check for Google Play Services APK</a></li>
+ <li><a href="#sample-register">Register for GCM</a></li>
+ <li><a href="#sample-send">Send a message</a></li>
+ <li><a href="#sample-receive">Receive a message</a></li>
+ </ol>
+ <li><a href="#run">Running the Sample</a></li>
+ <li><a href="#stats">Viewing Statistics</a></li>
+</li>
+
+</ol>
+
<h2>See Also</h2>
<ol class="toc">
<li><a href="gs.html">Getting Started</a></li>
-<li><a href="server.html">GCM Server</a></li>
+<li><a href="server.html">Implementing GCM Server</a></li>
</ol>
</div>
</div>
-<p>A GCM client is a GCM-enabled app that runs on an Android device. To write your client code, we recommend that you use the new <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> APIs. The client helper library that was offered in previous versions of GCM still works, but it has been superseded by the more efficient <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> APIs.</p>
+<p>A GCM client is a GCM-enabled app that runs on an Android device. To write your
+client code, we recommend that you use the
+<a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">
+{@code GoogleCloudMessaging}</a> APIs.
+The client helper library that was offered in previous versions of GCM still works,
+but it has been superseded by the more efficient
+<a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">
+{@code GoogleCloudMessaging}</a> APIs.</p>
+
+<p>A full GCM implementation requires both a client implementation and a server
+implementation. For more
+information about implementing the server side, see <a href="server.html">
+Implementing GCM Server</a>.</p>
+
+<p>The following sections walk you through the steps involved in writing a GCM
+client-side application. Your client app can be arbitrarily complex, but at bare
+minimum, a GCM client app must include code to register (and thereby get a
+registration ID), and a broadcast receiver to receive messages sent by GCM.
+</p>
+
+<h2 id="play-services">Step 1: Set Up Google Play Services</h2>
+
+<p>To write your client application, use the
+<a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">
+{@code GoogleCloudMessaging}</a> API.
+To use this API, you must set up your project to use the Google Play services SDK,
+as described in <a href="/google/play-services/setup.html">Setup Google Play
+Services SDK</a>.</p>
+
+<p class="note"><strong>Caution:</strong> When you add the Play Services library to
+your project, be sure to add it <em>with resources</em>, as described in
+<a href="{@docRoot}google/play-services/setup.html#Setup">
+Setup Google Play Services SDK</a>. The key point is that you must
+<em>reference</em> the library&mdash;simply adding a {@code .jar} file to
+your Eclipse project will not work. You must follow the directions
+for referencing a library, or your app won't be able to access
+the library's resources, and it won't run properly.
+If you're using Android Studio, this is the string to add to the
+{@code dependency} section of your application's {@code build.gradle} file:</p>
+
+<pre>dependencies {
+ compile: "com.google.android.gms:play-services:3.1.+"
+}
+</pre>
+
+
+<h2 id="manifest">Step 2: Edit Your Application's Manifest</h2>
+
+<p>Add the following to your application's manifest:</p>
+<ul>
+ <li>The <code>com.google.android.c2dm.permission.RECEIVE</code> permission so
+the Android application can register and receive messages.</li>
+ <li>The <code>android.permission.INTERNET</code> permission so the Android
+application can send the registration ID to the 3rd party server.</li>
+ <li>The <code>android.permission.GET_ACCOUNTS</code> permission as GCM requires
+a Google account (necessary only if if the device is running a version lower than
+Android 4.0.4)</li>
+ <li>The <code>android.permission.WAKE_LOCK</code> permission so the application
+can keep the processor from sleeping when a message is received. Optional&mdash;use
+only if the app wants to keep the device from sleeping.</li>
+ <li>An <code>applicationPackage + &quot;.permission.C2D_MESSAGE&quot;</code>
+permission to prevent other Android applications from registering and receiving
+the Android application's messages. The permission name must exactly match this
+pattern&mdash;otherwise the Android application will not receive the messages.</li>
+ <li>A receiver for <code>com.google.android.c2dm.intent.RECEIVE</code>, with
+the category set
+as <code>applicationPackage</code>. The receiver should require the
+<code>com.google.android.c2dm.SEND</code> permission, so that only the GCM
+Framework can send a message to it. If your app uses an {@link android.app.IntentService}
+(not required, but a common pattern), this receiver should be an instance of
+{@link android.support.v4.content.WakefulBroadcastReceiver}.
+A {@link android.support.v4.content.WakefulBroadcastReceiver} takes care of
+creating and managing a
+<a href="{@docRoot}reference/android/os/PowerManager.html#PARTIAL_WAKE_LOCK">
+partial wake lock</a> for your app.</li>
+
+<li>A {@link android.app.Service} (typically an {@link android.app.IntentService})
+to which the {@link android.support.v4.content.WakefulBroadcastReceiver} passes off
+the work of handling the GCM message, while ensuring that the device does not
+go back to sleep in the process. Including an {@link android.app.IntentService} is
+optional&mdash;you could choose to process your messages in a regular
+{@link android.content.BroadcastReceiver} instead, but realistically, most apps will
+use a {@link android.app.IntentService}.
+</li>
+ <li>If the GCM feature is critical to the Android application's function, be sure to
+set <code>android:minSdkVersion=&quot;8&quot;</code> or higher in the manifest. This
+ensures that the Android application cannot be installed in an environment in which it
+could not run properly. </li>
+</ul>
+
+<p>Here are excerpts from a sample manifest that supports GCM:</p>
+
+<pre class="prettyprint pretty-xml">
+&lt;manifest package="com.example.gcm" ...&gt;
+
+ &lt;uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17"/&gt;
+ &lt;uses-permission android:name="android.permission.INTERNET" /&gt;
+ &lt;uses-permission android:name="android.permission.GET_ACCOUNTS" /&gt;
+ &lt;uses-permission android:name="android.permission.WAKE_LOCK" /&gt;
+ &lt;uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" /&gt;
+
+ &lt;permission android:name="com.example.gcm.permission.C2D_MESSAGE"
+ android:protectionLevel="signature" /&gt;
+ &lt;uses-permission android:name="com.example.gcm.permission.C2D_MESSAGE" /&gt;
+
+ &lt;application ...&gt;
+ &lt;receiver
+ android:name=".GcmBroadcastReceiver"
+ android:permission="com.google.android.c2dm.permission.SEND" &gt;
+ &lt;intent-filter&gt;
+ &lt;action android:name="com.google.android.c2dm.intent.RECEIVE" /&gt;
+ &lt;category android:name="com.example.gcm" /&gt;
+ &lt;/intent-filter&gt;
+ &lt;/receiver&gt;
+ &lt;service android:name=".GcmIntentService" /&gt;
+ &lt;/application&gt;
+
+&lt;/manifest&gt;
+</pre>
+
+<h2 id="app"> Step 3: Write Your Application</h2>
+
+<p>Finally, write your application. This section features a sample client
+application that illustrates how to use the
+<a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">
+{@code GoogleCloudMessaging}</a> APIs. The sample consists of a main activity
+({@code DemoActivity}), a {@link android.support.v4.content.WakefulBroadcastReceiver}
+({@code GcmBroadcastReceiver}), and an {@link android.app.IntentService}
+({@code GcmIntentService}). You can find the complete source code for this sample at the
+<a href="http://code.google.com/p/gcm">open source site</a>.</p>
+
+<p>Note the following:</p>
+
+<ul>
+ <li>Among other things, the sample illustrates registration and upstream
+(device-to-cloud) messaging. Upstream messaging only applies to apps that are running against a
+<a href="ccs.html">CCS</a> (XMPP) server; HTTP-based servers don't support upstream messaging.</li>
+ <li>The <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">
+ {@code GoogleCloudMessaging}</a>
+registration APIs replace the old registration process, which was based on the
+now-obsolete client helper library. While the old registration process still works,
+we encourage you to use the newer
+<a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">
+{@code GoogleCloudMessaging}</a>
+registration APIs, regardless of your underlying server.</li>
+</ul>
+
+<h3 id="sample-play">Check for Google Play Services APK</h3>
+
+<p>As described in <a href="{@docRoot}google/play-services/setup.html">
+Setup Google Play Services SDK</a>, apps that rely on the Play Services SDK
+should always check the device for a compatible Google Play services APK before
+accessing Google Play services features. In the sample app this check is done in
+two places: in the main activity's {@code onCreate()} method, and in its
+{@code onResume()} method. The check in {@code onCreate()} ensures that the app
+can't be used without a successful check. The check in {@code onResume()} ensures
+that if the user returns to the running app through some other means, such as
+through the back button, the check is still performed. If the
+device doesn't have a compatible Google Play services APK, your app can call
+{@code GooglePlayServicesUtil.getErrorDialog()} to allow users to download the
+APK from the Google Play Store or enable it in the device's system settings.
+For example:</p>
+
+<pre>private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
+...
+&#64;Override
+public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.main);
+ mDisplay = (TextView) findViewById(R.id.display);
+
+ context = getApplicationContext();
+
+ // Check device for Play Services APK.
+ if (checkPlayServices()) {
+ // If this check succeeds, proceed with normal processing.
+ // Otherwise, prompt user to get valid Play Services APK.
+ ...
+ }
+}
+
+// You need to do the Play Services APK check here too.
+&#64;Override
+protected void onResume() {
+ super.onResume();
+ checkPlayServices();
+}
+
+/**
+ * Check the device to make sure it has the Google Play Services APK. If
+ * it doesn't, display a dialog that allows users to download the APK from
+ * the Google Play Store or enable it in the device's system settings.
+ */
+private boolean checkPlayServices() {
+ int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
+ if (resultCode != ConnectionResult.SUCCESS) {
+ if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
+ GooglePlayServicesUtil.getErrorDialog(resultCode, this,
+ PLAY_SERVICES_RESOLUTION_REQUEST).show();
+ } else {
+ Log.i(TAG, "This device is not supported.");
+ finish();
+ }
+ return false;
+ }
+ return true;
+}</pre>
+
+<h3 id="sample-register">Register for GCM</h3>
+<p>An Android application needs to register with GCM servers before it can receive
+messages. When an app registers, it receives a registration ID, which it can then
+store for future use. In the following snippet the {@code onCreate()} method in the sample app's
+main activity checks to see if the app is already registered with GCM and with
+the server:</p>
+
+<pre>/**
+ * Main UI for the demo app.
+ */
+public class DemoActivity extends Activity {
+
+ public static final String EXTRA_MESSAGE = "message";
+ public static final String PROPERTY_REG_ID = "registration_id";
+ private static final String PROPERTY_APP_VERSION = "appVersion";
+ private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;
+
+ /**
+ * Substitute you own sender ID here. This is the project number you got
+ * from the API Console, as described in "Getting Started."
+ */
+ String SENDER_ID = "Your-Sender-ID";
+
+ /**
+ * Tag used on log messages.
+ */
+ static final String TAG = "GCMDemo";
+
+ TextView mDisplay;
+ GoogleCloudMessaging gcm;
+ AtomicInteger msgId = new AtomicInteger();
+ SharedPreferences prefs;
+ Context context;
+
+ String regid;
+
+ &#64;Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
-<p>A full GCM implementation requires both a client implementation and a server-side implementation. For a step-by-step guide to creating a complete sample implementation that includes both client and server, see <a href="gs.html">Getting Started</a>. </p>
+ setContentView(R.layout.main);
+ mDisplay = (TextView) findViewById(R.id.display);
-<p>
+ context = getApplicationContext();
+
+ // Check device for Play Services APK. If check succeeds, proceed with
+ // GCM registration.
+ if (checkPlayServices()) {
+ gcm = GoogleCloudMessaging.getInstance(this);
+ regid = getRegistrationId(context);
+
+ if (regid.isEmpty()) {
+ registerInBackground();
+ }
+ } else {
+ Log.i(TAG, "No valid Google Play Services APK found.");
+ }
+ }
+...
+}</pre>
+
+<p>The app calls {@code getRegistrationId()} to see whether there is an existing
+registration ID stored in shared preferences:</p>
+
+<pre>/**
+ * Gets the current registration ID for application on GCM service.
+ * &lt;p&gt;
+ * If result is empty, the app needs to register.
+ *
+ * &#64;return registration ID, or empty string if there is no existing
+ * registration ID.
+ */
+private String getRegistrationId(Context context) {
+ final SharedPreferences prefs = getGCMPreferences(context);
+ String registrationId = prefs.getString(PROPERTY_REG_ID, "");
+ if (registrationId.isEmpty()) {
+ Log.i(TAG, "Registration not found.");
+ return "";
+ }
+ // Check if app was updated; if so, it must clear the registration ID
+ // since the existing regID is not guaranteed to work with the new
+ // app version.
+ int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);
+ int currentVersion = getAppVersion(context);
+ if (registeredVersion != currentVersion) {
+ Log.i(TAG, "App version changed.");
+ return "";
+ }
+ return registrationId;
+}
+...
+/**
+ * &#64;return Application's {&#64;code SharedPreferences}.
+ */
+private SharedPreferences getGCMPreferences(Context context) {
+ // This sample app persists the registration ID in shared preferences, but
+ // how you store the regID in your app is up to you.
+ return getSharedPreferences(DemoActivity.class.getSimpleName(),
+ Context.MODE_PRIVATE);
+}</pre>
+
+<p>If the registration ID doesn't exist or the app was updated,
+{@code getRegistrationId()} returns an empty string
+to indicate that the app needs to get a new regID. {@code getRegistrationId()} calls
+the following method to check the app version:</p>
+
+<pre>/**
+ * &#64;return Application's version code from the {&#64;code PackageManager}.
+ */
+private static int getAppVersion(Context context) {
+ try {
+ PackageInfo packageInfo = context.getPackageManager()
+ .getPackageInfo(context.getPackageName(), 0);
+ return packageInfo.versionCode;
+ } catch (NameNotFoundException e) {
+ // should never happen
+ throw new RuntimeException("Could not get package name: " + e);
+ }
+}</pre>
+
+
+<p>If there isn't a valid existing registration ID, {@code DemoActivity} calls the
+following {@code registerInBackground()} method to register. Note that because the GCM
+methods {@code register()} and {@code unregister()} are blocking, this has to
+take place on a background thread. This sample uses {@link android.os.AsyncTask}
+to accomplish this:</p>
+
+<pre>
+/**
+ * Registers the application with GCM servers asynchronously.
+ * &lt;p&gt;
+ * Stores the registration ID and app versionCode in the application's
+ * shared preferences.
+ */
+private void registerInBackground() {
+ new AsyncTask<Void, Void, String>() {
+ &#64;Override
+ protected String doInBackground(Void... params) {
+ String msg = "";
+ try {
+ if (gcm == null) {
+ gcm = GoogleCloudMessaging.getInstance(context);
+ }
+ regid = gcm.register(SENDER_ID);
+ msg = "Device registered, registration ID=" + regid;
+
+ // You should send the registration ID to your server over HTTP,
+ // so it can use GCM/HTTP or CCS to send messages to your app.
+ // The request to your server should be authenticated if your app
+ // is using accounts.
+ sendRegistrationIdToBackend();
+
+ // For this demo: we don't need to send it because the device
+ // will send upstream messages to a server that echo back the
+ // message using the 'from' address in the message.
+
+ // Persist the regID - no need to register again.
+ storeRegistrationId(context, regid);
+ } catch (IOException ex) {
+ msg = "Error :" + ex.getMessage();
+ // If there is an error, don't just keep trying to register.
+ // Require the user to click a button again, or perform
+ // exponential back-off.
+ }
+ return msg;
+ }
+
+ &#64;Override
+ protected void onPostExecute(String msg) {
+ mDisplay.append(msg + "\n");
+ }
+ }.execute(null, null, null);
+ ...
+ /**
+ * Sends the registration ID to your server over HTTP, so it can use GCM/HTTP
+ * or CCS to send messages to your app. Not needed for this demo since the
+ * device sends upstream messages to a server that echoes back the message
+ * using the 'from' address in the message.
+ */
+ private void sendRegistrationIdToBackend() {
+ // Your implementation here.
+ }
+}</pre>
+
+<p>After registering, the app calls {@code storeRegistrationId()} to store the
+registration ID in shared preferences for future use. This is just one way of
+persisting a regID. You might choose to use a different approach in your app:</p>
+
+<pre>/**
+ * Stores the registration ID and app versionCode in the application's
+ * {&#64;code SharedPreferences}.
+ *
+ * &#64;param context application's context.
+ * &#64;param regId registration ID
+ */
+private void storeRegistrationId(Context context, String regId) {
+ final SharedPreferences prefs = getGCMPreferences(context);
+ int appVersion = getAppVersion(context);
+ Log.i(TAG, "Saving regId on app version " + appVersion);
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putString(PROPERTY_REG_ID, regId);
+ editor.putInt(PROPERTY_APP_VERSION, appVersion);
+ editor.commit();
+}</pre>
+
+<h3 id="sample-send">Send a message</h3>
+<p>When the user clicks the app's <strong>Send</strong> button, the app sends an
+upstream message using the
+<a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">
+{@code GoogleCloudMessaging}</a> APIs. In order to receive the upstream message,
+your server should be connected to CCS. You can use one of the demo servers in
+<a href="ccs.html#implement">Implementing an XMPP-based App Server</a> to run the sample and connect
+to CCS.</p>
+
+<pre>public void onClick(final View view) {
+ if (view == findViewById(R.id.send)) {
+ new AsyncTask<Void, Void, String>() {
+ &#64;Override
+ protected String doInBackground(Void... params) {
+ String msg = "";
+ try {
+ Bundle data = new Bundle();
+ data.putString("my_message", "Hello World");
+ data.putString("my_action",
+ "com.google.android.gcm.demo.app.ECHO_NOW");
+ String id = Integer.toString(msgId.incrementAndGet());
+ gcm.send(SENDER_ID + "@gcm.googleapis.com", id, data);
+ msg = "Sent message";
+ } catch (IOException ex) {
+ msg = "Error :" + ex.getMessage();
+ }
+ return msg;
+ }
+
+ &#64;Override
+ protected void onPostExecute(String msg) {
+ mDisplay.append(msg + "\n");
+ }
+ }.execute(null, null, null);
+ } else if (view == findViewById(R.id.clear)) {
+ mDisplay.setText("");
+ }
+}</pre>
+
+<h3 id="sample-receive">Receive a message</h3>
+
+<p>As described above in <a href="#manifest">Step 2</a>, the app includes a
+{@link android.support.v4.content.WakefulBroadcastReceiver} for the <code>com.google.android.c2dm.intent.RECEIVE</code>
+intent. A broadcast receiver is the mechanism GCM uses to deliver messages. When {@code onClick()}
+calls {@code gcm.send()}, it triggers the broadcast receiver's {@code onReceive()}
+method, which has the responsibility of making sure that the GCM message gets handled.</p>
+<p>A {@link android.support.v4.content.WakefulBroadcastReceiver} is a special type of
+broadcast receiver that takes care of
+creating and managing a
+<a href="{@docRoot}reference/android/os/PowerManager.html#PARTIAL_WAKE_LOCK">
+partial wake lock</a> for your app.
+It passes off the work of processing the GCM message to a
+{@link android.app.Service} (typically an
+{@link android.app.IntentService}), while ensuring that the device does not
+go back to sleep in the transition. If you don't hold a wake lock while transitioning
+the work to a service, you are effectively allowing the device to go back to sleep before
+the work completes. The net result is that the app might not finish processing
+the GCM message until some arbitrary point in the future, which is not what you want.</p>
+
+<p class="note"><strong>Note:</strong> Using {@link android.support.v4.content.WakefulBroadcastReceiver}
+is not a requirement. If you have a relatively simple app that doesn't require
+a service, you can intercept the GCM message in a regular {@link android.content.BroadcastReceiver}
+and do your processing there. Once you get the intent that GCM passes into
+your broadcast receiver's {@code onReceive()} method, what you do with it
+is up to you.</p>
+
+<p>This snippet starts {@code GcmIntentService} with the method
+{@link android.support.v4.content.WakefulBroadcastReceiver#startWakefulService startWakefulService()}.
+This method is comparable to {@link android.content.Context#startService startService()}, except that
+the {@link android.support.v4.content.WakefulBroadcastReceiver} is holding a
+wake lock when the service starts. The intent that is passed with
+{@link android.support.v4.content.WakefulBroadcastReceiver#startWakefulService startWakefulService()}
+holds an extra identifying the wake lock:</p>
+
+
+<pre>public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
+ &#64;Override
+ public void onReceive(Context context, Intent intent) {
+ // Explicitly specify that GcmIntentService will handle the intent.
+ ComponentName comp = new ComponentName(context.getPackageName(),
+ GcmIntentService.class.getName());
+ // Start the service, keeping the device awake while it is launching.
+ startWakefulService(context, (intent.setComponent(comp)));
+ setResultCode(Activity.RESULT_OK);
+ }
+}</pre>
+
+<p>The intent service shown below does the actual work of handling the GCM
+message. When the service is finished, it calls
+{@link android.support.v4.content.WakefulBroadcastReceiver#completeWakefulIntent GcmBroadcastReceiver.completeWakefulIntent()}
+to release the wake lock. The
+{@link android.support.v4.content.WakefulBroadcastReceiver#completeWakefulIntent completeWakefulIntent()}
+method has as its parameter the same intent that was
+passed in from the {@link android.support.v4.content.WakefulBroadcastReceiver}.
+</p>
+
+<p>This snippet processes the GCM message based on message type, and posts the
+result in a notification. But what you do with GCM messages in your app is up to
+you&mdash;the possibilities are endless. For example, the message might be a ping,
+telling the app to sync to a server to retrieve new content, or it might be a
+chat message that you display in the UI.</p>
+
+<pre>
+public class GcmIntentService extends IntentService {
+ public static final int NOTIFICATION_ID = 1;
+ private NotificationManager mNotificationManager;
+ NotificationCompat.Builder builder;
+
+ public GcmIntentService() {
+ super("GcmIntentService");
+ }
+
+ &#64;Override
+ protected void onHandleIntent(Intent intent) {
+ Bundle extras = intent.getExtras();
+ GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
+ // The getMessageType() intent parameter must be the intent you received
+ // in your BroadcastReceiver.
+ String messageType = gcm.getMessageType(intent);
+
+ if (!extras.isEmpty()) { // has effect of unparcelling Bundle
+ /*
+ * Filter messages based on message type. Since it is likely that GCM
+ * will be extended in the future with new message types, just ignore
+ * any message types you're not interested in, or that you don't
+ * recognize.
+ */
+ if (GoogleCloudMessaging.
+ MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
+ sendNotification("Send error: " + extras.toString());
+ } else if (GoogleCloudMessaging.
+ MESSAGE_TYPE_DELETED.equals(messageType)) {
+ sendNotification("Deleted messages on server: " +
+ extras.toString());
+ // If it's a regular GCM message, do some work.
+ } else if (GoogleCloudMessaging.
+ MESSAGE_TYPE_MESSAGE.equals(messageType)) {
+ // This loop represents the service doing some work.
+ for (int i=0; i<5; i++) {
+ Log.i(TAG, "Working... " + (i+1)
+ + "/5 @ " + SystemClock.elapsedRealtime());
+ try {
+ Thread.sleep(5000);
+ } catch (InterruptedException e) {
+ }
+ }
+ Log.i(TAG, "Completed work @ " + SystemClock.elapsedRealtime());
+ // Post notification of received message.
+ sendNotification("Received: " + extras.toString());
+ Log.i(TAG, "Received: " + extras.toString());
+ }
+ }
+ // Release the wake lock provided by the WakefulBroadcastReceiver.
+ GcmBroadcastReceiver.completeWakefulIntent(intent);
+ }
+
+ // Put the message into a notification and post it.
+ // This is just one simple example of what you might choose to do with
+ // a GCM message.
+ private void sendNotification(String msg) {
+ mNotificationManager = (NotificationManager)
+ this.getSystemService(Context.NOTIFICATION_SERVICE);
+
+ PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
+ new Intent(this, DemoActivity.class), 0);
+
+ NotificationCompat.Builder mBuilder =
+ new NotificationCompat.Builder(this)
+ .setSmallIcon(R.drawable.ic_stat_gcm)
+ .setContentTitle("GCM Notification")
+ .setStyle(new NotificationCompat.BigTextStyle()
+ .bigText(msg))
+ .setContentText(msg);
+
+ mBuilder.setContentIntent(contentIntent);
+ mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
+ }
+}</pre>
+
+<h2 id="run">Running the Sample</h2>
+
+<p>To run the sample:</p>
+
+<ol>
+ <li>Follow the instructions in <a href="gs.html">Getting Started</a> to get your sender ID and
+ API key.</li>
+ <li>Implement your client app, as described in this document. You can find the complete source
+ code for the client app at the <a href="http://code.google.com/p/gcm">open source site</a>.</li>
+ <li>Run one of the demo servers (Java or Python) provided in
+<a href="ccs.html#implement">Implementing an XMPP-based App Server</a>. Whichever demo server you
+ choose, don't forget to edit its code before running it to supply
+your sender ID and API key.
+</li>
+
+</ol>
+
+<h2 id="stats">Viewing Statistics</h2>
+
+<p>To view statistics and any error messages for your GCM applications:</p>
+<ol>
+ <li> Go to the <code><a href="http://play.google.com/apps/publish">Developer Console</a></code>.</li>
+ <li>Login with your developer account.
+ <p>You will see a page that has a list of all of your apps.</p></li>
+ <li> Click on the &quot;statistics&quot; link next to the app for which you
+want to view GCM stats.
+ <p>Now you are on the statistics page.</p> </li>
+ <li>Go to the drop-down menu and select the GCM metric you want to view.
+ </li>
+</ol>
+<p class="note"><strong>Note:</strong> Stats on the Google API Console are not
+enabled for GCM. You must use the <a href="http://play.google.com/apps/publish">Developer Console</a>.</p>
diff --git a/docs/html/google/gcm/gcm.jd b/docs/html/google/gcm/gcm.jd
index ceb82b03702b..3c80b5f9ae5f 100644
--- a/docs/html/google/gcm/gcm.jd
+++ b/docs/html/google/gcm/gcm.jd
@@ -1,48 +1,23 @@
-page.title=GCM Architectural Overview
+page.title=Overview
@jd:body
<div id="qv-wrapper">
<div id="qv">
-<h2>Quickview</h2>
-
-<ul>
-<li>Get an introduction to key GCM terms and concepts.</li>
-<li>Learn the basic features of a GCM application.</li>
-<li>Understand the role of the 3rd-party application server, and how to send messages and process results.</li>
-</ul>
-
-
<h2>In this document</h2>
<ol class="toc">
- <li><a href="#intro">Introduction</a> </li>
- <li><a href="#arch">Architectural Overview</a>
- <ol>
- <li><a href="#lifecycle">Lifecycle Flow</a></li>
- <ol>
- <li><a href="#register">Enable GCM</a></li>
- <li><a href="#push-process">Send a message</a></li>
- <li><a href="#receiving">Receive a message</a></li>
- </ol>
- <li><a href="#user">What Does the User See?</a></li>
- </ol>
- </li>
- <li><a href="#server">Role of the 3rd-party Application Server</a>
+ <li><a href="#key">Key Concepts</a></li>
+ <li><a href="#arch">Architectural Overview</a></li>
+ <li><a href="#lifecycle">Lifecycle Flow</a>
<ol class="toc">
- <li><a href="#send-msg">Sending Messages</a>
- <ol>
- <li><a href="#request">Request format</a></li>
- <li><a href="#response">Response format</a></li>
- </ol>
- </li>
+ <li><a href="#register">Enable GCM</a></li>
+ <li><a href="#push-process">Send a message</a></li>
+ <li><a href="#receiving">Receive a message</a></li>
</ol>
- <li><a href="#stats">Viewing Statistics</a>
</li>
</ol>
-
-
</div>
</div>
@@ -50,24 +25,15 @@ page.title=GCM Architectural Overview
developers send data from servers to their Android applications on Android
devices, and upstream messages from the user's device back to the cloud.
This could be a lightweight message telling the Android application
-that there is new data to be fetched from the server (for instance, a movie
-uploaded by a friend), or it could be a message containing up to 4kb of payload
+that there is new data to be fetched from the server (for instance, a "new email"
+notification informing the application that it is out of sync with the back end),
+or it could be a message containing up to 4kb of payload
data (so apps like instant messaging can consume the message directly). The GCM
service handles all aspects of queueing of messages and delivery to the target
Android application running on the target device.</p>
-
-<p>GCM introduces GCM Cloud Connection Server (CCS), which you can use
-in tandem with GCM HTTP service/endpoint/APIs.
-CCS uses XMPP, and it offers asynchronous, bidirectional
-messaging. For more information, see
-<a href="ccs.html">GCM Cloud Connection Server</a>.
-
<p class="note"> To jump right into using GCM with your Android
- applications, see the instructions in <a href="gs.html">Getting Started</a>.</p>
-
-
-<h2 id="intro">Introduction</h2>
+ applications, see <a href="gs.html">Getting Started</a>.</p>
<p>Here are the primary characteristics of Google Cloud
Messaging (GCM):</p>
@@ -75,9 +41,11 @@ Messaging (GCM):</p>
<ul>
<li>It allows 3rd-party application servers to send messages to
their Android applications.</li>
- <li>Using the <a href="ccs.html">GCM Cloud Connection Server</a>, you can receive upstream messages from the user's device.</li>
+ <li>Using the <a href="ccs.html">GCM Cloud Connection Server</a>, you can receive
+upstream messages from the user's device.</li>
<li>An Android application on an Android device doesn't need to be running to receive
-messages. The system will wake up the Android application via Intent broadcast when the message arrives, as long as the application is set up with the proper
+messages. The system will wake up the Android application via Intent broadcast
+when the message arrives, as long as the application is set up with the proper
broadcast receiver and permissions.</li>
<li>It does not provide any built-in user interface or other handling for
message data. GCM simply passes raw message data received straight to the
@@ -85,57 +53,67 @@ Android application, which has full control of how to handle it. For example, t
application might post a notification, display a custom user interface, or
silently sync data.</li>
<li>It requires devices running Android 2.2 or higher that also have the
-Google Play Store application installed, or or an emulator running Android 2.2 with Google APIs. However, you are not limited to deploying your
+Google Play Store application installed, or or an emulator running Android 2.2
+with Google APIs. However, you are not limited to deploying your
Android applications through Google Play Store.</li>
- <li>It uses an existing connection for Google services. For pre-3.0 devices, this requires users to
-set up their Google account on their mobile devices. A Google account is not a requirement on devices running Android 4.0.4 or higher.</li>
+ <li>It uses an existing connection for Google services. For pre-3.0 devices,
+this requires users to
+set up their Google account on their mobile devices. A Google account is not a
+requirement on devices running Android 4.0.4 or higher.</li>
</ul>
-<h2 id="arch">Architectural Overview</h2>
-<p>This section gives an overview of how GCM works. </p>
+
+<h2 id="key">Key Concepts</h2>
+
<p>This table summarizes the key terms and concepts involved in GCM. It is
divided into these categories:</p>
<ul>
- <li><strong>Components</strong> &mdash; The physical entities that play a role in
+ <li><strong>Components</strong> &mdash; The entities that play a primary role in
GCM.</li>
<li><strong>Credentials</strong> &mdash; The IDs and tokens that are used in
different stages of GCM to ensure that all parties have been authenticated, and
that the message is going to the correct place.</li>
</ul>
+<p class="table-caption" id="table1">
+ <strong>Table 1.</strong> GCM components and credentials.</p>
+
<table>
<tr>
<th colspan="2">Components</th>
</tr>
<tr>
- <td width="165"><strong>Mobile Device</strong></td>
- <td width="1176">The device that is running an Android application that uses
-GCM. This must be a 2.2 Android device that has Google Play Store installed, and it must
-have at least one logged in Google account if the device is running a version lower than Android 4.0.4. Alternatively, for testing you can use an emulator running Android 2.2 with Google APIs.</td>
+ <td width="165"><strong>Client App</strong></td>
+ <td width="1176">The GCM-enabled Android application that is running on a
+ device. This must be a 2.2 Android device that has Google Play Store installed, and it must
+have at least one logged in Google account if the device is running a version
+lower than Android 4.0.4. Alternatively, for testing you can use an emulator
+running Android 2.2 with Google APIs.</td>
</tr>
<tr>
<td><strong>3rd-party Application Server</strong></td>
- <td>An application server that developers set up as part of implementing
-GCM in their applications. The 3rd-party application server sends data to an
-Android application on the device via the GCM server.</td>
+ <td>An application server that you write as part of implementing
+GCM. The 3rd-party application server sends data to an
+Android application on the device via the GCM connection server.</td>
</tr>
<tr>
- <td><strong>GCM Servers</strong></td>
- <td>The Google servers involved in taking messages from the 3rd-party
+ <td><strong>GCM Connection Servers</strong></td>
+ <td>The Google-provided servers involved in taking messages from the 3rd-party
application server and sending them to the device. </td>
</tr>
<tr>
- <th colspan="2"><strong>Credentials</strong></th>
+ <th colspan="2">Credentials</th>
</tr>
<tr>
<td><strong>Sender ID</strong></td>
- <td>A project number you acquire from the API console, as described in <a href="gs.html#create-proj">Getting Started</a>. The sender
-ID is used in the <a href="#registering">registration process</a> to identify an
-Android application that is permitted to send messages to the device.</td>
+ <td>A project number you acquire from the API console, as described in
+<a href="gs.html#create-proj">Getting Started</a>. The sender
+ID is used in the <a href="#register">registration process</a> to identify a
+3rd-party application server that is permitted to send messages to the device.</td>
</tr>
<tr>
<td><strong>Application ID</strong></td>
<td>The Android application that is registering to receive messages. The Android application
-is identified by the package name from the <a href="#manifest">manifest</a>.
+is identified by the package name from the <a href="client.html#manifest">manifest</a>.
This ensures that the messages are targeted to the correct Android application.</td>
</tr>
<tr>
@@ -158,7 +136,8 @@ which would cause delivery errors.
</tr>
<tr>
<td><strong>Google User Account</strong></td>
- <td>For GCM to work, the mobile device must include at least one Google account if the device is running a version lower than Android 4.0.4.</td>
+ <td>For GCM to work, the mobile device must include at least one Google
+account if the device is running a version lower than Android 4.0.4.</td>
</tr>
<tr>
<td><strong>Sender Auth Token</strong></td>
@@ -167,25 +146,46 @@ server that gives the application server authorized access to Google services.
The API key is included in the header of POST requests that send messages.</td>
</tr>
- <tr>
- <td><strong>Notification Key</strong></td>
- <td>Part of the user notifications feature, which provides a mapping between a user and instances of an app running on multiple devices owned by the user. The {@code notification_key} is the token that GCM uses to fan out notifications to all devices whose registration IDs are associated with the key. For more discussion of this topic, see <a href="notifications.html">User Notifications</a>.</td>
- </tr>
+</table>
-<tr>
- <td><strong>Notification Key Name</strong></td>
- <td>Part of the user notifications feature. The {@code notification_key_name} is a name or identifier (can be a username for a 3rd-party app) that is unique to a given user. It is used by third parties to group together registration IDs for a single user. For more discussion of this topic, see <a href="notifications.html">User Notifications</a>.</td>
- </tr>
+<h2 id="arch">Architectural Overview</h2>
-</table>
+<p>A GCM implementation includes a Google-provided
+connection server, a 3rd-party app server that interacts with the connection
+server, and a GCM-enabled client app running on an Android device:</p>
-<h3 id="lifecycle">Lifecycle Flow</h3>
+<img src="{@docRoot}images/gcm/GCM-arch.png">
+
+<p class="img-caption">
+ <strong>Figure 1.</strong> GCM Architecture.
+</p>
+
+<p>This is how these components interact:</p>
+<ul>
+ <li>Google-provided <strong>GCM Connection Servers</strong> take messages from
+a 3rd-party application server and send these messages to a
+GCM-enabled Android application (the &quot;client app&quot;) running on a device.
+Currently Google provides connection servers for <a href="http.html">HTTP</a>
+and <a href="ccs.html">XMPP</a>.</li>
+ <li>The <strong>3rd-Party Application Server</strong> is a component that you
+implement to work with your chosen GCM connection server(s). App servers send
+messages to a GCM connection server; the connection server enqueues and stores the
+message, and then sends it to the device when the device is online.
+For more information, see <a href="server.html">Implementing GCM Server</a>.</li>
+ <li>The <strong>Client App</strong> is a GCM-enabled Android application running
+on a device. To receive GCM messages, this app must register with GCM and get a
+registration ID. If you are using the <a href="ccs.html">XMPP</a> (CCS) connection
+server, the client app can send "upstream" messages back to the connection server.
+For more information on how to implement the client app, see
+<a href="client.html">Implementing GCM Client</a>.</li>
+</ul>
+
+<h2 id="lifecycle">Lifecycle Flow</h2>
<ul>
<li><a href="#register">Enable GCM</a>. An Android application running on a
mobile device registers to receive messages.</li>
- <li><a href="notifications.html">User Notifications</a>. A 3rd-party server can optionally group multiple registration IDs
-in a {@code notification_key} to send messages to multiple devices owned by a single user.</li>
+
<li><a href="#push-process">Send a message</a>. A 3rd-party application
server sends messages to the device.</li>
<li><a href="#receiving">Receive a message</a>. An Android application
@@ -194,62 +194,18 @@ receives a message from a GCM server.</li>
<p>These processes are described in more detail below.</p>
-<h4 id="register">Enable GCM</h4>
-
-<p>This is the sequence of events that occurs when an Android application
-running on a mobile device registers to receive messages:<span
-class="red-text"></span></p>
+<h3 id="register">Enable GCM</h3>
-<ol>
- <li>The first time the Android application needs to use the messaging service, it
-fires off a registration Intent to a GCM server.
- <p>This registration Intent
-(<code>com.google.android.c2dm.intent.REGISTER</code>) includes the sender ID, and the Android application ID.</p>
-<p class="note"><strong>Note:</strong> Because there is no lifecycle method that is called when the application is run for
-the first time, the registration intent should be sent on <code>onCreate()</code>, but only if the application is not registered yet.
+<p>The first time the Android application needs to use the messaging service, it
+calls the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">
+{@code GoogleCloudMessaging}</a> method {@code register()}, as discussed in
+<a href="client.html">Implementing GCM Client</a>.
+The {@code register()} method returns a registration ID. The Android
+application should store this ID for later use (for instance,
+to check in <code>onCreate()</code> if it is already registered).
</p>
- </li>
- <li>If the registration is successful, the GCM server broadcasts a <code>com.google.android.c2dm.intent.REGISTRATION</code> intent which gives the Android application a registration
-ID.
- <p>The Android application should store this ID for later use (for instance, to check on <code>onCreate()</code> if it is already registered).
-Note that Google may periodically refresh the registration ID, so you should design your Android application
-with the understanding that the <code>com.google.android.c2dm.intent.REGISTRATION</code> intent may be called
-multiple times. Your Android application needs to be able to respond
-accordingly.</p></li>
- <li>To complete the registration, the Android application sends the registration ID to
-the application server. The application server typically stores the registration
-ID in a database. </li>
-</ol>
-
-<p>The registration ID lasts until the Android application explicitly unregisters
-itself, or until Google refreshes the registration ID for your Android application.</p>
-
-<p class="note"><strong>Note:</strong> When users uninstall an application, it is not automatically unregistered on GCM. It is only unregistered when the GCM server tries to send a message to the device and the device answers that the application is uninstalled or it does not have a broadcast receiver configured to receive <code>com.google.android.c2dm.intent.RECEIVE</code> intents. At that point, your server should mark the device as unregistered (the server will receive a <code><a href="#unreg_device">NotRegistered</a></code> error).</p>
- <p>
-Note that it might take a few minutes for the registration ID to be completely removed from the GCM server. So if the 3rd-party server sends a message during this time, it will get a valid message ID, even though the message will not be delivered to the device.</p>
-
-
-
-<h4 id="push-process">Send a Message</h4>
-
-<p>For an application server to send a message to an Android application, the following things must be in
-place:</p>
-
-<ul>
- <li>The Android application has stored a target that it can specify as the recipient of a message. This can be one of the following:
- <ul>
- <li>A single registration ID (or an array of registration IDs) that allows the app to receive messages
-for a particular device.</li>
- <li>A {@code notification_key} and corresponding {@code notification_key_name}, used to map a single user to multiple registration IDs. For more discussion of this topic, see <a href="notifications.html">User Notifications</a>.</li>
- </ul>
- </li>
-
-<li>An API key. This is something that the developer must have already
-set up on the application server for the Android application (for more discussion, see
-<a href="#server">Role of the 3rd-party Application Server</a>). Now it will
-get used to send messages to the device. </li>
-</ul>
+<h3 id="push-process">Send a message</h3>
<p>Here is the sequence of events that occurs when the application server sends a
message:</p>
@@ -264,13 +220,14 @@ Android application via Intent broadcast with proper permissions, so that only t
targeted Android application gets the message. This wakes the Android application up. The
Android application does not need to be running beforehand to receive the message.</li>
<li>The Android application processes the message. If the Android application is doing
-non-trivial processing, you may want to grab a {@link android.os.PowerManager.WakeLock} and do any processing in a Service.</li>
+non-trivial processing, you may want to grab a
+{@link android.os.PowerManager.WakeLock} and do any processing in a service.</li>
</ol>
<p> An Android application can unregister GCM if it no longer wants to receive
messages.</p>
-<h4 id="receiving">Receive a Message</h4>
+<h3 id="receiving">Receive a message</h3>
<p>This is the sequence of events that occurs when an Android application
installed on a mobile device receives a message:</p>
@@ -282,482 +239,8 @@ pairs from the message payload, if any.</li>
in a <code>com.google.android.c2dm.intent.RECEIVE</code> Intent as a set of
extras.</li>
<li>The Android application extracts the raw data
-from the <code>com.google.android.c2dm.intent.RECEIVE</code><code> </code>Intent by key and processes the data.</li>
-</ol>
-
-<h3 id="user">What Does the User See?</h3>
-
-<p>When mobile device users install Android applications that include GCM, the Google Play Store will inform them that the Android application
-includes GCM. They must approve the use of this feature to install the
-Android application. </p>
-
-
-<h2 id="server">Role of the 3rd-party Application Server</h2>
-
-<p>Before you can write client Android applications that use the GCM feature, you must
-have an application server that meets the following criteria:</p>
-
-<ul>
- <li>Able to communicate with your client.</li>
- <li>Able to fire off HTTPS requests to the GCM server.</li>
- <li>Able to handle requests and resend them as needed, using <a href="http://en.wikipedia.org/wiki/Exponential_backoff">exponential back-off.</a></li>
- <li>Able to store the API key and client registration IDs. The
-API key is included in the header of POST requests that send
-messages.</li>
-</ul>
-
-<h3 id="send-msg">Sending Messages</h3>
-<p>This section describes how the 3rd-party application server sends messages to one or more mobile devices. Note the following:</p>
-<ul>
- <li>A 3rd-party application server can either send messages to a single device or to multiple devices. A message sent to multiple devices simultaneously is called a <em>multicast message</em>.</li>
- <li>To send a single message to multiple devices owned by a single user, you can use a {@code notification_key}, as described in <a href="notifications.html">User Notifications</a>.
-
- <li>You have 2 choices in how you construct requests and responses: plain text or JSON.</li>
- <li>However, to send multicast messages, you must use JSON. Plain text will not work.</li>
-</ul>
-<p>Before the 3rd-party application server can send a message to an
- Android application, it must have received a registration ID from it.</p>
-<h4 id="request">Request format</h4>
-<p>To send a message, the application server issues a POST request to <code>https://android.googleapis.com/gcm/send</code>.</p>
-<p>A message request is made of 2 parts: HTTP header and HTTP body.</p>
-
-<p>The HTTP header must contain the following headers:</p>
-<ul>
- <li><code>Authorization</code>: key=YOUR_API_KEY</li>
- <li><code>Content-Type</code>: <code>application/json</code> for JSON; <code>application/x-www-form-urlencoded;charset=UTF-8</code> for plain text.
- </li>
-</ul>
-
-<p>For example:
-</p>
-<pre>Content-Type:application/json
-Authorization:key=AIzaSyB-1uEai2WiUapxCs2Q0GZYzPu7Udno5aA
-
-{
- "registration_ids" : ["APA91bHun4MxP5egoKMwt2KZFBaFUH-1RYqx..."],
- "data" : {
- ...
- },
-}</pre>
-<p class="note">
- <p><strong>Note:</strong> If <code>Content-Type</code> is omitted, the format is assumed to be plain text.</p>
-</p>
-
-<p>The HTTP body content depends on whether you're using JSON or plain text. For JSON, it must contain a string representing a JSON object with the following fields:</p>
-<table>
- <tr>
- <th>Field</th>
- <th>Description</th>
- </tr>
- <tr>
- <td><code>registration_ids</code></td>
- <td>A string array with the list of devices (registration IDs) receiving the message. It must contain at least 1 and at most 1000 registration IDs. To send a multicast message, you must use JSON. For sending a single message to a single device, you could use a JSON object with just 1 registration id, or plain text (see below). A request must include a recipient&mdash;this can be either a registration ID, an array of registration IDs, or a {@code notification_key}.</td>
- </tr>
- <tr>
- <td><code>notification_key</code></td>
- <td>A string that maps a single user to multiple registration IDs associated with that user. This
-allows a 3rd-party server to send a single message to multiple app instances (typically on multiple devices) owned by a single user. A 3rd-party server can use {@code notification_key} as the target for a message instead of an individual registration ID (or array of registration IDs). The maximum number of members allowed for a {@code notification_key} is 10. For more discussion of this topic, see <a href="notifications.html">User Notifications</a>. Optional.</td>
- </tr>
-
-<tr>
- <td><code>notification_key_name</code></td>
- <td>A name or identifier (can be a username for a 3rd-party app) that is unique to a given user. It is used by 3rd parties to group together registration IDs for a single user. The <code>notification_key_name</code> should be uniquely named per app in case you have multiple apps for the same project ID. This ensures that notifications only go to the intended target app. For more discussion of this topic, see <a href="notifications.html">User Notifications</a>.</td>
- </tr>
-
- <tr>
- <td><code>collapse_key</code></td>
- <td>An arbitrary string (such as &quot;Updates Available&quot;) that is used to collapse a group of like messages
-when the device is offline, so that only the last message gets sent to the
-client. This is intended to avoid sending too many messages to the phone when it
-comes back online. Note that since there is no guarantee of the order in which
-messages get sent, the &quot;last&quot; message may not actually be the last
-message sent by the application server. See <a href="adv.html#collapsible">Advanced Topics</a> for more discussion of this topic. Optional.</td>
- </tr>
- <tr>
- <td><code>data</code></td>
- <td>A JSON object whose fields represents the key-value pairs of the message's payload data. If present, the payload data it will be
-included in the Intent as application data, with the key being the extra's name. For instance, <code>"data":{"score":"3x1"}</code> would result in an intent extra named <code>score</code> whose value is the string <code>3x1</code>.
-
-There is no limit on the number of key/value pairs, though there is a limit on the total size of the message (4kb). The values could be any JSON object, but we recommend using strings, since the values will be converted to strings in the GCM server anyway. If you want to include objects or other non-string data types (such as integers or booleans), you have to do the conversion to string yourself. Also note that the key cannot be a reserved word (<code>from</code> or any word starting with <code>google.</code>). To complicate things slightly, there are some reserved words (such as <code>collapse_key</code>) that are technically allowed in payload data. However, if the request also contains the word, the value in the request will overwrite the value in the payload data. Hence using words that are defined as field names in this table is not recommended, even in cases where they are technically allowed. Optional.</td>
-
-
- </tr>
- <tr>
- <td><code>delay_while_idle</code></td>
- <td>If included, indicates that the message should not be sent immediately
-if the device is idle. The server will wait for the device to become active, and
-then only the last message for each <code>collapse_key</code> value will be
-sent. Optional. The default value is <code>false</code>, and must be a JSON boolean.</td>
- </tr>
- <tr>
- <td><code>time_to_live</code></td>
- <td>How long (in seconds) the message should be kept on GCM storage if the device is offline. Optional (default time-to-live is 4 weeks, and must be set as a JSON number).</td>
- </tr>
-<tr>
- <td><code>restricted_package_name</code></td>
- <td>A string containing the package name of your application. When set, messages will only be sent to registration IDs that match the package name. Optional.
- </td>
-</tr>
-<tr>
- <td><code>dry_run</code></td>
- <td>If included, allows developers to test their request without actually sending a message. Optional. The default value is <code>false</code>, and must be a JSON boolean.
- </td>
-</tr>
-</table>
-
-<p>If you are using plain text instead of JSON, the message fields must be set as HTTP parameters sent in the body, and their syntax is slightly different, as described below:
-<table>
- <tr>
- <th>Field</th>
- <th>Description</th>
- </tr>
- <tr>
- <td><code>registration_id</code></td>
- <td>Must contain the registration ID of the single device receiving the message. Required.</td>
- </tr>
- <tr>
- <td><code>collapse_key</code></td>
- <td>Same as JSON (see previous table). Optional.</td>
- </tr>
- <tr>
- <td><code>data.&lt;key&gt;</code></td>
-
- <td>Payload data, expressed as parameters prefixed with <code>data.</code> and suffixed as the key. For instance, a parameter of <code>data.score=3x1</code> would result in an intent extra named <code>score</code> whose value is the string <code>3x1</code>. There is no limit on the number of key/value parameters, though there is a limit on the total size of the message. Also note that the key cannot be a reserved word (<code>from</code> or any word starting with
-<code>google.</code>). To complicate things slightly, there are some reserved words (such as <code>collapse_key</code>) that are technically allowed in payload data. However, if the request also contains the word, the value in the request will overwrite the value in the payload data. Hence using words that are defined as field names in this table is not recommended, even in cases where they are technically allowed. Optional.</td>
-
- </tr>
- <tr>
- <td><code>delay_while_idle</code></td>
- <td>Should be represented as <code>1</code> or <code>true</code> for <code>true</code>, anything else for <code>false</code>. Optional. The default value is <code>false</code>.</td>
- </tr>
- <tr>
- <td><code>time_to_live</code></td>
- <td>Same as JSON (see previous table). Optional.</td>
- </tr>
-<tr>
- <td><code>restricted_package_name</code></td>
- <td>Same as JSON (see previous table). Optional.
- </td>
-</tr>
-<tr>
- <td><code>dry_run</code></td>
- <td>Same as JSON (see previous table). Optional.
- </td>
-</tr>
-</table>
-
-<p>If you want to test your request (either JSON or plain text) without delivering the message to the devices, you can set an optional HTTP or JSON parameter called <code>dry_run</code> with the value <code>true</code>. The result will be almost identical to running the request without this parameter, except that the message will not be delivered to the devices. Consequently, the response will contain fake IDs for the message and multicast fields (see <a href="#response">Response format</a>).</p>
-
- <h4 id="example-requests">Example requests</h4>
- <p>Here is the smallest possible request (a message without any parameters and just one recipient) using JSON:</p>
- <pre class="prettyprint pretty-json">{ &quot;registration_ids&quot;: [ &quot;42&quot; ] }</pre>
-
- <p>And here the same example using plain text:</p>
- <pre class="prettyprint">registration_id=42</pre>
-
- <p> Here is a message with a payload and 6 recipients:</p>
- <pre class="prettyprint pretty-HTML">{ "data": {
- "score": "5x1",
- "time": "15:10"
- },
- "registration_ids": ["4", "8", "15", "16", "23", "42"]
-}</pre>
- <p>Here is a message with all optional fields set and 6 recipients:</p>
- <pre class="prettyprint pretty-json">{ "collapse_key": "score_update",
- "time_to_live": 108,
- "delay_while_idle": true,
- "data": {
- "score": "4x8",
- "time": "15:16.2342"
- },
- "registration_ids":["4", "8", "15", "16", "23", "42"]
-}</pre>
- <p>And here is the same message using plain-text format (but just 1 recipient): </p>
-
- <pre class="prettyprint">collapse_key=score_update&amp;time_to_live=108&amp;delay_while_idle=1&amp;data.score=4x8&amp;data.time=15:16.2342&amp;registration_id=42
- </pre>
-
-<p class="note"><strong>Note:</strong> If your organization has a firewall
-that restricts the traffic to or
-from the Internet, you need to configure it to allow connectivity with GCM in order for
-your Android devices to receive messages.
-The ports to open are: 5228, 5229, and 5230. GCM typically only uses 5228, but
-it sometimes uses 5229 and 5230. GCM doesn't provide specific IPs, so you should allow
-your firewall to accept outgoing connections to all IP addresses
-contained in the IP blocks listed in Google's ASN of 15169.</p>
-
-
-<h4 id="response">Response format</h4>
-
-<p>There are two possible outcomes when trying to send a message:</p>
-<ul>
- <li>The message is processed successfully.</li>
- <li>The GCM server rejects the request.</li>
-</ul>
-
-<p>When the message is processed successfully, the HTTP response has a 200 status and the body contains more information about the status of the message (including possible errors). When the request is rejected,
-the HTTP response contains a non-200 status code (such as 400, 401, or 503).</p>
-
-<p>The following table summarizes the statuses that the HTTP response header might contain. Click the troubleshoot link for advice on how to deal with each type of error.</p>
-<table border=1>
- <tr>
- <th>Response</th>
- <th>Description</th>
- </tr>
- <tr>
- <td>200</td>
- <td>Message was processed successfully. The response body will contain more details about the message status, but its format will depend whether the request was JSON or plain text. See <a href="#success">Interpreting a success response</a> for more details.</td>
- </tr>
- <tr>
- <td>400</td>
- <td><span id="internal-source-marker_0.2">Only applies for JSON requests. Indicates that the request could not be parsed as JSON, or it contained invalid fields (for instance, passing a string where a number was expected). The exact failure reason is described in the response and the problem should be addressed before the request can be retried.</td>
- </tr>
- <tr>
- <td>401</td>
- <td>There was an error authenticating the sender account. <a href="#auth_error">Troubleshoot</a></td>
- </tr>
- <tr>
- <td>5xx</td>
- <td>Errors in the 500-599 range (such as 500 or 503) indicate that there was an internal error in the GCM server while trying to process the request, or that the server is temporarily unavailable (for example, because of timeouts). Sender must retry later, honoring any <code>Retry-After</code> header included in the response. Application servers must implement exponential back-off. <a href="#internal_error">Troubleshoot</a></td>
- </tr>
-</table>
-
-<h4 id="success">Interpreting a success response</h4>
-<p>When a JSON request is successful (HTTP status code 200), the response body contains a JSON object with the following fields:</p>
-<table>
- <tr>
- <th>Field</th>
- <th>Description</th>
- </tr>
- <tr>
- <td><code>multicast_id</code></td>
- <td>Unique ID (number) identifying the multicast message.</td>
- </tr>
- <tr>
- <td><code>success</code></td>
- <td>Number of messages that were processed without an error.</td>
- </tr>
- <tr>
- <td><code>failure</code></td>
- <td>Number of messages that could not be processed.</td>
- </tr>
- <tr>
- <td><code>canonical_ids</code></td>
- <td>Number of results that contain a canonical registration ID. See <a href="adv.html#canonical">Advanced Topics</a> for more discussion of this topic.</td>
- </tr>
- <tr>
- <td><code>results</code></td>
- <td>Array of objects representing the status of the messages processed. The objects are listed in the same order as the request (i.e., for each registration ID in the request, its result is listed in the same index in the response) and they can have these fields:<br>
- <ul>
- <li><code>message_id</code>: String representing the message when it was successfully processed.</li>
- <li><code>registration_id</code>: If set, means that GCM processed the message but it has another canonical registration ID for that device, so sender should replace the IDs on future requests (otherwise they might be rejected). This field is never set if there is an error in the request.
- </li>
- <li><code>error</code>: String describing an error that occurred while processing the message for that recipient. The possible values are the same as documented in the above table, plus &quot;Unavailable&quot; (meaning GCM servers were busy and could not process the message for that particular recipient, so it could be retried).</li>
- </ul></td>
- </tr>
-</table>
-<p>If the value of <code>failure</code> and <code>canonical_ids</code> is 0, it's not necessary to parse the remainder of the response. Otherwise, we recommend that you iterate through the results field and do the following for each object in that list:</p>
-<ul>
- <li>If <code>message_id</code> is set, check for <code>registration_id</code>:
- <ul>
- <li>If <code>registration_id</code> is set, replace the original ID with the new value (canonical ID) in your server database. Note that the original ID is not part of the result, so you need to obtain it from the list of <code>registration_ids</code> passed in the request (using the same index).</li>
- </ul>
- </li>
- <li>Otherwise, get the value of <code>error</code>:
- <ul>
- <li>If it is <code>Unavailable</code>, you could retry to send it in another request.</li>
- <li>If it is <code>NotRegistered</code>, you should remove the registration ID from your server database because the application was uninstalled from the device or it does not have a broadcast receiver configured to receive <code>com.google.android.c2dm.intent.RECEIVE</code> intents.</li>
- <li>Otherwise, there is something wrong in the registration ID passed in the request; it is probably a non-recoverable error that will also require removing the registration from the server database. See <a href="#error_codes">Interpreting an error response</a> for all possible error values.</li>
- </ul>
- </li>
-</ul>
-
-<p>When a plain-text request is successful (HTTP status code 200), the response body contains 1 or 2 lines in the form of key/value pairs.
-The first line is always available and its content is either <code>id=<em>ID of sent message</em></code> or <code>Error=<em>GCM error code</em></code>. The second line, if available,
-has the format of <code>registration_id=<em>canonical ID</em></code>. The second line is optional, and it can only be sent if the first line is not an error. We recommend handling the plain-text response in a similar way as handling the JSON response:</p>
-<ul>
- <li>If first line starts with <code>id</code>, check second line:
- <ul>
- <li>If second line starts with <code>registration_id</code>, gets its value and replace the registration IDs in your server database.</li>
- </ul>
- </li>
- <li>Otherwise, get the value of <code>Error</code>:
- <ul>
- <li>If it is <code>NotRegistered</code>, remove the registration ID from your server database.</li>
- <li>Otherwise, there is probably a non-recoverable error (<strong>Note: </strong>Plain-text requests will never return <code>Unavailable</code> as the error code, they would have returned a 500 HTTP status instead).</li>
- </ul>
- </li>
-</ul>
-
-<h4 id="error_codes">Interpreting an error response</h4>
-<p>Here are the recommendations for handling the different types of error that might occur when trying to send a message to a device:</p>
-
-<dl>
-<dt id="missing_reg"><strong>Missing Registration ID</strong></dt>
-<dd>Check that the request contains a registration ID (either in the <code>registration_id</code> parameter in a plain text message, or in the <code>registration_ids</code> field in JSON).
-<br/>Happens when error code is <code>MissingRegistration</code>.</dd>
-
-<dt id="invalid_reg"><strong>Invalid Registration ID</strong></dt>
-<dd>Check the formatting of the registration ID that you pass to the server. Make sure it matches the registration ID the phone receives in the <code>com.google.android.c2dm.intent.REGISTRATION</code> intent and that you're not truncating it or adding additional characters.
-<br/>Happens when error code is <code>InvalidRegistration</code>.</dd>
-
-<dt id="mismatched_sender"><strong>Mismatched Sender</strong></dt>
-<dd>A registration ID is tied to a certain group of senders. When an application registers for GCM usage, it must specify which senders are allowed to send messages. Make sure you're using one of those when trying to send messages to the device. If you switch to a different sender, the existing registration IDs won't work.
-Happens when error code is <code>MismatchSenderId</code>.</dd>
-
-<dt id="unreg_device"><strong>Unregistered Device</strong></dt>
-<dd>An existing registration ID may cease to be valid in a number of scenarios, including:
-<ul>
- <li>If the application manually unregisters by issuing a <span class="prettyprint pretty-java"><code>com.google.android.c2dm.intent.UNREGISTER</code></span><code> </code>intent.</li>
- <li>If the application is automatically unregistered, which can happen (but is not guaranteed) if the user uninstalls the application.</li>
- <li>If the registration ID expires. Google might decide to refresh registration IDs. </li>
- <li>If the application is updated but the new version does not have a broadcast receiver configured to receive <code>com.google.android.c2dm.intent.RECEIVE</code> intents.</li>
-</ul>
-For all these cases, you should remove this registration ID from the 3rd-party server and stop using it to send
-messages.
-<br/>Happens when error code is <code>NotRegistered</code>.</dd>
-
-<dt id="big_msg"><strong>Message Too Big</strong></dt>
- <dd>The total size of the payload data that is included in a message can't exceed 4096 bytes. Note that this includes both the size of the keys as well as the values.
-<br/>Happens when error code is <code>MessageTooBig</code>.</dd>
-
-<dt id="invalid_datakey"><strong>Invalid Data Key</strong></dt>
-<dd>The payload data contains a key (such as <code>from</code> or any value prefixed by <code>google.</code>) that is used internally by GCM in the <code>com.google.android.c2dm.intent.RECEIVE</code> Intent and cannot be used. Note that some words (such as <code>collapse_key</code>) are also used by GCM but are allowed in the payload, in which case the payload value will be overridden by the GCM value.
-<br />
-Happens when the error code is <code>InvalidDataKey</code>.</dd>
-
-<dt id="ttl_error"><strong>Invalid Time To Live</strong></dt>
- <dd>The value for the Time to Live field must be an integer representing a duration in seconds between 0 and 2,419,200 (4 weeks). Happens when error code is <code>InvalidTtl</code>.
-</dd>
-
- <dt id="auth_error"><strong>Authentication Error</strong></dt>
- <dd>The sender account that you're trying to use to send a message couldn't be authenticated. Possible causes are: <ul>
-<li>Authorization header missing or with invalid syntax.</li>
-<li>Invalid project number sent as key.</li>
-<li>Key valid but with GCM service disabled.</li>
-<li>Request originated from a server not whitelisted in the Server Key IPs.</li>
-
-</ul>
-Check that the token you're sending inside the <code>Authorization</code> header is the correct API key associated with your project. You can check the validity of your API key by running the following command:<br/>
-
-<pre># api_key=YOUR_API_KEY
-
-# curl --header "Authorization: key=$api_key" --header Content-Type:"application/json" https://android.googleapis.com/gcm/send -d "{\"registration_ids\":[\"ABC\"]}"</pre>
-
-
-
-If you receive a 401 HTTP status code, your API key is not valid. Otherwise you should see something like this:<br/>
-
-<pre>
-{"multicast_id":6782339717028231855,"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"InvalidRegistration"}]}
-</pre>
-If you want to confirm the validity of a registration ID, you can do so by replacing "ABC" with the registration ID.
-<br/>
-Happens when the HTTP status code is 401.
-
- <dt id="timeout"><strong>Timeout</strong></dt>
-
-<dd>The server couldn't process the request in time. You should retry the
-same request, but you MUST obey the following requirements:
-
-<ul>
-
-<li>Honor the <code>Retry-After</code> header if it's included in the response from the GCM server.</li>
-
-
-<li>Implement exponential back-off in your retry mechanism. This means an
-exponentially increasing delay after each failed retry (e.g. if you waited one
-second before the first retry, wait at least two second before the next one,
-then 4 seconds and so on). If you're sending multiple messages, delay each one
-independently by an additional random amount to avoid issuing a new request for
-all messages at the same time.</li>
-
-
-Senders that cause problems risk being blacklisted.
-<br />
-Happens when the HTTP status code is between 501 and 599, or when the <code>error</code> field of a JSON object in the results array is <code>Unavailable</code>.
-</dd>
-
-<dt id="internal_error"><strong>Internal Server Error</strong></dt>
-
-<dd>
-The server encountered an error while trying to process the request. You
-could retry the same request (obeying the requirements listed in the <a href="#timeout">Timeout</a>
-section), but if the error persists, please report the problem in the <a href="https://groups.google.com/forum/?fromgroups#!forum/android-gcm">android-gcm group</a>.
-<br />
-Happens when the HTTP status code is 500, or when the <code>error</code> field of a JSON
-object in the results array is <code>InternalServerError</code>.
-</dd>
-
-<dt id="restricted_package_name"><strong>Invalid Package Name</strong></dt>
-
-<dd>
-A message was addressed to a registration ID whose package name did not match the value passed in the request. Happens when error code is
-<code>InvalidPackageName</code>.
-</dd>
-
-
-</dl>
-<h4>Example responses</h4>
-<p>This section shows a few examples of responses indicating messages that were processed successfully. See <a href="#example-requests">Example requests</a> for the requests these responses are based on.</p>
-<p> Here is a simple case of a JSON message successfully sent to one recipient without canonical IDs in the response:</p>
-<pre class="prettyprint pretty-json">{ "multicast_id": 108,
- "success": 1,
- "failure": 0,
- "canonical_ids": 0,
- "results": [
- { "message_id": "1:08" }
- ]
-}</pre>
-
-<p>Or if the request was in plain-text format:</p>
-<pre class="prettyprint">id=1:08
-</pre>
-
-<p>Here are JSON results for 6 recipients (IDs 4, 8, 15, 16, 23, and 42 respectively) with 3 messages successfully processed, 1 canonical registration ID returned, and 3 errors:</p>
-<pre class="prettyprint pretty-json">{ "multicast_id": 216,
- "success": 3,
- "failure": 3,
- "canonical_ids": 1,
- "results": [
- { "message_id": "1:0408" },
- { "error": "Unavailable" },
- { "error": "InvalidRegistration" },
- { "message_id": "1:1516" },
- { "message_id": "1:2342", "registration_id": "32" },
- { "error": "NotRegistered"}
- ]
-}
-</pre>
-<p> In this example:</p>
-<ul>
- <li>First message: success, not required.</li>
- <li>Second message: should be resent (to registration ID 8).</li>
- <li>Third message: had an unrecoverable error (maybe the value got corrupted in the database).</li>
- <li>Fourth message: success, nothing required.</li>
- <li>Fifth message: success, but the registration ID should be updated in the server database (from 23 to 32).</li>
- <li>Sixth message: registration ID (42) should be removed from the server database because the application was uninstalled from the device.</li>
-</ul>
-<p>Or if just the 4th message above was sent using plain-text format:</p>
-<pre class="prettyprint">Error=InvalidRegistration
-</pre>
-<p>If the 5th message above was also sent using plain-text format:</p>
-<pre class="prettyprint">id=1:2342
-registration_id=32
-</pre>
-
-<h3 id="stats">Viewing Statistics</h3>
-
-<p>To view statistics and any error messages for your GCM applications:</p>
-<ol>
- <li> Go to the <code><a href="http://play.google.com/apps/publish">Developer Console</a></code>.</li>
- <li>Login with your developer account.
- <p>You will see a page that has a list of all of your apps.</p></li>
- <li> Click on the &quot;statistics&quot; link next to the app for which you want to view GCM stats.
- <p>Now you are on the statistics page.</p> </li>
- <li>Go to the drop-down menu and select the GCM metric you want to view.
- </li>
+from the <code>com.google.android.c2dm.intent.RECEIVE</code><code> </code>Intent
+by key and processes the data.</li>
</ol>
-<p class="note"><strong>Note:</strong> Stats on the Google API Console are not enabled for GCM. You must use the <a href="http://play.google.com/apps/publish">Developer Console</a>.</p>
diff --git a/docs/html/google/gcm/gs.jd b/docs/html/google/gcm/gs.jd
index 8ceea0cc8b0d..f6b7ebe8244b 100644
--- a/docs/html/google/gcm/gs.jd
+++ b/docs/html/google/gcm/gs.jd
@@ -1,4 +1,4 @@
-page.title=Getting Started with GCM
+page.title=Getting Started
page.tags="cloud","push","messaging"
@jd:body
@@ -12,8 +12,7 @@ page.tags="cloud","push","messaging"
<li><a href="#create-proj">Creating a Google API Project</a></li>
<li><a href="#gcm-service">Enabling the GCM Service</a></li>
<li><a href="#access-key">Obtaining an API Key</a></li>
-<li><a href="#client">Writing a Client App</a></li>
-<li><a href="#server">Writing the Server Code</a></li>
+<li><a href="#next">Next Steps</a></li>
</ol>
<h2>See Also</h2>
@@ -26,12 +25,12 @@ page.tags="cloud","push","messaging"
</div>
</div>
-<p>The sections below guide you through the process of setting up a GCM
+<p>This document tells you how to get started setting up a GCM
implementation.
-Before you start, make sure to <a href="/google/play-services/setup.html">set up
-the Google Play Services SDK</a>. You need this SDK to use the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> methods.</p>
-
-<p>Note that a full GCM implementation requires a server-side implementation, in addition to the client implementation in your app. This document offers a complete example that includes both the client and server.</p>
+Before you begin, make sure to <a href="/google/play-services/setup.html">set up
+the Google Play Services SDK</a>. You need this SDK to use the
+<a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">
+{@code GoogleCloudMessaging}</a> methods.</p>
<h2 id="create-proj">Creating a Google API project</h2>
@@ -41,13 +40,17 @@ the Google Play Services SDK</a>. You need this SDK to use the <a href="{@docRoo
</li>
<li>If you haven't created an API project yet, this page will prompt you to do so:
<p><img src="{@docRoot}images/gcm/gcm-create-api-proj.png" class="screenshot" /></p>
-<p class="note"><strong>Note:</strong> If you already have existing projects, the first page you see will be the <strong>Dashboard</strong> page. From there you can create a new project by opening the project drop-down menu (upper left corner) and choosing <strong>Other projects > Create</strong>.</p></li>
+<p class="note"><strong>Note:</strong> If you already have existing projects,
+the first page you see will be the <strong>Dashboard</strong> page. From there
+you can create a new project by opening the project drop-down menu (upper left corner)
+and choosing <strong>Other projects > Create</strong>.</p></li>
<li> Click <strong>Create project</strong>.
Your browser URL will change to something like:</li>
<pre> https://code.google.com/apis/console/#project:<strong>4815162342</strong></pre>
- <li> Take note of the value after <code>#project:</code> (4815162342 in this example). This is your project number, and it will be used later on as the GCM sender ID.</li>
+ <li> Take note of the value after <code>#project:</code> (4815162342 in this
+example). This is your project number, and it will be used later on as the GCM sender ID.</li>
</ol>
<h2 id="gcm-service">Enabling the GCM Service</h2>
@@ -61,463 +64,53 @@ the Google Play Services SDK</a>. You need this SDK to use the <a href="{@docRoo
<h2 id="access-key">Obtaining an API Key</h2>
<p>To obtain an API key:</p>
<ol>
- <li> In the main Google APIs Console page, select <strong>API Access</strong>. You will see a screen that resembles the following:</li><br />
-
+ <li> In the main Google APIs Console page, select <strong>API Access</strong>.
+You will see a screen that resembles the following:</li>
-<img src="{@docRoot}images/gcm/gcm-api-access.png" style="width:400px;padding:4px;margin-bottom:0em;">
+<img src="{@docRoot}images/gcm/gcm-api-access.png" style="width:400px;padding:4px;">
- <li>Click <strong>Create new Server key</strong>. Either a server key or a browser key should work. The advantage to using a server key is that it allows you to whitelist IP addresses. The following screen appears:</li><br />
+ <li>Click <strong>Create new Server key</strong>. Either a server key or a
+browser key should work. The advantage to using a server key is that it allows
+you to whitelist IP addresses. The following screen appears:</li>
-<img src="{@docRoot}images/gcm/gcm-config-server-key.png" style="width:400px;padding:4px;margin-bottom:0em;">
+<img src="{@docRoot}images/gcm/gcm-config-server-key.png" style="width:400px;padding:4px;">
- <li>Click <strong>Create</strong>:</li><br />
+ <li>Click <strong>Create</strong>:</li>
-<img src="{@docRoot}images/gcm/gcm-api-key.png" style="width:400px;padding:4px;margin-bottom:0em;">
+<img src="{@docRoot}images/gcm/gcm-api-key.png" style="width:400px;padding:4px;">
</ol>
-<p> Take note of the <strong>API key</strong> value (<code>YourKeyWillBeShownHere</code>) in this example, as it will be used later on.</p>
-<p class="note"><strong>Note:</strong> If you need to rotate the key, click <strong>Generate new key</strong>. A new key will be created while the old one will still be active for up to 24 hours. If you want to get rid of the old key immediately (for example, if you feel it was compromised), click <strong>Delete key</strong>.</p>
-
-<p>The following sections walk you through the steps of creating client and server-side code.</p>
-
-<h2 id="client">Writing a Client App</h2>
-
-<p>This section walks you through the steps involved in writing a client-side application&mdash;that is, the GCM-enabled application that runs on an Android device. This client sample is designed to work in conjunction with the server code shown in <a href="#server">Writing the Server Code</a>, below.</p>
-
-
-
-<h3 id="manifest">Step 1: Edit Your App's Manifest</h3>
-<ul>
- <li>The <code>com.google.android.c2dm.permission.RECEIVE</code> permission so the Android application can register and receive messages.</li>
- <li>The <code>android.permission.INTERNET</code> permission so the Android application can send the registration ID to the 3rd party server.</li>
- <li>The <code>android.permission.GET_ACCOUNTS</code> permission as GCM requires a Google account (necessary only if if the device is running a version lower than Android 4.0.4)</li>
- <li>The <code>android.permission.WAKE_LOCK</code> permission so the application can keep the processor from sleeping when a message is received. Optional&mdash;use only if the app wants to keep the device from sleeping.</li>
- <li>An <code>applicationPackage + &quot;.permission.C2D_MESSAGE&quot;</code> permission to prevent other Android applications from registering and receiving the Android application's
-messages. The permission name must exactly match this pattern&mdash;otherwise the Android application will not receive the messages.</li>
- <li>A receiver for <code>com.google.android.c2dm.intent.RECEIVE</code>, with the category set
-as <code>applicationPackage</code>. The receiver should require the <code>com.google.android.c2dm.SEND</code> permission, so that only the GCM
-Framework can send a message to it. Note that the receiving
-of messages is implemented as an <a href="{@docRoot}guide/components/intents-filters.html">intent</a>.</li>
- <li>An intent service to handle the intents received by the broadcast receiver. Optional.</li>
- <li>If the GCM feature is critical to the Android application's function, be sure to
-set <code>android:minSdkVersion=&quot;8&quot;</code> in the manifest. This
-ensures that the Android application cannot be installed in an environment in which it
-could not run properly. </li>
-</ul>
-
-<p>Here are excerpts from a manifest that supports GCM:</p>
-
-<pre class="prettyprint pretty-xml">
-&lt;manifest package="com.example.gcm" ...&gt;
-
- &lt;uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17"/&gt;
- &lt;uses-permission android:name="android.permission.INTERNET" /&gt;
- &lt;uses-permission android:name="android.permission.GET_ACCOUNTS" /&gt;
- &lt;uses-permission android:name="android.permission.WAKE_LOCK" /&gt;
- &lt;uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" /&gt;
-
- &lt;permission android:name="com.example.gcm.permission.C2D_MESSAGE"
- android:protectionLevel="signature" /&gt;
- &lt;uses-permission android:name="com.example.gcm.permission.C2D_MESSAGE" /&gt;
-
- &lt;application ...&gt;
- &lt;receiver
- android:name=".MyBroadcastReceiver"
- android:permission="com.google.android.c2dm.permission.SEND" &gt;
- &lt;intent-filter&gt;
- &lt;action android:name="com.google.android.c2dm.intent.RECEIVE" /&gt;
- &lt;category android:name="com.example.gcm" /&gt;
- &lt;/intent-filter&gt;
- &lt;/receiver&gt;
- &lt;service android:name=".MyIntentService" /&gt;
- &lt;/application&gt;
-
-&lt;/manifest&gt;
-</pre>
-
-
-<h3 id="register">Step 2: Register for GCM</h3>
-
-<p>An Android application running on a mobile device registers to receive messages by calling
-the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> method
-<a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html#register">{@code register(senderID...)}</a>.
-This method registers the application for GCM and returns the registration ID. This streamlined approach replaces the previous
-GCM registration process. See the example below for details.</p>
-
-<h3 id="app"> Step 3: Write Your Application</h3>
-
-<p>Finally, write your application. GCM offers a variety of ways to get the job done:</p>
-
-<ul>
- <li>For your messaging server, you can either use the new <a href="ccs.html">GCM Cloud Connection Server</a> (CCS), the older <a href="gcm.html">GCM HTTP server</a>, or both in tandem. For more discussion, see see <a href="server.html">GCM Server</a>.</li>
- <li>To write your client application (that is, the GCM-enabled app that runs on an Android device), use the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> APIs as shown below. Don't forget to set up your project to use the Google Play services SDK as described in <a href="/google/play-services/setup.html">Setup Google Play Services SDK</a>.</li>
-</ul>
-</li>
-
-</ul>
-
-<h4 id="example">Example</h4>
-
-<p>Here is a sample client application that illustrates how to use the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> APIs. The sample consists of a main activity ({@code DemoActivity}) and a broadcast receiver ({@code GcmBroadcastReceiver}). You can use this client sample code in conjunction with the server code shown in <a href="#server">Writing the Server Code</a>.</p>
-
-<p>Note the following:</p>
-
-<ul>
- <li>The sample primarily illustrates two things: registration, and upstream messaging. Upstream messaging only applies to apps that are running against a <a href="ccs.html">CCS</a> server; HTTP-based servers don't support upstream messaging.</li>
- <li>The <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> registration APIs replace the old registration process, which was based on the now-obsolete client helper library. While the old registration process still works, we encourage you to use the newer <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> registration APIs, regardless of your underlying server.</li>
-</ul>
-
-<h5>Registering</h5>
-<p>An Android application needs to register with GCM servers before it can receive messages. So in its {@code onCreate()} method, {@code DemoActivity} checks to see whether the app is registered with GCM and with the server:</p>
-
-<pre>/**
- * Main UI for the demo app.
- */
-public class DemoActivity extends Activity {
-
- public static final String EXTRA_MESSAGE = "message";
- public static final String PROPERTY_REG_ID = "registration_id";
- private static final String PROPERTY_APP_VERSION = "appVersion";
- private static final String PROPERTY_ON_SERVER_EXPIRATION_TIME =
- "onServerExpirationTimeMs";
- /**
- * Default lifespan (7 days) of a reservation until it is considered expired.
- */
- public static final long REGISTRATION_EXPIRY_TIME_MS = 1000 * 3600 * 24 * 7;
-
- /**
- * Substitute you own sender ID here.
- */
- String SENDER_ID = "Your-Sender-ID";
-
- /**
- * Tag used on log messages.
- */
- static final String TAG = "GCMDemo";
-
- TextView mDisplay;
- GoogleCloudMessaging gcm;
- AtomicInteger msgId = new AtomicInteger();
- SharedPreferences prefs;
- Context context;
-
- String regid;
-
- &#64;Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setContentView(R.layout.main);
- mDisplay = (TextView) findViewById(R.id.display);
-
- context = getApplicationContext();
- regid = getRegistrationId(context);
-
- if (regid.length() == 0) {
- registerBackground();
- }
- gcm = GoogleCloudMessaging.getInstance(this);
- }
-...
-}</pre>
-
-<p>The app calls {@code getRegistrationId()} to see whether there is an existing registration ID stored in shared preferences:</p>
-
-<pre>/**
- * Gets the current registration id for application on GCM service.
- * &lt;p&gt;
- * If result is empty, the registration has failed.
- *
- * &#64;return registration id, or empty string if the registration is not
- * complete.
- */
-private String getRegistrationId(Context context) {
- final SharedPreferences prefs = getGCMPreferences(context);
- String registrationId = prefs.getString(PROPERTY_REG_ID, "");
- if (registrationId.length() == 0) {
- Log.v(TAG, "Registration not found.");
- return "";
- }
- // check if app was updated; if so, it must clear registration id to
- // avoid a race condition if GCM sends a message
- int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);
- int currentVersion = getAppVersion(context);
- if (registeredVersion != currentVersion || isRegistrationExpired()) {
- Log.v(TAG, "App version changed or registration expired.");
- return "";
- }
- return registrationId;
-}
+<p> Take note of the <strong>API key</strong> value (<code>YourKeyWillBeShownHere</code>)
+in this example, as it will be used later on.</p>
+<p class="note"><strong>Note:</strong> If you need to rotate the key, click
+<strong>Generate new key</strong>. A new key will be created while the old one
+will still be active for up to 24 hours. If you want to get rid of the old key
+immediately (for example, if you feel it was compromised), click <strong>Delete key</strong>.</p>
-...
+<h2 id="next">Next Steps</h2>
-/**
- * &#64;return Application's {&#64;code SharedPreferences}.
- */
-private SharedPreferences getGCMPreferences(Context context) {
- return getSharedPreferences(DemoActivity.class.getSimpleName(),
- Context.MODE_PRIVATE);
-}</pre>
-
-<p>If the registration ID doesn't exist, or the app was updated, or the registration ID has expired, {@code getRegistrationId()} returns an empty string to indicate that the app needs to get a new regID. {@code getRegistrationId()} calls the following methods to check the app version and whether the regID has expired:</p>
-
-<pre>/**
- * &#64;return Application's version code from the {&#64;code PackageManager}.
- */
-private static int getAppVersion(Context context) {
- try {
- PackageInfo packageInfo = context.getPackageManager()
- .getPackageInfo(context.getPackageName(), 0);
- return packageInfo.versionCode;
- } catch (NameNotFoundException e) {
- // should never happen
- throw new RuntimeException("Could not get package name: " + e);
- }
-}
-
-/**
- * Checks if the registration has expired.
- *
- * &lt;p&gt;To avoid the scenario where the device sends the registration to the
- * server but the server loses it, the app developer may choose to re-register
- * after REGISTRATION_EXPIRY_TIME_MS.
- *
- * &#64;return true if the registration has expired.
- */
-private boolean isRegistrationExpired() {
- final SharedPreferences prefs = getGCMPreferences(context);
- // checks if the information is not stale
- long expirationTime =
- prefs.getLong(PROPERTY_ON_SERVER_EXPIRATION_TIME, -1);
- return System.currentTimeMillis() > expirationTime;
-}</pre>
-
-
-<p>If there isn't a valid existing registration ID, {@code DemoActivity} calls the following {@code registerBackground()} method to register. Note that because GCM methods are blocking, this has to take place on a background thread. This sample uses {@link android.os.AsyncTask} to accomplish this:</p>
-
-<pre>
-/**
- * Registers the application with GCM servers asynchronously.
- * &lt;p&gt;
- * Stores the registration id, app versionCode, and expiration time in the
- * application's shared preferences.
- */
-private void registerBackground() {
- new AsyncTask<Void, Void, String>() {
- &#64;Override
- protected String doInBackground(Void... params) {
- String msg = "";
- try {
- if (gcm == null) {
- gcm = GoogleCloudMessaging.getInstance(context);
- }
- regid = gcm.register(SENDER_ID);
- msg = "Device registered, registration id=" + regid;
-
- // You should send the registration ID to your server over HTTP,
- // so it can use GCM/HTTP or CCS to send messages to your app.
-
- // For this demo: we don't need to send it because the device
- // will send upstream messages to a server that echo back the message
- // using the 'from' address in the message.
-
- // Save the regid - no need to register again.
- setRegistrationId(context, regid);
- } catch (IOException ex) {
- msg = "Error :" + ex.getMessage();
- }
- return msg;
- }
-
- &#64;Override
- protected void onPostExecute(String msg) {
- mDisplay.append(msg + "\n");
- }
- }.execute(null, null, null);
-}</pre>
-
-<p>After registering, the app calls {@code setRegistrationId()} to store the registration ID in shared preferences for future use:</p>
-
-<pre>/**
- * Stores the registration id, app versionCode, and expiration time in the
- * application's {&#64;code SharedPreferences}.
- *
- * &#64;param context application's context.
- * &#64;param regId registration id
- */
-private void setRegistrationId(Context context, String regId) {
- final SharedPreferences prefs = getGCMPreferences(context);
- int appVersion = getAppVersion(context);
- Log.v(TAG, "Saving regId on app version " + appVersion);
- SharedPreferences.Editor editor = prefs.edit();
- editor.putString(PROPERTY_REG_ID, regId);
- editor.putInt(PROPERTY_APP_VERSION, appVersion);
- long expirationTime = System.currentTimeMillis() + REGISTRATION_EXPIRY_TIME_MS;
-
- Log.v(TAG, "Setting registration expiry time to " +
- new Timestamp(expirationTime));
- editor.putLong(PROPERTY_ON_SERVER_EXPIRATION_TIME, expirationTime);
- editor.commit();
-}</pre>
-
-<h5>Sending a message</h5>
-<p>When the user clicks the app's <strong>Send</strong> button, the app sends an upstream message using the new <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> APIs. In order to receive the upstream message, your server should be connected to CCS. You can use the code shown in <a href="#server">Writing the Server Code</a> as a sample XMPP client to connect to CCS.</p>
-
-<pre>public void onClick(final View view) {
- if (view == findViewById(R.id.send)) {
- new AsyncTask<Void, Void, String>() {
- &#64;Override
- protected String doInBackground(Void... params) {
- String msg = "";
- try {
- Bundle data = new Bundle();
- data.putString("hello", "World");
- String id = Integer.toString(msgId.incrementAndGet());
- gcm.send(SENDER_ID + "&#64;gcm.googleapis.com", id, data);
- msg = "Sent message";
- } catch (IOException ex) {
- msg = "Error :" + ex.getMessage();
- }
- return msg;
- }
-
- &#64;Override
- protected void onPostExecute(String msg) {
- mDisplay.append(msg + "\n");
- }
- }.execute(null, null, null);
- } else if (view == findViewById(R.id.clear)) {
- mDisplay.setText("");
- }
-}</pre>
-
-<p>As described above in <a href="#manifest">Step 1</a>, the app includes a broadcast receiver for the <code>com.google.android.c2dm.intent.RECEIVE</code> intent. This is the mechanism GCM uses to deliver messages. When {@code onClick()} calls {@code gcm.send()}, it triggers the broadcast receiver's {@code onReceive()} method, which has the responsibility of handling the GCM message. In this sample the receiver's {@code onReceive()} method calls {@code sendNotification()} to put the message into a notification:</p>
-
-<pre>/**
- * Handling of GCM messages.
- */
-public class GcmBroadcastReceiver extends BroadcastReceiver {
- static final String TAG = "GCMDemo";
- public static final int NOTIFICATION_ID = 1;
- private NotificationManager mNotificationManager;
- NotificationCompat.Builder builder;
- Context ctx;
- &#64;Override
- public void onReceive(Context context, Intent intent) {
- GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context);
- ctx = context;
- String messageType = gcm.getMessageType(intent);
- if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
- sendNotification("Send error: " + intent.getExtras().toString());
- } else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) {
- sendNotification("Deleted messages on server: " +
- intent.getExtras().toString());
- } else {
- sendNotification("Received: " + intent.getExtras().toString());
- }
- setResultCode(Activity.RESULT_OK);
- }
-
- // Put the GCM message into a notification and post it.
- private void sendNotification(String msg) {
- mNotificationManager = (NotificationManager)
- ctx.getSystemService(Context.NOTIFICATION_SERVICE);
-
- PendingIntent contentIntent = PendingIntent.getActivity(ctx, 0,
- new Intent(ctx, DemoActivity.class), 0);
-
- NotificationCompat.Builder mBuilder =
- new NotificationCompat.Builder(ctx)
- .setSmallIcon(R.drawable.ic_stat_gcm)
- .setContentTitle("GCM Notification")
- .setStyle(new NotificationCompat.BigTextStyle()
- .bigText(msg))
- .setContentText(msg);
-
- mBuilder.setContentIntent(contentIntent);
- mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
- }
-}</pre>
-
-<h2 id="server">Writing the Server Code</h2>
-
-<p>Here is an example of a CCS server written in Python. You can use this in conjunction with the sample client code shown above. This sample echo server sends an initial message, and for every upstream message received, it sends a dummy response back to the application that sent the upstream message. This example illustrates how to connect,
-send, and receive GCM messages using XMPP. It shouldn't be used as-is
-on a production deployment. For examples of HTTP-based servers, see <a href="server.html">GCM Server</a>.</p>
-
-<pre>
-#!/usr/bin/python
-import sys, json, xmpp, random, string
-
-SERVER = 'gcm.googleapis.com'
-PORT = 5235
-USERNAME = ''
-PASSWORD = ''
-REGISTRATION_ID = ''
-
-unacked_messages_quota = 1000
-send_queue = []
-
-# Return a random alphanumerical id
-def random_id():
- rid = ''
- for x in range(8): rid += random.choice(string.ascii_letters + string.digits)
- return rid
-
-def message_callback(session, message):
- global unacked_messages_quota
- gcm = message.getTags('gcm')
- if gcm:
- gcm_json = gcm[0].getData()
- msg = json.loads(gcm_json)
- if not msg.has_key('message_type'):
- # Acknowledge the incoming message immediately.
- send({'to': msg['from'],
- 'message_type': 'ack',
- 'message_id': msg['message_id']})
- # Queue a response back to the server.
- if msg.has_key('from'):
- # Send a dummy echo response back to the app that sent the upstream message.
- send_queue.append({'to': msg['from'],
- 'message_id': random_id(),
- 'data': {'pong': 1}})
- elif msg['message_type'] == 'ack' or msg['message_type'] == 'nack':
- unacked_messages_quota += 1
-
-def send(json_dict):
- template = (&quot;&lt;message&gt;&lt;gcm xmlns='google:mobile:data'&gt;{1}&lt;/gcm&gt;&lt;/message&gt;&quot;)
- client.send(xmpp.protocol.Message(
- node=template.format(client.Bind.bound[0], json.dumps(json_dict))))
-
-def flush_queued_messages():
- global unacked_messages_quota
- while len(send_queue) and unacked_messages_quota &gt; 0:
- send(send_queue.pop(0))
- unacked_messages_quota -= 1
-
-client = xmpp.Client('gcm.googleapis.com', debug=['socket'])
-client.connect(server=(SERVER,PORT), secure=1, use_srv=False)
-auth = client.auth(USERNAME, PASSWORD)
-if not auth:
- print 'Authentication failed!'
- sys.exit(1)
-
-client.RegisterHandler('message', message_callback)
-
-send_queue.append({'to': REGISTRATION_ID,
- 'message_id': 'reg_id',
- 'data': {'message_destination': 'RegId',
- 'message_id': random_id()}})
-
-while True:
- client.Process(1)
- flush_queued_messages()</pre>
+<p>Once you've finished the tasks listed above, you're ready to start
+implementing GCM. Here is an overview of the basic steps:</p>
+<ol>
+ <li>Decide which Google-provided GCM connection server you want to use&mdash;
+ <a href="http.html">HTTP</a> or <a href="ccs.html">XMPP</a> (CCS). GCM connection servers
+take messages from a 3rd-party application
+server (written by you) and send them to a GCM-enabled Android application (the
+"client app," also written by you) running on a device. </li>
+ <li>Implement an application server (the "3rd-party application server") to interact
+with your chosen GCM connection server. The app server sends data to a
+GCM-enabled Android client application via the GCM connection server. For more
+information about implementing the server side, see <a href="server.html">
+Implementing GCM Server</a>.</li>
+<li>Write your client app. This is the GCM-enabled Android application that runs
+on a device. See <a href="client.html">Implementing GCM Client</a> for more information.</li>
+</ol>
diff --git a/docs/html/google/gcm/http.jd b/docs/html/google/gcm/http.jd
new file mode 100644
index 000000000000..b8d8659d941e
--- /dev/null
+++ b/docs/html/google/gcm/http.jd
@@ -0,0 +1,618 @@
+page.title=GCM HTTP Connection Server
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+
+<h2>In this document</h2>
+
+<ol class="toc">
+ <li><a href="#auth">Authentication</a> </li>
+ <li><a href="#request">Request Format</a> </li>
+ <li><a href="#response">Response Format</a>
+ <ol class="toc">
+ <li><a href="#success">Interpreting a success response</a>
+ <li><a href="#error_codes">Interpreting an error response</a>
+ <li><a href="#example-responses">Example responses</a>
+ </ol>
+ </li>
+ <li><a href="#app-server">Implementing an HTTP-Based App Server</a>
+</ol>
+
+<h2>See Also</h2>
+
+<ol class="toc">
+<li><a href="gs.html">Getting Started</a></li>
+<li><a href="client.html">Implementing GCM Client</a></li>
+<li><a href="ccs.html">Cloud Connection Server</a></li>
+
+
+</ol>
+
+</div>
+</div>
+
+<p>This document describes the GCM HTTP connection server. Connection servers
+are the Google-provided servers that take messages from the 3rd-party
+application server and sending them to the device.</p>
+
+
+
+<p class="note"><strong>Note:</strong> See
+<a href="server.html#params">Implementing GCM Server</a> for a list of all the message
+parameters and which connection server(s) supports them.</p>
+
+
+<h2 id="auth">Authentication</h2>
+
+<p>To send a message, the application server issues a POST request to
+<code>https://android.googleapis.com/gcm/send</code>.</p>
+<p>A message request is made of 2 parts: HTTP header and HTTP body.</p>
+
+<p>The HTTP header must contain the following headers:</p>
+<ul>
+ <li><code>Authorization</code>: key=YOUR_API_KEY</li>
+ <li><code>Content-Type</code>: <code>application/json</code> for JSON; <code>application/x-www-form-urlencoded;charset=UTF-8</code> for plain text.
+ </li>
+</ul>
+
+<p>For example:
+</p>
+<pre>Content-Type:application/json
+Authorization:key=AIzaSyB-1uEai2WiUapxCs2Q0GZYzPu7Udno5aA
+
+{
+ "registration_ids" : ["APA91bHun4MxP5egoKMwt2KZFBaFUH-1RYqx..."],
+ "data" : {
+ ...
+ },
+}</pre>
+<p class="note">
+ <p><strong>Note:</strong> If <code>Content-Type</code> is omitted, the format
+is assumed to be plain text.</p>
+</p>
+
+<p>The HTTP body content depends on whether you're using JSON or plain text.
+See
+<a href="server.html#params">Implementing GCM Server</a> for a list of all the
+parameters your JSON or plain text message can contain.</p>
+
+
+ <h2 id="request">Request Format</h2>
+ <p>Here is the smallest possible request (a message without any parameters and
+just one recipient) using JSON:</p>
+ <pre class="prettyprint pretty-json">{ &quot;registration_ids&quot;: [ &quot;42&quot; ] }</pre>
+
+ <p>And here the same example using plain text:</p>
+ <pre class="prettyprint">registration_id=42</pre>
+
+ <p> Here is a message with a payload and 6 recipients:</p>
+ <pre class="prettyprint pretty-HTML">{ "data": {
+ "score": "5x1",
+ "time": "15:10"
+ },
+ "registration_ids": ["4", "8", "15", "16", "23", "42"]
+}</pre>
+ <p>Here is a message with all optional fields set and 6 recipients:</p>
+ <pre class="prettyprint pretty-json">{ "collapse_key": "score_update",
+ "time_to_live": 108,
+ "delay_while_idle": true,
+ "data": {
+ "score": "4x8",
+ "time": "15:16.2342"
+ },
+ "registration_ids":["4", "8", "15", "16", "23", "42"]
+}</pre>
+ <p>And here is the same message using plain-text format (but just 1 recipient): </p>
+
+ <pre class="prettyprint">collapse_key=score_update&amp;time_to_live=108&amp;delay_while_idle=1&amp;data.score=4x8&amp;data.time=15:16.2342&amp;registration_id=42
+ </pre>
+
+<p class="note"><strong>Note:</strong> If your organization has a firewall
+that restricts the traffic to or
+from the Internet, you need to configure it to allow connectivity with GCM in order for
+your Android devices to receive messages.
+The ports to open are: 5228, 5229, and 5230. GCM typically only uses 5228, but
+it sometimes uses 5229 and 5230. GCM doesn't provide specific IPs, so you should allow
+your firewall to accept outgoing connections to all IP addresses
+contained in the IP blocks listed in Google's ASN of 15169.</p>
+
+
+
+<h2 id="response">Response format</h2>
+
+<p>There are two possible outcomes when trying to send a message:</p>
+<ul>
+ <li>The message is processed successfully.</li>
+ <li>The GCM server rejects the request.</li>
+</ul>
+
+<p>When the message is processed successfully, the HTTP response has a 200 status
+and the body contains more information about the status of the message
+(including possible errors). When the request is rejected,
+the HTTP response contains a non-200 status code (such as 400, 401, or 503).</p>
+
+<p>The following table summarizes the statuses that the HTTP response header might
+contain. Click the troubleshoot link for advice on how to deal with each type of
+error.</p>
+<table border=1>
+ <tr>
+ <th>Response</th>
+ <th>Description</th>
+ </tr>
+ <tr>
+ <td>200</td>
+ <td>Message was processed successfully. The response body will contain more
+details about the message status, but its format will depend whether the request
+was JSON or plain text. See <a href="#success">Interpreting a success response</a>
+for more details.</td>
+ </tr>
+ <tr>
+ <td>400</td>
+ <td><span id="internal-source-marker_0.2">Only applies for JSON requests.
+Indicates that the request could not be parsed as JSON, or it contained invalid
+fields (for instance, passing a string where a number was expected). The exact
+failure reason is described in the response and the problem should be addressed
+before the request can be retried.</td>
+ </tr>
+ <tr>
+ <td>401</td>
+ <td>There was an error authenticating the sender account.
+<a href="#auth_error">Troubleshoot</a></td>
+ </tr>
+ <tr>
+ <td>5xx</td>
+ <td>Errors in the 500-599 range (such as 500 or 503) indicate that there wa
+an internal error in the GCM server while trying to process the request, or that
+the server is temporarily unavailable (for example, because of timeouts). Sender
+must retry later, honoring any <code>Retry-After</code> header included in the
+response. Application servers must implement exponential back-off.
+<a href="#internal_error">Troubleshoot</a></td>
+ </tr>
+</table>
+
+<h3 id="success">Interpreting a success response</h3>
+<p>When a JSON request is successful (HTTP status code 200), the response body
+contains a JSON object with the following fields:</p>
+<table>
+ <tr>
+ <th>Field</th>
+ <th>Description</th>
+ </tr>
+ <tr>
+ <td><code>multicast_id</code></td>
+ <td>Unique ID (number) identifying the multicast message.</td>
+ </tr>
+ <tr>
+ <td><code>success</code></td>
+ <td>Number of messages that were processed without an error.</td>
+ </tr>
+ <tr>
+ <td><code>failure</code></td>
+ <td>Number of messages that could not be processed.</td>
+ </tr>
+ <tr>
+ <td><code>canonical_ids</code></td>
+ <td>Number of results that contain a canonical registration ID. See
+<a href="adv.html#canonical">Advanced Topics</a> for more discussion of this topic.</td>
+ </tr>
+ <tr>
+ <td><code>results</code></td>
+ <td>Array of objects representing the status of the messages processed. The
+objects are listed in the same order as the request (i.e., for each registration
+ID in the request, its result is listed in the same index in the response) and
+they can have these fields:<br>
+ <ul>
+ <li><code>message_id</code>: String representing the message when it was
+successfully processed.</li>
+ <li><code>registration_id</code>: If set, means that GCM processed the
+message but it has another canonical registration ID for that device, so sender
+should replace the IDs on future requests (otherwise they might be rejected).
+This field is never set if there is an error in the request.
+ </li>
+ <li><code>error</code>: String describing an error that occurred while
+processing the message for that recipient. The possible values are the same as
+documented in the above table, plus &quot;Unavailable&quot; (meaning GCM servers
+were busy and could not process the message for that particular recipient, so
+it could be retried).</li>
+ </ul></td>
+ </tr>
+</table>
+<p>If the value of <code>failure</code> and <code>canonical_ids</code> is 0, it's
+not necessary to parse the remainder of the response. Otherwise, we recommend
+that you iterate through the results field and do the following for each object
+in that list:</p>
+<ul>
+ <li>If <code>message_id</code> is set, check for <code>registration_id</code>:
+ <ul>
+ <li>If <code>registration_id</code> is set, replace the original ID with
+the new value (canonical ID) in your server database. Note that the original ID
+is not part of the result, so you need to obtain it from the list of
+code>registration_ids</code> passed in the request (using the same index).</li>
+ </ul>
+ </li>
+ <li>Otherwise, get the value of <code>error</code>:
+ <ul>
+ <li>If it is <code>Unavailable</code>, you could retry to send it in another
+request.</li>
+ <li>If it is <code>NotRegistered</code>, you should remove the registration
+ID from your server database because the application was uninstalled from the
+device or it does not have a broadcast receiver configured to receive
+<code>com.google.android.c2dm.intent.RECEIVE</code> intents.</li>
+ <li>Otherwise, there is something wrong in the registration ID passed in
+the request; it is probably a non-recoverable error that will also require removing
+the registration from the server database. See <a href="#error_codes">Interpreting
+an error response</a> for all possible error values.</li>
+ </ul>
+ </li>
+</ul>
+
+<p>When a plain-text request is successful (HTTP status code 200), the response
+body contains 1 or 2 lines in the form of key/value pairs.
+The first line is always available and its content is either <code>id=<em>ID of
+sent message</em></code> or <code>Error=<em>GCM error code</em></code>. The second
+line, if available,
+has the format of <code>registration_id=<em>canonical ID</em></code>. The second
+line is optional, and it can only be sent if the first line is not an error. We
+recommend handling the plain-text response in a similar way as handling the
+JSON response:</p>
+<ul>
+ <li>If first line starts with <code>id</code>, check second line:
+ <ul>
+ <li>If second line starts with <code>registration_id</code>, gets its value
+and replace the registration IDs in your server database.</li>
+ </ul>
+ </li>
+ <li>Otherwise, get the value of <code>Error</code>:
+ <ul>
+ <li>If it is <code>NotRegistered</code>, remove the registration ID from
+your server database.</li>
+ <li>Otherwise, there is probably a non-recoverable error (<strong>Note:
+</strong>Plain-text requests will never return <code>Unavailable</code> as the
+error code, they would have returned a 500 HTTP status instead).</li>
+ </ul>
+ </li>
+</ul>
+
+<h3 id="error_codes">Interpreting an error response</h3>
+<p>Here are the recommendations for handling the different types of error that
+might occur when trying to send a message to a device:</p>
+
+<dl>
+<dt id="missing_reg"><strong>Missing Registration ID</strong></dt>
+<dd>Check that the request contains a registration ID (either in the
+<code>registration_id</code> parameter in a plain text message, or in the
+<code>registration_ids</code> field in JSON).
+<br/>Happens when error code is <code>MissingRegistration</code>.</dd>
+
+<dt id="invalid_reg"><strong>Invalid Registration ID</strong></dt>
+<dd>Check the formatting of the registration ID that you pass to the server. Make
+sure it matches the registration ID the phone receives in the
+<code>com.google.android.c2dm.intent.REGISTRATION</code> intent and that you're
+not truncating it or adding additional characters.
+<br/>Happens when error code is <code>InvalidRegistration</code>.</dd>
+
+<dt id="mismatched_sender"><strong>Mismatched Sender</strong></dt>
+<dd>A registration ID is tied to a certain group of senders. When an application
+registers for GCM usage, it must specify which senders are allowed to send messages.
+Make sure you're using one of those when trying to send messages to the device.
+If you switch to a different sender, the existing registration IDs won't work.
+Happens when error code is <code>MismatchSenderId</code>.</dd>
+
+<dt id="unreg_device"><strong>Unregistered Device</strong></dt>
+<dd>An existing registration ID may cease to be valid in a number of scenarios, including:
+<ul>
+ <li>If the application manually unregisters by issuing a
+<span class="prettyprint pretty-java">
+<code>com.google.android.c2dm.intent.UNREGISTER</code></span><code>
+</code>intent.</li>
+ <li>If the application is automatically unregistered, which can happen
+(but is not guaranteed) if the user uninstalls the application.</li>
+ <li>If the registration ID expires. Google might decide to refresh registration
+IDs. </li>
+ <li>If the application is updated but the new version does not have a broadcast
+receiver configured to receive <code>com.google.android.c2dm.intent.RECEIVE</code>
+intents.</li>
+</ul>
+For all these cases, you should remove this registration ID from the 3rd-party
+server and stop using it to send
+messages.
+<br/>Happens when error code is <code>NotRegistered</code>.</dd>
+
+<dt id="big_msg"><strong>Message Too Big</strong></dt>
+ <dd>The total size of the payload data that is included in a message can't
+exceed 4096 bytes. Note that this includes both the size of the keys as well
+as the values.
+<br/>Happens when error code is <code>MessageTooBig</code>.</dd>
+
+<dt id="invalid_datakey"><strong>Invalid Data Key</strong></dt>
+<dd>The payload data contains a key (such as <code>from</code> or any value
+prefixed by <code>google.</code>) that is used internally by GCM in the
+<code>com.google.android.c2dm.intent.RECEIVE</code> Intent and cannot be used.
+Note that some words (such as <code>collapse_key</code>) are also used by GCM
+but are allowed in the payload, in which case the payload value will be
+overridden by the GCM value.
+<br />
+Happens when the error code is <code>InvalidDataKey</code>.</dd>
+
+<dt id="ttl_error"><strong>Invalid Time To Live</strong></dt>
+ <dd>The value for the Time to Live field must be an integer representing
+a duration in seconds between 0 and 2,419,200 (4 weeks). Happens when error code
+is <code>InvalidTtl</code>.
+</dd>
+
+ <dt id="auth_error"><strong>Authentication Error</strong></dt>
+ <dd>The sender account that you're trying to use to send a message couldn't be
+authenticated. Possible causes are: <ul>
+<li>Authorization header missing or with invalid syntax.</li>
+<li>Invalid project number sent as key.</li>
+<li>Key valid but with GCM service disabled.</li>
+<li>Request originated from a server not whitelisted in the Server Key IPs.</li>
+
+</ul>
+Check that the token you're sending inside the <code>Authorization</code> header
+is the correct API key associated with your project. You can check the validity
+of your API key by running the following command:<br/>
+
+<pre># api_key=YOUR_API_KEY
+
+# curl --header "Authorization: key=$api_key" --header Content-Type:"application/json" https://android.googleapis.com/gcm/send -d "{\"registration_ids\":[\"ABC\"]}"</pre>
+
+
+
+If you receive a 401 HTTP status code, your API key is not valid. Otherwise you
+should see something like this:<br/>
+
+<pre>
+{"multicast_id":6782339717028231855,"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"InvalidRegistration"}]}
+</pre>
+If you want to confirm the validity of a registration ID, you can do so by
+replacing "ABC" with the registration ID.
+<br/>
+Happens when the HTTP status code is 401.
+
+ <dt id="timeout"><strong>Timeout</strong></dt>
+
+<dd>The server couldn't process the request in time. You should retry the
+same request, but you MUST obey the following requirements:
+
+<ul>
+
+<li>Honor the <code>Retry-After</code> header if it's included in the response
+from the GCM server.</li>
+
+
+<li>Implement exponential back-off in your retry mechanism. This means an
+exponentially increasing delay after each failed retry (e.g. if you waited one
+second before the first retry, wait at least two second before the next one,
+then 4 seconds and so on). If you're sending multiple messages, delay each one
+independently by an additional random amount to avoid issuing a new request for
+all messages at the same time.</li>
+
+
+Senders that cause problems risk being blacklisted.
+<br />
+Happens when the HTTP status code is between 501 and 599, or when the
+<code>error</code> field of a JSON object in the results array is <code>Unavailable</code>.
+</dd>
+
+<dt id="internal_error"><strong>Internal Server Error</strong></dt>
+
+<dd>
+The server encountered an error while trying to process the request. You
+could retry the same request (obeying the requirements listed in the <a href="#timeout">Timeout</a>
+section), but if the error persists, please report the problem in the
+<a href="https://groups.google.com/forum/?fromgroups#!forum/android-gcm">android-gcm group</a>.
+<br />
+Happens when the HTTP status code is 500, or when the <code>error</code> field of a JSON
+object in the results array is <code>InternalServerError</code>.
+</dd>
+
+<dt id="restricted_package_name"><strong>Invalid Package Name</strong></dt>
+
+<dd>
+A message was addressed to a registration ID whose package name did not match
+the value passed in the request. Happens when error code is
+<code>InvalidPackageName</code>.
+</dd>
+</dl>
+
+<h3 id="example-responses">Example responses</h3>
+<p>This section shows a few examples of responses indicating messages that were
+processed successfully. See <a href="#request">Request Format</a> for
+the requests these responses are based on.</p>
+<p> Here is a simple case of a JSON message successfully sent to one recipient
+without canonical IDs in the response:</p>
+<pre class="prettyprint pretty-json">{ "multicast_id": 108,
+ "success": 1,
+ "failure": 0,
+ "canonical_ids": 0,
+ "results": [
+ { "message_id": "1:08" }
+ ]
+}</pre>
+
+<p>Or if the request was in plain-text format:</p>
+<pre class="prettyprint">id=1:08
+</pre>
+
+<p>Here are JSON results for 6 recipients (IDs 4, 8, 15, 16, 23, and 42 respectively)
+with 3 messages successfully processed, 1 canonical registration ID returned,
+and 3 errors:</p>
+<pre class="prettyprint pretty-json">{ "multicast_id": 216,
+ "success": 3,
+ "failure": 3,
+ "canonical_ids": 1,
+ "results": [
+ { "message_id": "1:0408" },
+ { "error": "Unavailable" },
+ { "error": "InvalidRegistration" },
+ { "message_id": "1:1516" },
+ { "message_id": "1:2342", "registration_id": "32" },
+ { "error": "NotRegistered"}
+ ]
+}
+</pre>
+<p> In this example:</p>
+<ul>
+ <li>First message: success, not required.</li>
+ <li>Second message: should be resent (to registration ID 8).</li>
+ <li>Third message: had an unrecoverable error (maybe the value got corrupted
+in the database).</li>
+ <li>Fourth message: success, nothing required.</li>
+ <li>Fifth message: success, but the registration ID should be updated in the
+server database (from 23 to 32).</li>
+ <li>Sixth message: registration ID (42) should be removed from the server database
+because the application was uninstalled from the device.</li>
+</ul>
+<p>Or if just the 4th message above was sent using plain-text format:</p>
+<pre class="prettyprint">Error=InvalidRegistration
+</pre>
+<p>If the 5th message above was also sent using plain-text format:</p>
+<pre class="prettyprint">id=1:2342
+registration_id=32
+</pre>
+
+
+<h2 id="app-server">Implementing an HTTP-Based App Server</h2>
+
+<p>This section gives examples of implementing an app server that works with the
+GCM HTTP connection server. Note that a full GCM implementation requires a
+client-side implementation, in addition to the server.</a>
+
+
+<p>Requirements</p>
+<p>For the web server:</p>
+<ul>
+ <li> <a href="http://ant.apache.org/">Ant 1.8</a> (it might work with earlier versions, but it's not guaranteed).</li>
+ <li>One of the following:
+ <ul>
+ <li>A running web server compatible with Servlets API version 2.5, such as
+<a href="http://tomcat.apache.org/">Tomcat 6</a> or <a href="http://jetty.codehaus.org/">Jetty</a>, or</li>
+ <li><a href="http://code.google.com/appengine/">Java App Engine SDK</a>
+version 1.6 or later.</li>
+ </ul>
+ </li>
+ <li>A Google account registered to use GCM.</li>
+ <li>The API key for that account.</li>
+</ul>
+<p>For the Android application:</p>
+<ul>
+ <li>Emulator (or device) running Android 2.2 with Google APIs.</li>
+ <li>The Google API project number of the account registered to use GCM.</li>
+</ul>
+
+<h3 id="gcm-setup">Setting Up GCM</h3>
+<p>Before proceeding with the server and client setup, it's necessary to register
+a Google account with the Google API Console, enable Google Cloud Messaging in GCM,
+and obtain an API key from the <a href="https://code.google.com/apis/console">
+Google API Console</a>.</p>
+<p>For instructions on how to set up GCM, see <a href="gs.html">Getting Started</a>.</p>
+
+
+<h3 id="server-setup">Setting Up an HTTP Server</h3>
+<p>This section describes the different options for setting up an HTTP server.</p>
+
+<h4 id="webserver-setup">Using a standard web server</h4>
+<p>To set up the server using a standard, servlet-compliant web server:</p>
+<ol>
+ <li>From the <a href="http://code.google.com/p/gcm">open source site</a>,
+download the following directories: <code>gcm-server</code>,
+<code>samples/gcm-demo-server</code>, and <code>samples/gcm-demo-appengine</code>.</p>
+
+
+ <li>In a text editor, edit the <code>samples/gcm-demo-server/WebContent/WEB-INF/classes/api.key</code> and replace the existing text with the API key obtained above.</li>
+ <li>In a shell window, go to the <code>samples/gcm-demo-server</code> directory.</li>
+ <li>Generate the server's WAR file by running <code>ant war</code>:</li>
+
+ <pre class="prettyprint">$ ant war
+
+Buildfile:build.xml
+
+init:
+ [mkdir] Created dir: build/classes
+ [mkdir] Created dir: dist
+
+compile:
+ [javac] Compiling 6 source files to build/classes
+
+war:
+ [war] Building war: <strong>dist/gcm-demo.war</strong>
+
+BUILD SUCCESSFUL
+Total time: 0 seconds
+</pre>
+
+ <li>Deploy the <code>dist/gcm-demo.war</code> to your running server. For instance, if you're using Jetty, copy <code>gcm-demo.war</code> to the <code>webapps</code> directory of the Jetty installation.</li>
+ <li>Open the server's main page in a browser. The URL depends on the server you're using and your machine's IP address, but it will be something like <code>http://192.168.1.10:8080/gcm-demo/home</code>, where <code>gcm-demo</code> is the application context and <code>/home</code> is the path of the main servlet.
+
+ </li>
+</ol>
+<p class="note"><strong>Note:</strong> You can get the IP by running <code>ifconfig</code> on Linux or MacOS, or <code>ipconfig</code> on Windows. </p>
+
+<p> You server is now ready.</p>
+
+<h4 id="appengine-setup">Using App Engine for Java</h4>
+
+<p>To set up the server using a standard App Engine for Java:</p>
+<ol>
+ <li>Get the files from the <a href="http://code.google.com/p/gcm">open source
+site</a>, as described above.</p>
+ </li>
+ <li>In a text editor, edit
+<code>samples/gcm-demo-appengine/src/com/google/android/gcm/demo/server/ApiKeyInitializer.java</code>
+and replace the existing text with the API key obtained above.
+
+ <p class="note"><strong>Note:</strong> The API key value set in that class will
+be used just once to create a persistent entity on App Engine. If you deploy
+the application, you can use App Engine's <code>Datastore Viewer</code> to change
+it later.</p>
+
+ </li>
+ <li>In a shell window, go to the <code>samples/gcm-demo-appengine</code> directory.</li>
+ <li>Start the development App Engine server by <code>ant runserver</code>,
+using the <code>-Dsdk.dir</code> to indicate the location of the App Engine SDK
+and <code>-Dserver.host</code> to set your server's hostname or IP address:</li>
+
+<pre class="prettyprint">
+$ ant -Dsdk.dir=/opt/google/appengine-java-sdk runserver -Dserver.host=192.168.1.10
+Buildfile: gcm-demo-appengine/build.xml
+
+init:
+ [mkdir] Created dir: gcm-demo-appengine/dist
+
+copyjars:
+
+compile:
+
+datanucleusenhance:
+ [enhance] DataNucleus Enhancer (version 1.1.4) : Enhancement of classes
+ [enhance] DataNucleus Enhancer completed with success for 0 classes. Timings : input=28 ms, enhance=0 ms, total=28 ms. Consult the log for full details
+ [enhance] DataNucleus Enhancer completed and no classes were enhanced. Consult the log for full details
+
+runserver:
+ [java] Jun 15, 2012 8:46:06 PM com.google.apphosting.utils.jetty.JettyLogger info
+ [java] INFO: Logging to JettyLogger(null) via com.google.apphosting.utils.jetty.JettyLogger
+ [java] Jun 15, 2012 8:46:06 PM com.google.apphosting.utils.config.AppEngineWebXmlReader readAppEngineWebXml
+ [java] INFO: Successfully processed gcm-demo-appengine/WebContent/WEB-INF/appengine-web.xml
+ [java] Jun 15, 2012 8:46:06 PM com.google.apphosting.utils.config.AbstractConfigXmlReader readConfigXml
+ [java] INFO: Successfully processed gcm-demo-appengine/WebContent/WEB-INF/web.xml
+ [java] Jun 15, 2012 8:46:09 PM com.google.android.gcm.demo.server.ApiKeyInitializer contextInitialized
+ [java] SEVERE: Created fake key. Please go to App Engine admin console, change its value to your API Key (the entity type is 'Settings' and its field to be changed is 'ApiKey'), then restart the server!
+ [java] Jun 15, 2012 8:46:09 PM com.google.appengine.tools.development.DevAppServerImpl start
+ [java] INFO: The server is running at http://192.168.1.10:8080/
+ [java] Jun 15, 2012 8:46:09 PM com.google.appengine.tools.development.DevAppServerImpl start
+ [java] INFO: The admin console is running at http://192.168.1.10:8080/_ah/admin
+</pre>
+
+ <li>Open the server's main page in a browser. The URL depends on the server
+you're using and your machine's IP address, but it will be something like
+<code>http://192.168.1.10:8080/home</code>, where <code>/home</code>
+is the path of the main servlet.</li>
+
+ <p class="note"><strong>Note:</strong> You can get the IP by running <code>ifconfig</code>
+on Linux or MacOS, or <code>ipconfig</code> on Windows.</p>
+
+</ol>
+<p> You server is now ready.</p>
diff --git a/docs/html/google/gcm/notifications.jd b/docs/html/google/gcm/notifications.jd
index 517185042248..43a7368f7eae 100644
--- a/docs/html/google/gcm/notifications.jd
+++ b/docs/html/google/gcm/notifications.jd
@@ -14,14 +14,15 @@ page.title=User Notifications
<h2>In this document</h2>
<ol class="toc">
- <li><a href="#what">What are User Notifications?</a> </li>
- <li><a href="#examples">Examples</a>
- <ol>
- <li><a href="#create">Generate a notification key</a></li>
- <li><a href="#add">Add registration IDs</a></li>
- <li><a href="#remove">Remove registration IDs</a></li>
- <li><a href="#upstream">Send upstream messages</a></li>
- <li><a href="#response">Response formats</a></li>
+ <li><a href="#request">Request Format</a></li>
+ <li><a href="#create">Generate a Notification Key</a></li>
+ <li><a href="#add">Add Registration IDs</a></li>
+ <li><a href="#remove">Remove Registration IDs</a></li>
+ <li><a href="#upstream">Send Upstream Messages</a></li>
+ <li><a href="#response">Response Formats</a>
+ <ol class="toc">
+ <li><a href="#response-create">Create/add/remove operations</a>
+ <li><a href="#response-send">Send operations</a>
</ol>
</li>
</ol>
@@ -38,32 +39,51 @@ page.title=User Notifications
<p class="note"><strong>Note:</strong> To try out this feature, sign up using <a href="https://services.google.com/fb/forms/gcm/">this form</a>.</p>
-<p>The upstream messaging (device-to-cloud) feature described in this document is part of the Google Play services platform. Upstream messaging is available through the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">GoogleCloudMessaging</a> APIs. To use upstream messaging and the new streamlined registration process, you must <a href="{@docRoot}google/play-services/setup.html">set up</a> the Google Play services SDK.</p>
-<h2 id="what">What are User Notifications?</h2>
-
-<p>Third party servers can send a single message to multiple instance of an app running on devices owned by a single user. This feature is called <em>user notifications</em>. User notifications make it possible for every app instance that a user owns to reflect the latest messaging state. For example:</p>
+<p>With user notifications, 3rd-party app servers can send a single message to
+multiple instance of an app running on devices owned by a single user. This feature
+is called <em>user notifications</em>. User notifications make it possible for every
+app instance that a user owns to reflect the latest messaging state. For example:</p>
<ul>
- <li>If a message has been handled on one device, the GCM message on the other devices are dismissed. For example, if a user has handled a calendar notification on one device, the notification will go away on the user's other devices.</li>
- <li>If a message has not been delivered yet to a device and but it has been handled, the GCM server removes it from the unsent queue for the other devices.</li>
- <li>Likewise, a device can send messages to the {@code notification_key}, which is the token that GCM uses to fan out notifications to all devices whose registration IDs are associated with the key.</li>
-</ul>
+ <li>If a message has been handled on one device, the GCM message on the other
+devices are dismissed. For example, if a user has handled a calendar notification
+on one device, the notification will go away on the user's other devices.</li>
-<p>The way this works is that during registration, the 3rd-party server requests a {@code notification_key}. The {@code notification_key} maps a particular user to all of the user's associated registration IDs (a regID represents a particular Android application running on a particular device). Then instead of sending one message to one regID at a time, the 3rd-party server can send a message to to the {@code notification_key}, which then sends the message to all of the user's regIDs.</p>
+ <li>If a message has not been delivered yet to a device and but it has been handled,
+the GCM server removes it from the unsent queue for the other devices.</li>
-<p class="note"><strong>Note:</strong> A notification dismissal message is like any other upstream message, meaning that it will be delivered to the other devices that belong to the specified {@code notification_key}. You should design your app to handle cases where the app receives a dismissal message, but has not yet displayed the notification that is being dismissed. You can solve this by caching the dismissal and then reconciling it with the corresponding notification.
-</p>
+ <li>Likewise, a device can send messages to the {@code notification_key}, which
+is the token that GCM uses to fan out notifications to all devices whose
+registration IDs are associated with the key.</li>
+</ul>
-<p>You can use this feature with either the new <a href="ccs.html">GCM Cloud Connection Server</a> (CCS), or the older <a href="gcm.html">GCM HTTP server</a>.</p>
+<p>The way this works is that during registration, the 3rd-party server requests
+a {@code notification_key}. The {@code notification_key} maps a particular user
+to all of the user's associated registration IDs (a regID represents a particular
+Android application running on a particular device). Then instead of sending one
+message to one regID at a time, the 3rd-party server can send a message to to the
+{@code notification_key}, which then sends the message to all of the user's regIDs.</p>
+
+<p class="note"><strong>Note:</strong> A notification dismissal message is like any
+other upstream message, meaning that it will be delivered to the other devices that
+belong to the specified {@code notification_key}. You should design your app to
+handle cases where the app receives a dismissal message, but has not yet displayed
+the notification that is being dismissed. You can solve this by caching the dismissal
+and then reconciling it with the corresponding notification.
+</p>
+<p>You can use this feature with either the <a href="ccs.html">XMPP</a> (CCS) or
+<a href="http.html">HTTP</a> connection server.</p>
-<h3 id="examples">Examples</h3>
-<p>The examples in this section show you how to perform generate/add/remove operations, and how to send upstream messages. For generate/add/remove operations, the message body is JSON.</p>
+<p>The examples below show you how to perform generate/add/remove operations,
+and how to send upstream messages. For generate/add/remove operations, the
+message body is JSON.</p>
-<h4 id="request">Request format</h4>
-<p>To send a message, the application server issues a POST request to <code>https://android.googleapis.com/gcm/notification</code>.</p>
+<h2 id="request">Request Format</h2>
+<p>To send a message, the application server issues a POST request to
+<code>https://android.googleapis.com/gcm/notification</code>.</p>
<p>Here is the HTTP request header you should use for all create/add/remove operations:</p>
@@ -72,12 +92,22 @@ Header : "project_id": &lt;projectID&gt;
Header: "Authorization", "key=API_KEY"
</pre>
-<h4 id="create">Generate a notification key</h4>
+<h2 id="create">Generate a Notification Key</h2>
-<p>This example shows how to create a new <code>notification_key</code> for a <code>notification_key_name</code> called <code>appUser-Chris</code>. The {@code notification_key_name} is a name or identifier (can be a username for a 3rd-party app) that is unique to a given user. It is used by third parties to group together registration IDs for a single user. Note that <code>notification_key_name</code> and <code>notification_key</code> are unique to a group of registration IDs. It is also important that <code>notification_key_name</code> be uniquely named per app in case you have multiple apps for the same project ID. This ensures that notifications only go to the intended target app.</p>
+<p>This example shows how to create a new <code>notification_key</code> for a
+<code>notification_key_name</code> called <code>appUser-Chris</code>.
+The {@code notification_key_name} is a name or identifier (can be a username for
+a 3rd-party app) that is unique to a given user. It is used by third parties to
+group together registration IDs for a single user. Note that <code>notification_key_name</code>
+and <code>notification_key</code> are unique to a group of registration IDs. It is also
+important that <code>notification_key_name</code> be uniquely named per app in case
+you have multiple apps for the same project ID. This ensures that notifications
+only go to the intended target app.</p>
-<p>A create operation returns a token (<code>notification_key</code>). Third parties must save this token (as well as its mapping to the <code>notification_key_name</code>) to use in subsequent operations:</p>
+<p>A create operation returns a token (<code>notification_key</code>). Third parties
+must save this token (as well as its mapping to the <code>notification_key_name</code>)
+to use in subsequent operations:</p>
<pre>request:
{
@@ -86,11 +116,14 @@ Header: "Authorization", "key=API_KEY"
&quot;registration_ids&quot;: [&quot;4&quot;, &quot;8&quot;, &quot;15&quot;, &quot;16&quot;, &quot;23&quot;, &quot;42&quot;]
}</pre>
-<h4 id="add">Add registration IDs</h4>
+<h2 id="add">Add Registration IDs</h2>
-<p>This example shows how to add registration IDs for a given notification key. The maximum number of members allowed for a {@code notification_key} is 10.</p>
+<p>This example shows how to add registration IDs for a given notification key.
+The maximum number of members allowed for a {@code notification_key} is 10.</p>
-<p>Note that the <code>notification_key_name</code> is not strictly required for adding/removing regIDs. But including it protects you against accidentally using the incorrect <code>notification_key</code>.</p>
+<p>Note that the <code>notification_key_name</code> is not strictly required for
+adding/removing regIDs. But including it protects you against accidentally using
+the incorrect <code>notification_key</code>.</p>
<pre>request:
{
@@ -100,7 +133,7 @@ Header: "Authorization", "key=API_KEY"
&quot;registration_ids&quot;: [&quot;4&quot;, &quot;8&quot;, &quot;15&quot;, &quot;16&quot;, &quot;23&quot;, &quot;42&quot;]
}</pre>
-<h4 id="remove">Remove registration IDs</h4>
+<h2 id="remove">Remove Registration IDs</h2>
<p>This example shows how to remove registration IDs for a given notification key:</p>
<pre>request:
@@ -111,9 +144,14 @@ Header: "Authorization", "key=API_KEY"
&quot;registration_ids&quot;: [&quot;4&quot;, &quot;8&quot;, &quot;15&quot;, &quot;16&quot;, &quot;23&quot;, &quot;42&quot;]
}</pre>
-<h4 id="upstream">Send upstream messages</h4>
+<h2 id="upstream">Send Upstream Messages</h2>
-<p>To send an upstream (device-to-cloud) message, you must use the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">GoogleCloudMessaging</a> API. Specifying a {@code notification_key} as the target for an upstream message allows a user on one device to send a message to other devices in the notification group&mdash;for example, to dismiss a notification. Here is an example that shows targeting a {@code notification_key}:</p>
+<p>To send an upstream (device-to-cloud) message, you must use the
+<a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">
+{@code GoogleCloudMessaging}</a> API. Specifying a {@code notification_key} as the target
+for an upstream message allows a user on one device to send a message to other
+devices in the notification group&mdash;for example, to dismiss a notification.
+Here is an example that shows targeting a {@code notification_key}:</p>
<pre>GoogleCloudMessaging gcm = GoogleCloudMessaging.get(context);
String to = NOTIFICATION_KEY;
@@ -125,17 +163,21 @@ data.putString("hello", "world");
gcm.send(to, id, data);
</pre>
-<p>This call generates the necessary XMPP stanza for sending the message. The Bundle data consists of a key-value pair.</p>
+<p>This call generates the necessary XMPP stanza for sending the message. The
+Bundle data consists of a key-value pair.</p>
-<p>For a complete example, see <a href="gs.html#gs_example">Getting Started</a>.
+<p>For a complete example, see <a href="client.html">Implementing GCM Client</a>.
-<h4 id="response">Response formats</h4>
+<h2 id="response">Response Formats</h2>
-<p>This section shows examples of the responses that can be returned for notification key operations.</p>
+<p>This section shows examples of the responses that can be returned for
+notification key operations.</p>
-<h5>Response for create/add/remove operations</h5>
+<h3 id="response-create">Create/add/remove operations</h3>
-<p>When you make a request to create a {@code notification_key} or to add/remove its the wayregIDs, a successful response always returns the <code>notification_key</code>. This is the {@code notification_key} you will use for sending messages:</p>
+<p>When you make a request to create a {@code notification_key} or to add/remove its
+regIDs, a successful response always returns the <code>notification_key</code>.
+his is the {@code notification_key} you will use for sending messages:</p>
<pre>HTTP status: 200
{
@@ -143,18 +185,23 @@ gcm.send(to, id, data);
}</pre>
-<h5>Response for send operations</h5>
+<h3 id="response-send">Send operations</h3>
-<p>For a send operation that has a {@code notification_key} as its target, the possible responses are success, partial success, and failure.</p>
+<p>For a send operation that has a {@code notification_key} as its target, the
+possible responses are success, partial success, and failure.</p>
-<p>Here is an example of "success"&mdash;the {@code notification_key} has 2 regIDs associated with it, and the message was successfully sent to both of them:</p>
+<p>Here is an example of "success"&mdash;the {@code notification_key} has 2 regIDs
+associated with it, and the message was successfully sent to both of them:</p>
<pre>{
"success": 2,
"failure": 0
}</pre>
-<p>Here is an example of "partial success"&mdash;the {@code notification_key} has 3 regIDs associated with it. The message was successfully send to 1 of the regIDs, but not to the other 2. The response message lists the regIDs that failed to receive the message:</p>
+<p>Here is an example of "partial success"&mdash;the {@code notification_key} has
+3 regIDs associated with it. The message was successfully send to 1 of the regIDs,
+but not to the other 2. The response message lists the regIDs that failed to
+receive the message:</p>
<pre>{
"success":1,
@@ -165,7 +212,9 @@ gcm.send(to, id, data);
]
}</pre>
-<p>In the case of failure, the response has HTTP code 503 and no JSON. When a message fails to be delivered to one or more of the regIDs associated with a {@code notification_key}, the 3rd-party server should retry.</p>
+<p>In the case of failure, the response has HTTP code 503 and no JSON. When a message
+fails to be delivered to one or more of the regIDs associated with a {@code notification_key},
+the 3rd-party server should retry.</p>
diff --git a/docs/html/google/gcm/server.jd b/docs/html/google/gcm/server.jd
index 92a1531cdbb4..b5e6b480d057 100644
--- a/docs/html/google/gcm/server.jd
+++ b/docs/html/google/gcm/server.jd
@@ -1,36 +1,34 @@
-page.title=GCM Server
+page.title=Implementing GCM Server
@jd:body
<div id="qv-wrapper">
<div id="qv">
-<h2>Quickview</h2>
-
-<ul>
-<li>Understand how to set up the server side of a GCM app.</li>
-<li>Become familiar with the <a href="{@docRoot}reference/com/google/android/gcm/server/package-summary.html">GCM server helper library</a>.</li>
-</ul>
-
-
<h2>In this document</h2>
-<ol>
- <li><a href="#requirements">Requirements</a> </li>
- <li><a href="#gcm-setup">Setting Up GCM</a></li>
- <li><a href="#server-setup">Setting Up an HTTP Server</a>
- <ol>
- <li><a href="#webserver-setup">Using a standard web server</a></li>
- <li><a href="#appengine-setup">Using App Engine for Java</a></li>
+<ol class="toc">
+ <li><a href="#choose">Choosing a GCM Connection Server</a></li>
+ <li><a href="#role">Role of the 3rd-party Application Server</a></li>
+ <li><a href="#send-msg">Sending Messages</a>
+ <ol class="toc">
+
+ <li><a href="#target">Target</a></li>
+ <li><a href="#payload">Payload</a></li>
+ <li><a href="#params">Message parameters</a>
</ol>
+ </li>
+ <li><a href="#receive">Receiving Messages</a> </li>
</li>
+
</ol>
<h2>See Also</h2>
<ol class="toc">
<li><a href="gs.html">Getting Started</a></li>
-<li><a href="client.html">GCM Client</a></li>
-<li><a href="ccs.html">Cloud Connection Server</a></li>
+<li><a href="client.html">Implementing GCM Client</a></li>
+<li><a href="ccs.html">Cloud Connection Server (XMPP)</a></li>
+<li><a href="http.html">HTTP Connection Server</a></li>
</ol>
@@ -39,122 +37,342 @@ page.title=GCM Server
</div>
+<p>The server side of GCM consists of 2 components:</p>
+<ul>
+<li>Google-provided <strong>GCM Connection Servers</strong>
+take messages from a 3rd-party application server and send them to a GCM-enabled
+Android application (the &quot;client app&quot;) running on a device. For example,
+Google provides connection servers for <a href="{@docRoot}google/gcm/http.html">
+HTTP</a> and <a href="{@docRoot}google/gcm/ccs.html">CCS</a> (XMPP).</li>
+<li>A <strong>3rd-party application server</strong> that you must implement. This application
+server sends data to a GCM-enabled Android application via the chosen GCM connection server.</li>
+</ul>
+</p>
+<p>Here are the basic steps you follow to implement your 3rd-party app server:</p>
-<p>This document gives examples of GCM server-side code for HTTP. For an example of an XMPP server (<a href="ccs.html">Cloud Connection Server</a>), see <a href="gs.html#server">Getting Started</a>. Note that a full GCM implementation requires a client-side implementation, in addition to the server. For a complete working example that includes client and server-side code, see <a href="gs.html">Getting Started</a>.</a>
-
-<h2 id="requirements">Requirements</h2>
-<p>For the web server:</p>
<ul>
- <li> <a href="http://ant.apache.org/">Ant 1.8</a> (it might work with earlier versions, but it's not guaranteed).</li>
- <li>One of the following:
- <ul>
- <li>A running web server compatible with Servlets API version 2.5, such as <a href="http://tomcat.apache.org/">Tomcat 6</a> or <a href="http://jetty.codehaus.org/">Jetty</a>, or</li>
- <li><a href="http://code.google.com/appengine/">Java App Engine SDK</a> version 1.6 or later.</li>
+ <li>Decide which GCM connection server(s) you want to use. Note that if you want to use
+ upstream messaging from your client applications, you must use CCS. For a more detailed
+ discussion of this, see <a href="#choose">
+ Choosing a GCM Connection Server</a>.</li>
+ <li>Decide how you want to implement your app server. For example:
+ <ul>
+ <li>If you decide to use the HTTP connection server, you can use the
+GCM server helper library and demo app to help in implementing your app server.</li>
+ <li>If you decide to use the XMPP connection server, you can use
+the provided Python or Java <a href="http://www.igniterealtime.org/projects/smack/">
+Smack</a> demo apps as a starting point.</li>
+ <li>Note that Google AppEngine does not support connections to CCS.</li>
+ </ul>
+ </li>
</ul>
</li>
- <li>A Google account registered to use GCM.</li>
- <li>The API key for that account.</li>
</ul>
-<p>For the Android application:</p>
-<ul>
- <li>Emulator (or device) running Android 2.2 with Google APIs.</li>
- <li>The Google API project number of the account registered to use GCM.</li>
-</ul>
-<h2 id="gcm-setup">Setting Up GCM</h2>
-<p>Before proceeding with the server and client setup, it's necessary to register a Google account with the Google API Console, enable Google Cloud Messaging in GCM, and obtain an API key from the <a href="https://code.google.com/apis/console">Google API Console</a>.</p>
-<p>For instructions on how to set up GCM, see <a href="gs.html">Getting Started</a>.</p>
+<p>A full GCM implementation requires both a client implementation and a server
+implementation. For more
+information about implementing the client side, see <a href="client.html">
+Implementing GCM Client</a>.</p>
-<h2 id="server-setup">Setting Up an HTTP Server</h2>
-<p>This section describes the different options for setting up an HTTP server.</p>
-<h3 id="webserver-setup">Using a standard web server</h3>
-<p>To set up the server using a standard, servlet-compliant web server:</p>
-<ol>
- <li>From the <a href="http://code.google.com/p/gcm">open source site</a>, download the following directories: <code>gcm-server</code>, <code>samples/gcm-demo-server</code>, and <code>samples/gcm-demo-appengine</code>.</p>
+<h2 id="choose">Choosing a GCM Connection Server</h2>
+<p>Currently GCM provides two connection servers: <a href="{@docRoot}google/gcm/http.html">
+HTTP</a> and <a href="{@docRoot}google/gcm/ccs.html">CCS</a> (XMPP). You can use them
+separately or in tandem. CCS messaging differs from GCM HTTP messaging in the following ways:</p>
+<ul>
+ <li>Upstream/Downstream messages
+ <ul>
+ <li>GCM HTTP: Downstream only: cloud-to-device. </li>
+ <li>CCS: Upstream and downstream (device-to-cloud, cloud-to-device). </li>
+ </ul>
+ </li>
+ <li>Asynchronous messaging
+ <ul>
+ <li>GCM HTTP: 3rd-party app servers send messages as HTTP POST requests and
+wait for a response. This mechanism is synchronous and causes the sender to block
+before sending another message.</li>
+ <li>CCS: 3rd-party app servers connect to Google infrastructure using a
+persistent XMPP connection and send/receive messages to/from all their devices
+at full line speed. CCS sends acknowledgment or failure notifications (in the
+form of special ACK and NACK JSON-encoded XMPP messages) asynchronously.</li>
+ </ul>
+ </li>
- <li>In a text editor, edit the <code>samples/gcm-demo-server/WebContent/WEB-INF/classes/api.key</code> and replace the existing text with the API key obtained above.</li>
- <li>In a shell window, go to the <code>samples/gcm-demo-server</code> directory.</li>
- <li>Generate the server's WAR file by running <code>ant war</code>:</li>
-
- <pre class="prettyprint">$ ant war
+ <li>JSON
+ <ul>
+ <li>GCM HTTP: JSON messages sent as HTTP POST.</li>
+ <li>CCS: JSON messages encapsulated in XMPP messages.</li>
+ </ul>
+ </li>
+</ul>
-Buildfile:build.xml
+<h2 id="role">Role of the 3rd-party Application Server</h2>
-init:
- [mkdir] Created dir: build/classes
- [mkdir] Created dir: dist
+<p>Before you can write client Android applications that use the GCM feature, you must
+have an application server that meets the following criteria:</p>
-compile:
- [javac] Compiling 6 source files to build/classes
+<ul>
+ <li>Able to communicate with your client.</li>
+ <li>Able to fire off properly formatted requests to the GCM server.</li>
+ <li>Able to handle requests and resend them as needed, using
+<a href="http://en.wikipedia.org/wiki/Exponential_backoff">exponential back-off.</a></li>
+ <li>Able to store the API key and client registration IDs. The
+API key is included in the header of POST requests that send
+messages.</li>
+ <li>Able to store the API key and client registration IDs.</li>
+ <li>Able to generate message IDs to uniquely identify each message it sends.</li>
+</ul>
-war:
- [war] Building war: <strong>dist/gcm-demo.war</strong>
+<h2 id="send-msg">Sending Messages</h2>
-BUILD SUCCESSFUL
-Total time: 0 seconds
-</pre>
-
- <li>Deploy the <code>dist/gcm-demo.war</code> to your running server. For instance, if you're using Jetty, copy <code>gcm-demo.war</code> to the <code>webapps</code> directory of the Jetty installation.</li>
- <li>Open the server's main page in a browser. The URL depends on the server you're using and your machine's IP address, but it will be something like <code>http://192.168.1.10:8080/gcm-demo/home</code>, where <code>gcm-demo</code> is the application context and <code>/home</code> is the path of the main servlet.
-
- </li>
+<p>Here is the general sequence of events that occurs when a 3rd-party application
+server sends a message:</p>
+<ol>
+ <li>The application server sends a message to GCM servers.</li>
+ <li>Google enqueues and stores the message in case the device is offline.</li>
+ <li>When the device is online, Google sends the message to the device.</li>
+ <li>On the device, the system broadcasts the message to the specified Android
+application via Intent broadcast with proper permissions, so that only the targeted
+ndroid application gets the message. This wakes the Android application up.
+The Android application does not need to be running beforehand to receive the message.</li>
+ <li>The Android application processes the message. </li>
</ol>
-<p class="note"><strong>Note:</strong> You can get the IP by running <code>ifconfig</code> on Linux or MacOS, or <code>ipconfig</code> on Windows. </p>
-<p> You server is now ready.</p>
+<p>The following sections describe the basic requirements for
+sending messages.</p>
-<h3 id="appengine-setup">Using App Engine for Java</h3>
+<h3 id="target">Target</h3>
+<p>Required. When your app server sends a message in GCM, it must specify a target.</p>
+<p>For HTTP you must specify the target as one of:</p>
+<ul>
+<li><code>registration_ids</code>: For sending to 1 more more devices (up to 1000).
+When you send a message to multiple registration IDs, that is called a multicast message.</li>
+<li><code>notification_key</code>: For sending to multiple devices owned by a single user.</li>
+</ul>
+<p>For CCS (XMPP):</p>
+<ul>
+<li>You must specify the target as the &quot;to&quot; field, where the &quot;to&quot;
+field may contain a single registration ID or a notification key.
+CCS does not support multicast messaging.</li>
+</ul>
+<h3 id="payload">Payload</h3>
+<p>Optional. If you are including a payload in the message, you use the <code>data</code>
+parameter to include the payload. This applies for both HTTP and CCS.</p>
+
+<h3 id="params">Message parameters</h3>
+
+<p>The following table lists the parameters that a 3rd-party app server might
+include in the JSON messages it sends to a connection server. See the "Where Supported"
+column for information about which connection servers support that particular
+parameter.</p>
+
+<p class="table-caption" id="table1">
+ <strong>Table 1.</strong> Message parameters.</p>
+
+<table>
+ <tr>
+ <th>Field</th>
+ <th>Description</th>
+<th>Where Supported</th>
+</tr>
+ <td><code>to</code></td>
+<td>In CCS, used in place of <code>registration_ids</code> to specify the
+recipient of a message. Its value must be a registration ID.
+The value is a string. Required.</td>
+<td>CCS</td>
+</tr>
+<tr>
+<td><code>message_id</code></td>
+<td>In CCS, uniquely identifies a message in an XMPP connection. The value is a
+string that uniquely identifies the associated message. The value is a string. Required.</td>
+<td>CCS</td>
+</tr>
+<tr>
+<td><code>message_type</code></td>
+<td>In CCS, indicates a special status message, typically sent by the system.
+However, your app server also uses this parameter to send an 'ack' or 'nack'
+message back to the CCS connection server. For more discussion of this topic, see
+<a href="ccs.html">Cloud Connection Server</a>. The value is a string. Optional.</td>
+<td>CCS</td>
+<tr>
+ <td><code>registration_ids</code></td>
+ <td>A string array with the list of devices (registration IDs) receiving the
+message. It must contain at least 1 and at most 1000 registration IDs. To send a
+multicast message, you must use JSON. For sending a single message to a single
+device, you could use a JSON object with just 1 registration id, or plain text
+(see below). A request must include a recipient&mdash;this can be either a
+registration ID, an array of registration IDs, or a {@code notification_key}.
+Required.</td>
+<td>HTTP</td>
+</tr>
+ <tr>
+ <td><code>notification_key</code></td>
+ <td>A string that maps a single user to multiple registration IDs associated
+with that user. This allows a 3rd-party server to send a single message to
+multiple app instances (typically on multiple devices) owned by a single user.
+A 3rd-party server can use {@code notification_key} as the target for a message
+instead of an individual registration ID (or array of registration IDs). The maximum
+number of members allowed for a {@code notification_key} is 10. For more discussion
+of this topic, see <a href="notifications.html">User Notifications</a>. Optional.
+</td>
+<td style="width:100px">HTTP. This feature is supported in CCS, but you use it by
+specifying a notification key in the &quot;to&quot; field.</td>
+</tr>
+ <tr>
+ <td><code>collapse_key</code></td>
+ <td>An arbitrary string (such as &quot;Updates Available&quot;) that is used
+to collapse a group of like messages
+when the device is offline, so that only the last message gets sent to the
+client. This is intended to avoid sending too many messages to the phone when it
+comes back online. Note that since there is no guarantee of the order in which
+messages get sent, the &quot;last&quot; message may not actually be the last
+message sent by the application server. Collapse keys are also called
+<a href="#s2s">send-to-sync messages</a>.
+<br>
+<strong>Note:</strong> GCM allows a maximum of 4 different collapse keys to be
+used by the GCM server
+at any given time. In other words, the GCM server can simultaneously store 4
+different send-to-sync messages per device, each with a different collapse key.
+If you exceed
+this number GCM will only keep 4 collapse keys, with no guarantees about which
+ones they will be. See <a href="adv.html#collapsible">Advanced Topics</a> for more
+discussion of this topic. Optional.</td>
+<td>CCS, HTTP</td>
+</tr>
+ <tr>
+ <td><code>data</code></td>
+ <td>A JSON object whose fields represents the key-value pairs of the message's
+payload data. If present, the payload data it will be
+included in the Intent as application data, with the key being the extra's name.
+For instance, <code>"data":{"score":"3x1"}</code> would result in an intent extra
+named <code>score</code> whose value is the string <code>3x1</code>.
+There is no limit on the number of key/value pairs, though there is a limit on
+the total size of the message (4kb). The values could be any JSON object, but we
+recommend using strings, since the values will be converted to strings in the GCM
+server anyway. If you want to include objects or other non-string data types
+(such as integers or booleans), you have to do the conversion to string yourself.
+Also note that the key cannot be a reserved word (<code>from</code> or any word
+starting with <code>google.</code>). To complicate things slightly, there are
+some reserved words (such as <code>collapse_key</code>) that are technically
+allowed in payload data. However, if the request also contains the word, the
+value in the request will overwrite the value in the payload data. Hence using
+words that are defined as field names in this table is not recommended, even in
+cases where they are technically allowed. Optional.</td>
+<td>CCS, HTTP</td>
+</tr>
+ <tr>
+ <td><code>delay_while_idle</code></td>
+ <td>If included, indicates that the message should not be sent immediately
+if the device is idle. The server will wait for the device to become active, and
+then only the last message for each <code>collapse_key</code> value will be
+sent. The default value is <code>false</code>, and must be a JSON boolean. Optional.</td>
+<td>CCS, HTTP</td>
+</tr>
+ <tr>
+ <td><code>time_to_live</code></td>
+ <td>How long (in seconds) the message should be kept on GCM storage if the
+device is offline. Optional (default time-to-live is 4 weeks, and must be set as
+a JSON number).</td>
+<td>CCS, HTTP</td>
+</tr>
+<tr>
+ <td><code>restricted_package_name</code></td>
+ <td>A string containing the package name of your application. When set, messages
+will only be sent to registration IDs that match the package name. Optional.
+ </td>
+<td>HTTP</td>
+</tr>
+<tr>
+ <td><code>dry_run</code></td>
+ <td>If included, allows developers to test their request without actually
+sending a message. Optional. The default value is <code>false</code>, and must
+be a JSON boolean.
+ </td>
+<td>HTTP</td>
+</tr>
+</table>
+
+<p>If you want to test your request (either JSON or plain text) without delivering
+the message to the devices, you can set an optional HTTP or JSON parameter called
+<code>dry_run</code> with the value <code>true</code>. The result will be almost
+identical to running the request without this parameter, except that the message
+will not be delivered to the devices. Consequently, the response will contain fake
+IDs for the message and multicast fields.</p>
+
+<h3 id="plain-text">Plain text (HTTP only)</h3>
+
+<p>If you are using plain text instead of JSON, the message fields must be set as
+HTTP parameters sent in the body, and their syntax is slightly different, as
+described below:
+<table>
+ <tr>
+ <th>Field</th>
+ <th>Description</th>
+ </tr>
+ <tr>
+ <td><code>registration_id</code></td>
+ <td>Must contain the registration ID of the single device receiving the message.
+Required.</td>
+ </tr>
+ <tr>
+ <td><code>collapse_key</code></td>
+ <td>Same as JSON (see previous table). Optional.</td>
+ </tr>
+ <tr>
+ <td><code>data.&lt;key&gt;</code></td>
+
+ <td>Payload data, expressed as parameters prefixed with <code>data.</code> and
+suffixed as the key. For instance, a parameter of <code>data.score=3x1</code> would
+result in an intent extra named <code>score</code> whose value is the string
+<code>3x1</code>. There is no limit on the number of key/value parameters, though
+there is a limit on the total size of the message. Also note that the key cannot
+be a reserved word (<code>from</code> or any word starting with
+<code>google.</code>). To complicate things slightly, there are some reserved words
+(such as <code>collapse_key</code>) that are technically allowed in payload data.
+However, if the request also contains the word, the value in the request will
+overwrite the value in the payload data. Hence using words that are defined as
+field names in this table is not recommended, even in cases where they are
+technically allowed. Optional.</td>
+
+ </tr>
+ <tr>
+ <td><code>delay_while_idle</code></td>
+ <td>Should be represented as <code>1</code> or <code>true</code> for
+<code>true</code>, anything else for <code>false</code>. Optional. The default
+value is <code>false</code>.</td>
+ </tr>
+ <tr>
+ <td><code>time_to_live</code></td>
+ <td>Same as JSON (see previous table). Optional.</td>
+ </tr>
+<tr>
+ <td><code>restricted_package_name</code></td>
+ <td>Same as JSON (see previous table). Optional.
+ </td>
+</tr>
+<tr>
+ <td><code>dry_run</code></td>
+ <td>Same as JSON (see previous table). Optional.
+ </td>
+</tr>
+</table>
+
+<h2 id="receive">Receiving Messages</h2>
+
+<p>This is the sequence of events that occurs when an Android application
+installed on a mobile device receives a message:</p>
-<p>To set up the server using a standard App Engine for Java:</p>
<ol>
- <li>Get the files from the <a href="http://code.google.com/p/gcm">open source site</a>, as described above.</p>
- </li>
- <li>In a text editor, edit <code>samples/gcm-demo-appengine/src/com/google/android/gcm/demo/server/ApiKeyInitializer.java</code> and replace the existing text with the API key obtained above.
-
- <p class="note"><strong>Note:</strong> The API key value set in that class will be used just once to create a persistent entity on App Engine. If you deploy the application, you can use App Engine's <code>Datastore Viewer</code> to change it later.</p>
-
- </li>
- <li>In a shell window, go to the <code>samples/gcm-demo-appengine</code> directory.</li>
- <li>Start the development App Engine server by <code>ant runserver</code>, using the <code>-Dsdk.dir</code> to indicate the location of the App Engine SDK and <code>-Dserver.host</code> to set your server's hostname or IP address:</li>
-
-<pre class="prettyprint">
-$ ant -Dsdk.dir=/opt/google/appengine-java-sdk runserver -Dserver.host=192.168.1.10
-Buildfile: gcm-demo-appengine/build.xml
-
-init:
- [mkdir] Created dir: gcm-demo-appengine/dist
-
-copyjars:
-
-compile:
-
-datanucleusenhance:
- [enhance] DataNucleus Enhancer (version 1.1.4) : Enhancement of classes
- [enhance] DataNucleus Enhancer completed with success for 0 classes. Timings : input=28 ms, enhance=0 ms, total=28 ms. Consult the log for full details
- [enhance] DataNucleus Enhancer completed and no classes were enhanced. Consult the log for full details
-
-runserver:
- [java] Jun 15, 2012 8:46:06 PM com.google.apphosting.utils.jetty.JettyLogger info
- [java] INFO: Logging to JettyLogger(null) via com.google.apphosting.utils.jetty.JettyLogger
- [java] Jun 15, 2012 8:46:06 PM com.google.apphosting.utils.config.AppEngineWebXmlReader readAppEngineWebXml
- [java] INFO: Successfully processed gcm-demo-appengine/WebContent/WEB-INF/appengine-web.xml
- [java] Jun 15, 2012 8:46:06 PM com.google.apphosting.utils.config.AbstractConfigXmlReader readConfigXml
- [java] INFO: Successfully processed gcm-demo-appengine/WebContent/WEB-INF/web.xml
- [java] Jun 15, 2012 8:46:09 PM com.google.android.gcm.demo.server.ApiKeyInitializer contextInitialized
- [java] SEVERE: Created fake key. Please go to App Engine admin console, change its value to your API Key (the entity type is 'Settings' and its field to be changed is 'ApiKey'), then restart the server!
- [java] Jun 15, 2012 8:46:09 PM com.google.appengine.tools.development.DevAppServerImpl start
- [java] INFO: The server is running at http://192.168.1.10:8080/
- [java] Jun 15, 2012 8:46:09 PM com.google.appengine.tools.development.DevAppServerImpl start
- [java] INFO: The admin console is running at http://192.168.1.10:8080/_ah/admin
-</pre>
-
- <li>Open the server's main page in a browser. The URL depends on the server you're using and your machine's IP address, but it will be something like <code>http://192.168.1.10:8080/home</code>, where <code>/home</code> is the path of the main servlet.</li>
-
- <p class="note"><strong>Note:</strong> You can get the IP by running <code>ifconfig</code> on Linux or MacOS, or <code>ipconfig</code> on Windows.</p>
-
+ <li>The system receives the incoming message and extracts the raw key/value
+pairs from the message payload, if any.</li>
+ <li>The system passes the key/value pairs to the targeted Android application
+in a <code>com.google.android.c2dm.intent.RECEIVE</code> Intent as a set of
+extras.</li>
+ <li>The Android application extracts the raw data
+from the <code>com.google.android.c2dm.intent.RECEIVE</code><code> </code>Intent
+by key and processes the data.</li>
</ol>
-<p> You server is now ready.</p>
-
+<p>See the documentation for each connection server for more detail on how it
+handles responses.</p>
diff --git a/docs/html/google/google_toc.cs b/docs/html/google/google_toc.cs
index 999c44e1734e..7f76c1242ad3 100644
--- a/docs/html/google/google_toc.cs
+++ b/docs/html/google/google_toc.cs
@@ -123,24 +123,27 @@
<span class="en">Google Cloud Messaging</span></a>
</div>
<ul>
+ <li><a href="<?cs var:toroot?>google/gcm/gcm.html">
+ <span class="en">Overview</span></a>
+ </li>
<li><a href="<?cs var:toroot?>google/gcm/gs.html">
<span class="en">Getting Started</span></a>
</li>
- <li><a href="<?cs var:toroot?>google/gcm/gcm.html">
- <span class="en">Architectural Overview</span></a>
+ <li><a href="<?cs var:toroot?>google/gcm/client.html">
+ <span class="en">Implementing GCM Client</span></a>
</li>
- <li><a href="<?cs var:toroot?>google/gcm/ccs.html">
- <span class="en">Cloud Connection Server</span></a>
+ <li class="nav-section"><div class="nav-section-header"><a href="<?cs var:toroot?>google/gcm/server.html">
+ <span class="en">Implementing GCM Server</span></a></div>
+ <ul>
+ <li><a href="<?cs var:toroot?>google/gcm/ccs.html">
+ <span class="en">CCS (XMPP)</span></a></li>
+ <li><a href="<?cs var:toroot?>google/gcm/http.html">
+ <span class="en">HTTP</span></a></li>
+ </ul>
</li>
<li><a href="<?cs var:toroot?>google/gcm/notifications.html">
<span class="en">User Notifications</span></a>
</li>
- <li><a href="<?cs var:toroot?>google/gcm/client.html">
- <span class="en">GCM Client</span></a>
- </li>
- <li><a href="<?cs var:toroot?>google/gcm/server.html">
- <span class="en">GCM Server</span></a>
- </li>
<li><a href="<?cs var:toroot?>google/gcm/adv.html">
<span class="en">Advanced Topics</span></a>
</li>
diff --git a/docs/html/images/gcm/CCS-ack.png b/docs/html/images/gcm/CCS-ack.png
new file mode 100644
index 000000000000..bce2ab2f5a1d
--- /dev/null
+++ b/docs/html/images/gcm/CCS-ack.png
Binary files differ
diff --git a/docs/html/images/gcm/GCM-arch.png b/docs/html/images/gcm/GCM-arch.png
new file mode 100644
index 000000000000..e8ffb154a36d
--- /dev/null
+++ b/docs/html/images/gcm/GCM-arch.png
Binary files differ
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index fdec22be9350..0ea4074c7eb0 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -114,9 +114,13 @@ public class Canvas {
* canvas.
*/
public Canvas() {
- // 0 means no native bitmap
- mNativeCanvas = initRaster(0);
- mFinalizer = new CanvasFinalizer(mNativeCanvas);
+ if (!isHardwareAccelerated()) {
+ // 0 means no native bitmap
+ mNativeCanvas = initRaster(0);
+ mFinalizer = new CanvasFinalizer(mNativeCanvas);
+ } else {
+ mFinalizer = null;
+ }
}
/**
@@ -1646,7 +1650,9 @@ public class Canvas {
*/
public void drawPicture(Picture picture) {
picture.endRecording();
- native_drawPicture(mNativeCanvas, picture.ni());
+ int restoreCount = save();
+ picture.draw(this);
+ restoreToCount(restoreCount);
}
/**
@@ -1831,7 +1837,5 @@ public class Canvas {
float hOffset,
float vOffset,
int flags, int paint);
- private static native void native_drawPicture(int nativeCanvas,
- int nativePicture);
private static native void finalizer(int nativeCanvas);
}
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 331cf6e6bc62..69d9916e3456 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -431,6 +431,8 @@ public class Paint {
mRasterizer = paint.mRasterizer;
if (paint.mShader != null) {
mShader = paint.mShader.copy();
+ } else {
+ mShader = null;
}
mTypeface = paint.mTypeface;
mXfermode = paint.mXfermode;
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 1b52b65457c7..42e11d009428 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -249,11 +249,16 @@ public:
}
// default empty constructor for bounds, to be overridden in child constructor body
- DrawBoundedOp(SkPaint* paint)
- : DrawOp(paint) {}
+ DrawBoundedOp(SkPaint* paint): DrawOp(paint) { }
bool getLocalBounds(Rect& localBounds) {
localBounds.set(mLocalBounds);
+ if (state.mDrawModifiers.mHasShadow) {
+ Rect shadow(mLocalBounds);
+ shadow.translate(state.mDrawModifiers.mShadowDx, state.mDrawModifiers.mShadowDy);
+ shadow.outset(state.mDrawModifiers.mShadowRadius);
+ localBounds.unionWith(shadow);
+ }
return true;
}
@@ -1442,8 +1447,10 @@ public:
}
virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
+ Rect bounds;
+ getLocalBounds(bounds);
return renderer.drawText(mText, mBytesCount, mCount, mX, mY,
- mPositions, getPaint(renderer), mTotalAdvance, mLocalBounds);
+ mPositions, getPaint(renderer), mTotalAdvance, bounds);
}
virtual status_t multiDraw(OpenGLRenderer& renderer, Rect& dirty,
@@ -1454,6 +1461,8 @@ public:
renderer.restoreDisplayState(ops[i]->state, true); // restore all but the clip
DrawTextOp& op = *((DrawTextOp*)ops[i]);
+ // quickReject() will not occure in drawText() so we can use mLocalBounds
+ // directly, we do not need to account for shadow by calling getLocalBounds()
status |= renderer.drawText(op.mText, op.mBytesCount, op.mCount, op.mX, op.mY,
op.mPositions, op.getPaint(renderer), op.mTotalAdvance, op.mLocalBounds,
drawOpMode);
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index ba4c2a0adcc9..90dcf931945e 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -464,10 +464,12 @@ void DisplayListRenderer::setupColorFilter(SkiaColorFilter* filter) {
void DisplayListRenderer::resetShadow() {
addStateOp(new (alloc()) ResetShadowOp());
+ OpenGLRenderer::resetShadow();
}
void DisplayListRenderer::setupShadow(float radius, float dx, float dy, int color) {
addStateOp(new (alloc()) SetupShadowOp(radius, dx, dy, color));
+ OpenGLRenderer::setupShadow(radius, dx, dy, color);
}
void DisplayListRenderer::resetPaintFilter() {
@@ -503,11 +505,17 @@ void DisplayListRenderer::addStateOp(StateOp* op) {
void DisplayListRenderer::addDrawOp(DrawOp* op) {
Rect localBounds;
+ if (mDrawModifiers.mHasShadow) {
+ op->state.mDrawModifiers = mDrawModifiers;
+ }
if (op->getLocalBounds(localBounds)) {
bool rejected = quickRejectNoScissor(localBounds.left, localBounds.top,
localBounds.right, localBounds.bottom);
op->setQuickRejected(rejected);
}
+ if (mDrawModifiers.mHasShadow) {
+ op->state.mDrawModifiers.reset();
+ }
mHasDrawOps = true;
addOpInternal(op);
}
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index d1bae1e45838..707f662bec4f 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1112,8 +1112,6 @@ void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) {
setupDrawMesh(&mMeshVertices[0].position[0], &mMeshVertices[0].texture[0]);
glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
-
- finishDrawTexture();
}
void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) {
@@ -1256,8 +1254,6 @@ void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) {
GL_UNSIGNED_SHORT, NULL));
}
- finishDrawTexture();
-
#if DEBUG_LAYERS_AS_REGIONS
drawRegionRects(layer->region);
#endif
@@ -2021,9 +2017,6 @@ void OpenGLRenderer::setupDrawIndexedVertices(GLvoid* vertices) {
mCaches.bindPositionVertexPointer(force, vertices, gVertexStride);
}
-void OpenGLRenderer::finishDrawTexture() {
-}
-
///////////////////////////////////////////////////////////////////////////////
// Drawing
///////////////////////////////////////////////////////////////////////////////
@@ -2308,8 +2301,6 @@ status_t OpenGLRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int mes
glDrawArrays(GL_TRIANGLES, 0, count);
- finishDrawTexture();
-
int slot = mCaches.currentProgram->getAttrib("colors");
if (slot >= 0) {
glDisableVertexAttribArray(slot);
@@ -3134,8 +3125,6 @@ status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y) {
mesh += (drawCount / 6) * 4;
}
- finishDrawTexture();
-
#if DEBUG_LAYERS_AS_REGIONS
drawRegionRects(layer->region);
#endif
@@ -3270,8 +3259,6 @@ void OpenGLRenderer::drawPathTexture(const PathTexture* texture,
setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset);
glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
-
- finishDrawTexture();
}
// Same values used by Skia
@@ -3488,8 +3475,6 @@ void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float b
setupDrawMesh(vertices, texCoords, vbo);
glDrawArrays(drawMode, 0, elementsCount);
-
- finishDrawTexture();
}
void OpenGLRenderer::drawIndexedTextureMesh(float left, float top, float right, float bottom,
@@ -3515,8 +3500,6 @@ void OpenGLRenderer::drawIndexedTextureMesh(float left, float top, float right,
setupDrawMeshIndices(vertices, texCoords, vbo);
glDrawElements(drawMode, elementsCount, GL_UNSIGNED_SHORT, NULL);
-
- finishDrawTexture();
}
void OpenGLRenderer::drawAlpha8TextureMesh(float left, float top, float right, float bottom,
@@ -3546,8 +3529,6 @@ void OpenGLRenderer::drawAlpha8TextureMesh(float left, float top, float right, f
setupDrawMesh(vertices, texCoords);
glDrawArrays(drawMode, 0, elementsCount);
-
- finishDrawTexture();
}
void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode,
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 2f8a2f0d28a7..54f6d76aa5f5 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -52,6 +52,14 @@ namespace android {
namespace uirenderer {
struct DrawModifiers {
+ DrawModifiers() {
+ reset();
+ }
+
+ void reset() {
+ memset(this, 0, sizeof(DrawModifiers));
+ }
+
SkiaShader* mShader;
SkiaColorFilter* mColorFilter;
float mOverrideLayerAlpha;
@@ -1003,7 +1011,6 @@ private:
void setupDrawMesh(GLvoid* vertices, GLvoid* texCoords, GLvoid* colors);
void setupDrawMeshIndices(GLvoid* vertices, GLvoid* texCoords, GLuint vbo = 0);
void setupDrawIndexedVertices(GLvoid* vertices);
- void finishDrawTexture();
void accountForClear(SkXfermode::Mode mode);
bool updateLayer(Layer* layer, bool inFrame);
diff --git a/location/lib/java/com/android/location/provider/FusedLocationHardware.java b/location/lib/java/com/android/location/provider/FusedLocationHardware.java
index abea9fb622a9..bc5a8a1a0f54 100644
--- a/location/lib/java/com/android/location/provider/FusedLocationHardware.java
+++ b/location/lib/java/com/android/location/provider/FusedLocationHardware.java
@@ -9,7 +9,7 @@
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIOS OF ANY KIND, either express or implied.
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@@ -21,20 +21,26 @@ import android.hardware.location.IFusedLocationHardwareSink;
import android.location.Location;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
-import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
/**
* Class that exposes IFusedLocationHardware functionality to unbundled services.
- * Namely this is used by GmsCore Fused Location Provider.
*/
public final class FusedLocationHardware {
private final String TAG = "FusedLocationHardware";
private IFusedLocationHardware mLocationHardware;
- ArrayList<FusedLocationHardwareSink> mSinkList = new ArrayList<FusedLocationHardwareSink>();
+
+ // the list uses a copy-on-write pattern to update its contents
+ HashMap<FusedLocationHardwareSink, DispatcherHandler> mSinkList =
+ new HashMap<FusedLocationHardwareSink, DispatcherHandler>();
private IFusedLocationHardwareSink mInternalSink = new IFusedLocationHardwareSink.Stub() {
@Override
@@ -48,6 +54,9 @@ public final class FusedLocationHardware {
}
};
+ /**
+ * @hide
+ */
public FusedLocationHardware(IFusedLocationHardware locationHardware) {
mLocationHardware = locationHardware;
}
@@ -55,19 +64,24 @@ public final class FusedLocationHardware {
/*
* Methods to provide a Facade for IFusedLocationHardware
*/
- public void registerSink(FusedLocationHardwareSink sink) {
- if(sink == null) {
- return;
+ public void registerSink(FusedLocationHardwareSink sink, Looper looper) {
+ if(sink == null || looper == null) {
+ throw new IllegalArgumentException("Parameter sink and looper cannot be null.");
}
- boolean registerSink = false;
+ boolean registerSink;
synchronized (mSinkList) {
// register only on first insertion
registerSink = mSinkList.size() == 0;
// guarantee uniqueness
- if(!mSinkList.contains(sink)) {
- mSinkList.add(sink);
+ if(mSinkList.containsKey(sink)) {
+ return;
}
+
+ HashMap<FusedLocationHardwareSink, DispatcherHandler> newSinkList =
+ new HashMap<FusedLocationHardwareSink, DispatcherHandler>(mSinkList);
+ newSinkList.put(sink, new DispatcherHandler(looper));
+ mSinkList = newSinkList;
}
if(registerSink) {
@@ -81,14 +95,23 @@ public final class FusedLocationHardware {
public void unregisterSink(FusedLocationHardwareSink sink) {
if(sink == null) {
- return;
+ throw new IllegalArgumentException("Parameter sink cannot be null.");
}
- boolean unregisterSink = false;
+ boolean unregisterSink;
synchronized(mSinkList) {
- mSinkList.remove(sink);
- // unregister after the last sink
- unregisterSink = mSinkList.size() == 0;
+ if(!mSinkList.containsKey(sink)) {
+ //done
+ return;
+ }
+
+ HashMap<FusedLocationHardwareSink, DispatcherHandler> newSinkList =
+ new HashMap<FusedLocationHardwareSink, DispatcherHandler>(mSinkList);
+ newSinkList.remove(sink);
+ //unregister after the last sink
+ unregisterSink = newSinkList.size() == 0;
+
+ mSinkList = newSinkList;
}
if(unregisterSink) {
@@ -176,27 +199,82 @@ public final class FusedLocationHardware {
}
/*
- * Helper methods
+ * Helper methods and classes
*/
+ private class DispatcherHandler extends Handler {
+ public static final int DISPATCH_LOCATION = 1;
+ public static final int DISPATCH_DIAGNOSTIC_DATA = 2;
+
+ public DispatcherHandler(Looper looper) {
+ super(looper, null /*callback*/ , true /*async*/);
+ }
+
+ @Override
+ public void handleMessage(Message message) {
+ MessageCommand command = (MessageCommand) message.obj;
+ switch(message.what) {
+ case DISPATCH_LOCATION:
+ command.dispatchLocation();
+ break;
+ case DISPATCH_DIAGNOSTIC_DATA:
+ command.dispatchDiagnosticData();
+ default:
+ Log.e(TAG, "Invalid dispatch message");
+ break;
+ }
+ }
+ }
+
+ private class MessageCommand {
+ private final FusedLocationHardwareSink mSink;
+ private final Location[] mLocations;
+ private final String mData;
+
+ public MessageCommand(
+ FusedLocationHardwareSink sink,
+ Location[] locations,
+ String data) {
+ mSink = sink;
+ mLocations = locations;
+ mData = data;
+ }
+
+ public void dispatchLocation() {
+ mSink.onLocationAvailable(mLocations);
+ }
+
+ public void dispatchDiagnosticData() {
+ mSink.onDiagnosticDataAvailable(mData);
+ }
+ }
+
private void dispatchLocations(Location[] locations) {
- ArrayList<FusedLocationHardwareSink> sinks = null;
+ HashMap<FusedLocationHardwareSink, DispatcherHandler> sinks;
synchronized (mSinkList) {
- sinks = new ArrayList<FusedLocationHardwareSink>(mSinkList);
+ sinks = mSinkList;
}
- for(FusedLocationHardwareSink sink : sinks) {
- sink.onLocationAvailable(locations);
+ for(Map.Entry<FusedLocationHardwareSink, DispatcherHandler> entry : sinks.entrySet()) {
+ Message message = Message.obtain(
+ entry.getValue(),
+ DispatcherHandler.DISPATCH_LOCATION,
+ new MessageCommand(entry.getKey(), locations, null /*data*/));
+ message.sendToTarget();
}
}
private void dispatchDiagnosticData(String data) {
- ArrayList<FusedLocationHardwareSink> sinks = null;
+ HashMap<FusedLocationHardwareSink, DispatcherHandler> sinks;
synchronized(mSinkList) {
- sinks = new ArrayList<FusedLocationHardwareSink>(mSinkList);
+ sinks = mSinkList;
}
- for(FusedLocationHardwareSink sink : sinks) {
- sink.onDiagnosticDataAvailable(data);
+ for(Map.Entry<FusedLocationHardwareSink, DispatcherHandler> entry : sinks.entrySet()) {
+ Message message = Message.obtain(
+ entry.getValue(),
+ DispatcherHandler.DISPATCH_DIAGNOSTIC_DATA,
+ new MessageCommand(entry.getKey(), null /*locations*/, data));
+ message.sendToTarget();
}
}
}
diff --git a/location/lib/java/com/android/location/provider/FusedLocationHardwareSink.java b/location/lib/java/com/android/location/provider/FusedLocationHardwareSink.java
index 118b6633972b..2c39fa86a459 100644
--- a/location/lib/java/com/android/location/provider/FusedLocationHardwareSink.java
+++ b/location/lib/java/com/android/location/provider/FusedLocationHardwareSink.java
@@ -20,7 +20,6 @@ import android.location.Location;
/**
* Base class for sinks to interact with FusedLocationHardware.
- * This is mainly used by GmsCore Fused Provider.
*/
public abstract class FusedLocationHardwareSink {
/*
diff --git a/location/lib/java/com/android/location/provider/FusedProvider.java b/location/lib/java/com/android/location/provider/FusedProvider.java
index bc9feefee52f..c966adeadc6f 100644
--- a/location/lib/java/com/android/location/provider/FusedProvider.java
+++ b/location/lib/java/com/android/location/provider/FusedProvider.java
@@ -28,8 +28,6 @@ import android.os.IBinder;
*
* <p>IMPORTANT: This class is effectively a public API for unbundled applications, and must remain
* API stable. See README.txt in the root of this package for more information.
- *
- * @hide
*/
public abstract class FusedProvider {
private IFusedProvider.Stub mProvider = new IFusedProvider.Stub() {
diff --git a/media/mca/filterfw/native/core/gl_env.cpp b/media/mca/filterfw/native/core/gl_env.cpp
index fdecda378220..84dad8ca70ee 100644
--- a/media/mca/filterfw/native/core/gl_env.cpp
+++ b/media/mca/filterfw/native/core/gl_env.cpp
@@ -26,6 +26,8 @@
#include <string>
#include <EGL/eglext.h>
+#include <gui/GLConsumer.h>
+
namespace android {
namespace filterfw {
diff --git a/media/mca/filterfw/native/core/gl_env.h b/media/mca/filterfw/native/core/gl_env.h
index 81e1e9dcb7a2..a709638f1c34 100644
--- a/media/mca/filterfw/native/core/gl_env.h
+++ b/media/mca/filterfw/native/core/gl_env.h
@@ -31,6 +31,9 @@
#include <gui/Surface.h>
namespace android {
+
+class GLConsumer;
+
namespace filterfw {
class ShaderProgram;
diff --git a/obex/javax/obex/ClientOperation.java b/obex/javax/obex/ClientOperation.java
index 05b498c1357f..294b50240daf 100644
--- a/obex/javax/obex/ClientOperation.java
+++ b/obex/javax/obex/ClientOperation.java
@@ -723,4 +723,7 @@ public final class ClientOperation implements Operation, BaseStream {
}
}
}
+
+ public void noBodyHeader(){
+ }
}
diff --git a/obex/javax/obex/HeaderSet.java b/obex/javax/obex/HeaderSet.java
index b89b707266fb..2b3066f0bda5 100644
--- a/obex/javax/obex/HeaderSet.java
+++ b/obex/javax/obex/HeaderSet.java
@@ -464,6 +464,8 @@ public final class HeaderSet {
return mHttpHeader;
case WHO:
return mWho;
+ case CONNECTION_ID:
+ return mConnectionID;
case OBJECT_CLASS:
return mObjectClass;
case APPLICATION_PARAMETER:
diff --git a/obex/javax/obex/Operation.java b/obex/javax/obex/Operation.java
index 25656ed5d6ab..5b4d5ace3669 100644
--- a/obex/javax/obex/Operation.java
+++ b/obex/javax/obex/Operation.java
@@ -178,4 +178,6 @@ public interface Operation {
void close() throws IOException;
int getMaxPacketSize();
+
+ public void noBodyHeader();
}
diff --git a/obex/javax/obex/ServerOperation.java b/obex/javax/obex/ServerOperation.java
index d1476d271cfc..fc441e0e165c 100644
--- a/obex/javax/obex/ServerOperation.java
+++ b/obex/javax/obex/ServerOperation.java
@@ -88,6 +88,8 @@ public final class ServerOperation implements Operation, BaseStream {
private boolean mHasBody;
+ private boolean mSendBodyHeader = true;
+
/**
* Creates new ServerOperation
* @param p the parent that created this object
@@ -364,24 +366,33 @@ public final class ServerOperation implements Operation, BaseStream {
* (End of Body) otherwise, we need to send 0x48 (Body)
*/
if ((finalBitSet) || (mPrivateOutput.isClosed())) {
- out.write(0x49);
+ if(mSendBodyHeader == true) {
+ out.write(0x49);
+ bodyLength += 3;
+ out.write((byte)(bodyLength >> 8));
+ out.write((byte)bodyLength);
+ out.write(body);
+ }
} else {
+ if(mSendBodyHeader == true) {
out.write(0x48);
+ bodyLength += 3;
+ out.write((byte)(bodyLength >> 8));
+ out.write((byte)bodyLength);
+ out.write(body);
+ }
}
- bodyLength += 3;
- out.write((byte)(bodyLength >> 8));
- out.write((byte)bodyLength);
- out.write(body);
}
}
if ((finalBitSet) && (type == ResponseCodes.OBEX_HTTP_OK) && (orginalBodyLength <= 0)) {
- out.write(0x49);
- orginalBodyLength = 3;
- out.write((byte)(orginalBodyLength >> 8));
- out.write((byte)orginalBodyLength);
-
+ if(mSendBodyHeader == true) {
+ out.write(0x49);
+ orginalBodyLength = 3;
+ out.write((byte)(orginalBodyLength >> 8));
+ out.write((byte)orginalBodyLength);
+ }
}
mResponseSize = 3;
@@ -711,4 +722,8 @@ public final class ServerOperation implements Operation, BaseStream {
public void streamClosed(boolean inStream) throws IOException {
}
+
+ public void noBodyHeader(){
+ mSendBodyHeader = false;
+ }
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index 8e7e087c487d..a536acbc3c8c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -72,7 +72,7 @@ public class DocumentsActivity extends Activity {
private final DisplayState mDisplayState = new DisplayState();
/** Current user navigation stack; empty implies recents. */
- private DocumentStack mStack;
+ private DocumentStack mStack = new DocumentStack();
/** Currently active search, overriding any stack. */
private String mCurrentSearch;
diff --git a/packages/PrintSpooler/src/com/android/printspooler/NotificationController.java b/packages/PrintSpooler/src/com/android/printspooler/NotificationController.java
index 130320b83f8d..c116d37cc635 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/NotificationController.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/NotificationController.java
@@ -86,7 +86,7 @@ public class NotificationController {
printJob.getLabel()))
.addAction(R.drawable.stat_notify_cancelling, mContext.getString(R.string.cancel),
createCancelIntent(printJob))
- .setContentText(printJob.getPrinterId().getPrinterName())
+ .setContentText(printJob.getPrinterName())
.setWhen(System.currentTimeMillis())
.setOngoing(true)
.setShowWhen(true);
@@ -119,7 +119,7 @@ public class NotificationController {
intent.setAction(INTENT_ACTION_CANCEL_PRINTJOB + "_" + String.valueOf(printJob.getId()));
intent.putExtra(INTENT_EXTRA_PRINTJOB_ID, printJob.getId());
intent.putExtra(INTENT_EXTRA_PRINTJOB_LABEL, printJob.getLabel());
- intent.putExtra(INTENT_EXTRA_PRINTER_NAME, printJob.getPrinterId().getPrinterName());
+ intent.putExtra(INTENT_EXTRA_PRINTER_NAME, printJob.getPrinterName());
return PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_ONE_SHOT);
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
index 654bb6d9155c..9160b7d1ffe8 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
@@ -34,7 +34,8 @@ import android.os.Message;
import android.os.RemoteException;
import android.print.ILayoutResultCallback;
import android.print.IPrintDocumentAdapter;
-import android.print.IPrinterDiscoveryObserver;
+import android.print.IPrinterDiscoverySessionController;
+import android.print.IPrinterDiscoverySessionObserver;
import android.print.IWriteResultCallback;
import android.print.PageRange;
import android.print.PrintAttributes;
@@ -42,6 +43,7 @@ import android.print.PrintAttributes.MediaSize;
import android.print.PrintDocumentAdapter;
import android.print.PrintDocumentInfo;
import android.print.PrintJobInfo;
+import android.print.PrinterCapabilitiesInfo;
import android.print.PrinterId;
import android.print.PrinterInfo;
import android.text.Editable;
@@ -70,6 +72,7 @@ import android.widget.TextView;
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;
@@ -133,7 +136,7 @@ public class PrintJobConfigActivity extends Activity {
private Editor mEditor;
private Document mDocument;
private PrintController mController;
- private PrinterDiscoveryObserver mPrinterDiscoveryObserver;
+ private PrinterDiscoverySessionObserver mPrinterDiscoverySessionObserver;
private int mPrintJobId;
@@ -181,8 +184,9 @@ public class PrintJobConfigActivity extends Activity {
mController.initialize();
mEditor.initialize();
- mPrinterDiscoveryObserver = new PrinterDiscoveryObserver(mEditor, getMainLooper());
- mSpooler.startPrinterDiscovery(mPrinterDiscoveryObserver);
+ mPrinterDiscoverySessionObserver = new PrinterDiscoverySessionObserver(mEditor,
+ getMainLooper());
+ mSpooler.createPrinterDiscoverySession(mPrinterDiscoverySessionObserver);
}
@Override
@@ -190,9 +194,9 @@ 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.
- mSpooler.stopPrinterDiscovery();
- mPrinterDiscoveryObserver.destroy();
- mPrinterDiscoveryObserver = null;
+ mPrinterDiscoverySessionObserver.close();
+ mPrinterDiscoverySessionObserver.destroy();
+ mPrinterDiscoverySessionObserver = null;
if (mController.hasStarted()) {
mController.finish();
}
@@ -622,14 +626,15 @@ public class PrintJobConfigActivity extends Activity {
SpinnerItem<PrinterInfo> dstItem = mDestinationSpinnerAdapter.getItem(position);
if (dstItem != null) {
PrinterInfo printer = dstItem.value;
- mSpooler.setPrintJobPrinterIdNoPersistence(mPrintJobId, printer.getId());
- printer.getDefaults(mCurrPrintAttributes);
- if (!printer.hasAllRequiredAttributes()) {
+ mSpooler.setPrintJobPrinterNoPersistence(mPrintJobId, printer);
+ PrinterCapabilitiesInfo capabilities = printer.getCapabilities();
+ if (capabilities == null) {
List<PrinterId> printerIds = new ArrayList<PrinterId>();
printerIds.add(printer.getId());
- mSpooler.onReqeustUpdatePrinters(printerIds);
+ mPrinterDiscoverySessionObserver.requestPrinterUpdate(printer.getId());
//TODO: We need a timeout for the update.
} else {
+ capabilities.getDefaults(mCurrPrintAttributes);
if (!mController.hasStarted()) {
mController.start();
}
@@ -1058,8 +1063,8 @@ public class PrintJobConfigActivity extends Activity {
final int selectedIndex = mDestinationSpinner.getSelectedItemPosition();
- if (selectedIndex < 0 || !mDestinationSpinnerAdapter.getItem(
- selectedIndex).value.hasAllRequiredAttributes()) {
+ if (selectedIndex < 0 || mDestinationSpinnerAdapter.getItem(
+ selectedIndex).value.getCapabilities() == null) {
// Destination
mDestinationSpinner.setEnabled(false);
@@ -1117,7 +1122,8 @@ public class PrintJobConfigActivity extends Activity {
} else {
PrintAttributes defaultAttributes = mTempPrintAttributes;
PrinterInfo printer = mDestinationSpinnerAdapter.getItem(selectedIndex).value;
- printer.getDefaults(defaultAttributes);
+ PrinterCapabilitiesInfo capabilities = printer.getCapabilities();
+ printer.getCapabilities().getDefaults(defaultAttributes);
// Destination
if (mDestinationSpinnerAdapter.getCount() > 1) {
@@ -1130,7 +1136,7 @@ public class PrintJobConfigActivity extends Activity {
mCopiesEditText.setEnabled(true);
// Media size.
- List<MediaSize> mediaSizes = printer.getMediaSizes();
+ List<MediaSize> mediaSizes = capabilities.getMediaSizes();
boolean mediaSizesChanged = false;
final int mediaSizeCount = mediaSizes.size();
if (mediaSizeCount != mMediaSizeSpinnerAdapter.getCount()) {
@@ -1168,7 +1174,7 @@ public class PrintJobConfigActivity extends Activity {
}
// Color mode.
- final int colorModes = printer.getColorModes();
+ final int colorModes = capabilities.getColorModes();
boolean colorModesChanged = false;
if (Integer.bitCount(colorModes) != mColorModeSpinnerAdapter.getCount()) {
colorModesChanged = true;
@@ -1219,7 +1225,7 @@ public class PrintJobConfigActivity extends Activity {
}
// Orientation.
- final int orientations = printer.getOrientations();
+ final int orientations = capabilities.getOrientations();
boolean orientationsChanged = false;
if (Integer.bitCount(orientations) != mOrientationSpinnerAdapter.getCount()) {
orientationsChanged = true;
@@ -1345,7 +1351,7 @@ public class PrintJobConfigActivity extends Activity {
}
if (!duplicate) {
mDestinationSpinnerAdapter.add(new SpinnerItem<PrinterInfo>(
- addedPrinter, addedPrinter.getId().getPrinterName()));
+ addedPrinter, addedPrinter.getName()));
} else {
Log.w(LOG_TAG, "Skipping a duplicate printer: " + addedPrinter);
}
@@ -1470,7 +1476,7 @@ public class PrintJobConfigActivity extends Activity {
PrinterInfo printerInfo = getItem(position).value;
TextView title = (TextView) convertView.findViewById(R.id.title);
- title.setText(printerInfo.getId().getPrinterName());
+ title.setText(printerInfo.getName());
try {
TextView subtitle = (TextView)
@@ -1489,21 +1495,35 @@ public class PrintJobConfigActivity extends Activity {
}
}
- private static final class PrinterDiscoveryObserver extends IPrinterDiscoveryObserver.Stub {
- private static final int MSG_ON_PRINTERS_ADDED = 1;
- private static final int MSG_ON_PRINTERS_REMOVED = 2;
- private static final int MSG_ON_PRINTERS_UPDATED = 3;
+ 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 PrinterDiscoveryObserver(Editor editor, Looper looper) {
+ 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);
@@ -1523,6 +1543,46 @@ public class PrintJobConfigActivity extends Activity {
};
}
+ 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);
+ }
+ }
+ }
+
+ 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();
+ }
+ }
+ }
+
@Override
public void onPrintersAdded(List<PrinterInfo> printers) {
synchronized (this) {
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintSpooler.java b/packages/PrintSpooler/src/com/android/printspooler/PrintSpooler.java
index 00e05bb15688..1b8b81a21fa6 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintSpooler.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintSpooler.java
@@ -21,7 +21,7 @@ import android.content.Context;
import android.os.AsyncTask;
import android.os.ParcelFileDescriptor;
import android.print.IPrintClient;
-import android.print.IPrinterDiscoveryObserver;
+import android.print.IPrinterDiscoverySessionObserver;
import android.print.PageRange;
import android.print.PrintAttributes;
import android.print.PrintAttributes.Margins;
@@ -32,6 +32,7 @@ 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;
@@ -199,16 +200,8 @@ public class PrintSpooler {
}
}
- public void startPrinterDiscovery(IPrinterDiscoveryObserver observer) {
- mService.startPrinterDiscovery(observer);
- }
-
- public void stopPrinterDiscovery() {
- mService.stopPrinterDiscovery();
- }
-
- public void onReqeustUpdatePrinters(List<PrinterId> printerIds) {
- mService.onReqeustUpdatePrinters(printerIds);
+ public void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer) {
+ mService.createPrinterDiscoverySession(observer);
}
private int generatePrintJobIdLocked() {
@@ -417,11 +410,12 @@ public class PrintSpooler {
}
}
- public void setPrintJobPrinterIdNoPersistence(int printJobId, PrinterId printerId) {
+ public void setPrintJobPrinterNoPersistence(int printJobId, PrinterInfo printer) {
synchronized (mLock) {
PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
if (printJob != null) {
- printJob.setPrinterId(printerId);
+ printJob.setPrinterId(printer.getId());
+ printJob.setPrinterName(printer.getName());
}
}
}
@@ -500,6 +494,7 @@ public class PrintSpooler {
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";
@@ -573,7 +568,7 @@ public class PrintSpooler {
PrinterId printerId = printJob.getPrinterId();
if (printerId != null) {
serializer.startTag(null, TAG_PRINTER_ID);
- serializer.attribute(null, ATTR_PRINTER_NAME, printerId.getPrinterName());
+ serializer.attribute(null, ATTR_PRINTER_NAME, printerId.getLocalId());
serializer.attribute(null, ATTR_SERVICE_NAME, printerId.getServiceName()
.flattenToString());
serializer.endTag(null, TAG_PRINTER_ID);
@@ -675,6 +670,7 @@ public class PrintSpooler {
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(
@@ -921,11 +917,13 @@ public class PrintSpooler {
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().setPageCount(pageCount)
+ PrintDocumentInfo info = new PrintDocumentInfo.Builder(name)
+ .setPageCount(pageCount)
.setContentType(contentType).create();
printJob.setDocumentInfo(info);
parser.next();
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java b/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
index e5153e759263..4fab4f886d5c 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
@@ -32,10 +32,9 @@ import android.print.IPrintDocumentAdapter;
import android.print.IPrintSpooler;
import android.print.IPrintSpoolerCallbacks;
import android.print.IPrintSpoolerClient;
-import android.print.IPrinterDiscoveryObserver;
+import android.print.IPrinterDiscoverySessionObserver;
import android.print.PrintAttributes;
import android.print.PrintJobInfo;
-import android.print.PrinterId;
import android.util.Log;
import android.util.Slog;
@@ -167,20 +166,11 @@ public final class PrintSpoolerService extends Service {
printJob).sendToTarget();
}
- public void onReqeustUpdatePrinters(List<PrinterId> printers) {
- mHandler.obtainMessage(MyHandler.MSG_ON_REQUEST_UPDATE_PRINTERS,
- printers).sendToTarget();
- }
-
- public void startPrinterDiscovery(IPrinterDiscoveryObserver observer) {
- mHandler.obtainMessage(MyHandler.MSG_ON_START_PRINTER_DISCOVERY,
+ public void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer) {
+ mHandler.obtainMessage(MyHandler.MSG_CREATE_PRINTER_DISCOVERY_SESSION,
observer).sendToTarget();
}
- public void stopPrinterDiscovery() {
- mHandler.sendEmptyMessage(MyHandler.MSG_ON_STOP_PRINTER_DISCOVERY);
- }
-
public void onAllPrintJobsForServiceHandled(ComponentName service) {
mHandler.obtainMessage(MyHandler.MSG_ON_ALL_PRINT_JOBS_FOR_SERIVICE_HANDLED,
service).sendToTarget();
@@ -193,12 +183,10 @@ public final class PrintSpoolerService extends Service {
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_ON_START_PRINTER_DISCOVERY = 3;
- public static final int MSG_ON_STOP_PRINTER_DISCOVERY = 4;
+ 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_ON_REQUEST_UPDATE_PRINTERS = 8;
public static final int MSG_CHECK_ALL_PRINTJOBS_HANDLED = 9;
public MyHandler(Looper looper) {
@@ -206,7 +194,6 @@ public final class PrintSpoolerService extends Service {
}
@Override
- @SuppressWarnings("unchecked")
public void handleMessage(Message message) {
switch (message.what) {
case MSG_SET_CLIENT: {
@@ -233,23 +220,14 @@ public final class PrintSpoolerService extends Service {
}
} break;
- case MSG_ON_START_PRINTER_DISCOVERY: {
- IPrinterDiscoveryObserver observer = (IPrinterDiscoveryObserver) message.obj;
- if (mClient != null) {
- try {
- mClient.onStartPrinterDiscovery(observer);
- } catch (RemoteException re) {
- Log.e(LOG_TAG, "Error notifying start printer discovery.", re);
- }
- }
- } break;
-
- case MSG_ON_STOP_PRINTER_DISCOVERY: {
+ case MSG_CREATE_PRINTER_DISCOVERY_SESSION: {
+ IPrinterDiscoverySessionObserver observer =
+ (IPrinterDiscoverySessionObserver) message.obj;
if (mClient != null) {
try {
- mClient.onStopPrinterDiscovery();
+ mClient.createPrinterDiscoverySession(observer);
} catch (RemoteException re) {
- Log.e(LOG_TAG, "Error notifying stop printer discovery.", re);
+ Log.e(LOG_TAG, "Error creating printer discovery session.", re);
}
}
} break;
@@ -287,17 +265,6 @@ public final class PrintSpoolerService extends Service {
}
} break;
- case MSG_ON_REQUEST_UPDATE_PRINTERS: {
- List<PrinterId> printerIds = (List<PrinterId>) message.obj;
- if (mClient != null) {
- try {
- mClient.onRequestUpdatePrinters(printerIds);
- } catch (RemoteException re) {
- Slog.e(LOG_TAG, "Error requesting to update pritners.", re);
- }
- }
- } break;
-
case MSG_CHECK_ALL_PRINTJOBS_HANDLED: {
PrintSpooler spooler = PrintSpooler.peekInstance();
if (spooler != null) {
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 05618bdfa57f..42ec9c518118 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -164,6 +164,8 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi gekoppel"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Soek vir GPS"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"Ligging deur GPS gestel"</string>
+ <!-- no translation found for accessibility_location_active (2427290146138169014) -->
+ <skip />
<string name="accessibility_clear_all" msgid="5235938559247164925">"Verwyder alle kennisgewings."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Programinligting"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Die skerm sal outomaties draai."</string>
@@ -200,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Sleep rand van skerm om balk te wys"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Sleep van rand van skerm af om stelselbalk te wys"</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 1d81ea7ced8c..41610a6ada84 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -164,6 +164,8 @@
<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_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>
@@ -200,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"አሞሌá‹áŠ• ለማሳየት የማያ ገጹን ጠርዠላይ ያንሸራትቱ"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"አሞሌá‹áŠ• ለማሳየት ከማያ ገጹ ጠርዠጀáˆáˆ¨á‹ ያንሸራትቱ"</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 c31d6d977428..291bcf5a50fc 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -164,6 +164,8 @@
<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_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>
@@ -200,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"مرر سريعًا Ù„Ø­Ø§ÙØ© الشاشة لإظهار الشريط"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"مرر سريعًا من Ø­Ø§ÙØ© الشاشة لإظهار شريط النظام"</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-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 6608b7906e8f..aaca584a2622 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -166,6 +166,8 @@
<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_clear_all" msgid="5235938559247164925">"Выдалiць уÑе апавÑшчÑннi."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Ð†Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ Ð¿Ñ€Ð° прыкладанне"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Экран паварочваецца аўтаматычна."</string>
@@ -204,8 +206,8 @@
<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 hideybar_confirmation_message (9050869548951044371) -->
+ <!-- no translation found for hiding_navigation_confirmation_message (3227814171674734332) -->
<skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
+ <!-- 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 6bf1040c91f8..b10f5ff14548 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -164,6 +164,8 @@
<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_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>
@@ -200,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Прекарайте пръÑÑ‚ по ръба на екрана, за да Ñе покаже лентата"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Прекарайте пръÑÑ‚ от ръба на екрана, за да Ñе покаже ÑиÑтемната лента"</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 eddeda3ace6e..0a9500523519 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -166,6 +166,8 @@
<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_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>
@@ -202,6 +204,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Fes lliscar el dit per la vora de la pantalla perquè es mostri la barra"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Fes lliscar el dit des de la vora de la pantalla perquè es mostri la barra 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 87ba67aa928e..f7f56c06cbbb 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -166,6 +166,8 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi: připojeno"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Vyhledávání satelitů GPS"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"Poloha nastavena pomocí systému GPS"</string>
+ <!-- no translation found for accessibility_location_active (2427290146138169014) -->
+ <skip />
<string name="accessibility_clear_all" msgid="5235938559247164925">"Vymazat všechna oznámení."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informace o aplikaci"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Obrazovka se automaticky otoÄí."</string>
@@ -184,10 +186,8 @@
<string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Automatické otáÄení"</string>
<string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"OtáÄení je uzamÄeno"</string>
<string name="quick_settings_ime_label" msgid="7073463064369468429">"Metoda zadávání dat"</string>
- <!-- no translation found for quick_settings_location_label (5011327048748762257) -->
- <skip />
- <!-- no translation found for quick_settings_location_off_label (7464544086507331459) -->
- <skip />
+ <string name="quick_settings_location_label" msgid="5011327048748762257">"Poloha"</string>
+ <string name="quick_settings_location_off_label" msgid="7464544086507331459">"Poloha vypnuta"</string>
<string name="quick_settings_media_device_label" msgid="1302906836372603762">"Mediální zařízení"</string>
<string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Pouze tísňová volání"</string>
@@ -204,6 +204,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Panel zobrazíte přejetím přes okraj obrazovky"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Systémový panel zobrazíte přejetím přes okraj obrazovky"</string>
+ <string name="hiding_navigation_confirmation_message" msgid="3227814171674734332">"Panel zobrazíte přejetím přes okraj obrazovky nahoru"</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 af4bb336e472..1c772b5715ef 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -164,6 +164,8 @@
<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_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>
@@ -200,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Stryg kanten af skærmen for at se bjælken"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Stryg fra skærmens kant for at se systembjælken"</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 2b59228f052b..86ea82ddb7c5 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -166,6 +166,8 @@
<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_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>
@@ -202,6 +204,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Zum Einblenden der Leiste vom Rand wischen"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Zum Einblenden der Systemleiste vom Display-Rand weg wischen"</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 ab43081a1679..cfd396eaddcd 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -166,6 +166,8 @@
<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_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 +204,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"ΣÏÏετε από την άκÏη της οθόνης για να εμφανίσετε τη γÏαμμή"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"ΣÏÏετε από την άκÏη της οθόνης για να εμφανίσετε τη γÏαμμή συστήματος"</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 6027553f4091..017844ca316e 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -164,6 +164,8 @@
<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>
+ <!-- no translation found for accessibility_location_active (2427290146138169014) -->
+ <skip />
<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>
@@ -200,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Swipe edge of screen to reveal bar"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Swipe from edge of screen to reveal system bar"</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-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 2a0f1f7e1c83..bdd036302e5c 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -166,6 +166,8 @@
<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_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>
@@ -202,6 +204,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Desliza el dedo desde el borde de la pantalla para mostrar la barra."</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Desliza el dedo desde el borde de la pantalla para mostrar la barra 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 64c3cab7fa76..4ae896755a4c 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -164,6 +164,8 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Con conexión Wi-Fi"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Buscando GPS"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"Ubicación definida por GPS"</string>
+ <!-- no translation found for accessibility_location_active (2427290146138169014) -->
+ <skip />
<string name="accessibility_clear_all" msgid="5235938559247164925">"Borrar 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>
@@ -200,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Desliza el borde de la pantalla para mostrar la barra"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Desliza el borde de la pantalla para mostrar la barra 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 6d9c838599d4..90a96268ecd2 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -164,6 +164,8 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"WiFi on ühendatud"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS-i otsimine"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS-i määratud asukoht"</string>
+ <!-- no translation found for accessibility_location_active (2427290146138169014) -->
+ <skip />
<string name="accessibility_clear_all" msgid="5235938559247164925">"Kustuta kõik teatised."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Rakenduse teave"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekraani pööramine toimub automaatselt."</string>
@@ -200,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Riba kuvamiseks pühkige ekraani serva"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Süsteemiriba kuvamiseks pühkige ekraani servast"</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 5f35ce6dc9d5..7fb8a119336b 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -164,6 +164,8 @@
<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_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>
@@ -200,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"برای نمایش نوار، انگشت خود را از لبه‌ ØµÙØ­Ù‡ به داخل بکشید"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"برای نمایش نوار سیستم، انگشت خود را از لبه‌ ØµÙØ­Ù‡ به داخل بکشید"</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 06e1926bf5ac..a5f834d6a9d4 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -164,6 +164,8 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wifi yhdistetty"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Haetaan GPS-yhteyttä"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"Sijainti määritetty GPS:n avulla"</string>
+ <!-- no translation found for accessibility_location_active (2427290146138169014) -->
+ <skip />
<string name="accessibility_clear_all" msgid="5235938559247164925">"Tyhjennä kaikki ilmoitukset."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Sovelluksen tiedot"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ruutu kääntyy automaattisesti."</string>
@@ -200,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Tuo palkki näkyviin liu\'uttamalla ruudun reunasta"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Tuo järjestelmäpalkki näkyviin liu\'uttamalla ruudun reunasta"</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/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 7db07e2a89c4..7fe114332749 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -166,6 +166,8 @@
<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_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>
@@ -184,10 +186,8 @@
<string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Rotation auto"</string>
<string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Rotation bloquée"</string>
<string name="quick_settings_ime_label" msgid="7073463064369468429">"Mode de saisie"</string>
- <!-- no translation found for quick_settings_location_label (5011327048748762257) -->
- <skip />
- <!-- no translation found for quick_settings_location_off_label (7464544086507331459) -->
- <skip />
+ <string name="quick_settings_location_label" msgid="5011327048748762257">"Localisation"</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>
@@ -204,6 +204,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Faites glisser votre doigt sur le côté de l\'écran pour afficher la barre."</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Faites glisser votre doigt à partir d\'un côté de l\'écran pour afficher la barre 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 862e2ef5346b..c02fc2be93b1 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -164,6 +164,8 @@
<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_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>
@@ -200,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"बार दिखाने के लिठसà¥à¤•à¥à¤°à¥€à¤¨ के किनारे को सà¥à¤µà¤¾à¤‡à¤ª करें"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"सिसà¥à¤Ÿà¤® बार दिखाने के लिठसà¥à¤•à¥à¤°à¥€à¤¨ के किनारे से सà¥à¤µà¤¾à¤‡à¤ª करें"</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 631d54961252..8989d0db858e 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -164,6 +164,8 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi povezan"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Traženje GPS-a"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"Lokaciju utvrdio GPS"</string>
+ <!-- no translation found for accessibility_location_active (2427290146138169014) -->
+ <skip />
<string name="accessibility_clear_all" msgid="5235938559247164925">"Brisanje svih obavijesti."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informacije o aplikaciji"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Zaslon će se automatski zakrenuti."</string>
@@ -200,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Prijeđite prstom po rubu zaslona da bi se prikazala traka"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Prijeđite prstom od ruba zaslona da bi se prikazala traka 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 c1c9136b00e3..567b2fcd92a4 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -164,6 +164,8 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi csatlakoztatva"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS keresése"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"A GPS beállította a helyet"</string>
+ <!-- no translation found for accessibility_location_active (2427290146138169014) -->
+ <skip />
<string name="accessibility_clear_all" msgid="5235938559247164925">"Minden értesítés törlése"</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Alkalmazásinformáció"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"A képernyő automatikusan forogni fog."</string>
@@ -200,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Csúsztassa ujját a képernyő szélén a sáv megjelenítéséhez"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Csúsztassa ujját a képernyő szélétől a rendszersáv megjeleníté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-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 6a702b9f3f85..013bd99f6e82 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -164,6 +164,8 @@
<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_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>
@@ -182,10 +184,8 @@
<string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Rotasi Otomatis"</string>
<string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Rotasi Dikunci"</string>
<string name="quick_settings_ime_label" msgid="7073463064369468429">"Metode Masukan"</string>
- <!-- no translation found for quick_settings_location_label (5011327048748762257) -->
- <skip />
- <!-- no translation found for quick_settings_location_off_label (7464544086507331459) -->
- <skip />
+ <string name="quick_settings_location_label" msgid="5011327048748762257">"Lokasi"</string>
+ <string name="quick_settings_location_off_label" msgid="7464544086507331459">"Lokasi Mati"</string>
<string name="quick_settings_media_device_label" msgid="1302906836372603762">"Perangkat media"</string>
<string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Panggilan Darurat Saja"</string>
@@ -202,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Gesek tepi layar untuk membuka bilah"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Gesek dari bagian tepi layar untuk membuka bilah 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 a350d38d9257..5dab6a17c7e7 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -166,6 +166,8 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi connesso"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Ricerca del GPS"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"Posizione stabilita dal GPS"</string>
+ <!-- no translation found for accessibility_location_active (2427290146138169014) -->
+ <skip />
<string name="accessibility_clear_all" msgid="5235938559247164925">"Cancella tutte le notifiche."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Informazioni applicazione"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Lo schermo ruoterà automaticamente."</string>
@@ -202,6 +204,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Fai scorrere il bordo dello schermo per visualizzare la barra"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Fai scorrere il dito dal bordo dello schermo per visualizzare la barra di 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 b274dccfeee4..c80ad7c6fb1d 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -164,6 +164,8 @@
<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_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>
@@ -200,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"החלק מקצה המסך כדי להציג ×ת הסרגל"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"החלק מקצה המסך כדי להציג ×ת סרגל המערכת"</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 7392ae9e09a9..73aa558cc0c5 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -166,6 +166,8 @@
<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_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 +204,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"ãƒãƒ¼ã‚’表示ã™ã‚‹ã«ã¯ã€ç”»é¢ã®ç«¯ã‹ã‚‰ã‚¹ãƒ¯ã‚¤ãƒ—ã—ã¾ã™"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"システムãƒãƒ¼ã‚’表示ã™ã‚‹ã«ã¯ã€ç”»é¢ã®ç«¯ã‹ã‚‰ã‚¹ãƒ¯ã‚¤ãƒ—ã—ã¾ã™"</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-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 1437601e4e44..403c94bc5cc2 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -164,6 +164,8 @@
<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_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>
@@ -182,10 +184,8 @@
<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>
- <!-- no translation found for quick_settings_location_label (5011327048748762257) -->
- <skip />
- <!-- no translation found for quick_settings_location_off_label (7464544086507331459) -->
- <skip />
+ <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>
@@ -202,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"화면 가장ìžë¦¬ì—서 스와ì´í”„하여 표시줄 표시"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"화면 가장ìžë¦¬ì—서 스와ì´í”„하여 시스템 표시줄 표시"</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-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index bf8662a2b800..11b67ed3f1c9 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -164,6 +164,8 @@
<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_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>
@@ -200,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Jei norite, kad būtų rodoma juosta, perbraukite ekrano krašte"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Jei norite, kad būtų rodoma sistemos juosta, perbraukite iš ekrano krašto"</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 b96a786eb807..85ab3fdc0fd3 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -164,6 +164,8 @@
<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_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>
@@ -200,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Velciet no ekrÄna malas, lai piekļūtu joslai."</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Velciet no ekrÄna malas, lai piekļūtu sistÄ“mas joslai."</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-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 498e922dd9d1..d5becc0a3f87 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -164,6 +164,8 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi disambungkan"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Mencari GPS"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"Lokasi ditetapkan oleh GPS"</string>
+ <!-- no translation found for accessibility_location_active (2427290146138169014) -->
+ <skip />
<string name="accessibility_clear_all" msgid="5235938559247164925">"Padamkan semua pemberitahuan."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Maklumat apl"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skrin akan berputar secara automatik."</string>
@@ -200,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Leret ke bahagian tepi skrin untuk menampakkan bar"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Leret dari tepi skrin untuk menampakkan bar 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 778be83a5090..6f7d7270e382 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -164,6 +164,8 @@
<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_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>
@@ -200,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Sveip på kanten av skjermen for å få frem feltet"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Sveip fra kanten på skjermen for å få frem systemfeltet"</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-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index ab77839c233f..1216bbf455eb 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -164,6 +164,8 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Verbonden via wifi"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Zoeken naar GPS"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"Locatie bepaald met GPS"</string>
+ <!-- no translation found for accessibility_location_active (2427290146138169014) -->
+ <skip />
<string name="accessibility_clear_all" msgid="5235938559247164925">"Alle meldingen wissen."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"App-info"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Scherm wordt automatisch geroteerd."</string>
@@ -200,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Veeg vanaf de rand om balk weer te geven"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Veeg vanaf de rand van het scherm om de systeembalk 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 c94cfc8c828c..d17c45ea5a53 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -164,6 +164,8 @@
<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_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>
@@ -200,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Przesuń palcem od krawędzi ekranu, by odkryć pasek"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Przesuń palcem od krawędzi ekranu, by odkryć pasek systemu"</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 c106329e04dc..b52031957dd8 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -164,6 +164,8 @@
<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_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>
@@ -200,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Deslize da extremidade do ecrã para revelar a barra"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Deslize da extremidade do ecrã para revelar a barra 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 9be073976ef9..2a2f336ba8d7 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -166,6 +166,8 @@
<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_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>
@@ -202,6 +204,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Deslize a borda da tela para ver a barra"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Deslize a partir da borda da tela ver a barra 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 d7772ed26b13..22a857edda52 100644
--- a/packages/SystemUI/res/values-rm/strings.xml
+++ b/packages/SystemUI/res/values-rm/strings.xml
@@ -298,6 +298,8 @@
<skip />
<!-- no translation found for gps_notification_found_text (4619274244146446464) -->
<skip />
+ <!-- no translation found for accessibility_location_active (2427290146138169014) -->
+ <skip />
<!-- no translation found for accessibility_clear_all (5235938559247164925) -->
<skip />
<!-- no translation found for status_bar_notification_inspect_item_title (1163547729015390250) -->
@@ -370,8 +372,8 @@
<skip />
<!-- no translation found for status_bar_help_text (7874607155052076323) -->
<skip />
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
+ <!-- no translation found for hiding_navigation_confirmation_message (3227814171674734332) -->
<skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
+ <!-- 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 42e2d4801bc4..375d12cbf273 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -164,6 +164,8 @@
<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_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>
@@ -182,10 +184,8 @@
<string name="quick_settings_rotation_unlocked_label" msgid="336054930362580584">"Rotire automată"</string>
<string name="quick_settings_rotation_locked_label" msgid="8058646447242565486">"Rotire blocată"</string>
<string name="quick_settings_ime_label" msgid="7073463064369468429">"Metodă de introducere"</string>
- <!-- no translation found for quick_settings_location_label (5011327048748762257) -->
- <skip />
- <!-- no translation found for quick_settings_location_off_label (7464544086507331459) -->
- <skip />
+ <string name="quick_settings_location_label" msgid="5011327048748762257">"Locație"</string>
+ <string name="quick_settings_location_off_label" msgid="7464544086507331459">"Localizarea este dezactivată"</string>
<string name="quick_settings_media_device_label" msgid="1302906836372603762">"Dispozitiv media"</string>
<string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
<string name="quick_settings_rssi_emergency_only" msgid="2713774041672886750">"Numai apeluri de urgenţă"</string>
@@ -202,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Glisați dinspre marginea ecranului pentru a afișa bara"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Glisați dinspre marginea ecranului pentru a afișa bara de sistem"</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 233fee8a8a52..15adf90c901a 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -166,6 +166,8 @@
<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_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>
@@ -186,10 +188,8 @@
<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>
- <!-- no translation found for quick_settings_location_label (5011327048748762257) -->
- <skip />
- <!-- no translation found for quick_settings_location_off_label (7464544086507331459) -->
- <skip />
+ <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>
@@ -206,6 +206,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Чтобы открыть панель, проведите пальцем от ÐºÑ€Ð°Ñ Ðº центру Ñкрана"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Чтобы открыть панель навигации, проведите пальцем от ÐºÑ€Ð°Ñ Ðº центру Ñкрана"</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-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index c54540c5319b..bb70f36f48d7 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -166,6 +166,8 @@
<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_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>
@@ -202,6 +204,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Panel zobrazíte posunutím cez okraj obrazovky"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Systémový panel zobrazíte posunutím cez okraj obrazovky"</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 3fc4882ecf64..46a5826d890f 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -164,6 +164,8 @@
<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_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>
@@ -200,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Vrstico prikažete tako, da povleÄete z roba zaslona"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Sistemsko vrstico prikažete tako, da povleÄete z roba zaslona"</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 7ba2da5d9de8..350f1dccccd7 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -164,6 +164,8 @@
<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_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>
@@ -200,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Превуците по ивици екрана да би Ñе приказала трака"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Превуците од ивице екрана да би Ñе приказала ÑиÑтемÑка трака"</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 022e2f2ec695..c5335f414f77 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -164,6 +164,8 @@
<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_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>
@@ -200,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Dra från kanten av skärmen om du vill visa fältet"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Dra från kanten av skärmen om du vill visa systemfältet"</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 bdfd27de8cee..ab06b3f9b52b 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -162,6 +162,8 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Mtandao-hewa umeunganishwa"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Inatafuta GPS"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"Mahali pamewekwa na GPS"</string>
+ <!-- no translation found for accessibility_location_active (2427290146138169014) -->
+ <skip />
<string name="accessibility_clear_all" msgid="5235938559247164925">"Futa arifa zote."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Taarifa ya programu"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skrini itazunguka kiotomatiki."</string>
@@ -198,6 +200,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Papasa kwa kasi kutoka ukingo wa skrini ili kuonyesha upau"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Papasa kwa kasi kutoka ukingo wa skrini ili kuonyesha upau wa 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 dc643c400f6a..6fef06254e08 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -164,6 +164,8 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"เชื่อมต่อ WiFi à¹à¸¥à¹‰à¸§"</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_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>
@@ -200,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"à¸à¸§à¸²à¸”ขอบของหน้าจอเพื่อà¹à¸ªà¸”งà¹à¸–บ"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"à¸à¸§à¸²à¸”จาà¸à¸‚อบของหน้าจอเพื่อà¹à¸ªà¸”งà¹à¸–บระบบ"</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 0053be4884df..6dc4e9cc7ba9 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -164,6 +164,8 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"nakakonekta ang Wi-Fi"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Naghahanap ng GPS"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"Lokasyong itinatakda ng GPS"</string>
+ <!-- no translation found for accessibility_location_active (2427290146138169014) -->
+ <skip />
<string name="accessibility_clear_all" msgid="5235938559247164925">"I-clear ang lahat ng notification."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Impormasyon ng app"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Awtomatikong iikot ang screen."</string>
@@ -200,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Mag-swipe sa gilid ng screen upang ipakita ang bar"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Mag-swipe mula sa gilid ng screen upang ipakita ang system bar"</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 2185b16182aa..f7b34de9b819 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -164,6 +164,8 @@
<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_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>
@@ -200,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Çubuğu görüntülemek için ekranın kenarından hızlıca kaydırın"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Sistem çubuğunu görüntülemek için ekranın kenarından hızlıca 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 18f67a218e9f..23e276b0b80e 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -164,6 +164,8 @@
<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_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>
@@ -200,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Гортайте від краю екрана, щоб з’ÑвилаÑÑŒ панель"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Проведіть пальцем від краю екрана, щоб з’ÑвилаÑÑŒ навігаційна панель"</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 acc7e0e517a2..31fc2c8b3aa9 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -164,6 +164,8 @@
<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_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>
@@ -200,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Vuốt cạnh màn hình để hiển thị thanh"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Vuốt từ cạnh màn hình để hiển thị thanh 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 0a62ee3024e1..b8b56c9179d9 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -166,6 +166,8 @@
<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_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>
@@ -184,10 +186,8 @@
<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>
- <!-- no translation found for quick_settings_location_label (5011327048748762257) -->
- <skip />
- <!-- no translation found for quick_settings_location_off_label (7464544086507331459) -->
- <skip />
+ <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>
@@ -204,6 +204,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"从边缘å‘é‡Œæ»‘å¯æ˜¾ç¤ºç³»ç»Ÿæ "</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"从å±å¹•边缘å‘里滑动å³å¯æ˜¾ç¤ºç³»ç»Ÿæ "</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-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 2cfdb59c03ac..397e23d568ad 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -166,6 +166,8 @@
<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_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 +204,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"滑動螢幕邊緣å³å¯é¡¯ç¤ºå°Žè¦½åˆ—"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"從螢幕邊緣å‘內滑動å³å¯é¡¯ç¤ºå°Žè¦½åˆ—"</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 007d33849ec5..1efcbcb6e687 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -164,6 +164,8 @@
<string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"I-Wi-Fi ixhunyiwe"</string>
<string name="gps_notification_searching_text" msgid="8574247005642736060">"Isesha i-GPS"</string>
<string name="gps_notification_found_text" msgid="4619274244146446464">"Indawo ihlelwe i-GPS"</string>
+ <!-- no translation found for accessibility_location_active (2427290146138169014) -->
+ <skip />
<string name="accessibility_clear_all" msgid="5235938559247164925">"Susa zonke izaziso."</string>
<string name="status_bar_notification_inspect_item_title" msgid="1163547729015390250">"Ulwazi lohlelo lokusebenza"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Isikrini sizophenduka ngokuzenzakalela."</string>
@@ -200,6 +202,6 @@
<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="hideybar_confirmation_message" msgid="9050869548951044371">"Swayipha unqenqema wesikrini ukuze uveze ibha"</string>
- <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Swayipha kusukela kunqenqema ukuze uveze ibha yesistimu"</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/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 26f910eb2567..a3bd785772a8 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -67,6 +67,7 @@ import android.view.ContextThemeWrapper;
import android.view.Gravity;
import android.view.IRotationWatcher;
import android.view.IWindowManager;
+import android.view.InputEvent;
import android.view.InputQueue;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
@@ -79,6 +80,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.ViewManager;
import android.view.ViewParent;
+import android.view.ViewRootImpl;
import android.view.ViewStub;
import android.view.Window;
import android.view.WindowManager;
@@ -1459,6 +1461,27 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
}
+ @Override
+ public void setLocalFocus(boolean hasFocus, boolean inTouchMode) {
+ getViewRootImpl().windowFocusChanged(hasFocus, inTouchMode);
+
+ }
+
+ @Override
+ public void injectInputEvent(InputEvent event) {
+ getViewRootImpl().dispatchInputEvent(event);
+ }
+
+ private ViewRootImpl getViewRootImpl() {
+ if (mDecor != null) {
+ ViewRootImpl viewRootImpl = mDecor.getViewRootImpl();
+ if (viewRootImpl != null) {
+ return viewRootImpl;
+ }
+ }
+ throw new IllegalStateException("view not added");
+ }
+
/**
* Request that key events come to this activity. Use this if your activity
* has no views with focus, but the activity still wants a chance to process
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 1f71471256da..bb0d2483aea6 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -2221,15 +2221,26 @@ public class ConnectivityService extends IConnectivityManager.Stub {
}
}
+ if (DBG) log("handleCaptivePortalTrackerCheck: call captivePortalCheckComplete ni=" + info);
thisNet.captivePortalCheckComplete();
}
/** @hide */
+ @Override
public void captivePortalCheckComplete(NetworkInfo info) {
enforceConnectivityInternalPermission();
+ if (DBG) log("captivePortalCheckComplete: ni=" + info);
mNetTrackers[info.getType()].captivePortalCheckComplete();
}
+ /** @hide */
+ @Override
+ public void captivePortalCheckCompleted(NetworkInfo info, boolean isCaptivePortal) {
+ enforceConnectivityInternalPermission();
+ if (DBG) log("captivePortalCheckCompleted: ni=" + info + " captive=" + isCaptivePortal);
+ mNetTrackers[info.getType()].captivePortalCheckCompleted(isCaptivePortal);
+ }
+
/**
* Setup data activity tracking for the given network interface.
*
@@ -4287,7 +4298,9 @@ public class ConnectivityService extends IConnectivityManager.Stub {
return null;
}
- private String getMobileRedirectedProvisioningUrl() {
+ @Override
+ public String getMobileRedirectedProvisioningUrl() {
+ enforceConnectivityInternalPermission();
String url = getProvisioningUrlBaseFromFile(REDIRECTED_PROVISIONING);
if (TextUtils.isEmpty(url)) {
url = mContext.getResources().getString(R.string.mobile_redirected_provisioning_url);
@@ -4295,14 +4308,15 @@ public class ConnectivityService extends IConnectivityManager.Stub {
return url;
}
+ @Override
public String getMobileProvisioningUrl() {
enforceConnectivityInternalPermission();
String url = getProvisioningUrlBaseFromFile(PROVISIONING);
if (TextUtils.isEmpty(url)) {
url = mContext.getResources().getString(R.string.mobile_provisioning_url);
- log("getProvisioningUrl: mobile_provisioining_url from resource =" + url);
+ log("getMobileProvisioningUrl: mobile_provisioining_url from resource =" + url);
} else {
- log("getProvisioningUrl: mobile_provisioning_url from File =" + url);
+ log("getMobileProvisioningUrl: mobile_provisioning_url from File =" + url);
}
// populate the iccid, imei and phone number in the provisioning url.
if (!TextUtils.isEmpty(url)) {
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java
index 4c8100628805..43f95c3d7615 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -2378,7 +2378,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
@Override
- public boolean setDeviceOwner(String packageName) {
+ public boolean setDeviceOwner(String packageName, String ownerName) {
if (packageName == null
|| !DeviceOwner.isInstalled(packageName, mContext.getPackageManager())) {
throw new IllegalArgumentException("Invalid package name " + packageName
@@ -2386,7 +2386,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
synchronized (this) {
if (mDeviceOwner == null && !isDeviceProvisioned()) {
- mDeviceOwner = new DeviceOwner(packageName);
+ mDeviceOwner = new DeviceOwner(packageName, ownerName);
mDeviceOwner.writeOwnerFile();
return true;
} else {
@@ -2415,6 +2415,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return null;
}
+ @Override
+ public String getDeviceOwnerName() {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
+ synchronized (this) {
+ if (mDeviceOwner != null) {
+ return mDeviceOwner.getName();
+ }
+ }
+ return null;
+ }
+
private boolean isDeviceProvisioned() {
return Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, 0) > 0;
@@ -2488,15 +2499,18 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
static class DeviceOwner {
private static final String DEVICE_OWNER_XML = "device_owner.xml";
private static final String TAG_DEVICE_OWNER = "device-owner";
+ private static final String ATTR_NAME = "name";
private static final String ATTR_PACKAGE = "package";
private String mPackageName;
+ private String mOwnerName;
DeviceOwner() {
readOwnerFile();
}
- DeviceOwner(String packageName) {
+ DeviceOwner(String packageName, String ownerName) {
this.mPackageName = packageName;
+ this.mOwnerName = ownerName;
}
static boolean isRegistered() {
@@ -2508,6 +2522,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return mPackageName;
}
+ String getName() {
+ return mOwnerName;
+ }
+
static boolean isInstalled(String packageName, PackageManager pm) {
try {
PackageInfo pi;
@@ -2539,6 +2557,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
"Device Owner file does not start with device-owner tag: found " + tag);
}
mPackageName = parser.getAttributeValue(null, ATTR_PACKAGE);
+ mOwnerName = parser.getAttributeValue(null, ATTR_NAME);
input.close();
} catch (XmlPullParserException xppe) {
Slog.e(TAG, "Error parsing device-owner file\n" + xppe);
@@ -2563,6 +2582,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
out.startDocument(null, true);
out.startTag(null, TAG_DEVICE_OWNER);
out.attribute(null, ATTR_PACKAGE, mPackageName);
+ if (mOwnerName != null) {
+ out.attribute(null, ATTR_NAME, mOwnerName);
+ }
out.endTag(null, TAG_DEVICE_OWNER);
out.endDocument();
out.flush();
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 49746ffc6241..a32699a19df0 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -437,7 +437,10 @@ public class LocationManagerService extends ILocationManager.Stub {
FusedProxy fusedProxy = FusedProxy.createAndBind(
mContext,
mLocationHandler,
- flpHardwareProvider.getLocationHardware());
+ flpHardwareProvider.getLocationHardware(),
+ com.android.internal.R.bool.config_enableFusedLocationOverlay,
+ com.android.internal.R.string.config_fusedLocationProviderPackageName,
+ com.android.internal.R.array.config_locationProviderPackageNames);
if(fusedProxy == null) {
Slog.e(TAG, "No FusedProvider found.");
diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java
index 18b46fbec4e6..8fb3998f4859 100644
--- a/services/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/java/com/android/server/accessibility/TouchExplorer.java
@@ -41,6 +41,7 @@ import com.android.internal.R;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
/**
* This class is a strategy for performing touch exploration. It
@@ -52,10 +53,8 @@ import java.util.Arrays;
* <li>2. One finger moving fast around performs gestures.</li>
* <li>3. Two close fingers moving in the same direction perform a drag.</li>
* <li>4. Multi-finger gestures are delivered to view hierarchy.</li>
- * <li>5. Pointers that have not moved more than a specified distance after they
- * went down are considered inactive.</li>
- * <li>6. Two fingers moving in different directions are considered a multi-finger gesture.</li>
- * <li>7. Double tapping clicks on the on the last touch explored location of it was in
+ * <li>5. Two fingers moving in different directions are considered a multi-finger gesture.</li>
+ * <li>7. Double tapping clicks on the on the last touch explored location if it was in
* a window that does not take focus, otherwise the click is within the accessibility
* focused rectangle.</li>
* <li>7. Tapping and holding for a while performs a long press in a similar fashion
@@ -102,9 +101,6 @@ class TouchExplorer implements EventStreamTransformation {
// The timeout after which we are no longer trying to detect a gesture.
private static final int EXIT_GESTURE_DETECTION_TIMEOUT = 2000;
- // Temporary array for storing pointer IDs.
- private final int[] mTempPointerIds = new int[MAX_POINTER_COUNT];
-
// Timeout before trying to decide what the user is trying to do.
private final int mDetermineUserIntentTimeout;
@@ -129,11 +125,11 @@ class TouchExplorer implements EventStreamTransformation {
// Handler for performing asynchronous operations.
private final Handler mHandler;
- // Command for delayed sending of a hover enter event.
- private final SendHoverDelayed mSendHoverEnterDelayed;
+ // Command for delayed sending of a hover enter and move event.
+ private final SendHoverEnterAndMoveDelayed mSendHoverEnterAndMoveDelayed;
// Command for delayed sending of a hover exit event.
- private final SendHoverDelayed mSendHoverExitDelayed;
+ private final SendHoverExitDelayed mSendHoverExitDelayed;
// Command for delayed sending of touch exploration end events.
private final SendAccessibilityEventDelayed mSendTouchExplorationEndDelayed;
@@ -220,7 +216,7 @@ class TouchExplorer implements EventStreamTransformation {
public TouchExplorer(Context context, AccessibilityManagerService service) {
mContext = context;
mAms = service;
- mReceivedPointerTracker = new ReceivedPointerTracker(context);
+ mReceivedPointerTracker = new ReceivedPointerTracker();
mInjectedPointerTracker = new InjectedPointerTracker();
mTapTimeout = ViewConfiguration.getTapTimeout();
mDetermineUserIntentTimeout = ViewConfiguration.getDoubleTapTimeout();
@@ -234,8 +230,8 @@ class TouchExplorer implements EventStreamTransformation {
mGestureLibrary.setOrientationStyle(8);
mGestureLibrary.setSequenceType(GestureStore.SEQUENCE_SENSITIVE);
mGestureLibrary.load();
- mSendHoverEnterDelayed = new SendHoverDelayed(MotionEvent.ACTION_HOVER_ENTER, true);
- mSendHoverExitDelayed = new SendHoverDelayed(MotionEvent.ACTION_HOVER_EXIT, false);
+ mSendHoverEnterAndMoveDelayed = new SendHoverEnterAndMoveDelayed();
+ mSendHoverExitDelayed = new SendHoverExitDelayed();
mSendTouchExplorationEndDelayed = new SendAccessibilityEventDelayed(
AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END,
mDetermineUserIntentTimeout);
@@ -283,12 +279,12 @@ class TouchExplorer implements EventStreamTransformation {
} break;
}
// Remove all pending callbacks.
- mSendHoverEnterDelayed.remove();
- mSendHoverExitDelayed.remove();
- mPerformLongPressDelayed.remove();
- mExitGestureDetectionModeDelayed.remove();
- mSendTouchExplorationEndDelayed.remove();
- mSendTouchInteractionEndDelayed.remove();
+ mSendHoverEnterAndMoveDelayed.cancel();
+ mSendHoverExitDelayed.cancel();
+ mPerformLongPressDelayed.cancel();
+ mExitGestureDetectionModeDelayed.cancel();
+ mSendTouchExplorationEndDelayed.cancel();
+ mSendTouchInteractionEndDelayed.cancel();
// Reset the pointer trackers.
mReceivedPointerTracker.clear();
mInjectedPointerTracker.clear();
@@ -347,7 +343,7 @@ class TouchExplorer implements EventStreamTransformation {
// last hover exit event.
if (mSendTouchExplorationEndDelayed.isPending()
&& eventType == AccessibilityEvent.TYPE_VIEW_HOVER_EXIT) {
- mSendTouchExplorationEndDelayed.remove();
+ mSendTouchExplorationEndDelayed.cancel();
sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END);
}
@@ -355,7 +351,7 @@ class TouchExplorer implements EventStreamTransformation {
// last hover exit and the touch exploration gesture end events.
if (mSendTouchInteractionEndDelayed.isPending()
&& eventType == AccessibilityEvent.TYPE_VIEW_HOVER_EXIT) {
- mSendTouchInteractionEndDelayed.remove();
+ mSendTouchInteractionEndDelayed.cancel();
sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
}
@@ -390,95 +386,80 @@ class TouchExplorer implements EventStreamTransformation {
private void handleMotionEventStateTouchExploring(MotionEvent event, MotionEvent rawEvent,
int policyFlags) {
ReceivedPointerTracker receivedTracker = mReceivedPointerTracker;
- final int activePointerCount = receivedTracker.getActivePointerCount();
mVelocityTracker.addMovement(rawEvent);
mDoubleTapDetector.onMotionEvent(event, policyFlags);
switch (event.getActionMasked()) {
- case MotionEvent.ACTION_DOWN:
+ case MotionEvent.ACTION_DOWN: {
mAms.onTouchInteractionStart();
+
// Pre-feed the motion events to the gesture detector since we
// have a distance slop before getting into gesture detection
// mode and not using the points within this slop significantly
// decreases the quality of gesture recognition.
handleMotionEventGestureDetecting(rawEvent, policyFlags);
- //$FALL-THROUGH$
- case MotionEvent.ACTION_POINTER_DOWN: {
- switch (activePointerCount) {
- case 0: {
- throw new IllegalStateException("The must always be one active pointer in"
- + "touch exploring state!");
- }
- case 1: {
- // If we still have not notified the user for the last
- // touch, we figure out what to do. If were waiting
- // we resent the delayed callback and wait again.
- if (mSendHoverEnterDelayed.isPending()) {
- mSendHoverEnterDelayed.remove();
- mSendHoverExitDelayed.remove();
- }
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_START);
- if (mSendTouchExplorationEndDelayed.isPending()) {
- mSendTouchExplorationEndDelayed.forceSendAndRemove();
- }
+ // If we still have not notified the user for the last
+ // touch, we figure out what to do. If were waiting
+ // we resent the delayed callback and wait again.
+ mSendHoverEnterAndMoveDelayed.cancel();
+ mSendHoverExitDelayed.cancel();
+ mPerformLongPressDelayed.cancel();
- if (mSendTouchInteractionEndDelayed.isPending()) {
- mSendTouchInteractionEndDelayed.forceSendAndRemove();
- }
+ if (mSendTouchExplorationEndDelayed.isPending()) {
+ mSendTouchExplorationEndDelayed.forceSendAndRemove();
+ }
- // Every pointer that goes down is active until it moves or
- // another one goes down. Hence, having more than one pointer
- // down we have already send the interaction start event.
- if (event.getPointerCount() == 1) {
- sendAccessibilityEvent(
- AccessibilityEvent.TYPE_TOUCH_INTERACTION_START);
- }
+ if (mSendTouchInteractionEndDelayed.isPending()) {
+ mSendTouchInteractionEndDelayed.forceSendAndRemove();
+ }
- mPerformLongPressDelayed.remove();
-
- // If we have the first tap schedule a long press and break
- // since we do not want to schedule hover enter because
- // the delayed callback will kick in before the long click.
- // This would lead to a state transition resulting in long
- // pressing the item below the double taped area which is
- // not necessary where accessibility focus is.
- if (mDoubleTapDetector.firstTapDetected()) {
- // We got a tap now post a long press action.
- mPerformLongPressDelayed.post(event, policyFlags);
- break;
- }
- if (!mTouchExplorationInProgress) {
- // Deliver hover enter with a delay to have a chance
- // to detect what the user is trying to do.
- final int pointerId = receivedTracker.getPrimaryActivePointerId();
- final int pointerIdBits = (1 << pointerId);
- mSendHoverEnterDelayed.post(event, true, pointerIdBits, policyFlags);
- }
- } break;
- default: {
- /* do nothing - let the code for ACTION_MOVE decide what to do */
- } break;
+ // Cache the event until we discern exploration from gesturing.
+ mSendHoverEnterAndMoveDelayed.addEvent(event);
+
+ // If we have the first tap, schedule a long press and break
+ // since we do not want to schedule hover enter because
+ // the delayed callback will kick in before the long click.
+ // This would lead to a state transition resulting in long
+ // pressing the item below the double taped area which is
+ // not necessary where accessibility focus is.
+ if (mDoubleTapDetector.firstTapDetected()) {
+ // We got a tap now post a long press action.
+ mPerformLongPressDelayed.post(event, policyFlags);
+ break;
}
+ if (!mTouchExplorationInProgress) {
+ // Deliver hover enter with a delay to have a chance
+ // to detect what the user is trying to do.
+ final int pointerId = receivedTracker.getPrimaryPointerId();
+ final int pointerIdBits = (1 << pointerId);
+ mSendHoverEnterAndMoveDelayed.post(event, true, pointerIdBits, policyFlags);
+ }
+ } break;
+ case MotionEvent.ACTION_POINTER_DOWN: {
+ /* do nothing - let the code for ACTION_MOVE decide what to do */
} break;
case MotionEvent.ACTION_MOVE: {
- final int pointerId = receivedTracker.getPrimaryActivePointerId();
+ final int pointerId = receivedTracker.getPrimaryPointerId();
final int pointerIndex = event.findPointerIndex(pointerId);
final int pointerIdBits = (1 << pointerId);
- switch (activePointerCount) {
- case 0: {
- /* do nothing - no active pointers so we swallow the event */
- } break;
+ switch (event.getPointerCount()) {
case 1: {
// We have not started sending events since we try to
// figure out what the user is doing.
- if (mSendHoverEnterDelayed.isPending()) {
+ if (mSendHoverEnterAndMoveDelayed.isPending()) {
// Pre-feed the motion events to the gesture detector since we
// have a distance slop before getting into gesture detection
// mode and not using the points within this slop significantly
// decreases the quality of gesture recognition.
handleMotionEventGestureDetecting(rawEvent, policyFlags);
+
+ // Cache the event until we discern exploration from gesturing.
+ mSendHoverEnterAndMoveDelayed.addEvent(event);
+
// It is *important* to use the distance traveled by the pointers
// on the screen which may or may not be magnified.
final float deltaX = receivedTracker.getReceivedPointerDownX(pointerId)
@@ -500,9 +481,9 @@ class TouchExplorer implements EventStreamTransformation {
// clear the current state and try to detect.
mCurrentState = STATE_GESTURE_DETECTING;
mVelocityTracker.clear();
- mSendHoverEnterDelayed.remove();
- mSendHoverExitDelayed.remove();
- mPerformLongPressDelayed.remove();
+ mSendHoverEnterAndMoveDelayed.cancel();
+ mSendHoverExitDelayed.cancel();
+ mPerformLongPressDelayed.cancel();
mExitGestureDetectionModeDelayed.post();
// Send accessibility event to announce the start
// of gesture recognition.
@@ -511,9 +492,9 @@ class TouchExplorer implements EventStreamTransformation {
} else {
// We have just decided that the user is touch,
// exploring so start sending events.
- mSendHoverEnterDelayed.forceSendAndRemove();
- mSendHoverExitDelayed.remove();
- mPerformLongPressDelayed.remove();
+ mSendHoverEnterAndMoveDelayed.forceSendAndRemove();
+ mSendHoverExitDelayed.cancel();
+ mPerformLongPressDelayed.cancel();
sendMotionEvent(event, MotionEvent.ACTION_HOVER_MOVE,
pointerIdBits, policyFlags);
}
@@ -532,11 +513,11 @@ class TouchExplorer implements EventStreamTransformation {
final double moveDelta = Math.hypot(deltaX, deltaY);
// The user has moved enough for us to decide.
if (moveDelta > mTouchSlop) {
- mPerformLongPressDelayed.remove();
+ mPerformLongPressDelayed.cancel();
}
}
- // The user is wither double tapping or performing long
- // press so do not send move events yet.
+ // The user is either double tapping or performing a long
+ // press, so do not send move events yet.
if (mDoubleTapDetector.firstTapDetected()) {
break;
}
@@ -548,14 +529,14 @@ class TouchExplorer implements EventStreamTransformation {
case 2: {
// More than one pointer so the user is not touch exploring
// and now we have to decide whether to delegate or drag.
- if (mSendHoverEnterDelayed.isPending()) {
+ if (mSendHoverEnterAndMoveDelayed.isPending()) {
// We have not started sending events so cancel
// scheduled sending events.
- mSendHoverEnterDelayed.remove();
- mSendHoverExitDelayed.remove();
- mPerformLongPressDelayed.remove();
+ mSendHoverEnterAndMoveDelayed.cancel();
+ mSendHoverExitDelayed.cancel();
+ mPerformLongPressDelayed.cancel();
} else {
- mPerformLongPressDelayed.remove();
+ mPerformLongPressDelayed.cancel();
// If the user is touch exploring the second pointer may be
// performing a double tap to activate an item without need
// for the user to lift his exploring finger.
@@ -590,21 +571,21 @@ class TouchExplorer implements EventStreamTransformation {
} else {
// Two pointers moving arbitrary are delegated to the view hierarchy.
mCurrentState = STATE_DELEGATING;
- sendDownForAllActiveNotInjectedPointers(event, policyFlags);
+ sendDownForAllNotInjectedPointers(event, policyFlags);
}
mVelocityTracker.clear();
} break;
default: {
// More than one pointer so the user is not touch exploring
// and now we have to decide whether to delegate or drag.
- if (mSendHoverEnterDelayed.isPending()) {
+ if (mSendHoverEnterAndMoveDelayed.isPending()) {
// We have not started sending events so cancel
// scheduled sending events.
- mSendHoverEnterDelayed.remove();
- mSendHoverExitDelayed.remove();
- mPerformLongPressDelayed.remove();
+ mSendHoverEnterAndMoveDelayed.cancel();
+ mSendHoverExitDelayed.cancel();
+ mPerformLongPressDelayed.cancel();
} else {
- mPerformLongPressDelayed.remove();
+ mPerformLongPressDelayed.cancel();
// We are sending events so send exit and gesture
// end since we transition to another state.
sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
@@ -612,43 +593,34 @@ class TouchExplorer implements EventStreamTransformation {
// More than two pointers are delegated to the view hierarchy.
mCurrentState = STATE_DELEGATING;
- sendDownForAllActiveNotInjectedPointers(event, policyFlags);
+ sendDownForAllNotInjectedPointers(event, policyFlags);
mVelocityTracker.clear();
}
}
} break;
- case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_UP: {
mAms.onTouchInteractionEnd();
// We know that we do not need the pre-fed gesture points are not
// needed anymore since the last pointer just went up.
mStrokeBuffer.clear();
- //$FALL-THROUGH$
- case MotionEvent.ACTION_POINTER_UP: {
- final int pointerId = receivedTracker.getLastReceivedUpPointerId();
+ final int pointerId = event.getPointerId(event.getActionIndex());
final int pointerIdBits = (1 << pointerId);
- switch (activePointerCount) {
- case 0: {
- // If the pointer that went up was not active we have nothing to do.
- if (!receivedTracker.wasLastReceivedUpPointerActive()) {
- break;
- }
- mPerformLongPressDelayed.remove();
+ mPerformLongPressDelayed.cancel();
+ mVelocityTracker.clear();
- // If we have not delivered the enter schedule exit.
- if (mSendHoverEnterDelayed.isPending()) {
- mSendHoverExitDelayed.post(event, false, pointerIdBits, policyFlags);
- } else {
- // The user is touch exploring so we send events for end.
- sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
- }
+ if (mSendHoverEnterAndMoveDelayed.isPending()) {
+ // If we have not delivered the enter schedule an exit.
+ mSendHoverExitDelayed.post(event, pointerIdBits, policyFlags);
+ } else {
+ // The user is touch exploring so we send events for end.
+ sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
+ }
- if (!mSendTouchInteractionEndDelayed.isPending()) {
- mSendTouchInteractionEndDelayed.post();
- }
- } break;
+ if (!mSendTouchInteractionEndDelayed.isPending()) {
+ mSendTouchInteractionEndDelayed.post();
}
- mVelocityTracker.clear();
+
} break;
case MotionEvent.ACTION_CANCEL: {
clear(event, policyFlags);
@@ -676,29 +648,19 @@ class TouchExplorer implements EventStreamTransformation {
if (mDraggingPointerId != INVALID_POINTER_ID) {
sendMotionEvent(event, MotionEvent.ACTION_UP, pointerIdBits, policyFlags);
}
- sendDownForAllActiveNotInjectedPointers(event, policyFlags);
+ sendDownForAllNotInjectedPointers(event, policyFlags);
} break;
case MotionEvent.ACTION_MOVE: {
- final int activePointerCount = mReceivedPointerTracker.getActivePointerCount();
- switch (activePointerCount) {
+ switch (event.getPointerCount()) {
case 1: {
// do nothing
} break;
case 2: {
if (isDraggingGesture(event)) {
- // If the dragging pointer are closer that a given distance we
- // use the location of the primary one. Otherwise, we take the
- // middle between the pointers.
- int[] pointerIds = mTempPointerIds;
- mReceivedPointerTracker.populateActivePointerIds(pointerIds);
-
- final int firstPtrIndex = event.findPointerIndex(pointerIds[0]);
- final int secondPtrIndex = event.findPointerIndex(pointerIds[1]);
-
- final float firstPtrX = event.getX(firstPtrIndex);
- final float firstPtrY = event.getY(firstPtrIndex);
- final float secondPtrX = event.getX(secondPtrIndex);
- final float secondPtrY = event.getY(secondPtrIndex);
+ final float firstPtrX = event.getX(0);
+ final float firstPtrY = event.getY(0);
+ final float secondPtrX = event.getX(1);
+ final float secondPtrY = event.getY(1);
final float deltaX = firstPtrX - secondPtrX;
final float deltaY = firstPtrY - secondPtrY;
@@ -718,8 +680,8 @@ class TouchExplorer implements EventStreamTransformation {
// Send an event to the end of the drag gesture.
sendMotionEvent(event, MotionEvent.ACTION_UP, pointerIdBits,
policyFlags);
- // Deliver all active pointers to the view hierarchy.
- sendDownForAllActiveNotInjectedPointers(event, policyFlags);
+ // Deliver all pointers to the view hierarchy.
+ sendDownForAllNotInjectedPointers(event, policyFlags);
}
} break;
default: {
@@ -727,8 +689,8 @@ class TouchExplorer implements EventStreamTransformation {
// Send an event to the end of the drag gesture.
sendMotionEvent(event, MotionEvent.ACTION_UP, pointerIdBits,
policyFlags);
- // Deliver all active pointers to the view hierarchy.
- sendDownForAllActiveNotInjectedPointers(event, policyFlags);
+ // Deliver all pointers to the view hierarchy.
+ sendDownForAllNotInjectedPointers(event, policyFlags);
}
}
} break;
@@ -771,37 +733,21 @@ class TouchExplorer implements EventStreamTransformation {
throw new IllegalStateException("Delegating state can only be reached if "
+ "there is at least one pointer down!");
}
- case MotionEvent.ACTION_MOVE: {
- // Check whether some other pointer became active because they have moved
- // a given distance and if such exist send them to the view hierarchy
- final int notInjectedCount = getNotInjectedActivePointerCount(
- mReceivedPointerTracker, mInjectedPointerTracker);
- if (notInjectedCount > 0) {
- MotionEvent prototype = MotionEvent.obtain(event);
- sendDownForAllActiveNotInjectedPointers(prototype, policyFlags);
- }
- } break;
- case MotionEvent.ACTION_UP:
- // Announce the end of a new touch interaction.
- sendAccessibilityEvent(
- AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
- //$FALL-THROUGH$
- case MotionEvent.ACTION_POINTER_UP: {
+ case MotionEvent.ACTION_UP: {
+ // Announce the end of a the touch interaction.
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
mAms.onTouchInteractionEnd();
mLongPressingPointerId = -1;
mLongPressingPointerDeltaX = 0;
mLongPressingPointerDeltaY = 0;
- // No active pointers => go to initial state.
- if (mReceivedPointerTracker.getActivePointerCount() == 0) {
- mCurrentState = STATE_TOUCH_EXPLORING;
- }
+ mCurrentState = STATE_TOUCH_EXPLORING;
} break;
case MotionEvent.ACTION_CANCEL: {
clear(event, policyFlags);
} break;
}
- // Deliver the event striping out inactive pointers.
- sendMotionEventStripInactivePointers(event, policyFlags);
+ // Deliver the event.
+ sendMotionEvent(event, event.getAction(), ALL_POINTER_ID_BITS, policyFlags);
}
private void handleMotionEventGestureDetecting(MotionEvent event, int policyFlags) {
@@ -826,12 +772,10 @@ class TouchExplorer implements EventStreamTransformation {
} break;
case MotionEvent.ACTION_UP: {
mAms.onTouchInteractionEnd();
- // Announce the end of gesture recognition.
- sendAccessibilityEvent(
- AccessibilityEvent.TYPE_GESTURE_DETECTION_END);
- // Announce the end of a new touch interaction.
- sendAccessibilityEvent(
- AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
+ // Announce the end of the gesture recognition.
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_GESTURE_DETECTION_END);
+ // Announce the end of a the touch interaction.
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
float x = event.getX();
float y = event.getY();
@@ -858,7 +802,7 @@ class TouchExplorer implements EventStreamTransformation {
}
mStrokeBuffer.clear();
- mExitGestureDetectionModeDelayed.remove();
+ mExitGestureDetectionModeDelayed.cancel();
mCurrentState = STATE_TOUCH_EXPLORING;
} break;
case MotionEvent.ACTION_CANCEL: {
@@ -889,40 +833,26 @@ class TouchExplorer implements EventStreamTransformation {
}
/**
- * Sends down events to the view hierarchy for all active pointers which are
+ * Sends down events to the view hierarchy for all pointers which are
* not already being delivered i.e. pointers that are not yet injected.
*
* @param prototype The prototype from which to create the injected events.
* @param policyFlags The policy flags associated with the event.
*/
- private void sendDownForAllActiveNotInjectedPointers(MotionEvent prototype, int policyFlags) {
- ReceivedPointerTracker receivedPointers = mReceivedPointerTracker;
+ private void sendDownForAllNotInjectedPointers(MotionEvent prototype, int policyFlags) {
InjectedPointerTracker injectedPointers = mInjectedPointerTracker;
+
+ // Inject the injected pointers.
int pointerIdBits = 0;
final int pointerCount = prototype.getPointerCount();
-
- // Find which pointers are already injected.
- for (int i = 0; i < pointerCount; i++) {
- final int pointerId = prototype.getPointerId(i);
- if (injectedPointers.isInjectedPointerDown(pointerId)) {
- pointerIdBits |= (1 << pointerId);
- }
- }
-
- // Inject the active and not injected pointers.
for (int i = 0; i < pointerCount; i++) {
final int pointerId = prototype.getPointerId(i);
- // Skip inactive pointers.
- if (!receivedPointers.isActivePointer(pointerId)) {
- continue;
- }
// Do not send event for already delivered pointers.
- if (injectedPointers.isInjectedPointerDown(pointerId)) {
- continue;
+ if (!injectedPointers.isInjectedPointerDown(pointerId)) {
+ pointerIdBits |= (1 << pointerId);
+ final int action = computeInjectionAction(MotionEvent.ACTION_DOWN, i);
+ sendMotionEvent(prototype, action, pointerIdBits, policyFlags);
}
- pointerIdBits |= (1 << pointerId);
- final int action = computeInjectionAction(MotionEvent.ACTION_DOWN, i);
- sendMotionEvent(prototype, action, pointerIdBits, policyFlags);
}
}
@@ -959,7 +889,7 @@ class TouchExplorer implements EventStreamTransformation {
}
/**
- * Sends up events to the view hierarchy for all active pointers which are
+ * Sends up events to the view hierarchy for all pointers which are
* already being delivered i.e. pointers that are injected.
*
* @param prototype The prototype from which to create the injected events.
@@ -982,58 +912,13 @@ class TouchExplorer implements EventStreamTransformation {
}
/**
- * Sends a motion event by first stripping the inactive pointers.
- *
- * @param prototype The prototype from which to create the injected event.
- * @param policyFlags The policy flags associated with the event.
- */
- private void sendMotionEventStripInactivePointers(MotionEvent prototype, int policyFlags) {
- ReceivedPointerTracker receivedTracker = mReceivedPointerTracker;
-
- // All pointers active therefore we just inject the event as is.
- if (prototype.getPointerCount() == receivedTracker.getActivePointerCount()) {
- sendMotionEvent(prototype, prototype.getAction(), ALL_POINTER_ID_BITS, policyFlags);
- return;
- }
-
- // No active pointers and the one that just went up was not
- // active, therefore we have nothing to do.
- if (receivedTracker.getActivePointerCount() == 0
- && !receivedTracker.wasLastReceivedUpPointerActive()) {
- return;
- }
-
- // If the action pointer going up/down is not active we have nothing to do.
- // However, for moves we keep going to report moves of active pointers.
- final int actionMasked = prototype.getActionMasked();
- final int actionPointerId = prototype.getPointerId(prototype.getActionIndex());
- if (actionMasked != MotionEvent.ACTION_MOVE) {
- if (!receivedTracker.isActiveOrWasLastActiveUpPointer(actionPointerId)) {
- return;
- }
- }
-
- // If the pointer is active or the pointer that just went up
- // was active we keep the pointer data in the event.
- int pointerIdBits = 0;
- final int pointerCount = prototype.getPointerCount();
- for (int pointerIndex = 0; pointerIndex < pointerCount; pointerIndex++) {
- final int pointerId = prototype.getPointerId(pointerIndex);
- if (receivedTracker.isActiveOrWasLastActiveUpPointer(pointerId)) {
- pointerIdBits |= (1 << pointerId);
- }
- }
- sendMotionEvent(prototype, prototype.getAction(), pointerIdBits, policyFlags);
- }
-
- /**
* Sends an up and down events.
*
* @param prototype The prototype from which to create the injected events.
* @param policyFlags The policy flags associated with the event.
*/
private void sendActionDownAndUp(MotionEvent prototype, int policyFlags) {
- // Tap with the pointer that last explored - we may have inactive pointers.
+ // Tap with the pointer that last explored.
final int pointerId = prototype.getPointerId(prototype.getActionIndex());
final int pointerIdBits = (1 << pointerId);
sendMotionEvent(prototype, MotionEvent.ACTION_DOWN, pointerIdBits, policyFlags);
@@ -1215,9 +1100,9 @@ class TouchExplorer implements EventStreamTransformation {
}
// Remove pending event deliveries.
- mSendHoverEnterDelayed.remove();
- mSendHoverExitDelayed.remove();
- mPerformLongPressDelayed.remove();
+ mSendHoverEnterAndMoveDelayed.cancel();
+ mSendHoverExitDelayed.cancel();
+ mPerformLongPressDelayed.cancel();
if (mSendTouchExplorationEndDelayed.isPending()) {
mSendTouchExplorationEndDelayed.forceSendAndRemove();
@@ -1307,21 +1192,16 @@ class TouchExplorer implements EventStreamTransformation {
*/
private boolean isDraggingGesture(MotionEvent event) {
ReceivedPointerTracker receivedTracker = mReceivedPointerTracker;
- int[] pointerIds = mTempPointerIds;
- receivedTracker.populateActivePointerIds(pointerIds);
-
- final int firstPtrIndex = event.findPointerIndex(pointerIds[0]);
- final int secondPtrIndex = event.findPointerIndex(pointerIds[1]);
- final float firstPtrX = event.getX(firstPtrIndex);
- final float firstPtrY = event.getY(firstPtrIndex);
- final float secondPtrX = event.getX(secondPtrIndex);
- final float secondPtrY = event.getY(secondPtrIndex);
+ final float firstPtrX = event.getX(0);
+ final float firstPtrY = event.getY(0);
+ final float secondPtrX = event.getX(1);
+ final float secondPtrY = event.getY(1);
- final float firstPtrDownX = receivedTracker.getReceivedPointerDownX(firstPtrIndex);
- final float firstPtrDownY = receivedTracker.getReceivedPointerDownY(firstPtrIndex);
- final float secondPtrDownX = receivedTracker.getReceivedPointerDownX(secondPtrIndex);
- final float secondPtrDownY = receivedTracker.getReceivedPointerDownY(secondPtrIndex);
+ final float firstPtrDownX = receivedTracker.getReceivedPointerDownX(0);
+ final float firstPtrDownY = receivedTracker.getReceivedPointerDownY(0);
+ final float secondPtrDownX = receivedTracker.getReceivedPointerDownX(1);
+ final float secondPtrDownY = receivedTracker.getReceivedPointerDownY(1);
return GestureUtils.isDraggingGesture(firstPtrDownX, firstPtrDownY, secondPtrDownX,
secondPtrDownY, firstPtrX, firstPtrY, secondPtrX, secondPtrY,
@@ -1350,16 +1230,6 @@ class TouchExplorer implements EventStreamTransformation {
}
/**
- * @return The number of non injected active pointers.
- */
- private int getNotInjectedActivePointerCount(ReceivedPointerTracker receivedTracker,
- InjectedPointerTracker injectedTracker) {
- final int pointerState = receivedTracker.getActivePointers()
- & ~injectedTracker.getInjectedPointersDown();
- return Integer.bitCount(pointerState);
- }
-
- /**
* Class for delayed exiting from gesture detecting mode.
*/
private final class ExitGestureDetectionModeDelayed implements Runnable {
@@ -1368,7 +1238,7 @@ class TouchExplorer implements EventStreamTransformation {
mHandler.postDelayed(this, EXIT_GESTURE_DETECTION_TIMEOUT);
}
- public void remove() {
+ public void cancel() {
mHandler.removeCallbacks(this);
}
@@ -1396,21 +1266,21 @@ class TouchExplorer implements EventStreamTransformation {
mHandler.postDelayed(this, ViewConfiguration.getLongPressTimeout());
}
- public void remove() {
- if (isPending()) {
+ public void cancel() {
+ if (mEvent != null) {
mHandler.removeCallbacks(this);
clear();
}
}
- public boolean isPending() {
- return (mEvent != null);
+ private boolean isPending() {
+ return mHandler.hasCallbacks(this);
}
@Override
public void run() {
- // Active pointers should not be zero when running this command.
- if (mReceivedPointerTracker.getActivePointerCount() == 0) {
+ // Pointers should not be zero when running this command.
+ if (mReceivedPointerTracker.getLastReceivedEvent().getPointerCount() == 0) {
return;
}
@@ -1461,14 +1331,11 @@ class TouchExplorer implements EventStreamTransformation {
sendHoverExitAndTouchExplorationGestureEndIfNeeded(mPolicyFlags);
mCurrentState = STATE_DELEGATING;
- sendDownForAllActiveNotInjectedPointers(mEvent, mPolicyFlags);
+ sendDownForAllNotInjectedPointers(mEvent, mPolicyFlags);
clear();
}
private void clear() {
- if (!isPending()) {
- return;
- }
mEvent.recycle();
mEvent = null;
mPolicyFlags = 0;
@@ -1476,59 +1343,114 @@ class TouchExplorer implements EventStreamTransformation {
}
/**
- * Class for delayed sending of hover events.
+ * Class for delayed sending of hover enter and move events.
*/
- class SendHoverDelayed implements Runnable {
- private final String LOG_TAG_SEND_HOVER_DELAYED = SendHoverDelayed.class.getName();
+ class SendHoverEnterAndMoveDelayed implements Runnable {
+ private final String LOG_TAG_SEND_HOVER_DELAYED = "SendHoverEnterAndMoveDelayed";
- private final int mHoverAction;
- private final boolean mGestureStarted;
+ private final List<MotionEvent> mEvents = new ArrayList<MotionEvent>();
- private MotionEvent mPrototype;
private int mPointerIdBits;
private int mPolicyFlags;
- public SendHoverDelayed(int hoverAction, boolean gestureStarted) {
- mHoverAction = hoverAction;
- mGestureStarted = gestureStarted;
- }
-
- public void post(MotionEvent prototype, boolean touchExplorationInProgress,
+ public void post(MotionEvent event, boolean touchExplorationInProgress,
int pointerIdBits, int policyFlags) {
- remove();
- mPrototype = MotionEvent.obtain(prototype);
+ cancel();
+ addEvent(event);
mPointerIdBits = pointerIdBits;
mPolicyFlags = policyFlags;
mHandler.postDelayed(this, mDetermineUserIntentTimeout);
}
- public float getX() {
+ public void addEvent(MotionEvent event) {
+ mEvents.add(MotionEvent.obtain(event));
+ }
+
+ public void cancel() {
if (isPending()) {
- return mPrototype.getX();
+ mHandler.removeCallbacks(this);
+ clear();
+ }
+ }
+
+ private boolean isPending() {
+ return mHandler.hasCallbacks(this);
+ }
+
+ private void clear() {
+ mPointerIdBits = -1;
+ mPolicyFlags = 0;
+ final int eventCount = mEvents.size();
+ for (int i = eventCount - 1; i >= 0; i--) {
+ mEvents.remove(i).recycle();
}
- return 0;
}
- public float getY() {
+ public void forceSendAndRemove() {
if (isPending()) {
- return mPrototype.getY();
+ run();
+ cancel();
}
- return 0;
}
- public void remove() {
- mHandler.removeCallbacks(this);
+ public void run() {
+ // Send an accessibility event to announce the touch exploration start.
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START);
+
+ if (!mEvents.isEmpty()) {
+ // Deliver a down event.
+ sendMotionEvent(mEvents.get(0), MotionEvent.ACTION_HOVER_ENTER,
+ mPointerIdBits, mPolicyFlags);
+ if (DEBUG) {
+ Slog.d(LOG_TAG_SEND_HOVER_DELAYED,
+ "Injecting motion event: ACTION_HOVER_ENTER");
+ }
+
+ // Deliver move events.
+ final int eventCount = mEvents.size();
+ for (int i = 1; i < eventCount; i++) {
+ sendMotionEvent(mEvents.get(i), MotionEvent.ACTION_HOVER_MOVE,
+ mPointerIdBits, mPolicyFlags);
+ if (DEBUG) {
+ Slog.d(LOG_TAG_SEND_HOVER_DELAYED,
+ "Injecting motion event: ACTION_HOVER_MOVE");
+ }
+ }
+ }
clear();
}
+ }
+
+ /**
+ * Class for delayed sending of hover exit events.
+ */
+ class SendHoverExitDelayed implements Runnable {
+ private final String LOG_TAG_SEND_HOVER_DELAYED = "SendHoverExitDelayed";
+
+ private MotionEvent mPrototype;
+ private int mPointerIdBits;
+ private int mPolicyFlags;
+
+ public void post(MotionEvent prototype, int pointerIdBits, int policyFlags) {
+ cancel();
+ mPrototype = MotionEvent.obtain(prototype);
+ mPointerIdBits = pointerIdBits;
+ mPolicyFlags = policyFlags;
+ mHandler.postDelayed(this, mDetermineUserIntentTimeout);
+ }
+
+ public void cancel() {
+ if (isPending()) {
+ mHandler.removeCallbacks(this);
+ clear();
+ }
+ }
private boolean isPending() {
- return (mPrototype != null);
+ return mHandler.hasCallbacks(this);
}
private void clear() {
- if (!isPending()) {
- return;
- }
mPrototype.recycle();
mPrototype = null;
mPointerIdBits = -1;
@@ -1538,29 +1460,25 @@ class TouchExplorer implements EventStreamTransformation {
public void forceSendAndRemove() {
if (isPending()) {
run();
- remove();
+ cancel();
}
}
public void run() {
if (DEBUG) {
- Slog.d(LOG_TAG_SEND_HOVER_DELAYED, "Injecting motion event: "
- + MotionEvent.actionToString(mHoverAction));
- Slog.d(LOG_TAG_SEND_HOVER_DELAYED, mGestureStarted ?
- "touchExplorationGestureStarted" : "touchExplorationGestureEnded");
+ Slog.d(LOG_TAG_SEND_HOVER_DELAYED, "Injecting motion event:"
+ + " ACTION_HOVER_EXIT");
}
- if (mGestureStarted) {
- sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START);
- } else {
- if (!mSendTouchExplorationEndDelayed.isPending()) {
- mSendTouchExplorationEndDelayed.post();
- }
- if (mSendTouchInteractionEndDelayed.isPending()) {
- mSendTouchInteractionEndDelayed.remove();
- mSendTouchInteractionEndDelayed.post();
- }
+ sendMotionEvent(mPrototype, MotionEvent.ACTION_HOVER_EXIT,
+ mPointerIdBits, mPolicyFlags);
+ if (!mSendTouchExplorationEndDelayed.isPending()) {
+ mSendTouchExplorationEndDelayed.cancel();
+ mSendTouchExplorationEndDelayed.post();
+ }
+ if (mSendTouchInteractionEndDelayed.isPending()) {
+ mSendTouchInteractionEndDelayed.cancel();
+ mSendTouchInteractionEndDelayed.post();
}
- sendMotionEvent(mPrototype, mHoverAction, mPointerIdBits, mPolicyFlags);
clear();
}
}
@@ -1574,7 +1492,7 @@ class TouchExplorer implements EventStreamTransformation {
mDelay = delay;
}
- public void remove() {
+ public void cancel() {
mHandler.removeCallbacks(this);
}
@@ -1589,7 +1507,7 @@ class TouchExplorer implements EventStreamTransformation {
public void forceSendAndRemove() {
if (isPending()) {
run();
- remove();
+ cancel();
}
}
@@ -1736,15 +1654,6 @@ class TouchExplorer implements EventStreamTransformation {
class ReceivedPointerTracker {
private static final String LOG_TAG_RECEIVED_POINTER_TRACKER = "ReceivedPointerTracker";
- // The coefficient by which to multiply
- // ViewConfiguration.#getScaledTouchSlop()
- // to compute #mThresholdActivePointer.
- private static final int COEFFICIENT_ACTIVE_POINTER = 2;
-
- // Pointers that moved less than mThresholdActivePointer
- // are considered active i.e. are ignored.
- private final double mThresholdActivePointer;
-
// Keep track of where and when a pointer went down.
private final float[] mReceivedPointerDownX = new float[MAX_POINTER_COUNT];
private final float[] mReceivedPointerDownY = new float[MAX_POINTER_COUNT];
@@ -1756,36 +1665,19 @@ class TouchExplorer implements EventStreamTransformation {
// The edge flags of the last received down event.
private int mLastReceivedDownEdgeFlags;
- // Which down pointers are active.
- private int mActivePointers;
-
- // Primary active pointer which is either the first that went down
- // or if it goes up the next active that most recently went down.
- private int mPrimaryActivePointerId;
-
- // Flag indicating that there is at least one active pointer moving.
- private boolean mHasMovingActivePointer;
+ // Primary pointer which is either the first that went down
+ // or if it goes up the next one that most recently went down.
+ private int mPrimaryPointerId;
// Keep track of the last up pointer data.
private long mLastReceivedUpPointerDownTime;
private int mLastReceivedUpPointerId;
- private boolean mLastReceivedUpPointerActive;
private float mLastReceivedUpPointerDownX;
private float mLastReceivedUpPointerDownY;
private MotionEvent mLastReceivedEvent;
/**
- * Creates a new instance.
- *
- * @param context Context for looking up resources.
- */
- public ReceivedPointerTracker(Context context) {
- mThresholdActivePointer =
- ViewConfiguration.get(context).getScaledTouchSlop() * COEFFICIENT_ACTIVE_POINTER;
- }
-
- /**
* Clears the internals state.
*/
public void clear() {
@@ -1793,12 +1685,9 @@ class TouchExplorer implements EventStreamTransformation {
Arrays.fill(mReceivedPointerDownY, 0);
Arrays.fill(mReceivedPointerDownTime, 0);
mReceivedPointersDown = 0;
- mActivePointers = 0;
- mPrimaryActivePointerId = 0;
- mHasMovingActivePointer = false;
+ mPrimaryPointerId = 0;
mLastReceivedUpPointerDownTime = 0;
mLastReceivedUpPointerId = 0;
- mLastReceivedUpPointerActive = false;
mLastReceivedUpPointerDownX = 0;
mLastReceivedUpPointerDownY = 0;
}
@@ -1822,9 +1711,6 @@ class TouchExplorer implements EventStreamTransformation {
case MotionEvent.ACTION_POINTER_DOWN: {
handleReceivedPointerDown(event.getActionIndex(), event);
} break;
- case MotionEvent.ACTION_MOVE: {
- handleReceivedPointerMove(event);
- } break;
case MotionEvent.ACTION_UP: {
handleReceivedPointerUp(event.getActionIndex(), event);
} break;
@@ -1852,20 +1738,6 @@ class TouchExplorer implements EventStreamTransformation {
}
/**
- * @return The bits of the pointers that are active.
- */
- public int getActivePointers() {
- return mActivePointers;
- }
-
- /**
- * @return The number of down input pointers that are active.
- */
- public int getActivePointerCount() {
- return Integer.bitCount(mActivePointers);
- }
-
- /**
* Whether an received pointer is down.
*
* @param pointerId The unique pointer id.
@@ -1877,17 +1749,6 @@ class TouchExplorer implements EventStreamTransformation {
}
/**
- * Whether an input pointer is active.
- *
- * @param pointerId The unique pointer id.
- * @return True if the pointer is active.
- */
- public boolean isActivePointer(int pointerId) {
- final int pointerFlag = (1 << pointerId);
- return (mActivePointers & pointerFlag) != 0;
- }
-
- /**
* @param pointerId The unique pointer id.
* @return The X coordinate where the pointer went down.
*/
@@ -1914,11 +1775,11 @@ class TouchExplorer implements EventStreamTransformation {
/**
* @return The id of the primary pointer.
*/
- public int getPrimaryActivePointerId() {
- if (mPrimaryActivePointerId == INVALID_POINTER_ID) {
- mPrimaryActivePointerId = findPrimaryActivePointer();
+ public int getPrimaryPointerId() {
+ if (mPrimaryPointerId == INVALID_POINTER_ID) {
+ mPrimaryPointerId = findPrimaryPointer();
}
- return mPrimaryActivePointerId;
+ return mPrimaryPointerId;
}
/**
@@ -1929,14 +1790,6 @@ class TouchExplorer implements EventStreamTransformation {
}
/**
- * @return The id of the last received pointer that went up.
- */
- public int getLastReceivedUpPointerId() {
- return mLastReceivedUpPointerId;
- }
-
-
- /**
* @return The down X of the last received pointer that went up.
*/
public float getLastReceivedUpPointerDownX() {
@@ -1958,39 +1811,6 @@ class TouchExplorer implements EventStreamTransformation {
}
/**
- * @return Whether the last received pointer that went up was active.
- */
- public boolean wasLastReceivedUpPointerActive() {
- return mLastReceivedUpPointerActive;
- }
- /**
- * Populates the active pointer IDs to the given array.
- * <p>
- * Note: The client is responsible for providing large enough array.
- *
- * @param outPointerIds The array to which to write the active pointers.
- */
- public void populateActivePointerIds(int[] outPointerIds) {
- int index = 0;
- for (int idBits = mActivePointers; idBits != 0; ) {
- final int id = Integer.numberOfTrailingZeros(idBits);
- idBits &= ~(1 << id);
- outPointerIds[index] = id;
- index++;
- }
- }
-
- /**
- * @param pointerId The unique pointer id.
- * @return Whether the pointer is active or was the last active than went up.
- */
- public boolean isActiveOrWasLastActiveUpPointer(int pointerId) {
- return (isActivePointer(pointerId)
- || (mLastReceivedUpPointerId == pointerId
- && mLastReceivedUpPointerActive));
- }
-
- /**
* Handles a received pointer down event.
*
* @param pointerIndex The index of the pointer that has changed.
@@ -2002,7 +1822,6 @@ class TouchExplorer implements EventStreamTransformation {
mLastReceivedUpPointerId = 0;
mLastReceivedUpPointerDownTime = 0;
- mLastReceivedUpPointerActive = false;
mLastReceivedUpPointerDownX = 0;
mLastReceivedUpPointerDownX = 0;
@@ -2013,25 +1832,7 @@ class TouchExplorer implements EventStreamTransformation {
mReceivedPointerDownY[pointerId] = event.getY(pointerIndex);
mReceivedPointerDownTime[pointerId] = event.getEventTime();
- if (!mHasMovingActivePointer) {
- // If still no moving active pointers every
- // down pointer is the only active one.
- mActivePointers = pointerFlag;
- mPrimaryActivePointerId = pointerId;
- } else {
- // If at least one moving active pointer every
- // subsequent down pointer is active.
- mActivePointers |= pointerFlag;
- }
- }
-
- /**
- * Handles a received pointer move event.
- *
- * @param event The event to be handled.
- */
- private void handleReceivedPointerMove(MotionEvent event) {
- detectActivePointers(event);
+ mPrimaryPointerId = pointerId;
}
/**
@@ -2046,80 +1847,34 @@ class TouchExplorer implements EventStreamTransformation {
mLastReceivedUpPointerId = pointerId;
mLastReceivedUpPointerDownTime = getReceivedPointerDownTime(pointerId);
- mLastReceivedUpPointerActive = isActivePointer(pointerId);
mLastReceivedUpPointerDownX = mReceivedPointerDownX[pointerId];
mLastReceivedUpPointerDownY = mReceivedPointerDownY[pointerId];
mReceivedPointersDown &= ~pointerFlag;
- mActivePointers &= ~pointerFlag;
mReceivedPointerDownX[pointerId] = 0;
mReceivedPointerDownY[pointerId] = 0;
mReceivedPointerDownTime[pointerId] = 0;
- if (mActivePointers == 0) {
- mHasMovingActivePointer = false;
- }
- if (mPrimaryActivePointerId == pointerId) {
- mPrimaryActivePointerId = INVALID_POINTER_ID;
- }
- }
-
- /**
- * Detects the active pointers in an event.
- *
- * @param event The event to examine.
- */
- private void detectActivePointers(MotionEvent event) {
- for (int i = 0, count = event.getPointerCount(); i < count; i++) {
- final int pointerId = event.getPointerId(i);
- if (mHasMovingActivePointer) {
- // If already active => nothing to do.
- if (isActivePointer(pointerId)) {
- continue;
- }
- }
- // Active pointers are ones that moved more than a given threshold.
- final float pointerDeltaMove = computePointerDeltaMove(i, event);
- if (pointerDeltaMove > mThresholdActivePointer) {
- final int pointerFlag = (1 << pointerId);
- mActivePointers |= pointerFlag;
- mHasMovingActivePointer = true;
- }
+ if (mPrimaryPointerId == pointerId) {
+ mPrimaryPointerId = INVALID_POINTER_ID;
}
}
/**
- * @return The primary active pointer.
+ * @return The primary pointer.
*/
- private int findPrimaryActivePointer() {
- int primaryActivePointerId = INVALID_POINTER_ID;
+ private int findPrimaryPointer() {
+ int primaryPointerId = INVALID_POINTER_ID;
long minDownTime = Long.MAX_VALUE;
- // Find the active pointer that went down first.
+ // Find the pointer that went down first.
for (int i = 0, count = mReceivedPointerDownTime.length; i < count; i++) {
- if (isActivePointer(i)) {
- final long downPointerTime = mReceivedPointerDownTime[i];
- if (downPointerTime < minDownTime) {
- minDownTime = downPointerTime;
- primaryActivePointerId = i;
- }
+ final long downPointerTime = mReceivedPointerDownTime[i];
+ if (downPointerTime < minDownTime) {
+ minDownTime = downPointerTime;
+ primaryPointerId = i;
}
}
- return primaryActivePointerId;
- }
-
- /**
- * Computes the move for a given action pointer index since the
- * corresponding pointer went down.
- *
- * @param pointerIndex The action pointer index.
- * @param event The event to examine.
- * @return The distance the pointer has moved.
- */
- private float computePointerDeltaMove(int pointerIndex, MotionEvent event) {
- final int pointerId = event.getPointerId(pointerIndex);
- final float deltaX = event.getX(pointerIndex) - mReceivedPointerDownX[pointerId];
- final float deltaY = event.getY(pointerIndex) - mReceivedPointerDownY[pointerId];
- return (float) Math.hypot(deltaX, deltaY);
+ return primaryPointerId;
}
@Override
@@ -2136,18 +1891,8 @@ class TouchExplorer implements EventStreamTransformation {
}
}
builder.append("]");
- builder.append("\nActive pointers #");
- builder.append(getActivePointerCount());
- builder.append(" [ ");
- for (int i = 0; i < MAX_POINTER_COUNT; i++) {
- if (isActivePointer(i)) {
- builder.append(i);
- builder.append(" ");
- }
- }
- builder.append("]");
- builder.append("\nPrimary active pointer id [ ");
- builder.append(getPrimaryActivePointerId());
+ builder.append("\nPrimary pointer id [ ");
+ builder.append(getPrimaryPointerId());
builder.append(" ]");
builder.append("\n=========================");
return builder.toString();
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 9dba2ed332c8..49e86425db38 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -210,7 +210,7 @@ public final class ActivityManagerService extends ActivityManagerNative
static final boolean DEBUG_BACKGROUND_BROADCAST = DEBUG_BROADCAST || false;
static final boolean DEBUG_CLEANUP = localLOGV || false;
static final boolean DEBUG_CONFIGURATION = localLOGV || false;
- static final boolean DEBUG_FOCUS = true;
+ static final boolean DEBUG_FOCUS = false;
static final boolean DEBUG_IMMERSIVE = localLOGV || false;
static final boolean DEBUG_MU = localLOGV || false;
static final boolean DEBUG_OOM_ADJ = localLOGV || false;
@@ -13830,7 +13830,7 @@ public final class ActivityManagerService extends ActivityManagerNative
for (int is = app.services.size()-1;
is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
- || procState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
+ || procState > ActivityManager.PROCESS_STATE_TOP);
is--) {
ServiceRecord s = app.services.valueAt(is);
if (s.startRequested) {
@@ -13871,13 +13871,13 @@ public final class ActivityManagerService extends ActivityManagerNative
for (int conni = s.connections.size()-1;
conni >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
- || procState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
+ || procState > ActivityManager.PROCESS_STATE_TOP);
conni--) {
ArrayList<ConnectionRecord> clist = s.connections.valueAt(conni);
for (int i = 0;
i < clist.size() && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
- || procState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
+ || procState > ActivityManager.PROCESS_STATE_TOP);
i++) {
// XXX should compute this based on the max of
// all connected clients.
@@ -13987,8 +13987,16 @@ public final class ActivityManagerService extends ActivityManagerNative
if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
schedGroup = Process.THREAD_GROUP_DEFAULT;
}
- if (clientProcState <
- ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
+ if (clientProcState <=
+ ActivityManager.PROCESS_STATE_PERSISTENT_UI &&
+ clientProcState >=
+ ActivityManager.PROCESS_STATE_PERSISTENT) {
+ // Persistent processes don't allow us to become top.
+ // However the top process DOES allow us to become top,
+ // because in that case we are running because the current
+ // top process wants us, so we should be counted as part
+ // of the top set and not just running for some random
+ // unknown reason in the background.
clientProcState =
ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
}
@@ -14040,13 +14048,13 @@ public final class ActivityManagerService extends ActivityManagerNative
for (int provi = app.pubProviders.size()-1;
provi >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
- || procState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
+ || procState > ActivityManager.PROCESS_STATE_TOP);
provi--) {
ContentProviderRecord cpr = app.pubProviders.valueAt(provi);
for (int i = cpr.connections.size()-1;
i >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
|| schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE
- || procState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
+ || procState > ActivityManager.PROCESS_STATE_TOP);
i--) {
ContentProviderConnection conn = cpr.connections.get(i);
ProcessRecord client = conn.client;
@@ -14078,9 +14086,21 @@ public final class ActivityManagerService extends ActivityManagerNative
app.adjSourceOom = clientAdj;
app.adjTarget = cpr.name;
}
+ if (clientProcState <=
+ ActivityManager.PROCESS_STATE_PERSISTENT_UI &&
+ clientProcState >=
+ ActivityManager.PROCESS_STATE_PERSISTENT) {
+ // Persistent processes don't allow us to become top.
+ // However the top process DOES allow us to become top,
+ // because in that case we are running because the current
+ // top process wants us, so we should be counted as part
+ // of the top set and not just running for some random
+ // unknown reason in the background.
+ clientProcState =
+ ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
+ }
if (procState > clientProcState) {
- procState = clientProcState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
- ? clientProcState : ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
+ procState = clientProcState;
}
if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
schedGroup = Process.THREAD_GROUP_DEFAULT;
diff --git a/services/java/com/android/server/am/ProcessStatsService.java b/services/java/com/android/server/am/ProcessStatsService.java
index 81b56188b2af..4ba26fbe3107 100644
--- a/services/java/com/android/server/am/ProcessStatsService.java
+++ b/services/java/com/android/server/am/ProcessStatsService.java
@@ -103,17 +103,7 @@ public final class ProcessStatsService extends IProcessStats.Stub {
public ProcessStats.ServiceState getServiceStateLocked(String packageName, int uid,
String processName, String className) {
- final ProcessStats.PackageState as = mProcessStats.getPackageStateLocked(packageName, uid);
- ProcessStats.ServiceState ss = as.mServices.get(className);
- if (ss != null) {
- ss.makeActive();
- return ss;
- }
- final ProcessStats.ProcessState ps = mProcessStats.getProcessStateLocked(packageName,
- uid, processName);
- ss = new ProcessStats.ServiceState(mProcessStats, packageName, ps);
- as.mServices.put(className, ss);
- return ss;
+ return mProcessStats.getServiceStateLocked(packageName, uid, processName, className);
}
public boolean isMemFactorLowered() {
@@ -271,40 +261,11 @@ public final class ProcessStatsService extends IProcessStats.Stub {
}
}
- static byte[] readFully(FileInputStream stream) throws java.io.IOException {
- int pos = 0;
- int avail = stream.available();
- byte[] data = new byte[avail];
- while (true) {
- int amt = stream.read(data, pos, data.length-pos);
- //Log.i("foo", "Read " + amt + " bytes at " + pos
- // + " of avail " + data.length);
- if (amt <= 0) {
- //Log.i("foo", "**** FINISHED READING: pos=" + pos
- // + " len=" + data.length);
- return data;
- }
- pos += amt;
- avail = stream.available();
- if (avail > data.length-pos) {
- byte[] newData = new byte[pos+avail];
- System.arraycopy(data, 0, newData, 0, pos);
- data = newData;
- }
- }
- }
-
boolean readLocked(ProcessStats stats, AtomicFile file) {
try {
FileInputStream stream = file.openRead();
-
- byte[] raw = readFully(stream);
- Parcel in = Parcel.obtain();
- in.unmarshall(raw, 0, raw.length);
- in.setDataPosition(0);
+ stats.read(stream);
stream.close();
-
- stats.readFromParcel(in);
if (stats.mReadError != null) {
Slog.w(TAG, "Ignoring existing stats; " + stats.mReadError);
if (DEBUG) {
@@ -474,6 +435,12 @@ public final class ProcessStatsService extends IProcessStats.Stub {
return current.marshall();
}
+ public int getCurrentMemoryState() {
+ synchronized (mAm) {
+ return mLastMemOnlyState;
+ }
+ }
+
static private void dumpHelp(PrintWriter pw) {
pw.println("Process stats (procstats) dump options:");
pw.println(" [--checkin|-c|--csv] [--csv-screen] [--csv-proc] [--csv-mem]");
diff --git a/services/java/com/android/server/connectivity/PacManager.java b/services/java/com/android/server/connectivity/PacManager.java
index 189c6261c39a..defe9f075147 100644
--- a/services/java/com/android/server/connectivity/PacManager.java
+++ b/services/java/com/android/server/connectivity/PacManager.java
@@ -83,6 +83,12 @@ public class PacManager implements Runnable {
mContext = context;
mProxyService = IProxyService.Stub.asInterface(
ServiceManager.getService(PROXY_SERVICE));
+ if (mProxyService == null) {
+ // Added because of b10267814 where mako is restarting.
+ Log.e(TAG, "PacManager: no proxy service");
+ } else {
+ Log.d(TAG, "PacManager: mProxyService available");
+ }
mPacRefreshIntent = PendingIntent.getBroadcast(
context, 0, new Intent(ACTION_PAC_REFRESH), 0);
@@ -98,6 +104,10 @@ public class PacManager implements Runnable {
}
public void setCurrentProxyScriptUrl(ProxyProperties proxy) {
+ if (mProxyService == null) {
+ Log.e(TAG, "setCurrentProxyScriptUrl: no proxy service");
+ return;
+ }
if (!TextUtils.isEmpty(proxy.getPacFileUrl())) {
try {
mProxyService.startPacSystem();
@@ -212,6 +222,10 @@ public class PacManager implements Runnable {
}
private boolean setCurrentProxyScript(String script) {
+ if (mProxyService == null) {
+ Log.e(TAG, "setCurrentProxyScript: no proxy service");
+ return false;
+ }
try {
if (mProxyService.setPacFile(script) != NO_ERROR) {
Log.e(TAG, "Unable to parse proxy script.");
diff --git a/services/java/com/android/server/location/FlpHardwareProvider.java b/services/java/com/android/server/location/FlpHardwareProvider.java
index 469f7ce45ff8..226c18c2ad8e 100644
--- a/services/java/com/android/server/location/FlpHardwareProvider.java
+++ b/services/java/com/android/server/location/FlpHardwareProvider.java
@@ -28,11 +28,10 @@ import android.location.LocationManager;
import android.content.Context;
import android.os.Bundle;
-import android.os.Handler;
+import android.os.Looper;
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Log;
-import android.util.Slog;
/**
* This class is an interop layer for JVM types and the JNI code that interacts
@@ -48,6 +47,7 @@ public class FlpHardwareProvider {
private final static String TAG = "FlpHardwareProvider";
private final Context mContext;
+ private final Object mLocationSinkLock = new Object();
public static FlpHardwareProvider getInstance(Context context) {
if (sSingletonInstance == null) {
@@ -61,7 +61,6 @@ public class FlpHardwareProvider {
mContext = context;
// register for listening for passive provider data
- Handler handler = new Handler();
LocationManager manager = (LocationManager) mContext.getSystemService(
Context.LOCATION_SERVICE);
manager.requestLocationUpdates(
@@ -69,7 +68,7 @@ public class FlpHardwareProvider {
0 /* minTime */,
0 /* minDistance */,
new NetworkLocationListener(),
- handler.getLooper());
+ Looper.myLooper());
}
public static boolean isSupported() {
@@ -87,9 +86,13 @@ public class FlpHardwareProvider {
location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
}
+ IFusedLocationHardwareSink sink;
+ synchronized (mLocationSinkLock) {
+ sink = mLocationSink;
+ }
try {
- if (mLocationSink != null) {
- mLocationSink.onLocationAvailable(locations);
+ if (sink != null) {
+ sink.onLocationAvailable(locations);
}
} catch (RemoteException e) {
Log.e(TAG, "RemoteException calling onLocationAvailable");
@@ -98,9 +101,13 @@ public class FlpHardwareProvider {
// FlpDiagnosticCallbacks members
private void onDataReport(String data) {
+ IFusedLocationHardwareSink sink;
+ synchronized (mLocationSinkLock) {
+ sink = mLocationSink;
+ }
try {
if (mLocationSink != null) {
- mLocationSink.onDiagnosticDataAvailable(data);
+ sink.onDiagnosticDataAvailable(data);
}
} catch (RemoteException e) {
Log.e(TAG, "RemoteException calling onDiagnosticDataAvailable");
@@ -199,19 +206,24 @@ public class FlpHardwareProvider {
private final IFusedLocationHardware mLocationHardware = new IFusedLocationHardware.Stub() {
@Override
public void registerSink(IFusedLocationHardwareSink eventSink) {
- // only one sink is allowed at the moment
- if (mLocationSink != null) {
- throw new RuntimeException("IFusedLocationHardware does not support multiple sinks");
+ synchronized (mLocationSinkLock) {
+ // only one sink is allowed at the moment
+ if (mLocationSink != null) {
+ throw new RuntimeException(
+ "IFusedLocationHardware does not support multiple sinks");
+ }
+
+ mLocationSink = eventSink;
}
-
- mLocationSink = eventSink;
}
@Override
public void unregisterSink(IFusedLocationHardwareSink eventSink) {
- // don't throw if the sink is not registered, simply make it a no-op
- if (mLocationSink == eventSink) {
- mLocationSink = null;
+ synchronized (mLocationSinkLock) {
+ // don't throw if the sink is not registered, simply make it a no-op
+ if (mLocationSink == eventSink) {
+ mLocationSink = null;
+ }
}
}
diff --git a/services/java/com/android/server/location/FusedProxy.java b/services/java/com/android/server/location/FusedProxy.java
index 8278b96b7803..f7fac774c979 100644
--- a/services/java/com/android/server/location/FusedProxy.java
+++ b/services/java/com/android/server/location/FusedProxy.java
@@ -33,10 +33,8 @@ import android.util.Log;
*/
public final class FusedProxy {
private final String TAG = "FusedProxy";
-
- private ServiceWatcher mServiceWatcher;
-
- private FusedLocationHardwareSecure mLocationHardware;
+ private final ServiceWatcher mServiceWatcher;
+ private final FusedLocationHardwareSecure mLocationHardware;
/**
* Constructor of the class.
@@ -46,7 +44,13 @@ public final class FusedProxy {
* @param handler The handler needed for construction.
* @param locationHardware The instance of the Fused location hardware assigned to the proxy.
*/
- private FusedProxy(Context context, Handler handler, IFusedLocationHardware locationHardware) {
+ private FusedProxy(
+ Context context,
+ Handler handler,
+ IFusedLocationHardware locationHardware,
+ int overlaySwitchResId,
+ int defaultServicePackageNameResId,
+ int initialPackageNameResId) {
mLocationHardware = new FusedLocationHardwareSecure(
locationHardware,
context,
@@ -63,9 +67,9 @@ public final class FusedProxy {
context,
TAG,
"com.android.location.service.FusedProvider",
- com.android.internal.R.bool.config_enableFusedLocationOverlay,
- com.android.internal.R.string.config_fusedLocationProviderPackageName,
- com.android.internal.R.array.config_locationProviderPackageNames,
+ overlaySwitchResId,
+ defaultServicePackageNameResId,
+ initialPackageNameResId,
newServiceWork,
handler);
}
@@ -82,9 +86,17 @@ public final class FusedProxy {
public static FusedProxy createAndBind(
Context context,
Handler handler,
- IFusedLocationHardware locationHardware
- ) {
- FusedProxy fusedProxy = new FusedProxy(context, handler, locationHardware);
+ IFusedLocationHardware locationHardware,
+ int overlaySwitchResId,
+ int defaultServicePackageNameResId,
+ int initialPackageNameResId) {
+ FusedProxy fusedProxy = new FusedProxy(
+ context,
+ handler,
+ locationHardware,
+ overlaySwitchResId,
+ defaultServicePackageNameResId,
+ initialPackageNameResId);
// try to bind the Fused provider
if (!fusedProxy.mServiceWatcher.start()) {
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index 163536ab49aa..e78362bae63b 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -22,6 +22,8 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
+import static android.os.Process.SYSTEM_UID;
+import static android.os.Process.PACKAGE_INFO_GID;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
@@ -117,6 +119,7 @@ final class Settings {
private final File mPackageListFilename;
private final File mStoppedPackagesFilename;
private final File mBackupStoppedPackagesFilename;
+
final HashMap<String, PackageSetting> mPackages =
new HashMap<String, PackageSetting>();
// List of replaced system applications
@@ -201,6 +204,8 @@ final class Settings {
mSettingsFilename = new File(mSystemDir, "packages.xml");
mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
mPackageListFilename = new File(mSystemDir, "packages.list");
+ FileUtils.setPermissions(mPackageListFilename, 0660, SYSTEM_UID, PACKAGE_INFO_GID);
+
// Deprecated: Needed for migration
mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
@@ -1369,13 +1374,15 @@ final class Settings {
-1, -1);
// Write package list file now, use a JournaledFile.
- //
- File tempFile = new File(mPackageListFilename.toString() + ".tmp");
+ File tempFile = new File(mPackageListFilename.getAbsolutePath() + ".tmp");
JournaledFile journal = new JournaledFile(mPackageListFilename, tempFile);
- fstr = new FileOutputStream(journal.chooseForWrite());
+ final File writeTarget = journal.chooseForWrite();
+ fstr = new FileOutputStream(writeTarget);
str = new BufferedOutputStream(fstr);
try {
+ FileUtils.setPermissions(fstr.getFD(), 0660, SYSTEM_UID, PACKAGE_INFO_GID);
+
StringBuilder sb = new StringBuilder();
for (final PackageSetting pkg : mPackages.values()) {
ApplicationInfo ai = pkg.pkg.applicationInfo;
@@ -1400,6 +1407,7 @@ final class Settings {
// DO NOT MODIFY THIS FORMAT UNLESS YOU CAN ALSO MODIFY ITS USERS
// FROM NATIVE CODE. AT THE MOMENT, LOOK AT THE FOLLOWING SOURCES:
// system/core/run-as/run-as.c
+ // system/core/sdcard/sdcard.c
//
sb.setLength(0);
sb.append(ai.packageName);
@@ -1421,11 +1429,6 @@ final class Settings {
journal.rollback();
}
- FileUtils.setPermissions(mPackageListFilename.toString(),
- FileUtils.S_IRUSR|FileUtils.S_IWUSR
- |FileUtils.S_IRGRP|FileUtils.S_IWGRP,
- -1, -1);
-
writeAllUsersPackageRestrictionsLPr();
return;
diff --git a/services/java/com/android/server/print/RemotePrintService.java b/services/java/com/android/server/print/RemotePrintService.java
index 28a7362bc6cd..322de6cae3aa 100644
--- a/services/java/com/android/server/print/RemotePrintService.java
+++ b/services/java/com/android/server/print/RemotePrintService.java
@@ -24,13 +24,14 @@ import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
+import android.os.IBinder.DeathRecipient;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.UserHandle;
-import android.os.IBinder.DeathRecipient;
-import android.print.IPrinterDiscoveryObserver;
+import android.print.IPrinterDiscoverySessionController;
+import android.print.IPrinterDiscoverySessionObserver;
import android.print.PrintJobInfo;
import android.print.PrintManager;
import android.print.PrinterId;
@@ -128,18 +129,18 @@ final class RemotePrintService implements DeathRecipient {
printJob).sendToTarget();
}
- private void handleOnRequestCancelPrintJob(final PrintJobInfo printJob) {
+ private void handleRequestCancelPrintJob(final PrintJobInfo printJob) {
throwIfDestroyed();
// If we are not bound, then we have no print jobs to handle
// which means that there are no print jobs to be cancelled.
if (isBound()) {
if (DEBUG) {
- Slog.i(LOG_TAG, "[user: " + mUserId + "] handleOnRequestCancelPrintJob()");
+ Slog.i(LOG_TAG, "[user: " + mUserId + "] handleRequestCancelPrintJob()");
}
try {
- mPrintService.onRequestCancelPrintJob(printJob);
+ mPrintService.requestCancelPrintJob(printJob);
} catch (RemoteException re) {
- Slog.e(LOG_TAG, "Error canceling pring job.", re);
+ Slog.e(LOG_TAG, "Error canceling a pring job.", re);
}
}
}
@@ -171,85 +172,34 @@ final class RemotePrintService implements DeathRecipient {
}
}
- public void onStartPrinterDiscovery(IPrinterDiscoveryObserver observer) {
- mHandler.obtainMessage(MyHandler.MSG_ON_START_PRINTER_DISCOVERY, observer).sendToTarget();
+ public void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer) {
+ mHandler.obtainMessage(MyHandler.MSG_CREATE_PRINTER_DISCOVERY_SESSION,
+ observer).sendToTarget();
}
- private void handleOnStartPrinterDiscovery(final IPrinterDiscoveryObserver observer) {
+ private void handleCreatePrinterDiscoverySession(
+ final IPrinterDiscoverySessionObserver observer) {
throwIfDestroyed();
if (!isBound()) {
ensureBound();
mPendingCommands.add(new Runnable() {
@Override
public void run() {
- handleOnStartPrinterDiscovery(observer);
+ handleCreatePrinterDiscoverySession(observer);
}
});
} else {
if (DEBUG) {
- Slog.i(LOG_TAG, "[user: " + mUserId + "] onStartPrinterDiscovery()");
+ Slog.i(LOG_TAG, "[user: " + mUserId + "] createPrinterDiscoverySession()");
}
try {
- mPrintService.onStartPrinterDiscovery(observer);
+ mPrintService.createPrinterDiscoverySession(observer);
} catch (RemoteException re) {
Slog.e(LOG_TAG, "Error announcing start printer dicovery.", re);
}
}
}
- public void onStopPrinterDiscovery() {
- mHandler.sendEmptyMessage(MyHandler.MSG_ON_STOP_PRINTER_DISCOVERY);
- }
-
- private void handleStopPrinterDiscovery() {
- throwIfDestroyed();
- if (!isBound()) {
- ensureBound();
- mPendingCommands.add(new Runnable() {
- @Override
- public void run() {
- handleStopPrinterDiscovery();
- }
- });
- } else {
- if (DEBUG) {
- Slog.i(LOG_TAG, "[user: " + mUserId + "] onStopPrinterDiscovery()");
- }
- try {
- mPrintService.onStopPrinterDiscovery();
- } catch (RemoteException re) {
- Slog.e(LOG_TAG, "Error announcing stop printer dicovery.", re);
- }
- }
- }
-
- public void onRequestUpdatePrinters(List<PrinterId> printerIds) {
- mHandler.obtainMessage(MyHandler.MSG_ON_REQUEST_UPDATE_PRINTERS,
- printerIds).sendToTarget();
- }
-
- private void handleReqeustUpdatePrinters(final List<PrinterId> printerIds) {
- throwIfDestroyed();
- if (!isBound()) {
- ensureBound();
- mPendingCommands.add(new Runnable() {
- @Override
- public void run() {
- handleReqeustUpdatePrinters(printerIds);
- }
- });
- } else {
- if (DEBUG) {
- Slog.i(LOG_TAG, "[user: " + mUserId + "] handleReqeustUpdatePrinters()");
- }
- try {
- mPrintService.onRequestUpdatePrinters(printerIds);
- } catch (RemoteException re) {
- Slog.e(LOG_TAG, "Error requesting to update printers.", re);
- }
- }
- }
-
private boolean isBound() {
return mPrintService != null;
}
@@ -331,18 +281,15 @@ final class RemotePrintService implements DeathRecipient {
public static final int MSG_ON_ALL_PRINT_JOBS_HANDLED = 1;
public static final int MSG_ON_REQUEST_CANCEL_PRINT_JOB = 2;
public static final int MSG_ON_PRINT_JOB_QUEUED = 3;
- public static final int MSG_ON_START_PRINTER_DISCOVERY = 4;
- public static final int MSG_ON_STOP_PRINTER_DISCOVERY = 5;
- public static final int MSG_ON_REQUEST_UPDATE_PRINTERS = 6;
- public static final int MSG_DESTROY = 7;
- public static final int MSG_BINDER_DIED = 8;
+ public static final int MSG_CREATE_PRINTER_DISCOVERY_SESSION = 4;
+ public static final int MSG_DESTROY = 6;
+ public static final int MSG_BINDER_DIED = 7;
public MyHandler(Looper looper) {
super(looper, null, false);
}
@Override
- @SuppressWarnings("unchecked")
public void handleMessage(Message message) {
switch (message.what) {
case MSG_ON_ALL_PRINT_JOBS_HANDLED: {
@@ -351,7 +298,7 @@ final class RemotePrintService implements DeathRecipient {
case MSG_ON_REQUEST_CANCEL_PRINT_JOB: {
PrintJobInfo printJob = (PrintJobInfo) message.obj;
- handleOnRequestCancelPrintJob(printJob);
+ handleRequestCancelPrintJob(printJob);
} break;
case MSG_ON_PRINT_JOB_QUEUED: {
@@ -359,21 +306,13 @@ final class RemotePrintService implements DeathRecipient {
handleOnPrintJobQueued(printJob);
} break;
- case MSG_ON_START_PRINTER_DISCOVERY: {
- IPrinterDiscoveryObserver observer = (IPrinterDiscoveryObserver) message.obj;
- handleOnStartPrinterDiscovery(new SecurePrinterDiscoveryObserver(
+ case MSG_CREATE_PRINTER_DISCOVERY_SESSION: {
+ IPrinterDiscoverySessionObserver observer =
+ (IPrinterDiscoverySessionObserver) message.obj;
+ handleCreatePrinterDiscoverySession(new SecurePrinterDiscoverySessionObserver(
mComponentName, observer));
} break;
- case MSG_ON_REQUEST_UPDATE_PRINTERS: {
- List<PrinterId> printerIds = (List<PrinterId>) message.obj;
- handleReqeustUpdatePrinters(printerIds);
- } break;
-
- case MSG_ON_STOP_PRINTER_DISCOVERY: {
- handleStopPrinterDiscovery();
- } break;
-
case MSG_DESTROY: {
handleDestroy();
} break;
@@ -464,14 +403,14 @@ final class RemotePrintService implements DeathRecipient {
}
}
- private static final class SecurePrinterDiscoveryObserver
- extends IPrinterDiscoveryObserver.Stub {
+ private static final class SecurePrinterDiscoverySessionObserver
+ extends IPrinterDiscoverySessionObserver.Stub {
private final ComponentName mComponentName;
- private final IPrinterDiscoveryObserver mDecoratedObsever;
+ private final IPrinterDiscoverySessionObserver mDecoratedObsever;
- public SecurePrinterDiscoveryObserver(ComponentName componentName,
- IPrinterDiscoveryObserver observer) {
+ public SecurePrinterDiscoverySessionObserver(ComponentName componentName,
+ IPrinterDiscoverySessionObserver observer) {
mComponentName = componentName;
mDecoratedObsever = observer;
}
@@ -506,6 +445,15 @@ final class RemotePrintService implements DeathRecipient {
}
}
+ @Override
+ public void setController(IPrinterDiscoverySessionController controller) {
+ try {
+ mDecoratedObsever.setController(controller);
+ } catch (RemoteException re) {
+ Slog.e(LOG_TAG, "Error setting controller", re);
+ }
+ }
+
private void throwIfPrinterIdsForPrinterInfoTampered(
List<PrinterInfo> printerInfos) {
final int printerInfoCount = printerInfos.size();
diff --git a/services/java/com/android/server/print/RemotePrintSpooler.java b/services/java/com/android/server/print/RemotePrintSpooler.java
index 3a96a5bc74f2..c932e9b418f8 100644
--- a/services/java/com/android/server/print/RemotePrintSpooler.java
+++ b/services/java/com/android/server/print/RemotePrintSpooler.java
@@ -32,10 +32,9 @@ import android.print.IPrintDocumentAdapter;
import android.print.IPrintSpooler;
import android.print.IPrintSpoolerCallbacks;
import android.print.IPrintSpoolerClient;
-import android.print.IPrinterDiscoveryObserver;
+import android.print.IPrinterDiscoverySessionObserver;
import android.print.PrintAttributes;
import android.print.PrintJobInfo;
-import android.print.PrinterId;
import android.util.Slog;
import android.util.TimedRemoteCaller;
@@ -92,10 +91,8 @@ final class RemotePrintSpooler {
public static interface PrintSpoolerCallbacks {
public void onPrintJobQueued(PrintJobInfo printJob);
- public void onStartPrinterDiscovery(IPrinterDiscoveryObserver observer);
- public void onStopPrinterDiscovery();
public void onAllPrintJobsForServiceHandled(ComponentName printService);
- public void onRequestUpdatePrinters(List<PrinterId> printerIds);
+ public void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer);
}
public RemotePrintSpooler(Context context, int userId,
@@ -600,38 +597,12 @@ final class RemotePrintSpooler {
}
@Override
- public void onStartPrinterDiscovery(IPrinterDiscoveryObserver observer) {
+ public void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer) {
RemotePrintSpooler spooler = mWeakSpooler.get();
if (spooler != null) {
final long identity = Binder.clearCallingIdentity();
try {
- spooler.mCallbacks.onStartPrinterDiscovery(observer);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
- }
-
- @Override
- public void onStopPrinterDiscovery() {
- RemotePrintSpooler spooler = mWeakSpooler.get();
- if (spooler != null) {
- final long identity = Binder.clearCallingIdentity();
- try {
- spooler.mCallbacks.onStopPrinterDiscovery();
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
- }
-
- @Override
- public void onRequestUpdatePrinters(List<PrinterId> printerIds) {
- RemotePrintSpooler spooler = mWeakSpooler.get();
- if (spooler != null) {
- final long identity = Binder.clearCallingIdentity();
- try {
- spooler.mCallbacks.onRequestUpdatePrinters(printerIds);
+ spooler.mCallbacks.createPrinterDiscoverySession(observer);
} finally {
Binder.restoreCallingIdentity(identity);
}
diff --git a/services/java/com/android/server/print/UserState.java b/services/java/com/android/server/print/UserState.java
index 00cc2ffca0e0..ffcc9c3057bf 100644
--- a/services/java/com/android/server/print/UserState.java
+++ b/services/java/com/android/server/print/UserState.java
@@ -21,9 +21,8 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.print.IPrinterDiscoveryObserver;
+import android.print.IPrinterDiscoverySessionObserver;
import android.print.PrintJobInfo;
-import android.print.PrinterId;
import android.printservice.PrintServiceInfo;
import android.provider.Settings;
import android.text.TextUtils;
@@ -106,7 +105,7 @@ final class UserState implements PrintSpoolerCallbacks {
}
@Override
- public void onStartPrinterDiscovery(IPrinterDiscoveryObserver observer) {
+ public void createPrinterDiscoverySession(IPrinterDiscoverySessionObserver observer) {
final List<RemotePrintService> services;
synchronized (mLock) {
throwIfDestroyedLocked();
@@ -118,39 +117,7 @@ final class UserState implements PrintSpoolerCallbacks {
final int serviceCount = services.size();
for (int i = 0; i < serviceCount; i++) {
RemotePrintService service = services.get(i);
- service.onStartPrinterDiscovery(observer);
- }
- }
-
- @Override
- public void onStopPrinterDiscovery() {
- final List<RemotePrintService> services;
- synchronized (mLock) {
- throwIfDestroyedLocked();
- if (mActiveServices.isEmpty()) {
- return;
- }
- services = new ArrayList<RemotePrintService>(mActiveServices.values());
- }
- final int serviceCount = services.size();
- for (int i = 0; i < serviceCount; i++) {
- RemotePrintService service = services.get(i);
- service.onStopPrinterDiscovery();
- }
- }
-
- @Override
- public void onRequestUpdatePrinters(List<PrinterId> printerIds) {
- final RemotePrintService service;
- synchronized (mLock) {
- throwIfDestroyedLocked();
- if (mActiveServices.isEmpty()) {
- return;
- }
- service = mActiveServices.get(printerIds.get(0).getServiceName());
- }
- if (service != null) {
- service.onRequestUpdatePrinters(printerIds);
+ service.createPrinterDiscoverySession(observer);
}
}
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 364b854c2cd7..07e1e12cf39f 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -194,9 +194,6 @@ public class WindowManagerService extends IWindowManager.Stub
static final boolean PROFILE_ORIENTATION = false;
static final boolean localLOGV = DEBUG;
- final static boolean REVERSE_ITERATOR = true;
- final static boolean FORWARD_ITERATOR = false;
-
/** How much to multiply the policy's type layer, to reserve room
* for multiple windows of the same type and Z-ordering adjustment
* with TYPE_LAYER_OFFSET. */
@@ -9574,19 +9571,15 @@ public class WindowManagerService extends IWindowManager.Stub
return doRequest;
}
- /** If a window that has an animation specifying a colored background is the current wallpaper
- * target, then the color goes *below* the wallpaper so we don't cause the wallpaper to
+ /** If a window that has an animation specifying a colored background and the current wallpaper
+ * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to
* suddenly disappear. */
int adjustAnimationBackground(WindowStateAnimator winAnimator) {
- final WindowState win = winAnimator.mWin;
- if (mWallpaperTarget == win || mLowerWallpaperTarget == win
- || mUpperWallpaperTarget == win) {
- WindowList windows = win.getWindowList();
- for (int i = windows.size() - 1; i >= 0; --i) {
- WindowState testWin = windows.get(i);
- if (testWin.mIsWallpaper) {
- return testWin.mWinAnimator.mAnimLayer;
- }
+ WindowList windows = winAnimator.mWin.getWindowList();
+ for (int i = windows.size() - 1; i >= 0; --i) {
+ WindowState testWin = windows.get(i);
+ if (testWin.mIsWallpaper && testWin.isVisibleNow()) {
+ return testWin.mWinAnimator.mAnimLayer;
}
}
return winAnimator.mAnimLayer;
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java
index 6fa9cd0c7576..73325cbf5afc 100644
--- a/services/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/java/com/android/server/wm/WindowStateAnimator.java
@@ -1272,6 +1272,11 @@ class WindowStateAnimator {
if (mIsWallpaper) {
mService.dispatchWallpaperVisibility(w, true);
}
+ // This draw means the difference between unique content and mirroring.
+ // Run another pass through performLayout to set mHasContent in the
+ // LogicalDisplay.
+ mAnimator.setPendingLayoutChanges(w.getDisplayId(),
+ WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM);
} else {
w.mOrientationChanging = false;
}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index 4171bb54b31c..361f5d7a8bef 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -1148,14 +1148,6 @@ public final class Canvas_Delegate {
}
@LayoutlibDelegate
- /*package*/ static void native_drawPicture(int nativeCanvas,
- int nativePicture) {
- // FIXME
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Canvas.drawPicture is not supported.", null, null /*data*/);
- }
-
- @LayoutlibDelegate
/*package*/ static void finalizer(int nativeCanvas) {
// get the delegate from the native int so that it can be disposed.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 91702f97b92a..1fcd6093e430 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -3198,6 +3198,7 @@ public class WifiStateMachine extends StateMachine {
class VerifyingLinkState extends State {
@Override
public void enter() {
+ log(getName() + " enter");
setNetworkDetailedState(DetailedState.VERIFYING_POOR_LINK);
mWifiConfigStore.updateStatus(mLastNetworkId, DetailedState.VERIFYING_POOR_LINK);
sendNetworkStateChangeBroadcast(mLastBssid);
@@ -3207,11 +3208,14 @@ public class WifiStateMachine extends StateMachine {
switch (message.what) {
case WifiWatchdogStateMachine.POOR_LINK_DETECTED:
//stay here
+ log(getName() + " POOR_LINK_DETECTED: no transition");
break;
case WifiWatchdogStateMachine.GOOD_LINK_DETECTED:
+ log(getName() + " GOOD_LINK_DETECTED: transition to captive portal check");
transitionTo(mCaptivePortalCheckState);
break;
default:
+ log(getName() + " what=" + message.what + " NOT_HANDLED");
return NOT_HANDLED;
}
return HANDLED;
@@ -3221,6 +3225,7 @@ public class WifiStateMachine extends StateMachine {
class CaptivePortalCheckState extends State {
@Override
public void enter() {
+ log(getName() + " enter");
setNetworkDetailedState(DetailedState.CAPTIVE_PORTAL_CHECK);
mWifiConfigStore.updateStatus(mLastNetworkId, DetailedState.CAPTIVE_PORTAL_CHECK);
sendNetworkStateChangeBroadcast(mLastBssid);
@@ -3229,6 +3234,7 @@ public class WifiStateMachine extends StateMachine {
public boolean processMessage(Message message) {
switch (message.what) {
case CMD_CAPTIVE_CHECK_COMPLETE:
+ log(getName() + " CMD_CAPTIVE_CHECK_COMPLETE");
try {
mNwService.enableIpv6(mInterfaceName);
} catch (RemoteException re) {
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index cf75381e6c45..461dedb8a04b 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -120,6 +120,11 @@ public class WifiStateTracker implements NetworkStateTracker {
mWifiManager.captivePortalCheckComplete();
}
+ @Override
+ public void captivePortalCheckCompleted(boolean isCaptivePortal) {
+ // not implemented
+ }
+
/**
* Turn the wireless radio off for a network.
* @param turnOn {@code true} to turn the radio on, {@code false}