Merge "Update ListMenuItemView to use a single RelativeLayout"
diff --git a/Android.mk b/Android.mk
index 618f404..db6a704 100644
--- a/Android.mk
+++ b/Android.mk
@@ -125,6 +125,8 @@
core/java/android/hardware/ICameraClient.aidl \
core/java/android/hardware/IProCameraUser.aidl \
core/java/android/hardware/IProCameraCallbacks.aidl \
+ core/java/android/hardware/photography/ICameraDeviceUser.aidl \
+ core/java/android/hardware/photography/ICameraDeviceCallbacks.aidl \
core/java/android/hardware/ISerialManager.aidl \
core/java/android/hardware/display/IDisplayManager.aidl \
core/java/android/hardware/display/IDisplayManagerCallback.aidl \
@@ -160,7 +162,7 @@
core/java/android/print/IPrinterDiscoveryObserver.aidl \
core/java/android/print/IPrintAdapter.aidl \
core/java/android/print/IPrintClient.aidl \
- core/java/android/print/IPrintProgressListener.aidl \
+ core/java/android/print/IPrintResultCallback.aidl \
core/java/android/print/IPrintManager.aidl \
core/java/android/print/IPrintSpoolerService.aidl \
core/java/android/print/IPrintSpoolerServiceCallbacks.aidl \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 0c3ccec..6118fc3 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -161,6 +161,7 @@
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/com/android/internal/view/IInputMethodCallback.*)
$(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_intermediates)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates)
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
# ************************************************
diff --git a/api/current.txt b/api/current.txt
index 4debd4d..ac3144d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2697,6 +2697,7 @@
method public void addContentView(android.view.View, android.view.ViewGroup.LayoutParams);
method public void closeContextMenu();
method public void closeOptionsMenu();
+ method public void convertToOpaque();
method public android.app.PendingIntent createPendingResult(int, android.content.Intent, int);
method public final deprecated void dismissDialog(int);
method public boolean dispatchGenericMotionEvent(android.view.MotionEvent);
@@ -2904,6 +2905,7 @@
method public android.app.PendingIntent getRunningServiceControlPanel(android.content.ComponentName) throws java.lang.SecurityException;
method public java.util.List<android.app.ActivityManager.RunningServiceInfo> getRunningServices(int) throws java.lang.SecurityException;
method public java.util.List<android.app.ActivityManager.RunningTaskInfo> getRunningTasks(int) throws java.lang.SecurityException;
+ method public boolean isLowRamDevice();
method public static boolean isRunningInTestHarness();
method public static boolean isUserAMonkey();
method public void killBackgroundProcesses(java.lang.String);
@@ -6155,6 +6157,7 @@
field public static final java.lang.String ACTION_PROVIDER_CHANGED = "android.intent.action.PROVIDER_CHANGED";
field public static final java.lang.String ACTION_QUICK_CLOCK = "android.intent.action.QUICK_CLOCK";
field public static final java.lang.String ACTION_REBOOT = "android.intent.action.REBOOT";
+ field public static final java.lang.String ACTION_RESTRICTIONS_PIN_CHALLENGE = "android.intent.action.RESTRICTIONS_PIN_CHALLENGE";
field public static final java.lang.String ACTION_RUN = "android.intent.action.RUN";
field public static final java.lang.String ACTION_SCREEN_OFF = "android.intent.action.SCREEN_OFF";
field public static final java.lang.String ACTION_SCREEN_ON = "android.intent.action.SCREEN_ON";
@@ -9154,8 +9157,11 @@
method public void draw(android.graphics.Canvas, android.graphics.RectF);
method public void draw(android.graphics.Canvas, android.graphics.Rect);
method public void draw(android.graphics.Canvas, android.graphics.Rect, android.graphics.Paint);
+ method public android.graphics.Bitmap getBitmap();
method public int getDensity();
method public int getHeight();
+ method public java.lang.String getName();
+ method public android.graphics.Paint getPaint();
method public final android.graphics.Region getTransparentRegion(android.graphics.Rect);
method public int getWidth();
method public final boolean hasAlpha();
@@ -10653,7 +10659,7 @@
package android.hardware.photography {
- public class CameraAccessException extends java.lang.Exception {
+ public class CameraAccessException extends android.util.AndroidException {
ctor public CameraAccessException(int);
ctor public CameraAccessException(int, java.lang.String);
ctor public CameraAccessException(int, java.lang.String, java.lang.Throwable);
@@ -10665,19 +10671,18 @@
field public static final int MAX_CAMERAS_IN_USE = 2; // 0x2
}
- public final class CameraDevice implements java.lang.AutoCloseable {
- ctor public CameraDevice();
- method public void capture(android.hardware.photography.CaptureRequest, android.hardware.photography.CameraDevice.CaptureListener) throws android.hardware.photography.CameraAccessException;
- method public void captureBurst(java.util.List<android.hardware.photography.CaptureRequest>, android.hardware.photography.CameraDevice.CaptureListener) throws android.hardware.photography.CameraAccessException;
- method public void close();
- method public void configureOutputs(java.util.List<android.view.Surface>);
- method public android.hardware.photography.CaptureRequest createCaptureRequest(int) throws android.hardware.photography.CameraAccessException;
- method public android.hardware.photography.CameraProperties getProperties() throws android.hardware.photography.CameraAccessException;
- method public void setErrorListener(android.hardware.photography.CameraDevice.ErrorListener);
- method public void setRepeatingBurst(java.util.List<android.hardware.photography.CaptureRequest>, android.hardware.photography.CameraDevice.CaptureListener) throws android.hardware.photography.CameraAccessException;
- method public void setRepeatingRequest(android.hardware.photography.CaptureRequest, android.hardware.photography.CameraDevice.CaptureListener) throws android.hardware.photography.CameraAccessException;
- method public void stopRepeating() throws android.hardware.photography.CameraAccessException;
- method public void waitUntilIdle() throws android.hardware.photography.CameraAccessException;
+ public abstract interface CameraDevice implements java.lang.AutoCloseable {
+ method public abstract void capture(android.hardware.photography.CaptureRequest, android.hardware.photography.CameraDevice.CaptureListener) throws android.hardware.photography.CameraAccessException;
+ method public abstract void captureBurst(java.util.List<android.hardware.photography.CaptureRequest>, android.hardware.photography.CameraDevice.CaptureListener) throws android.hardware.photography.CameraAccessException;
+ method public abstract void close() throws java.lang.Exception;
+ method public abstract void configureOutputs(java.util.List<android.view.Surface>) throws android.hardware.photography.CameraAccessException;
+ method public abstract android.hardware.photography.CaptureRequest createCaptureRequest(int) throws android.hardware.photography.CameraAccessException;
+ method public abstract android.hardware.photography.CameraProperties getProperties() throws android.hardware.photography.CameraAccessException;
+ method public abstract void setErrorListener(android.hardware.photography.CameraDevice.ErrorListener);
+ method public abstract void setRepeatingBurst(java.util.List<android.hardware.photography.CaptureRequest>, android.hardware.photography.CameraDevice.CaptureListener) throws android.hardware.photography.CameraAccessException;
+ method public abstract void setRepeatingRequest(android.hardware.photography.CaptureRequest, android.hardware.photography.CameraDevice.CaptureListener) throws android.hardware.photography.CameraAccessException;
+ method public abstract void stopRepeating() throws android.hardware.photography.CameraAccessException;
+ method public abstract void waitUntilIdle() throws android.hardware.photography.CameraAccessException;
field public static final int TEMPLATE_MANUAL = 5; // 0x5
field public static final int TEMPLATE_PREVIEW = 1; // 0x1
field public static final int TEMPLATE_RECORD = 2; // 0x2
@@ -10699,7 +10704,7 @@
public final class CameraManager {
method public android.hardware.photography.CameraProperties getCameraProperties(java.lang.String) throws android.hardware.photography.CameraAccessException;
- method public java.lang.String[] getDeviceIdList();
+ method public java.lang.String[] getDeviceIdList() throws android.hardware.photography.CameraAccessException;
method public android.hardware.photography.CameraDevice openCamera(java.lang.String) throws android.hardware.photography.CameraAccessException;
method public void registerCameraListener(android.hardware.photography.CameraManager.CameraListener);
method public void unregisterCameraListener(android.hardware.photography.CameraManager.CameraListener);
@@ -10710,10 +10715,12 @@
method public abstract void onCameraUnavailable(java.lang.String);
}
- public class CameraMetadata implements android.os.Parcelable {
+ public class CameraMetadata implements java.lang.AutoCloseable android.os.Parcelable {
ctor public CameraMetadata();
+ method public void close() throws java.lang.Exception;
method public int describeContents();
method public T get(android.hardware.photography.CameraMetadata.Key<T>);
+ method public void readFromParcel(android.os.Parcel);
method public void set(android.hardware.photography.CameraMetadata.Key<T>, T);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
@@ -10742,9 +10749,10 @@
field public static final android.hardware.photography.CameraMetadata.Key SENSOR_PIXEL_ARRAY_SIZE;
}
- public final class CaptureRequest extends android.hardware.photography.CameraMetadata {
+ public final class CaptureRequest extends android.hardware.photography.CameraMetadata implements android.os.Parcelable {
method public void addTarget(android.view.Surface);
method public void removeTarget(android.view.Surface);
+ field public static final android.os.Parcelable.Creator CREATOR;
field public static final android.hardware.photography.CameraMetadata.Key SENSOR_EXPOSURE_TIME;
field public static final android.hardware.photography.CameraMetadata.Key SENSOR_SENSITIVITY;
}
@@ -11814,26 +11822,24 @@
field public static final int EULER_Z = 2; // 0x2
}
- public abstract class Image implements java.lang.AutoCloseable {
- ctor public Image();
+ public abstract interface Image implements java.lang.AutoCloseable {
method public abstract void close();
- method protected final void finalize();
- method public int getFormat();
- method public int getHeight();
- method public android.media.Image.Plane[] getPlanes();
- method public long getTimestamp();
- method public int getWidth();
+ method public abstract int getFormat();
+ method public abstract int getHeight();
+ method public abstract android.media.Image.Plane[] getPlanes();
+ method public abstract long getTimestamp();
+ method public abstract int getWidth();
}
- public static final class Image.Plane {
- ctor public Image.Plane();
- method public java.nio.ByteBuffer getBuffer();
- method public int getPixelStride();
- method public int getRowStride();
+ public static abstract interface Image.Plane {
+ method public abstract java.nio.ByteBuffer getBuffer();
+ method public abstract int getPixelStride();
+ method public abstract int getRowStride();
}
- public final class ImageReader {
+ public final class ImageReader implements java.lang.AutoCloseable {
ctor public ImageReader(int, int, int, int);
+ method public void close();
method public int getHeight();
method public int getImageFormat();
method public int getMaxImages();
@@ -11841,7 +11847,7 @@
method public android.view.Surface getSurface();
method public int getWidth();
method public void releaseImage(android.media.Image);
- method public void setOnImageAvailableListener(android.media.ImageReader.OnImageAvailableListener);
+ method public void setImageAvailableListener(android.media.ImageReader.OnImageAvailableListener, android.os.Handler);
}
public static abstract interface ImageReader.OnImageAvailableListener {
@@ -17962,6 +17968,7 @@
method public java.lang.String getUserName();
method public android.os.Bundle getUserRestrictions();
method public android.os.Bundle getUserRestrictions(android.os.UserHandle);
+ method public boolean hasRestrictionsPin();
method public boolean isUserAGoat();
method public boolean isUserRunning(android.os.UserHandle);
method public boolean isUserRunningOrStopping(android.os.UserHandle);
@@ -18404,12 +18411,12 @@
ctor public PrintAdapter();
method public abstract android.print.PrintAdapterInfo getInfo();
method public void onFinish();
- method public abstract void onPrint(java.util.List<android.print.PageRange>, java.io.FileDescriptor, android.os.CancellationSignal, android.print.PrintAdapter.PrintProgressCallback);
+ method public abstract void onPrint(java.util.List<android.print.PageRange>, java.io.FileDescriptor, android.os.CancellationSignal, android.print.PrintAdapter.PrintResultCallback);
method public boolean onPrintAttributesChanged(android.print.PrintAttributes);
method public void onStart();
}
- public static abstract class PrintAdapter.PrintProgressCallback {
+ public static abstract class PrintAdapter.PrintResultCallback {
method public void onPrintFailed(java.lang.CharSequence);
method public void onPrintFinished(java.util.List<android.print.PageRange>);
}
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 3bbdc48..87ea4fd 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -153,7 +153,7 @@
" test runners.\n" +
" --user <USER_ID> | current: Specify user instrumentation runs in;\n" +
" current user if not specified.\n" +
- " --no-window-animation: turn off window animations will running.\n" +
+ " --no-window-animation: turn off window animations while running.\n" +
"\n" +
"am profile: start and stop profiler on a process. The given <PROCESS> argument\n" +
" may be either a process name or pid. Options are:\n" +
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 6f57ae0..d1ded10 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -147,6 +147,16 @@
return;
}
+ if ("block".equals(op)) {
+ runSetBlockedSetting(true);
+ return;
+ }
+
+ if ("unblock".equals(op)) {
+ runSetBlockedSetting(false);
+ return;
+ }
+
if ("grant".equals(op)) {
runGrantRevokePermission(true);
return;
@@ -1256,6 +1266,36 @@
}
}
+ private void runSetBlockedSetting(boolean state) {
+ int userId = 0;
+ String option = nextOption();
+ if (option != null && option.equals("--user")) {
+ String optionData = nextOptionData();
+ if (optionData == null || !isNumber(optionData)) {
+ System.err.println("Error: no USER_ID specified");
+ showUsage();
+ return;
+ } else {
+ userId = Integer.parseInt(optionData);
+ }
+ }
+
+ String pkg = nextArg();
+ if (pkg == null) {
+ System.err.println("Error: no package or component specified");
+ showUsage();
+ return;
+ }
+ try {
+ mPm.setApplicationBlockedSettingAsUser(pkg, state, userId);
+ System.err.println("Package " + pkg + " new blocked state: "
+ + mPm.getApplicationBlockedSettingAsUser(pkg, userId));
+ } catch (RemoteException e) {
+ System.err.println(e.toString());
+ System.err.println(PM_NOT_RUNNING_ERR);
+ }
+ }
+
private void runGrantRevokePermission(boolean grant) {
String pkg = nextArg();
if (pkg == null) {
@@ -1482,6 +1522,8 @@
System.err.println(" pm disable [--user USER_ID] PACKAGE_OR_COMPONENT");
System.err.println(" pm disable-user [--user USER_ID] PACKAGE_OR_COMPONENT");
System.err.println(" pm disable-until-used [--user USER_ID] PACKAGE_OR_COMPONENT");
+ System.err.println(" pm block [--user USER_ID] PACKAGE_OR_COMPONENT");
+ System.err.println(" pm unblock [--user USER_ID] PACKAGE_OR_COMPONENT");
System.err.println(" pm grant PACKAGE PERMISSION");
System.err.println(" pm revoke PACKAGE PERMISSION");
System.err.println(" pm set-install-location [0/auto] [1/internal] [2/external]");
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 7f2f744..e87d805 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -4862,6 +4862,25 @@
}
/**
+ * Convert a translucent themed Activity {@link android.R.attr#windowIsTranslucent} to a
+ * fullscreen opaque Activity.
+ *
+ * Call this whenever the background of a translucent Activity has changed to become opaque.
+ * Doing so will allow the previously visible Activity behind this one to be stopped. Stopped
+ * apps consume no CPU cycles and are eligible for removal when reclaiming memory.
+ *
+ * This call has no effect on non-translucent activities or on activities with the
+ * {@link android.R.attr#windowIsFloating} attribute.
+ */
+ public void convertToOpaque() {
+ try {
+ ActivityManagerNative.getDefault().convertToOpaque(mToken);
+ } catch (RemoteException e) {
+ // pass
+ }
+ }
+
+ /**
* Adjust the current immersive mode setting.
*
* Note that changing this value will have no effect on the activity's
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 62ed697..780b522 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -16,11 +16,13 @@
package android.app;
+import android.R;
import android.os.BatteryStats;
import android.os.IBinder;
import com.android.internal.app.IUsageStats;
import com.android.internal.os.PkgUsageStats;
import com.android.internal.os.TransferPipe;
+import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.MemInfoReader;
import android.content.ComponentName;
@@ -376,7 +378,23 @@
String vmHeapSize = SystemProperties.get("dalvik.vm.heapsize", "16m");
return Integer.parseInt(vmHeapSize.substring(0, vmHeapSize.length()-1));
}
-
+
+ /**
+ * Returns true if this is a low-RAM device. Exactly whether a device is low-RAM
+ * is ultimately up to the device configuration, but currently it generally means
+ * something in the class of a 512MB device with about a 800x480 or less screen.
+ * This is mostly intended to be used by apps to determine whether they should turn
+ * off certain features that require more RAM.
+ */
+ public boolean isLowRamDevice() {
+ return isLowRamDeviceStatic();
+ }
+
+ /** @hide */
+ public static boolean isLowRamDeviceStatic() {
+ return Resources.getSystem().getBoolean(com.android.internal.R.bool.config_lowRamDevice);
+ }
+
/**
* Used by persistent processes to determine if they are running on a
* higher-end device so should be okay using hardware drawing acceleration
@@ -384,43 +402,8 @@
* @hide
*/
static public boolean isHighEndGfx() {
- MemInfoReader reader = new MemInfoReader();
- reader.readMemInfo();
- if (reader.getTotalSize() >= (512*1024*1024)) {
- // If the device has at least 512MB RAM available to the kernel,
- // we can afford the overhead of graphics acceleration.
- return true;
- }
-
- Display display = DisplayManagerGlobal.getInstance().getRealDisplay(
- Display.DEFAULT_DISPLAY);
- Point p = new Point();
- display.getRealSize(p);
- int pixels = p.x * p.y;
- if (pixels >= (1024*600)) {
- // If this is a sufficiently large screen, then there are enough
- // pixels on it that we'd really like to use hw drawing.
- return true;
- }
- return false;
- }
-
- /**
- * Use to decide whether the running device can be considered a "large
- * RAM" device. Exactly what memory limit large RAM is will vary, but
- * it essentially means there is plenty of RAM to have lots of background
- * processes running under decent loads.
- * @hide
- */
- static public boolean isLargeRAM() {
- MemInfoReader reader = new MemInfoReader();
- reader.readMemInfo();
- if (reader.getTotalSize() >= (640*1024*1024)) {
- // Currently 640MB RAM available to the kernel is the point at
- // which we have plenty of RAM to spare.
- return true;
- }
- return false;
+ return !isLowRamDeviceStatic() &&
+ !Resources.getSystem().getBoolean(com.android.internal.R.bool.config_avoidGfxAccel);
}
/**
@@ -2206,12 +2189,14 @@
*/
public static void dumpPackageStateStatic(FileDescriptor fd, String packageName) {
FileOutputStream fout = new FileOutputStream(fd);
- PrintWriter pw = new PrintWriter(fout);
- dumpService(pw, fd, Context.ACTIVITY_SERVICE, new String[] { "package", packageName});
+ PrintWriter pw = new FastPrintWriter(fout);
+ dumpService(pw, fd, Context.ACTIVITY_SERVICE, new String[] { "package", packageName });
pw.println();
- dumpService(pw, fd, "package", new String[] { packageName});
+ dumpService(pw, fd, "procstats", new String[] { packageName });
pw.println();
- dumpService(pw, fd, BatteryStats.SERVICE_NAME, new String[] { packageName});
+ dumpService(pw, fd, "package", new String[] { packageName });
+ pw.println();
+ dumpService(pw, fd, BatteryStats.SERVICE_NAME, new String[] { packageName });
pw.flush();
}
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 1573398..b966d6d 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1499,6 +1499,14 @@
return true;
}
+ case CONVERT_TO_OPAQUE_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ IBinder token = data.readStrongBinder();
+ convertToOpaque(token);
+ reply.writeNoException();
+ return true;
+ }
+
case SET_IMMERSIVE_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder token = data.readStrongBinder();
@@ -3823,7 +3831,19 @@
data.recycle();
reply.recycle();
}
-
+
+ public void convertToOpaque(IBinder token)
+ throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeStrongBinder(token);
+ mRemote.transact(CONVERT_TO_OPAQUE_TRANSACTION, data, reply, 0);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+
public void setImmersive(IBinder token, boolean immersive)
throws RemoteException {
Parcel data = Parcel.obtain();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 4a41896..bf89fa6 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -16,6 +16,8 @@
package android.app;
+import static android.view.DisplayAdjustments.DEVELOPMENT_RESOURCES_DEPEND_ON_ACTIVITY_TOKEN;
+
import android.app.backup.BackupAgent;
import android.content.BroadcastReceiver;
import android.content.ComponentCallbacks2;
@@ -75,7 +77,7 @@
import android.util.LogPrinter;
import android.util.PrintWriterPrinter;
import android.util.Slog;
-import android.view.CompatibilityInfoHolder;
+import android.view.DisplayAdjustments;
import android.view.Display;
import android.view.HardwareRenderer;
import android.view.View;
@@ -91,6 +93,7 @@
import com.android.internal.os.BinderInternal;
import com.android.internal.os.RuntimeInit;
import com.android.internal.os.SamplingProfilerIntegration;
+import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.Objects;
import com.android.org.conscrypt.OpenSSLSocketImpl;
@@ -209,8 +212,8 @@
= new HashMap<String, WeakReference<LoadedApk>>();
final HashMap<String, WeakReference<LoadedApk>> mResourcePackages
= new HashMap<String, WeakReference<LoadedApk>>();
- final HashMap<CompatibilityInfo, DisplayMetrics> mDefaultDisplayMetrics
- = new HashMap<CompatibilityInfo, DisplayMetrics>();
+ final HashMap<DisplayAdjustments, DisplayMetrics> mDefaultDisplayMetrics
+ = new HashMap<DisplayAdjustments, DisplayMetrics>();
final HashMap<ResourcesKey, WeakReference<Resources> > mActiveResources
= new HashMap<ResourcesKey, WeakReference<Resources> >();
final ArrayList<ActivityClientRecord> mRelaunchingActivities
@@ -897,7 +900,7 @@
public Debug.MemoryInfo dumpMemInfo(FileDescriptor fd, boolean checkin,
boolean dumpInfo, boolean dumpDalvik, String[] args) {
FileOutputStream fout = new FileOutputStream(fd);
- PrintWriter pw = new PrintWriter(fout);
+ PrintWriter pw = new FastPrintWriter(fout);
try {
return dumpMemInfo(pw, checkin, dumpInfo, dumpDalvik);
} finally {
@@ -1174,7 +1177,7 @@
@Override
public void dumpDbInfo(FileDescriptor fd, String[] args) {
- PrintWriter pw = new PrintWriter(new FileOutputStream(fd));
+ PrintWriter pw = new FastPrintWriter(new FileOutputStream(fd));
PrintWriterPrinter printer = new PrintWriterPrinter(pw);
SQLiteDebug.dump(printer, args);
pw.flush();
@@ -1554,6 +1557,7 @@
}
private class Idler implements MessageQueue.IdleHandler {
+ @Override
public final boolean queueIdle() {
ActivityClientRecord a = mNewActivities;
boolean stopProfiling = false;
@@ -1592,6 +1596,7 @@
}
final class GcIdler implements MessageQueue.IdleHandler {
+ @Override
public final boolean queueIdle() {
doGcIfNeeded();
return false;
@@ -1604,8 +1609,10 @@
final private Configuration mOverrideConfiguration;
final private float mScale;
final private int mHash;
+ final private IBinder mToken;
- ResourcesKey(String resDir, int displayId, Configuration overrideConfiguration, float scale) {
+ ResourcesKey(String resDir, int displayId, Configuration overrideConfiguration,
+ float scale, IBinder token) {
mResDir = resDir;
mDisplayId = displayId;
if (overrideConfiguration != null) {
@@ -1621,6 +1628,12 @@
hash = 31 * hash + (mOverrideConfiguration != null
? mOverrideConfiguration.hashCode() : 0);
hash = 31 * hash + Float.floatToIntBits(mScale);
+ if (DEVELOPMENT_RESOURCES_DEPEND_ON_ACTIVITY_TOKEN) {
+ mToken = token;
+ hash = 31 * hash + (mToken == null ? 0 : mToken.hashCode());
+ } else {
+ mToken = null;
+ }
mHash = hash;
}
@@ -1693,9 +1706,13 @@
mDefaultDisplayMetrics.clear();
}
- DisplayMetrics getDisplayMetricsLocked(int displayId, CompatibilityInfo ci) {
+ DisplayMetrics getDisplayMetricsLocked(int displayId) {
+ return getDisplayMetricsLocked(displayId, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
+ }
+
+ DisplayMetrics getDisplayMetricsLocked(int displayId, DisplayAdjustments daj) {
boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
- DisplayMetrics dm = isDefaultDisplay ? mDefaultDisplayMetrics.get(ci) : null;
+ DisplayMetrics dm = isDefaultDisplay ? mDefaultDisplayMetrics.get(daj) : null;
if (dm != null) {
return dm;
}
@@ -1709,12 +1726,10 @@
}
if (isDefaultDisplay) {
- mDefaultDisplayMetrics.put(ci, dm);
+ mDefaultDisplayMetrics.put(daj, dm);
}
- CompatibilityInfoHolder cih = new CompatibilityInfoHolder();
- cih.set(ci);
- Display d = displayManager.getCompatibleDisplay(displayId, cih);
+ Display d = displayManager.getCompatibleDisplay(displayId, daj);
if (d != null) {
d.getMetrics(dm);
} else {
@@ -1736,7 +1751,7 @@
if (config == null) {
return null;
}
- if (compat != null && !compat.supportsScreen()) {
+ if (!compat.supportsScreen()) {
mMainThreadConfig.setTo(config);
config = mMainThreadConfig;
compat.applyToConfiguration(displayDensity, config);
@@ -1748,21 +1763,19 @@
* Creates the top level Resources for applications with the given compatibility info.
*
* @param resDir the resource directory.
- * @param compInfo the compability info. It will use the default compatibility info when it's
- * null.
+ * @param compatInfo the compability info. Must not be null.
+ * @param token the application token for determining stack bounds.
*/
- Resources getTopLevelResources(String resDir,
- int displayId, Configuration overrideConfiguration,
- CompatibilityInfo compInfo) {
- ResourcesKey key = new ResourcesKey(resDir,
- displayId, overrideConfiguration,
- compInfo.applicationScale);
+ Resources getTopLevelResources(String resDir, int displayId,
+ Configuration overrideConfiguration, CompatibilityInfo compatInfo, IBinder token) {
+ final float scale = compatInfo.applicationScale;
+ ResourcesKey key = new ResourcesKey(resDir, displayId, overrideConfiguration, scale,
+ token);
Resources r;
synchronized (mPackages) {
// Resources is app scale dependent.
if (false) {
- Slog.w(TAG, "getTopLevelResources: " + resDir + " / "
- + compInfo.applicationScale);
+ Slog.w(TAG, "getTopLevelResources: " + resDir + " / " + scale);
}
WeakReference<Resources> wr = mActiveResources.get(key);
r = wr != null ? wr.get() : null;
@@ -1787,7 +1800,7 @@
}
//Slog.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
- DisplayMetrics dm = getDisplayMetricsLocked(displayId, null);
+ DisplayMetrics dm = getDisplayMetricsLocked(displayId);
Configuration config;
boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
if (!isDefaultDisplay || key.mOverrideConfiguration != null) {
@@ -1801,7 +1814,7 @@
} else {
config = getConfiguration();
}
- r = new Resources(assets, dm, config, compInfo);
+ r = new Resources(assets, dm, config, compatInfo, token);
if (false) {
Slog.i(TAG, "Created app resources " + resDir + " " + r + ": "
+ r.getConfiguration() + " appScale="
@@ -1831,7 +1844,7 @@
int displayId, Configuration overrideConfiguration,
LoadedApk pkgInfo) {
return getTopLevelResources(resDir, displayId, overrideConfiguration,
- pkgInfo.mCompatibilityInfo.get());
+ pkgInfo.getCompatibilityInfo(), null);
}
final Handler getHandler() {
@@ -2005,10 +2018,8 @@
LoadedApk info = new LoadedApk(this, "android", context, null,
CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO);
context.init(info, null, this);
- context.getResources().updateConfiguration(
- getConfiguration(), getDisplayMetricsLocked(
- Display.DEFAULT_DISPLAY,
- CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO));
+ context.getResources().updateConfiguration(getConfiguration(),
+ getDisplayMetricsLocked(Display.DEFAULT_DISPLAY));
mSystemContext = context;
//Slog.i(TAG, "Created system resources " + context.getResources()
// + ": " + context.getResources().getConfiguration());
@@ -2034,7 +2045,7 @@
dalvik.system.VMRuntime.getRuntime().startJitCompilation();
}
}
-
+
void scheduleGcIdler() {
if (!mGcIdlerScheduled) {
mGcIdlerScheduled = true;
@@ -2301,7 +2312,7 @@
DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
for (int displayId : dm.getDisplayIds()) {
if (displayId != Display.DEFAULT_DISPLAY) {
- Display display = dm.getRealDisplay(displayId);
+ Display display = dm.getRealDisplay(displayId, r.token);
baseContext = appContext.createDisplayContext(display);
break;
}
@@ -2720,7 +2731,8 @@
try {
Service s = mServices.get(info.token);
if (s != null) {
- PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd.getFileDescriptor()));
+ PrintWriter pw = new FastPrintWriter(new FileOutputStream(
+ info.fd.getFileDescriptor()));
s.dump(info.fd.getFileDescriptor(), pw, info.args);
pw.flush();
}
@@ -2735,7 +2747,8 @@
try {
ActivityClientRecord r = mActivities.get(info.token);
if (r != null && r.activity != null) {
- PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd.getFileDescriptor()));
+ PrintWriter pw = new FastPrintWriter(new FileOutputStream(
+ info.fd.getFileDescriptor()));
r.activity.dump(info.prefix, info.fd.getFileDescriptor(), pw, info.args);
pw.flush();
}
@@ -2750,7 +2763,8 @@
try {
ProviderClientRecord r = mLocalProviders.get(info.token);
if (r != null && r.mLocalProvider != null) {
- PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd.getFileDescriptor()));
+ PrintWriter pw = new FastPrintWriter(new FileOutputStream(
+ info.fd.getFileDescriptor()));
r.mLocalProvider.dump(info.fd.getFileDescriptor(), pw, info.args);
pw.flush();
}
@@ -3408,11 +3422,11 @@
private void handleUpdatePackageCompatibilityInfo(UpdateCompatibilityData data) {
LoadedApk apk = peekPackageInfo(data.pkg, false);
if (apk != null) {
- apk.mCompatibilityInfo.set(data.info);
+ apk.setCompatibilityInfo(data.info);
}
apk = peekPackageInfo(data.pkg, true);
if (apk != null) {
- apk.mCompatibilityInfo.set(data.info);
+ apk.setCompatibilityInfo(data.info);
}
handleConfigurationChanged(mConfiguration, data.info);
WindowManagerGlobal.getInstance().reportNewConfiguration(mConfiguration);
@@ -3844,8 +3858,9 @@
for (ActivityClientRecord ar : mActivities.values()) {
Activity a = ar.activity;
if (a != null) {
- Configuration thisConfig = applyConfigCompatMainThread(mCurDefaultDisplayDpi,
- newConfig, ar.packageInfo.mCompatibilityInfo.getIfNeeded());
+ Configuration thisConfig = applyConfigCompatMainThread(
+ mCurDefaultDisplayDpi, newConfig,
+ ar.packageInfo.getCompatibilityInfo());
if (!ar.activity.mFinished && (allActivities || !ar.paused)) {
// If the activity is currently resumed, its configuration
// needs to change right now.
@@ -3945,8 +3960,7 @@
}
int changes = mResConfiguration.updateFrom(config);
flushDisplayMetricsLocked();
- DisplayMetrics defaultDisplayMetrics = getDisplayMetricsLocked(
- Display.DEFAULT_DISPLAY, null);
+ DisplayMetrics defaultDisplayMetrics = getDisplayMetricsLocked(Display.DEFAULT_DISPLAY);
if (compat != null && (mResCompatibilityInfo == null ||
!mResCompatibilityInfo.equals(compat))) {
@@ -3986,7 +4000,7 @@
}
tmpConfig.setTo(config);
if (!isDefaultDisplay) {
- dm = getDisplayMetricsLocked(displayId, null);
+ dm = getDisplayMetricsLocked(displayId);
applyNonDefaultDisplayMetricsToConfigurationLocked(dm, tmpConfig);
}
if (overrideConfig != null) {
diff --git a/core/java/android/app/ApplicationErrorReport.java b/core/java/android/app/ApplicationErrorReport.java
index 954476d..c117486 100644
--- a/core/java/android/app/ApplicationErrorReport.java
+++ b/core/java/android/app/ApplicationErrorReport.java
@@ -28,6 +28,7 @@
import android.os.SystemProperties;
import android.provider.Settings;
import android.util.Printer;
+import com.android.internal.util.FastPrintWriter;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -327,7 +328,9 @@
*/
public CrashInfo(Throwable tr) {
StringWriter sw = new StringWriter();
- tr.printStackTrace(new PrintWriter(sw));
+ PrintWriter pw = new FastPrintWriter(sw, false, 256);
+ tr.printStackTrace(pw);
+ pw.flush();
stackTrace = sw.toString();
exceptionMessage = tr.getMessage();
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 271494f..432e9b1 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1296,6 +1296,28 @@
return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
}
+ @Override
+ public boolean setApplicationBlockedSettingAsUser(String packageName, boolean blocked,
+ UserHandle user) {
+ try {
+ return mPM.setApplicationBlockedSettingAsUser(packageName, blocked,
+ user.getIdentifier());
+ } catch (RemoteException re) {
+ // Should never happen!
+ }
+ return false;
+ }
+
+ @Override
+ public boolean getApplicationBlockedSettingAsUser(String packageName, UserHandle user) {
+ try {
+ return mPM.getApplicationBlockedSettingAsUser(packageName, user.getIdentifier());
+ } catch (RemoteException re) {
+ // Should never happen!
+ }
+ return false;
+ }
+
/**
* @hide
*/
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index 1b1d341..89ee145 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -21,6 +21,7 @@
import android.text.TextUtils;
import android.util.Log;
import android.util.LogWriter;
+import com.android.internal.util.FastPrintWriter;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -583,8 +584,9 @@
if (FragmentManagerImpl.DEBUG) {
Log.v(TAG, "Commit: " + this);
LogWriter logw = new LogWriter(Log.VERBOSE, TAG);
- PrintWriter pw = new PrintWriter(logw);
+ PrintWriter pw = new FastPrintWriter(logw, false, 1024);
dump(" ", null, pw, null);
+ pw.flush();
}
mCommitted = true;
if (mAddToBackStack) {
@@ -691,8 +693,9 @@
if (FragmentManagerImpl.DEBUG) {
Log.v(TAG, "popFromBackStack: " + this);
LogWriter logw = new LogWriter(Log.VERBOSE, TAG);
- PrintWriter pw = new PrintWriter(logw);
+ PrintWriter pw = new FastPrintWriter(logw, false, 1024);
dump(" ", null, pw, null);
+ pw.flush();
}
bumpBackStackNesting(-1);
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 992d8b7..a5106e4 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -99,7 +99,7 @@
import android.util.ArrayMap;
import android.util.Log;
import android.util.Slog;
-import android.view.CompatibilityInfoHolder;
+import android.view.DisplayAdjustments;
import android.view.ContextThemeWrapper;
import android.view.Display;
import android.view.WindowManagerImpl;
@@ -205,6 +205,8 @@
private static final String[] EMPTY_FILE_LIST = {};
+ final private DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
+
/**
* Override this class when the system service constructor needs a
* ContextImpl. Else, use StaticServiceFetcher below.
@@ -547,9 +549,9 @@
return new AppOpsManager(ctx, service);
}});
- registerService(CAMERA_SERVICE, new StaticServiceFetcher() {
- public Object createStaticService() {
- return new CameraManager();
+ registerService(CAMERA_SERVICE, new ServiceFetcher() {
+ public Object createService(ContextImpl ctx) {
+ return new CameraManager(ctx);
}
});
@@ -1830,10 +1832,8 @@
ContextImpl c = new ContextImpl();
c.init(mPackageInfo, null, mMainThread);
- c.mResources = mMainThread.getTopLevelResources(
- mPackageInfo.getResDir(),
- getDisplayId(), overrideConfiguration,
- mResources.getCompatibilityInfo());
+ c.mResources = mMainThread.getTopLevelResources(mPackageInfo.getResDir(), getDisplayId(),
+ overrideConfiguration, mResources.getCompatibilityInfo(), mActivityToken);
return c;
}
@@ -1844,17 +1844,13 @@
}
int displayId = display.getDisplayId();
- CompatibilityInfo ci = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
- CompatibilityInfoHolder cih = getCompatibilityInfo(displayId);
- if (cih != null) {
- ci = cih.get();
- }
ContextImpl context = new ContextImpl();
context.init(mPackageInfo, null, mMainThread);
context.mDisplay = display;
- context.mResources = mMainThread.getTopLevelResources(
- mPackageInfo.getResDir(), displayId, null, ci);
+ DisplayAdjustments daj = getDisplayAdjustments(displayId);
+ context.mResources = mMainThread.getTopLevelResources(mPackageInfo.getResDir(), displayId,
+ null, daj.getCompatibilityInfo(), null);
return context;
}
@@ -1868,8 +1864,8 @@
}
@Override
- public CompatibilityInfoHolder getCompatibilityInfo(int displayId) {
- return displayId == Display.DEFAULT_DISPLAY ? mPackageInfo.mCompatibilityInfo : null;
+ public DisplayAdjustments getDisplayAdjustments(int displayId) {
+ return mDisplayAdjustments;
}
private File getDataDirFile() {
@@ -1921,6 +1917,7 @@
mUser = context.mUser;
mDisplay = context.mDisplay;
mOuterContext = this;
+ mDisplayAdjustments.setCompatibilityInfo(mPackageInfo.getCompatibilityInfo());
}
final void init(LoadedApk packageInfo, IBinder activityToken, ActivityThread mainThread) {
@@ -1933,16 +1930,26 @@
mBasePackageName = basePackageName != null ? basePackageName : packageInfo.mPackageName;
mResources = mPackageInfo.getResources(mainThread);
- if (mResources != null && container != null
- && container.getCompatibilityInfo().applicationScale !=
- mResources.getCompatibilityInfo().applicationScale) {
+ CompatibilityInfo compatInfo =
+ container == null ? null : container.getCompatibilityInfo();
+ if (mResources != null &&
+ ((compatInfo != null && compatInfo.applicationScale !=
+ mResources.getCompatibilityInfo().applicationScale)
+ || activityToken != null)) {
if (DEBUG) {
Log.d(TAG, "loaded context has different scaling. Using container's" +
" compatiblity info:" + container.getDisplayMetrics());
}
- mResources = mainThread.getTopLevelResources(
- mPackageInfo.getResDir(), Display.DEFAULT_DISPLAY,
- null, container.getCompatibilityInfo());
+ if (compatInfo == null) {
+ compatInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
+ }
+ mDisplayAdjustments.setCompatibilityInfo(compatInfo);
+ mDisplayAdjustments.setActivityToken(activityToken);
+ mResources = mainThread.getTopLevelResources(mPackageInfo.getResDir(),
+ Display.DEFAULT_DISPLAY, null, compatInfo, activityToken);
+ } else {
+ mDisplayAdjustments.setCompatibilityInfo(packageInfo.getCompatibilityInfo());
+ mDisplayAdjustments.setActivityToken(activityToken);
}
mMainThread = mainThread;
mActivityToken = activityToken;
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 72c9156..7358f73 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -36,6 +36,7 @@
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
+import com.android.internal.util.FastPrintWriter;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -445,12 +446,13 @@
private void throwException(RuntimeException ex) {
Log.e(TAG, ex.getMessage());
LogWriter logw = new LogWriter(Log.ERROR, TAG);
- PrintWriter pw = new PrintWriter(logw);
+ PrintWriter pw = new FastPrintWriter(logw, false, 1024);
if (mActivity != null) {
Log.e(TAG, "Activity state:");
try {
mActivity.dump(" ", null, pw, new String[] { });
} catch (Exception e) {
+ pw.flush();
Log.e(TAG, "Failed dumping state", e);
}
} else {
@@ -458,9 +460,11 @@
try {
dump(" ", null, pw, new String[] { });
} catch (Exception e) {
+ pw.flush();
Log.e(TAG, "Failed dumping state", e);
}
}
+ pw.flush();
throw ex;
}
@@ -1806,8 +1810,9 @@
Log.v(TAG, "restoreAllState: back stack #" + i
+ " (index " + bse.mIndex + "): " + bse);
LogWriter logw = new LogWriter(Log.VERBOSE, TAG);
- PrintWriter pw = new PrintWriter(logw);
+ PrintWriter pw = new FastPrintWriter(logw, false, 1024);
bse.dump(" ", pw, false);
+ pw.flush();
}
mBackStack.add(bse);
if (bse.mIndex >= 0) {
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index c8791a4..39f4cfa 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -301,6 +301,8 @@
public void finishHeavyWeightApp() throws RemoteException;
+ public void convertToOpaque(IBinder token) throws RemoteException;
+
public void setImmersive(IBinder token, boolean immersive) throws RemoteException;
public boolean isImmersive(IBinder token) throws RemoteException;
public boolean isTopActivityImmersive() throws RemoteException;
@@ -666,4 +668,5 @@
int GET_STACK_BOXES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+170;
int SET_FOCUSED_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+171;
int GET_STACK_BOX_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+172;
+ int CONVERT_TO_OPAQUE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+173;
}
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 2224490..573a6aa 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -40,7 +40,7 @@
import android.os.UserHandle;
import android.util.AndroidRuntimeException;
import android.util.Slog;
-import android.view.CompatibilityInfoHolder;
+import android.view.DisplayAdjustments;
import android.view.Display;
import java.io.File;
@@ -84,7 +84,7 @@
private final ClassLoader mBaseClassLoader;
private final boolean mSecurityViolation;
private final boolean mIncludeCode;
- public final CompatibilityInfoHolder mCompatibilityInfo = new CompatibilityInfoHolder();
+ private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
Resources mResources;
private ClassLoader mClassLoader;
private Application mApplication;
@@ -132,7 +132,7 @@
mBaseClassLoader = baseLoader;
mSecurityViolation = securityViolation;
mIncludeCode = includeCode;
- mCompatibilityInfo.set(compatInfo);
+ mDisplayAdjustments.setCompatibilityInfo(compatInfo);
if (mAppDir == null) {
if (ActivityThread.mSystemContext == null) {
@@ -141,7 +141,7 @@
ActivityThread.mSystemContext.getResources().updateConfiguration(
mainThread.getConfiguration(),
mainThread.getDisplayMetricsLocked(
- Display.DEFAULT_DISPLAY, compatInfo),
+ Display.DEFAULT_DISPLAY, mDisplayAdjustments),
compatInfo);
//Slog.i(TAG, "Created system resources "
// + mSystemContext.getResources() + ": "
@@ -169,7 +169,7 @@
mIncludeCode = true;
mClassLoader = systemContext.getClassLoader();
mResources = systemContext.getResources();
- mCompatibilityInfo.set(compatInfo);
+ mDisplayAdjustments.setCompatibilityInfo(compatInfo);
}
public String getPackageName() {
@@ -184,6 +184,14 @@
return mSecurityViolation;
}
+ public CompatibilityInfo getCompatibilityInfo() {
+ return mDisplayAdjustments.getCompatibilityInfo();
+ }
+
+ public void setCompatibilityInfo(CompatibilityInfo compatInfo) {
+ mDisplayAdjustments.setCompatibilityInfo(compatInfo);
+ }
+
/**
* Gets the array of shared libraries that are listed as
* used by the given package.
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 7c9117c..d8bf6ba 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -35,7 +35,7 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.util.AttributeSet;
-import android.view.CompatibilityInfoHolder;
+import android.view.DisplayAdjustments;
import android.view.Display;
import android.view.WindowManager;
@@ -2760,15 +2760,15 @@
public abstract Context createDisplayContext(Display display);
/**
- * Gets the compatibility info holder for this context. This information
- * is provided on a per-application basis and is used to simulate lower density
- * display metrics for legacy applications.
+ * Gets the display adjustments holder for this context. This information
+ * is provided on a per-application or activity basis and is used to simulate lower density
+ * display metrics for legacy applications and restricted screen sizes.
*
* @param displayId The display id for which to get compatibility info.
* @return The compatibility info holder, or null if not required by the application.
* @hide
*/
- public abstract CompatibilityInfoHolder getCompatibilityInfo(int displayId);
+ public abstract DisplayAdjustments getDisplayAdjustments(int displayId);
/**
* Indicates whether this Context is restricted.
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 2f1bf8c..606a1f4 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -35,7 +35,7 @@
import android.os.Looper;
import android.os.RemoteException;
import android.os.UserHandle;
-import android.view.CompatibilityInfoHolder;
+import android.view.DisplayAdjustments;
import android.view.Display;
import java.io.File;
@@ -646,7 +646,7 @@
/** @hide */
@Override
- public CompatibilityInfoHolder getCompatibilityInfo(int displayId) {
- return mBase.getCompatibilityInfo(displayId);
+ public DisplayAdjustments getDisplayAdjustments(int displayId) {
+ return mBase.getDisplayAdjustments(displayId);
}
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 897e6fe..bda7112 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2440,6 +2440,18 @@
"android.intent.action.GET_RESTRICTION_ENTRIES";
/**
+ * Activity to challenge the user for a PIN that was configured when setting up
+ * restrictions. Launch the activity using
+ * {@link android.app.Activity#startActivityForResult(Intent, int)} and check if the
+ * result is {@link android.app.Activity#RESULT_OK} for a successful response to the
+ * challenge.<p/>
+ * Before launching this activity, make sure that there is a PIN in effect, by calling
+ * {@link android.os.UserManager#hasRestrictionsPin()}.
+ */
+ public static final String ACTION_RESTRICTIONS_PIN_CHALLENGE =
+ "android.intent.action.RESTRICTIONS_PIN_CHALLENGE";
+
+ /**
* Sent the first time a user is starting, to allow system apps to
* perform one time initialization. (This will not be seen by third
* party applications because a newly initialized user does not have any
diff --git a/core/java/android/content/SyncStatusInfo.java b/core/java/android/content/SyncStatusInfo.java
index ff628d9..bb24ccd 100644
--- a/core/java/android/content/SyncStatusInfo.java
+++ b/core/java/android/content/SyncStatusInfo.java
@@ -42,7 +42,10 @@
public long initialFailureTime;
public boolean pending;
public boolean initialize;
- public ArrayList<Long> periodicSyncTimes;
+
+ // Warning: It is up to the external caller to ensure there are
+ // no race conditions when accessing this list
+ private ArrayList<Long> periodicSyncTimes;
private static final String TAG = "Sync";
@@ -126,11 +129,59 @@
}
}
+ public SyncStatusInfo(SyncStatusInfo other) {
+ authorityId = other.authorityId;
+ totalElapsedTime = other.totalElapsedTime;
+ numSyncs = other.numSyncs;
+ numSourcePoll = other.numSourcePoll;
+ numSourceServer = other.numSourceServer;
+ numSourceLocal = other.numSourceLocal;
+ numSourceUser = other.numSourceUser;
+ numSourcePeriodic = other.numSourcePeriodic;
+ lastSuccessTime = other.lastSuccessTime;
+ lastSuccessSource = other.lastSuccessSource;
+ lastFailureTime = other.lastFailureTime;
+ lastFailureSource = other.lastFailureSource;
+ lastFailureMesg = other.lastFailureMesg;
+ initialFailureTime = other.initialFailureTime;
+ pending = other.pending;
+ initialize = other.initialize;
+ if (other.periodicSyncTimes != null) {
+ periodicSyncTimes = new ArrayList<Long>(other.periodicSyncTimes);
+ }
+ }
+
public void setPeriodicSyncTime(int index, long when) {
+ // The list is initialized lazily when scheduling occurs so we need to make sure
+ // we initialize elements < index to zero (zero is ignore for scheduling purposes)
ensurePeriodicSyncTimeSize(index);
periodicSyncTimes.set(index, when);
}
+ public long getPeriodicSyncTime(int index) {
+ if (periodicSyncTimes != null && index < periodicSyncTimes.size()) {
+ return periodicSyncTimes.get(index);
+ } else {
+ return 0;
+ }
+ }
+
+ public void removePeriodicSyncTime(int index) {
+ if (periodicSyncTimes != null && index < periodicSyncTimes.size()) {
+ periodicSyncTimes.remove(index);
+ }
+ }
+
+ public static final Creator<SyncStatusInfo> CREATOR = new Creator<SyncStatusInfo>() {
+ public SyncStatusInfo createFromParcel(Parcel in) {
+ return new SyncStatusInfo(in);
+ }
+
+ public SyncStatusInfo[] newArray(int size) {
+ return new SyncStatusInfo[size];
+ }
+ };
+
private void ensurePeriodicSyncTimeSize(int index) {
if (periodicSyncTimes == null) {
periodicSyncTimes = new ArrayList<Long>(0);
@@ -143,26 +194,4 @@
}
}
}
-
- public long getPeriodicSyncTime(int index) {
- if (periodicSyncTimes == null || periodicSyncTimes.size() < (index + 1)) {
- return 0;
- }
- return periodicSyncTimes.get(index);
- }
-
- public void removePeriodicSyncTime(int index) {
- ensurePeriodicSyncTimeSize(index);
- periodicSyncTimes.remove(index);
- }
-
- public static final Creator<SyncStatusInfo> CREATOR = new Creator<SyncStatusInfo>() {
- public SyncStatusInfo createFromParcel(Parcel in) {
- return new SyncStatusInfo(in);
- }
-
- public SyncStatusInfo[] newArray(int size) {
- return new SyncStatusInfo[size];
- }
- };
}
\ No newline at end of file
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 2250331..9c46d96 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -315,6 +315,14 @@
public static final int FLAG_IS_DATA_ONLY = 1<<24;
/**
+ * Value for {@link #flags}: set to {@code true} if the application
+ * is permitted to hold privileged permissions.
+ *
+ * {@hide}
+ */
+ public static final int FLAG_PRIVILEGED = 1<<30;
+
+ /**
* Value for {@link #flags}: Set to true if the application has been
* installed using the forward lock option.
*
@@ -338,12 +346,11 @@
public static final int FLAG_CANT_SAVE_STATE = 1<<28;
/**
- * Value for {@link #flags}: set to {@code true} if the application
- * is permitted to hold privileged permissions.
- *
+ * Value for {@link #flags}: true if the application is blocked via restrictions and for
+ * most purposes is considered as not installed.
* {@hide}
*/
- public static final int FLAG_PRIVILEGED = 1<<29;
+ public static final int FLAG_BLOCKED = 1<<27;
/**
* Flags associated with the application. Any combination of
@@ -359,7 +366,7 @@
* {@link #FLAG_INSTALLED}.
*/
public int flags = 0;
-
+
/**
* The required smallest screen width the application can run on. If 0,
* nothing has been specified. Comes from
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index a0e1555..eaff7b2 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -399,4 +399,7 @@
/** Reflects current DeviceStorageMonitorService state */
boolean isStorageLow();
+
+ boolean setApplicationBlockedSettingAsUser(String packageName, boolean blocked, int userId);
+ boolean getApplicationBlockedSettingAsUser(String packageName, int userId);
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 4266d85..8a8751e 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3083,6 +3083,23 @@
public abstract int getApplicationEnabledSetting(String packageName);
/**
+ * Puts the package in a blocked state, which is almost like an uninstalled state,
+ * making the package unavailable, but it doesn't remove the data or the actual
+ * package file.
+ * @hide
+ */
+ public abstract boolean setApplicationBlockedSettingAsUser(String packageName, boolean blocked,
+ UserHandle userHandle);
+
+ /**
+ * Returns the blocked state of a package.
+ * @see #setApplicationBlockedSettingAsUser(String, boolean, UserHandle)
+ * @hide
+ */
+ public abstract boolean getApplicationBlockedSettingAsUser(String packageName,
+ UserHandle userHandle);
+
+ /**
* Return whether the device has been booted into safe mode.
*/
public abstract boolean isSafeMode();
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 883516e..8f0c62d 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -159,7 +159,8 @@
private static WeakReference<byte[]> mReadBuffer;
private static boolean sCompatibilityModeEnabled = true;
- private static final int PARSE_DEFAULT_INSTALL_LOCATION = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
+ private static final int PARSE_DEFAULT_INSTALL_LOCATION =
+ PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
static class ParsePackageItemArgs {
final Package owner;
@@ -274,15 +275,20 @@
grantedPermissions, state, UserHandle.getCallingUserId());
}
- private static boolean checkUseInstalled(int flags, PackageUserState state) {
- return state.installed || ((flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0);
+ /**
+ * Returns true if the package is installed and not blocked, or if the caller
+ * explicitly wanted all uninstalled and blocked packages as well.
+ */
+ private static boolean checkUseInstalledOrBlocked(int flags, PackageUserState state) {
+ return (state.installed && !state.blocked)
+ || (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0;
}
public static PackageInfo generatePackageInfo(PackageParser.Package p,
int gids[], int flags, long firstInstallTime, long lastUpdateTime,
HashSet<String> grantedPermissions, PackageUserState state, int userId) {
- if (!checkUseInstalled(flags, state)) {
+ if (!checkUseInstalledOrBlocked(flags, state)) {
return null;
}
PackageInfo pi = new PackageInfo();
@@ -3724,7 +3730,7 @@
return true;
}
}
- if (!state.installed) {
+ if (!state.installed || state.blocked) {
return true;
}
if (state.stopped) {
@@ -3757,6 +3763,11 @@
} else {
ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
}
+ if (state.blocked) {
+ ai.flags |= ApplicationInfo.FLAG_BLOCKED;
+ } else {
+ ai.flags &= ~ApplicationInfo.FLAG_BLOCKED;
+ }
if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
ai.enabled = true;
} else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
@@ -3771,7 +3782,7 @@
public static ApplicationInfo generateApplicationInfo(Package p, int flags,
PackageUserState state, int userId) {
if (p == null) return null;
- if (!checkUseInstalled(flags, state)) {
+ if (!checkUseInstalledOrBlocked(flags, state)) {
return null;
}
if (!copyNeeded(flags, p, state, null, userId)
@@ -3855,7 +3866,7 @@
public static final ActivityInfo generateActivityInfo(Activity a, int flags,
PackageUserState state, int userId) {
if (a == null) return null;
- if (!checkUseInstalled(flags, state)) {
+ if (!checkUseInstalledOrBlocked(flags, state)) {
return null;
}
if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
@@ -3892,7 +3903,7 @@
public static final ServiceInfo generateServiceInfo(Service s, int flags,
PackageUserState state, int userId) {
if (s == null) return null;
- if (!checkUseInstalled(flags, state)) {
+ if (!checkUseInstalledOrBlocked(flags, state)) {
return null;
}
if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) {
@@ -3937,7 +3948,7 @@
public static final ProviderInfo generateProviderInfo(Provider p, int flags,
PackageUserState state, int userId) {
if (p == null) return null;
- if (!checkUseInstalled(flags, state)) {
+ if (!checkUseInstalledOrBlocked(flags, state)) {
return null;
}
if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index dcd54fc..94e3f79 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -28,6 +28,7 @@
public boolean stopped;
public boolean notLaunched;
public boolean installed;
+ public boolean blocked; // Is the app restricted by owner / admin
public int enabled;
public String lastDisableAppCaller;
@@ -37,6 +38,7 @@
public PackageUserState() {
installed = true;
+ blocked = false;
enabled = COMPONENT_ENABLED_STATE_DEFAULT;
}
@@ -45,6 +47,7 @@
stopped = o.stopped;
notLaunched = o.notLaunched;
enabled = o.enabled;
+ blocked = o.blocked;
lastDisableAppCaller = o.lastDisableAppCaller;
disabledComponents = o.disabledComponents != null
? new HashSet<String>(o.disabledComponents) : null;
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index 28c751c..da35ee9 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -471,8 +471,7 @@
* Compute the frame Rect for applications runs under compatibility mode.
*
* @param dm the display metrics used to compute the frame size.
- * @param orientation the orientation of the screen.
- * @param outRect the output parameter which will contain the result.
+ * @param outDm If non-null the width and height will be set to their scaled values.
* @return Returns the scaling factor for the window.
*/
public static float computeCompatibleScaling(DisplayMetrics dm, DisplayMetrics outDm) {
@@ -518,6 +517,9 @@
@Override
public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
try {
CompatibilityInfo oc = (CompatibilityInfo)o;
if (mCompatibilityFlags != oc.mCompatibilityFlags) return false;
@@ -579,10 +581,12 @@
public static final Parcelable.Creator<CompatibilityInfo> CREATOR
= new Parcelable.Creator<CompatibilityInfo>() {
+ @Override
public CompatibilityInfo createFromParcel(Parcel source) {
return new CompatibilityInfo(source);
}
+ @Override
public CompatibilityInfo[] newArray(int size) {
return new CompatibilityInfo[size];
}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index cff974d..c24e0ee 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -28,6 +28,7 @@
import android.graphics.drawable.Drawable.ConstantState;
import android.os.Build;
import android.os.Bundle;
+import android.os.IBinder;
import android.os.Trace;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
@@ -35,6 +36,7 @@
import android.util.Slog;
import android.util.TypedValue;
import android.util.LongSparseArray;
+import android.view.DisplayAdjustments;
import java.io.IOException;
import java.io.InputStream;
@@ -117,8 +119,9 @@
private final Configuration mConfiguration = new Configuration();
/*package*/ final DisplayMetrics mMetrics = new DisplayMetrics();
private NativePluralRules mPluralRule;
-
- private CompatibilityInfo mCompatibilityInfo;
+
+ private CompatibilityInfo mCompatibilityInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
+ private WeakReference<IBinder> mToken;
static {
sPreloadedDrawables = new LongSparseArray[2];
@@ -173,7 +176,7 @@
* selecting/computing resource values (optional).
*/
public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config) {
- this(assets, metrics, config, null);
+ this(assets, metrics, config, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
}
/**
@@ -184,15 +187,16 @@
* selecting/computing resource values.
* @param config Desired device configuration to consider when
* selecting/computing resource values (optional).
- * @param compInfo this resource's compatibility info. It will use the default compatibility
- * info when it's null.
+ * @param compatInfo this resource's compatibility info. Must not be null.
+ * @param token The Activity token for determining stack affiliation. Usually null.
* @hide
*/
- public Resources(AssetManager assets, DisplayMetrics metrics,
- Configuration config, CompatibilityInfo compInfo) {
+ public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config,
+ CompatibilityInfo compatInfo, IBinder token) {
mAssets = assets;
mMetrics.setToDefaults();
- mCompatibilityInfo = compInfo;
+ mCompatibilityInfo = compatInfo;
+ mToken = new WeakReference<IBinder>(token);
updateConfiguration(config, metrics);
assets.ensureStringBlocks();
}
diff --git a/core/java/android/hardware/ICameraService.aidl b/core/java/android/hardware/ICameraService.aidl
index b8fbfdb..2d0c099 100644
--- a/core/java/android/hardware/ICameraService.aidl
+++ b/core/java/android/hardware/ICameraService.aidl
@@ -20,6 +20,8 @@
import android.hardware.ICameraClient;
import android.hardware.IProCameraUser;
import android.hardware.IProCameraCallbacks;
+import android.hardware.photography.ICameraDeviceUser;
+import android.hardware.photography.ICameraDeviceCallbacks;
import android.hardware.ICameraServiceListener;
import android.hardware.CameraInfo;
@@ -43,6 +45,10 @@
String clientPackageName,
int clientUid);
+ ICameraDeviceUser connectDevice(ICameraDeviceCallbacks callbacks, int cameraId,
+ String clientPackageName,
+ int clientUid);
+
int addListener(ICameraServiceListener listener);
int removeListener(ICameraServiceListener listener);
}
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index dcf50cd..9e2e4ba 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -159,7 +159,7 @@
Display display = mDisplays.get(displayId);
if (display == null) {
display = mGlobal.getCompatibleDisplay(displayId,
- mContext.getCompatibilityInfo(displayId));
+ mContext.getDisplayAdjustments(displayId));
if (display != null) {
mDisplays.put(displayId, display);
}
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index 3ab882d..320185d 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -28,7 +28,7 @@
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
-import android.view.CompatibilityInfoHolder;
+import android.view.DisplayAdjustments;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.Surface;
@@ -164,18 +164,18 @@
* Gets information about a logical display.
*
* The display metrics may be adjusted to provide compatibility
- * for legacy applications.
+ * for legacy applications or limited screen areas.
*
* @param displayId The logical display id.
- * @param cih The compatibility info, or null if none is required.
+ * @param daj The compatibility info and activityToken.
* @return The display object, or null if there is no display with the given id.
*/
- public Display getCompatibleDisplay(int displayId, CompatibilityInfoHolder cih) {
+ public Display getCompatibleDisplay(int displayId, DisplayAdjustments daj) {
DisplayInfo displayInfo = getDisplayInfo(displayId);
if (displayInfo == null) {
return null;
}
- return new Display(this, displayId, displayInfo, cih);
+ return new Display(this, displayId, displayInfo, daj);
}
/**
@@ -185,7 +185,18 @@
* @return The display object, or null if there is no display with the given id.
*/
public Display getRealDisplay(int displayId) {
- return getCompatibleDisplay(displayId, null);
+ return getCompatibleDisplay(displayId, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
+ }
+
+ /**
+ * Gets information about a logical display without applying any compatibility metrics.
+ *
+ * @param displayId The logical display id.
+ * @param IBinder the activity token for this display.
+ * @return The display object, or null if there is no display with the given id.
+ */
+ public Display getRealDisplay(int displayId, IBinder token) {
+ return getCompatibleDisplay(displayId, new DisplayAdjustments(token));
}
public void registerDisplayListener(DisplayListener listener, Handler handler) {
diff --git a/core/java/android/hardware/photography/CameraAccessException.java b/core/java/android/hardware/photography/CameraAccessException.java
index 01114df..fac5086 100644
--- a/core/java/android/hardware/photography/CameraAccessException.java
+++ b/core/java/android/hardware/photography/CameraAccessException.java
@@ -16,6 +16,8 @@
package android.hardware.photography;
+import android.util.AndroidException;
+
/**
* <p><code>CameraAccessException</code> is thrown if a camera device could not
* be queried or opened by the {@link CameraManager}, or if the connection to an
@@ -24,7 +26,7 @@
* @see CameraManager
* @see CameraDevice
*/
-public class CameraAccessException extends Exception {
+public class CameraAccessException extends AndroidException {
/**
* The camera device is in use already
*/
@@ -51,7 +53,10 @@
*/
public static final int CAMERA_DISCONNECTED = 4;
- private int mReason;
+ // Make the eclipse warning about serializable exceptions go away
+ private static final long serialVersionUID = 5630338637471475675L; // randomly generated
+
+ private final int mReason;
/**
* The reason for the failure to access the camera.
@@ -66,6 +71,7 @@
}
public CameraAccessException(int problem) {
+ super(getDefaultMessage(problem));
mReason = problem;
}
@@ -80,7 +86,25 @@
}
public CameraAccessException(int problem, Throwable cause) {
- super(cause);
+ super(getDefaultMessage(problem), cause);
mReason = problem;
}
+
+ private static String getDefaultMessage(int problem) {
+ switch (problem) {
+ case CAMERA_IN_USE:
+ return "The camera device is in use already";
+ case MAX_CAMERAS_IN_USE:
+ return "The system-wide limit for number of open cameras has been reached, " +
+ "and more camera devices cannot be opened until previous instances " +
+ "are closed.";
+ case CAMERA_DISABLED:
+ return "The camera is disabled due to a device policy, and cannot be opened.";
+ case CAMERA_DISCONNECTED:
+ return "The camera device is removable and has been disconnected from the Android" +
+ " device, or the camera service has shut down the connection due to a " +
+ "higher-priority access request for the camera device.";
+ }
+ return null;
+ }
}
diff --git a/core/java/android/hardware/photography/CameraDevice.java b/core/java/android/hardware/photography/CameraDevice.java
index 2062db2..5fb14dc 100644
--- a/core/java/android/hardware/photography/CameraDevice.java
+++ b/core/java/android/hardware/photography/CameraDevice.java
@@ -16,9 +16,6 @@
package android.hardware.photography;
-import android.graphics.ImageFormat;
-import android.renderscript.Allocation;
-import android.renderscript.RenderScript;
import android.view.Surface;
import java.lang.AutoCloseable;
@@ -47,7 +44,7 @@
* @see CameraManager#openCamera
* @see android.Manifest.permission#CAMERA
*/
-public final class CameraDevice implements AutoCloseable {
+public interface CameraDevice extends AutoCloseable {
/**
* Create a request suitable for a camera preview window. Specifically, this
@@ -111,10 +108,7 @@
*
* @see CameraManager#getCameraProperties
*/
- public CameraProperties getProperties() throws CameraAccessException {
- return null;
- }
-
+ public CameraProperties getProperties() throws CameraAccessException;
/**
* <p>Set up a new output set of Surfaces for the camera device.</p>
*
@@ -196,8 +190,7 @@
* @throws IllegalStateException if the camera device is not idle, or has
* encountered a fatal error
*/
- public void configureOutputs(List<Surface> outputs) {
- }
+ public void configureOutputs(List<Surface> outputs) throws CameraAccessException;
/**
* <p>Create a {@link CaptureRequest} initialized with template for a target
@@ -223,9 +216,7 @@
* @see #TEMPLATE_MANUAL
*/
public CaptureRequest createCaptureRequest(int templateType)
- throws CameraAccessException {
- return null;
- }
+ throws CameraAccessException;
/**
* <p>Submit a request for an image to be captured by this CameraDevice.</p>
@@ -257,8 +248,7 @@
* @see #setRepeatingBurst
*/
public void capture(CaptureRequest request, CaptureListener listener)
- throws CameraAccessException {
- }
+ throws CameraAccessException;
/**
* <p>Submit a list of requests to be captured in sequence as a burst. The
@@ -289,8 +279,7 @@
* @see #setRepeatingBurst
*/
public void captureBurst(List<CaptureRequest> requests,
- CaptureListener listener) throws CameraAccessException {
- }
+ CaptureListener listener) throws CameraAccessException;
/**
* <p>Request endlessly repeating capture of images by this
@@ -332,8 +321,7 @@
* @see #setRepeatingBurst
*/
public void setRepeatingRequest(CaptureRequest request, CaptureListener listener)
- throws CameraAccessException {
- }
+ throws CameraAccessException;
/**
* <p>Request endlessly repeating capture of a sequence of images by this
@@ -377,8 +365,7 @@
* @see #setRepeatingRequest
*/
public void setRepeatingBurst(List<CaptureRequest> requests, CaptureListener listener)
- throws CameraAccessException {
- }
+ throws CameraAccessException;
/**
* <p>Cancel any ongoing repeating capture set by either
@@ -404,8 +391,7 @@
* device has encountered a fatal error, or if there is an active repeating
* request or burst.
*/
- public void stopRepeating() throws CameraAccessException {
- }
+ public void stopRepeating() throws CameraAccessException;
/**
* <p>Wait until all the submitted requests have finished processing</p>
@@ -430,8 +416,7 @@
* device has encountered a fatal error, or if there is an active repeating
* request or burst.
*/
- public void waitUntilIdle() throws CameraAccessException {
- }
+ public void waitUntilIdle() throws CameraAccessException;
/**
* Set the error listener object to call when an asynchronous error
@@ -443,16 +428,17 @@
* notifications to. Setting this to null will stop notifications about
* asynchronous errors.
*/
- public void setErrorListener(ErrorListener listener) {
- }
+ public void setErrorListener(ErrorListener listener);
/**
* Close the connection to this camera device. After this call, all calls to
* the camera device interface will throw a {@link IllegalStateException},
* except for calls to close().
+ * @throws Exception
*/
- public void close() {
- }
+ @Override
+ public void close() throws Exception;
+ // TODO: We should decide on the behavior of in-flight requests should be on close.
/**
* A listener for receiving metadata about completed image captures. The
@@ -551,5 +537,4 @@
*/
public void onCameraDeviceError(CameraDevice camera, int error);
}
-
}
diff --git a/core/java/android/hardware/photography/CameraManager.java b/core/java/android/hardware/photography/CameraManager.java
index 328ba4b..c1c9435 100644
--- a/core/java/android/hardware/photography/CameraManager.java
+++ b/core/java/android/hardware/photography/CameraManager.java
@@ -16,6 +16,22 @@
package android.hardware.photography;
+import android.content.Context;
+import android.hardware.ICameraService;
+import android.hardware.ICameraServiceListener;
+import android.hardware.IProCameraUser;
+import android.hardware.photography.utils.CameraBinderDecorator;
+import android.hardware.photography.utils.CameraRuntimeException;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+
/**
* <p>An interface for iterating, listing, and connecting to
* {@link CameraDevice CameraDevices}.</p>
@@ -32,9 +48,40 @@
public final class CameraManager {
/**
+ * This should match the ICameraService definition
+ */
+ private static final String CAMERA_SERVICE_BINDER_NAME = "media.camera";
+ private static final int USE_CALLING_UID = -1;
+
+ private final ICameraService mCameraService;
+ private ArrayList<String> mDeviceIdList;
+ private HashSet<CameraListener> mListenerSet;
+ private final Context mContext;
+ private final Object mLock = new Object();
+
+ /**
* @hide
*/
- public CameraManager() {
+ public CameraManager(Context context) {
+ mContext = context;
+
+ IBinder cameraServiceBinder = ServiceManager.getService(CAMERA_SERVICE_BINDER_NAME);
+ ICameraService cameraServiceRaw = ICameraService.Stub.asInterface(cameraServiceBinder);
+
+ /**
+ * Wrap the camera service in a decorator which automatically translates return codes
+ * into exceptions, and RemoteExceptions into other exceptions.
+ */
+ mCameraService = CameraBinderDecorator.newInstance(cameraServiceRaw);
+
+ try {
+ mCameraService.addListener(new CameraServiceListener());
+ } catch(CameraRuntimeException e) {
+ throw new IllegalStateException("Failed to register a camera service listener",
+ e.asChecked());
+ } catch (RemoteException e) {
+ // impossible
+ }
}
/**
@@ -45,25 +92,43 @@
*
* @return The list of currently connected camera devices.
*/
- public String[] getDeviceIdList() {
- return null;
+ public String[] getDeviceIdList() throws CameraAccessException {
+ synchronized (mLock) {
+ try {
+ return getOrCreateDeviceIdListLocked().toArray(new String[0]);
+ } catch(CameraAccessException e) {
+ // this should almost never happen, except if mediaserver crashes
+ throw new IllegalStateException(
+ "Failed to query camera service for device ID list", e);
+ }
+ }
}
/**
* Register a listener to be notified about camera device availability.
*
- * @param listener the new listener to send camera availablity notices to.
+ * Registering a listener more than once has no effect.
+ *
+ * @param listener the new listener to send camera availability notices to.
*/
public void registerCameraListener(CameraListener listener) {
+ synchronized (mLock) {
+ mListenerSet.add(listener);
+ }
}
/**
* Remove a previously-added listener; the listener will no longer receive
* connection and disconnection callbacks.
*
+ * Removing a listener that isn't registered has no effect.
+ *
* @param listener the listener to remove from the notification list
*/
public void unregisterCameraListener(CameraListener listener) {
+ synchronized (mLock) {
+ mListenerSet.remove(listener);
+ }
}
/**
@@ -84,7 +149,18 @@
*/
public CameraProperties getCameraProperties(String cameraId)
throws CameraAccessException {
- throw new IllegalArgumentException();
+
+ synchronized (mLock) {
+ if (!getOrCreateDeviceIdListLocked().contains(cameraId)) {
+ throw new IllegalArgumentException(String.format("Camera id %s does not match any" +
+ " currently connected camera device", cameraId));
+ }
+ }
+
+ // TODO: implement and call a service function to get the capabilities on C++ side
+
+ // TODO: get properties from service
+ return new CameraProperties();
}
/**
@@ -107,7 +183,48 @@
* @see android.app.admin.DevicePolicyManager#setCameraDisabled
*/
public CameraDevice openCamera(String cameraId) throws CameraAccessException {
- throw new IllegalArgumentException();
+
+ try {
+
+ synchronized (mLock) {
+
+ ICameraDeviceUser cameraUser;
+
+ android.hardware.photography.impl.CameraDevice device =
+ new android.hardware.photography.impl.CameraDevice(cameraId);
+
+ cameraUser = mCameraService.connectDevice(device.getCallbacks(),
+ Integer.parseInt(cameraId),
+ mContext.getPackageName(), USE_CALLING_UID);
+
+ // TODO: change ICameraService#connectDevice to return status_t
+ if (cameraUser == null) {
+ // TEMPORARY CODE.
+ // catch-all exception since we aren't yet getting the actual error code
+ throw new IllegalStateException("Failed to open camera device");
+ }
+
+ // TODO: factor out listener to be non-nested, then move setter to constructor
+ device.setRemoteDevice(cameraUser);
+
+ return device;
+
+ }
+
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("Expected cameraId to be numeric, but it was: "
+ + cameraId);
+ } catch (CameraRuntimeException e) {
+ if (e.getReason() == CameraAccessException.CAMERA_DISCONNECTED) {
+ throw new IllegalArgumentException("Invalid camera ID specified -- " +
+ "perhaps the camera was physically disconnected", e);
+ } else {
+ throw e.asChecked();
+ }
+ } catch (RemoteException e) {
+ // impossible
+ return null;
+ }
}
/**
@@ -135,4 +252,135 @@
*/
public void onCameraUnavailable(String cameraId);
}
-}
+
+ private ArrayList<String> getOrCreateDeviceIdListLocked() throws CameraAccessException {
+ if (mDeviceIdList == null) {
+ int numCameras = 0;
+
+ try {
+ numCameras = mCameraService.getNumberOfCameras();
+ } catch(CameraRuntimeException e) {
+ throw e.asChecked();
+ } catch (RemoteException e) {
+ // impossible
+ return null;
+ }
+
+ mDeviceIdList = new ArrayList<String>();
+ for (int i = 0; i < numCameras; ++i) {
+ // Non-removable cameras use integers starting at 0 for their
+ // identifiers
+ mDeviceIdList.add(String.valueOf(i));
+ }
+
+ }
+ return mDeviceIdList;
+ }
+
+ // TODO: this class needs unit tests
+ // TODO: extract class into top level
+ private class CameraServiceListener extends Binder implements ICameraServiceListener {
+
+ // Keep up-to-date with ICameraServiceListener.h
+
+ // Device physically unplugged
+ public static final int STATUS_NOT_PRESENT = 0;
+ // Device physically has been plugged in
+ // and the camera can be used exclusively
+ public static final int STATUS_PRESENT = 1;
+ // Device physically has been plugged in
+ // but it will not be connect-able until enumeration is complete
+ public static final int STATUS_ENUMERATING = 2;
+ // Camera is in use by another app and cannot be used exclusively
+ public static final int STATUS_NOT_AVAILABLE = 0x80000000;
+
+ // Camera ID -> Status map
+ private final HashMap<String, Integer> mDeviceStatus = new HashMap<String, Integer>();
+
+ private static final String TAG = "CameraServiceListener";
+
+ @Override
+ public IBinder asBinder() {
+ return this;
+ }
+
+ private boolean isAvailable(int status) {
+ switch (status) {
+ case STATUS_PRESENT:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ private boolean validStatus(int status) {
+ switch (status) {
+ case STATUS_NOT_PRESENT:
+ case STATUS_PRESENT:
+ case STATUS_ENUMERATING:
+ case STATUS_NOT_AVAILABLE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ @Override
+ public void onStatusChanged(int status, int cameraId) throws RemoteException {
+ synchronized(CameraManager.this.mLock) {
+
+ Log.v(TAG,
+ String.format("Camera id %d has status changed to 0x%x", cameraId, status));
+
+ String id = String.valueOf(cameraId);
+
+ if (!validStatus(status)) {
+ Log.e(TAG, String.format("Ignoring invalid device %d status 0x%x", cameraId,
+ status));
+ return;
+ }
+
+ Integer oldStatus = mDeviceStatus.put(id, status);
+
+ if (oldStatus == status) {
+ Log.v(TAG, String.format(
+ "Device status changed to 0x%x, which is what it already was",
+ status));
+ return;
+ }
+
+ // TODO: consider abstracting out this state minimization + transition
+ // into a separate
+ // more easily testable class
+ // i.e. (new State()).addState(STATE_AVAILABLE)
+ // .addState(STATE_NOT_AVAILABLE)
+ // .addTransition(STATUS_PRESENT, STATE_AVAILABLE),
+ // .addTransition(STATUS_NOT_PRESENT, STATE_NOT_AVAILABLE)
+ // .addTransition(STATUS_ENUMERATING, STATE_NOT_AVAILABLE);
+ // .addTransition(STATUS_NOT_AVAILABLE, STATE_NOT_AVAILABLE);
+
+ // Translate all the statuses to either 'available' or 'not available'
+ // available -> available => no new update
+ // not available -> not available => no new update
+ if (oldStatus != null && isAvailable(status) == isAvailable(oldStatus)) {
+
+ Log.v(TAG,
+ String.format(
+ "Device status was previously available (%d), " +
+ " and is now again available (%d)" +
+ "so no new client visible update will be sent",
+ isAvailable(status), isAvailable(status)));
+ return;
+ }
+
+ for (CameraListener listener : mListenerSet) {
+ if (isAvailable(status)) {
+ listener.onCameraAvailable(id);
+ } else {
+ listener.onCameraUnavailable(id);
+ }
+ } // for
+ } // synchronized
+ } // onStatusChanged
+ } // CameraServiceListener
+} // CameraManager
diff --git a/core/java/android/hardware/photography/CameraMetadata.aidl b/core/java/android/hardware/photography/CameraMetadata.aidl
new file mode 100644
index 0000000..b4dc9ac
--- /dev/null
+++ b/core/java/android/hardware/photography/CameraMetadata.aidl
@@ -0,0 +1,20 @@
+/*
+ * 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.hardware.photography;
+
+/** @hide */
+parcelable CameraMetadata;
diff --git a/core/java/android/hardware/photography/CameraMetadata.java b/core/java/android/hardware/photography/CameraMetadata.java
index 385a1b9..5488952 100644
--- a/core/java/android/hardware/photography/CameraMetadata.java
+++ b/core/java/android/hardware/photography/CameraMetadata.java
@@ -18,6 +18,8 @@
import android.os.Parcelable;
import android.os.Parcel;
+import android.util.Log;
+
import java.util.HashMap;
import java.util.Map;
@@ -32,27 +34,34 @@
* @see CameraManager
* @see CameraProperties
**/
-public class CameraMetadata implements Parcelable {
+public class CameraMetadata implements Parcelable, AutoCloseable {
public CameraMetadata() {
mMetadataMap = new HashMap<Key<?>, Object>();
- }
- private CameraMetadata(Parcel in) {
-
+ mMetadataPtr = nativeAllocate();
+ if (mMetadataPtr == 0) {
+ throw new OutOfMemoryError("Failed to allocate native CameraMetadata");
+ }
}
public static final Parcelable.Creator<CameraMetadata> CREATOR =
new Parcelable.Creator<CameraMetadata>() {
+ @Override
public CameraMetadata createFromParcel(Parcel in) {
- return new CameraMetadata(in);
+ CameraMetadata metadata = new CameraMetadata();
+ metadata.readFromParcel(in);
+ return metadata;
}
+ @Override
public CameraMetadata[] newArray(int size) {
return new CameraMetadata[size];
}
};
+ private static final String TAG = "CameraMetadataJV";
+
/**
* Set a camera metadata field to a value. The field definitions can be
* found in {@link CameraProperties}, {@link CaptureResult}, and
@@ -63,6 +72,8 @@
* type to the key.
*/
public <T> void set(Key<T> key, T value) {
+ Log.e(TAG, "Not fully implemented yet");
+
mMetadataMap.put(key, value);
}
@@ -76,6 +87,8 @@
*/
@SuppressWarnings("unchecked")
public <T> T get(Key<T> key) {
+ Log.e(TAG, "Not fully implemented yet");
+
return (T) mMetadataMap.get(key);
}
@@ -86,7 +99,15 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
+ nativeWriteToParcel(dest);
+ }
+ /**
+ * Expand this object from a Parcel.
+ * @param in The Parcel from which the object should be read
+ */
+ public void readFromParcel(Parcel in) {
+ nativeReadFromParcel(in);
}
public static class Key<T> {
@@ -125,5 +146,88 @@
private final String mName;
}
- private Map<Key<?>, Object> mMetadataMap;
+ private final Map<Key<?>, Object> mMetadataMap;
+
+ /**
+ * @hide
+ */
+ private long mMetadataPtr; // native CameraMetadata*
+
+ private native long nativeAllocate();
+ private native synchronized void nativeWriteToParcel(Parcel dest);
+ private native synchronized void nativeReadFromParcel(Parcel source);
+ private native synchronized void nativeSwap(CameraMetadata other) throws NullPointerException;
+ private native synchronized void nativeClose();
+ private native synchronized boolean nativeIsEmpty();
+ private native synchronized int nativeGetEntryCount();
+ private static native void nativeClassInit();
+
+ /**
+ * <p>Perform a 0-copy swap of the internal metadata with another object.</p>
+ *
+ * <p>Useful to convert a CameraMetadata into e.g. a CaptureRequest.</p>
+ *
+ * @param other metadata to swap with
+ * @throws NullPointerException if other was null
+ * @hide
+ */
+ public void swap(CameraMetadata other) {
+ nativeSwap(other);
+ }
+
+ /**
+ * @hide
+ */
+ public int getEntryCount() {
+ return nativeGetEntryCount();
+ }
+
+ /**
+ * Does this metadata contain at least 1 entry?
+ *
+ * @hide
+ */
+ public boolean isEmpty() {
+ return nativeIsEmpty();
+ }
+
+ /**
+ * <p>Closes this object, and releases all native resources associated with it.</p>
+ *
+ * <p>Calling any other public method after this will result in an IllegalStateException
+ * being thrown.</p>
+ */
+ @Override
+ public void close() throws Exception {
+ // this sets mMetadataPtr to 0
+ nativeClose();
+ mMetadataPtr = 0; // set it to 0 again to prevent eclipse from making this field final
+ }
+
+ /**
+ * Whether or not {@link #close} has already been called (at least once) on this object.
+ * @hide
+ */
+ public boolean isClosed() {
+ synchronized (this) {
+ return mMetadataPtr == 0;
+ }
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ close();
+ } finally {
+ super.finalize();
+ }
+ }
+
+ /**
+ * We use a class initializer to allow the native code to cache some field offsets
+ */
+ static {
+ System.loadLibrary("media_jni");
+ nativeClassInit();
+ }
}
\ No newline at end of file
diff --git a/core/java/android/hardware/photography/CameraProperties.java b/core/java/android/hardware/photography/CameraProperties.java
index 1bfd712..ad42285 100644
--- a/core/java/android/hardware/photography/CameraProperties.java
+++ b/core/java/android/hardware/photography/CameraProperties.java
@@ -39,7 +39,7 @@
* {@link #INFO_IDENTIFIER} can be used to distinguish between multiple
* removable cameras of the same model.
*/
- public static final Key INFO_MODEL =
+ public static final Key<String> INFO_MODEL =
new Key<String>("android.info.model");
/**
@@ -48,7 +48,7 @@
* same model and manufacturer. For non-removable cameras, the
* identifier is equal to the the device's id.
*/
- public static final Key INFO_IDENTIFIER =
+ public static final Key<String> INFO_IDENTIFIER =
new Key<String>("android.info.identifier");
/**
@@ -58,7 +58,7 @@
* to be disconnected during use. Use the {@link #INFO_IDENTIFIER} field to
* determine if this camera is a match for a camera device seen earlier.</p>
*/
- public static final Key INFO_REMOVABLE =
+ public static final Key<Boolean> INFO_REMOVABLE =
new Key<Boolean>("android.info.isRemovable");
/**
@@ -99,7 +99,7 @@
* @see #INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED
* @see #INFO_SUPPORTED_HARDWARE_LEVEL_FULL
*/
- public static final Key INFO_SUPPORTED_HARDWARE_LEVEL =
+ public static final Key<Integer> INFO_SUPPORTED_HARDWARE_LEVEL =
new Key<Integer>("android.info.supportedHardwareLevel");
/**
@@ -164,7 +164,7 @@
* {@link android.graphics.ImageFormat#YUV_420_888} are guaranteed to be
* supported.</p>
*/
- public static final Key SCALER_AVAILABLE_FORMATS =
+ public static final Key<Integer[]> SCALER_AVAILABLE_FORMATS =
new Key<Integer[]>("android.scaler.availableFormats");
/**
@@ -173,7 +173,7 @@
* target, the ImageReader must be configured to use one of these sizes
* when using format {@link android.graphics.ImageFormat#JPEG}.</p>
*/
- public static final Key SCALER_AVAILABLE_JPEG_SIZES =
+ public static final Key<Size[]> SCALER_AVAILABLE_JPEG_SIZES =
new Key<Size[]>("android.scaler.availableJpegSizes");
/**
@@ -193,7 +193,7 @@
* when using format {@link android.graphics.ImageFormat#YUV_420_888}.</p>
*
*/
- public static final Key SCALER_AVAILABLE_PROCESSED_SIZES =
+ public static final Key<Size[]> SCALER_AVAILABLE_PROCESSED_SIZES =
new Key<Size[]>("android.scaler.availableProcessedSizes");
/**
@@ -206,7 +206,7 @@
* target, the ImageReader must be configured to use one of these sizes
* when using image format {@link android.graphics.ImageFormat#RAW_SENSOR}.</p>
*/
- public static final Key SCALER_AVAILABLE_RAW_SIZES =
+ public static final Key<Size[]> SCALER_AVAILABLE_RAW_SIZES =
new Key<Size[]>("android.scaler.availableRawSizes");
/**
@@ -229,7 +229,7 @@
* a coordinate system based on the active array dimensions, with (0,0)
* being the top-left corner of the active array.</p>
*/
- public static final Key SENSOR_ACTIVE_ARRAY_SIZE =
+ public static final Key<Rect> SENSOR_ACTIVE_ARRAY_SIZE =
new Key<Rect>("android.sensor.activeArraySize");
/**
@@ -239,7 +239,7 @@
* this. If raw sensor capture is supported by this device, this is one of
* the supported capture sizes.</p>
*/
- public static final Key SENSOR_PIXEL_ARRAY_SIZE =
+ public static final Key<Size> SENSOR_PIXEL_ARRAY_SIZE =
new Key<Size>("android.sensor.activeArraySize");
// TODO: Many more of these.
diff --git a/core/java/android/hardware/photography/CaptureRequest.aidl b/core/java/android/hardware/photography/CaptureRequest.aidl
new file mode 100644
index 0000000..64fb6f2
--- /dev/null
+++ b/core/java/android/hardware/photography/CaptureRequest.aidl
@@ -0,0 +1,20 @@
+/*
+ * 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.hardware.photography;
+
+/** @hide */
+parcelable CaptureRequest;
diff --git a/core/java/android/hardware/photography/CaptureRequest.java b/core/java/android/hardware/photography/CaptureRequest.java
index a54c743..ac2041b 100644
--- a/core/java/android/hardware/photography/CaptureRequest.java
+++ b/core/java/android/hardware/photography/CaptureRequest.java
@@ -16,9 +16,11 @@
package android.hardware.photography;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.view.Surface;
-import java.util.List;
+import java.util.HashSet;
/**
@@ -47,24 +49,30 @@
* @see CameraDevice#setRepeatingRequest
* @see CameraDevice#createRequest
*/
-public final class CaptureRequest extends CameraMetadata {
+public final class CaptureRequest extends CameraMetadata implements Parcelable {
+
+ private final Object mLock = new Object();
+ private final HashSet<Surface> mSurfaceSet = new HashSet<Surface>();
/**
* The exposure time for this capture, in nanoseconds.
*/
- public static final Key SENSOR_EXPOSURE_TIME =
+ public static final Key<Long> SENSOR_EXPOSURE_TIME =
new Key<Long>("android.sensor.exposureTime");
/**
* The sensor sensitivity (gain) setting for this camera.
* This is represented as an ISO sensitivity value
*/
- public static final Key SENSOR_SENSITIVITY =
+ public static final Key<Integer> SENSOR_SENSITIVITY =
new Key<Integer>("android.sensor.sensitivity");
// Many more settings
- CaptureRequest() {
+ /**
+ * @hide
+ */
+ public CaptureRequest() {
}
/**
@@ -72,14 +80,76 @@
*
* <p>The Surface added must be one of the surfaces included in the last
* call to {@link CameraDevice#configureOutputs}.</p>
+ *
+ * <p>Adding a target more than once has no effect.</p>
+ *
+ * @param outputTarget surface to use as an output target for this request
*/
public void addTarget(Surface outputTarget) {
+ synchronized (mLock) {
+ mSurfaceSet.add(outputTarget);
+ }
}
/**
* <p>Remove a surface from the list of targets for this request.</p>
+ *
+ * <p>Removing a target that is not currently added has no effect.</p>
+ *
+ * @param outputTarget surface to use as an output target for this request
*/
public void removeTarget(Surface outputTarget) {
+ synchronized (mLock) {
+ mSurfaceSet.remove(outputTarget);
+ }
+ }
+
+ public static final Parcelable.Creator<CaptureRequest> CREATOR =
+ new Parcelable.Creator<CaptureRequest>() {
+ @Override
+ public CaptureRequest createFromParcel(Parcel in) {
+ CaptureRequest request = new CaptureRequest();
+ request.readFromParcel(in);
+ return request;
+ }
+
+ @Override
+ public CaptureRequest[] newArray(int size) {
+ return new CaptureRequest[size];
+ }
+ };
+
+ /**
+ * Expand this object from a Parcel.
+ * @param in The parcel from which the object should be read
+ */
+ @Override
+ public void readFromParcel(Parcel in) {
+ synchronized (mLock) {
+ super.readFromParcel(in);
+
+ mSurfaceSet.clear();
+
+ Parcelable[] parcelableArray = in.readParcelableArray(Surface.class.getClassLoader());
+
+ if (parcelableArray == null) {
+ return;
+ }
+
+ for (Parcelable p : parcelableArray) {
+ Surface s = (Surface) p;
+ mSurfaceSet.add(s);
+ }
+ }
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ synchronized (mLock) {
+ super.writeToParcel(dest, flags);
+
+ dest.writeParcelableArray(mSurfaceSet.toArray(new Surface[mSurfaceSet.size()]), flags);
+ }
}
}
\ No newline at end of file
diff --git a/core/java/android/hardware/photography/CaptureResult.java b/core/java/android/hardware/photography/CaptureResult.java
index dd36f1d..b502c4c 100644
--- a/core/java/android/hardware/photography/CaptureResult.java
+++ b/core/java/android/hardware/photography/CaptureResult.java
@@ -101,7 +101,10 @@
// TODO: Many many more
- CaptureResult() {
+ /**
+ * @hide
+ */
+ public CaptureResult() {
}
/**
diff --git a/core/java/android/hardware/photography/ICameraDeviceCallbacks.aidl b/core/java/android/hardware/photography/ICameraDeviceCallbacks.aidl
new file mode 100644
index 0000000..c506800
--- /dev/null
+++ b/core/java/android/hardware/photography/ICameraDeviceCallbacks.aidl
@@ -0,0 +1,30 @@
+/*
+ * 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.hardware.photography;
+
+import android.hardware.photography.CameraMetadata;
+
+/** @hide */
+interface ICameraDeviceCallbacks
+{
+ /**
+ * Keep up-to-date with frameworks/av/include/camera/photography/ICameraDeviceCallbacks.h
+ */
+
+ void notifyCallback(int msgType, int ext1, int ext2);
+ void onResultReceived(int frameId, in CameraMetadata result);
+}
diff --git a/core/java/android/hardware/photography/ICameraDeviceUser.aidl b/core/java/android/hardware/photography/ICameraDeviceUser.aidl
new file mode 100644
index 0000000..d1310fb
--- /dev/null
+++ b/core/java/android/hardware/photography/ICameraDeviceUser.aidl
@@ -0,0 +1,44 @@
+/*
+ * 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.hardware.photography;
+
+import android.view.Surface;
+import android.hardware.photography.CameraMetadata;
+import android.hardware.photography.CaptureRequest;
+
+/** @hide */
+interface ICameraDeviceUser
+{
+ /**
+ * Keep up-to-date with frameworks/av/include/camera/photography/ICameraDeviceUser.h
+ */
+ void disconnect();
+
+ // ints here are status_t
+
+ // non-negative value is the requestId. negative value is status_t
+ int submitRequest(in CaptureRequest request, boolean streaming);
+
+ int cancelRequest(int requestId);
+
+ int deleteStream(int streamId);
+
+ // non-negative value is the stream ID. negative value is status_t
+ int createStream(int width, int height, int format, in Surface surface);
+
+ int createDefaultRequest(int templateId, out CameraMetadata request);
+}
diff --git a/core/java/android/hardware/photography/impl/CameraDevice.java b/core/java/android/hardware/photography/impl/CameraDevice.java
new file mode 100644
index 0000000..b1e3f6a
--- /dev/null
+++ b/core/java/android/hardware/photography/impl/CameraDevice.java
@@ -0,0 +1,322 @@
+/*
+ * 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.hardware.photography.impl;
+
+import android.hardware.photography.CameraMetadata;
+import android.hardware.photography.CaptureResult;
+import android.hardware.photography.ICameraDeviceUser;
+import android.hardware.photography.ICameraDeviceCallbacks;
+import android.hardware.photography.CameraAccessException;
+import android.hardware.photography.CameraProperties;
+import android.hardware.photography.CaptureRequest;
+import android.hardware.photography.utils.CameraRuntimeException;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.Surface;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Stack;
+
+/**
+ * HAL2.1+ implementation of CameraDevice Use CameraManager#open to instantiate
+ */
+public class CameraDevice implements android.hardware.photography.CameraDevice {
+
+ private final String TAG;
+
+ // TODO: guard every function with if (!mRemoteDevice) check (if it was closed)
+ private ICameraDeviceUser mRemoteDevice;
+
+ private final Object mLock = new Object();
+ private final CameraDeviceCallbacks mCallbacks = new CameraDeviceCallbacks();
+
+ // XX: Make this a WeakReference<CaptureListener> ?
+ private final HashMap<Integer, CaptureListenerHolder> mCaptureListenerMap =
+ new HashMap<Integer, CaptureListenerHolder>();
+
+ private final Stack<Integer> mRepeatingRequestIdStack = new Stack<Integer>();
+
+ private final String mCameraId;
+
+ public CameraDevice(String cameraId) {
+ mCameraId = cameraId;
+ TAG = String.format("CameraDevice-%s-JV", mCameraId);
+ }
+
+ public CameraDeviceCallbacks getCallbacks() {
+ return mCallbacks;
+ }
+
+ /**
+ * @hide
+ */
+ public void setRemoteDevice(ICameraDeviceUser remoteDevice) {
+ mRemoteDevice = remoteDevice;
+ }
+
+ @Override
+ public CameraProperties getProperties() throws CameraAccessException {
+ // TODO
+ Log.v(TAG, "TODO: Implement getProperties");
+ return new CameraProperties();
+ }
+
+ @Override
+ public void configureOutputs(List<Surface> outputs) throws CameraAccessException {
+ synchronized (mLock) {
+ // TODO: delete outputs that aren't in this list that were configured previously
+ for (Surface s : outputs) {
+ try {
+ // TODO: remove width,height,format since we are ignoring
+ // it.
+ mRemoteDevice.createStream(0, 0, 0, s);
+ } catch (CameraRuntimeException e) {
+ throw e.asChecked();
+ } catch (RemoteException e) {
+ // impossible
+ return;
+ }
+ }
+ }
+ }
+
+ @Override
+ public CaptureRequest createCaptureRequest(int templateType) throws CameraAccessException {
+
+ synchronized (mLock) {
+
+ CameraMetadata templatedRequest = new CameraMetadata();
+
+ try {
+ mRemoteDevice.createDefaultRequest(templateType, /* out */templatedRequest);
+ } catch (CameraRuntimeException e) {
+ throw e.asChecked();
+ } catch (RemoteException e) {
+ // impossible
+ return null;
+ }
+
+ CaptureRequest request = new CaptureRequest();
+
+ // XX: could also change binder signature but that's more work than
+ // just using swap.
+ request.swap(templatedRequest);
+
+ return request;
+
+ }
+ }
+
+ @Override
+ public void capture(CaptureRequest request, CaptureListener listener)
+ throws CameraAccessException {
+ submitCaptureRequest(request, listener, /*streaming*/false);
+ }
+
+ @Override
+ public void captureBurst(List<CaptureRequest> requests, CaptureListener listener)
+ throws CameraAccessException {
+ // TODO
+ throw new UnsupportedOperationException("Burst capture implemented yet");
+
+ }
+
+ private void submitCaptureRequest(CaptureRequest request, CaptureListener listener,
+ boolean repeating) throws CameraAccessException {
+
+ synchronized (mLock) {
+
+ int requestId;
+
+ try {
+ requestId = mRemoteDevice.submitRequest(request, repeating);
+ } catch (CameraRuntimeException e) {
+ throw e.asChecked();
+ } catch (RemoteException e) {
+ // impossible
+ return;
+ }
+
+ mCaptureListenerMap.put(requestId, new CaptureListenerHolder(listener, request,
+ repeating));
+
+ if (repeating) {
+ mRepeatingRequestIdStack.add(requestId);
+ }
+
+ }
+ }
+
+ @Override
+ public void setRepeatingRequest(CaptureRequest request, CaptureListener listener)
+ throws CameraAccessException {
+ submitCaptureRequest(request, listener, /*streaming*/true);
+ }
+
+ @Override
+ public void setRepeatingBurst(List<CaptureRequest> requests, CaptureListener listener)
+ throws CameraAccessException {
+ // TODO
+ throw new UnsupportedOperationException("Burst capture implemented yet");
+ }
+
+ @Override
+ public void stopRepeating() throws CameraAccessException {
+
+ synchronized (mLock) {
+
+ while (!mRepeatingRequestIdStack.isEmpty()) {
+ int requestId = mRepeatingRequestIdStack.pop();
+
+ try {
+ mRemoteDevice.cancelRequest(requestId);
+ } catch (CameraRuntimeException e) {
+ throw e.asChecked();
+ } catch (RemoteException e) {
+ // impossible
+ return;
+ }
+ }
+ }
+ }
+
+ @Override
+ public void waitUntilIdle() throws CameraAccessException {
+ // TODO: implement
+ }
+
+ @Override
+ public void setErrorListener(ErrorListener listener) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void close() throws Exception {
+
+ // TODO: every method should throw IllegalStateException after close has been called
+
+ synchronized (mLock) {
+
+ try {
+ mRemoteDevice.disconnect();
+ } catch (CameraRuntimeException e) {
+ throw e.asChecked();
+ } catch (RemoteException e) {
+ // impossible
+ }
+
+ mRemoteDevice = null;
+
+ }
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ close();
+ } catch (CameraRuntimeException e) {
+ Log.e(TAG, "Got error while trying to finalize, ignoring: " + e.getMessage());
+ }
+ finally {
+ super.finalize();
+ }
+ }
+
+ static class CaptureListenerHolder {
+
+ private final boolean mRepeating;
+ private final CaptureListener mListener;
+ private final CaptureRequest mRequest;
+
+ CaptureListenerHolder(CaptureListener listener, CaptureRequest request, boolean repeating) {
+ mRepeating = repeating;
+ mRequest = request;
+ mListener = listener;
+ }
+
+ public boolean isRepeating() {
+ return mRepeating;
+ }
+
+ public CaptureListener getListener() {
+ return mListener;
+ }
+
+ public CaptureRequest getRequest() {
+ return mRequest;
+ }
+ }
+
+ // TODO: unit tests
+ public class CameraDeviceCallbacks extends Binder implements ICameraDeviceCallbacks {
+
+ @Override
+ public IBinder asBinder() {
+ return this;
+ }
+
+ // TODO: consider rename to onMessageReceived
+ @Override
+ public void notifyCallback(int msgType, int ext1, int ext2) throws RemoteException {
+ Log.d(TAG, "Got message " + msgType + " ext1: " + ext1 + " , ext2: " + ext2);
+ // TODO implement rest
+ }
+
+ @Override
+ public void onResultReceived(int frameId, CameraMetadata result) throws RemoteException {
+ Log.d(TAG, "Received result for frameId " + frameId);
+
+ CaptureListenerHolder holder;
+
+ synchronized (mLock) {
+ // TODO: move this whole map into this class to make it more testable,
+ // exposing the methods necessary like subscribeToRequest, unsubscribe..
+ // TODO: make class static class
+
+ holder = CameraDevice.this.mCaptureListenerMap.get(frameId);
+
+ // Clean up listener once we no longer expect to see it.
+
+ // TODO: how to handle repeating listeners?
+ // we probably want cancelRequest to return # of times it already enqueued and
+ // keep a counter.
+ if (holder != null && !holder.isRepeating()) {
+ CameraDevice.this.mCaptureListenerMap.remove(frameId);
+ }
+ }
+
+ if (holder == null) {
+ Log.e(TAG, "Result had no listener holder associated with it, dropping result");
+ return;
+ }
+
+ CaptureResult resultAsCapture = new CaptureResult();
+ resultAsCapture.swap(result);
+
+ if (holder.getListener() != null) {
+ holder.getListener().onCaptureComplete(CameraDevice.this, holder.getRequest(),
+ resultAsCapture);
+ }
+ }
+
+ }
+
+}
diff --git a/core/java/android/hardware/photography/impl/package.html b/core/java/android/hardware/photography/impl/package.html
new file mode 100644
index 0000000..783d0a1
--- /dev/null
+++ b/core/java/android/hardware/photography/impl/package.html
@@ -0,0 +1,3 @@
+<body>
+{@hide}
+</body>
diff --git a/core/java/android/hardware/photography/utils/CameraBinderDecorator.java b/core/java/android/hardware/photography/utils/CameraBinderDecorator.java
new file mode 100644
index 0000000..1a44b97f
--- /dev/null
+++ b/core/java/android/hardware/photography/utils/CameraBinderDecorator.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.photography.utils;
+
+import static android.hardware.photography.CameraAccessException.CAMERA_DISABLED;
+import static android.hardware.photography.CameraAccessException.CAMERA_DISCONNECTED;
+import static android.hardware.photography.CameraAccessException.CAMERA_IN_USE;
+
+import android.os.DeadObjectException;
+import android.os.RemoteException;
+
+import java.lang.reflect.Method;
+
+/**
+ * Translate camera service status_t return values into exceptions.
+ *
+ * @see android.hardware.photography.utils.CameraBinderDecorator#newInstance
+ * @hide
+ */
+public class CameraBinderDecorator {
+
+ public static final int NO_ERROR = 0;
+ public static final int PERMISSION_DENIED = -1;
+ public static final int ALREADY_EXISTS = -17;
+ public static final int BAD_VALUE = -22;
+ public static final int DEAD_OBJECT = -32;
+
+ /**
+ * TODO: add as error codes in Errors.h
+ * - POLICY_PROHIBITS
+ * - RESOURCE_BUSY
+ * - NO_SUCH_DEVICE
+ */
+ public static final int EACCES = -13;
+ public static final int EBUSY = -16;
+ public static final int ENODEV = -19;
+
+ private static class CameraBinderDecoratorListener implements Decorator.DecoratorListener {
+
+ @Override
+ public void onBeforeInvocation(Method m, Object[] args) {
+ }
+
+ @Override
+ public void onAfterInvocation(Method m, Object[] args, Object result) {
+ // int return type => status_t => convert to exception
+ if (m.getReturnType() == Integer.TYPE) {
+ int returnValue = (Integer) result;
+
+ switch (returnValue) {
+ case NO_ERROR:
+ return;
+ case PERMISSION_DENIED:
+ throw new SecurityException("Lacking privileges to access camera service");
+ case ALREADY_EXISTS:
+ // This should be handled at the call site. Typically this isn't bad,
+ // just means we tried to do an operation that already completed.
+ return;
+ case BAD_VALUE:
+ throw new IllegalArgumentException("Bad argument passed to camera service");
+ case DEAD_OBJECT:
+ UncheckedThrow.throwAnyException(new CameraRuntimeException(
+ CAMERA_DISCONNECTED));
+ // TODO: Camera service (native side) should return
+ // EACCES error
+ // when there's a policy manager disabled causing this
+ case EACCES:
+ UncheckedThrow.throwAnyException(new CameraRuntimeException(
+ CAMERA_DISABLED));
+ case EBUSY:
+ UncheckedThrow.throwAnyException(new CameraRuntimeException(
+ CAMERA_IN_USE));
+ case ENODEV:
+ UncheckedThrow.throwAnyException(new CameraRuntimeException(
+ CAMERA_DISCONNECTED));
+ }
+
+ /**
+ * Trap the rest of the negative return values. If we have known
+ * error codes i.e. ALREADY_EXISTS that aren't really runtime
+ * errors, then add them to the top switch statement
+ */
+ if (returnValue < 0) {
+ throw new UnsupportedOperationException(String.format("Unknown error %d",
+ returnValue));
+ }
+ }
+ }
+
+ @Override
+ public boolean onCatchException(Method m, Object[] args, Throwable t) {
+
+ if (t instanceof DeadObjectException) {
+ UncheckedThrow.throwAnyException(new CameraRuntimeException(
+ CAMERA_DISCONNECTED,
+ "Process hosting the camera service has died unexpectedly",
+ t));
+ } else if (t instanceof RemoteException) {
+ throw new UnsupportedOperationException("An unknown RemoteException was thrown" +
+ " which should never happen.", t);
+ }
+
+ return false;
+ }
+
+ @Override
+ public void onFinally(Method m, Object[] args) {
+ }
+
+ }
+
+ /**
+ * <p>
+ * Wraps the type T with a proxy that will check 'status_t' return codes
+ * from the native side of the camera service, and throw Java exceptions
+ * automatically based on the code.
+ * </p>
+ * <p>
+ * In addition it also rewrites binder's RemoteException into either a
+ * CameraAccessException or an UnsupportedOperationException.
+ * </p>
+ * <p>
+ * As a result of calling any method on the proxy, RemoteException is
+ * guaranteed never to be thrown.
+ * </p>
+ *
+ * @param obj object that will serve as the target for all method calls
+ * @param <T> the type of the element you want to wrap. This must be an interface.
+ * @return a proxy that will intercept all invocations to obj
+ */
+ public static <T> T newInstance(T obj) {
+ return Decorator.<T> newInstance(obj, new CameraBinderDecoratorListener());
+ }
+}
diff --git a/core/java/android/hardware/photography/utils/CameraRuntimeException.java b/core/java/android/hardware/photography/utils/CameraRuntimeException.java
new file mode 100644
index 0000000..25dfc62
--- /dev/null
+++ b/core/java/android/hardware/photography/utils/CameraRuntimeException.java
@@ -0,0 +1,63 @@
+package android.hardware.photography.utils;
+
+import android.hardware.photography.CameraAccessException;
+
+/**
+ * @hide
+ */
+public class CameraRuntimeException extends RuntimeException {
+
+ private final int mReason;
+ private String mMessage;
+ private Throwable mCause;
+
+ public final int getReason() {
+ return mReason;
+ }
+
+ public CameraRuntimeException(int problem) {
+ super();
+ mReason = problem;
+ }
+
+ public CameraRuntimeException(int problem, String message) {
+ super(message);
+ mReason = problem;
+ mMessage = message;
+ }
+
+ public CameraRuntimeException(int problem, String message, Throwable cause) {
+ super(message, cause);
+ mReason = problem;
+ mMessage = message;
+ mCause = cause;
+ }
+
+ public CameraRuntimeException(int problem, Throwable cause) {
+ super(cause);
+ mReason = problem;
+ mCause = cause;
+ }
+
+ /**
+ * Recreate this exception as the CameraAccessException equivalent.
+ * @return CameraAccessException
+ */
+ public CameraAccessException asChecked() {
+ CameraAccessException e;
+
+ if (mMessage != null && mCause != null) {
+ e = new CameraAccessException(mReason, mMessage, mCause);
+ } else if (mMessage != null) {
+ e = new CameraAccessException(mReason, mMessage);
+ } else if (mCause != null) {
+ e = new CameraAccessException(mReason, mCause);
+ } else {
+ e = new CameraAccessException(mReason);
+ }
+ // throw and catch, so java has a chance to fill out the stack trace
+ e.setStackTrace(this.getStackTrace());
+
+ return e;
+ }
+}
diff --git a/core/java/android/hardware/photography/utils/Decorator.java b/core/java/android/hardware/photography/utils/Decorator.java
new file mode 100644
index 0000000..ed05dd2
--- /dev/null
+++ b/core/java/android/hardware/photography/utils/Decorator.java
@@ -0,0 +1,92 @@
+
+package android.hardware.photography.utils;
+
+import java.lang.reflect.*;
+
+/**
+ * This is an implementation of the 'decorator' design pattern using Java's proxy mechanism.
+ *
+ * @see android.hardware.photography.utils.Decorator#newInstance
+ *
+ * @hide
+ */
+public class Decorator<T> implements InvocationHandler {
+
+ public interface DecoratorListener {
+ /**
+ * This method is called before the target method is invoked
+ * @param args arguments to target method
+ * @param m Method being called
+ */
+ void onBeforeInvocation(Method m, Object[] args);
+ /**
+ * This function is called after the target method is invoked
+ * if there were no uncaught exceptions
+ * @param args arguments to target method
+ * @param m Method being called
+ * @param result return value of target method
+ */
+ void onAfterInvocation(Method m, Object[] args, Object result);
+ /**
+ * This method is called only if there was an exception thrown by the target method
+ * during its invocation.
+ *
+ * @param args arguments to target method
+ * @param m Method being called
+ * @param t Throwable that was thrown
+ * @return false to rethrow exception, true if the exception was handled
+ */
+ boolean onCatchException(Method m, Object[] args, Throwable t);
+ /**
+ * This is called after the target method is invoked, regardless of whether or not
+ * there were any exceptions.
+ * @param args arguments to target method
+ * @param m Method being called
+ */
+ void onFinally(Method m, Object[] args);
+ }
+
+ private final T mObject;
+ private final DecoratorListener mListener;
+
+ /**
+ * Create a decorator wrapping the specified object's method calls.
+ *
+ * @param obj the object whose method calls you want to intercept
+ * @param listener the decorator handler for intercepted method calls
+ * @param <T> the type of the element you want to wrap. This must be an interface.
+ * @return a wrapped interface-compatible T
+ */
+ @SuppressWarnings("unchecked")
+ public static<T> T newInstance(T obj, DecoratorListener listener) {
+ return (T)java.lang.reflect.Proxy.newProxyInstance(
+ obj.getClass().getClassLoader(),
+ obj.getClass().getInterfaces(),
+ new Decorator<T>(obj, listener));
+ }
+
+ private Decorator(T obj, DecoratorListener listener) {
+ this.mObject = obj;
+ this.mListener = listener;
+ }
+
+ @Override
+ public Object invoke(Object proxy, Method m, Object[] args)
+ throws Throwable
+ {
+ Object result = null;
+ try {
+ mListener.onBeforeInvocation(m, args);
+ result = m.invoke(mObject, args);
+ mListener.onAfterInvocation(m, args, result);
+ } catch (InvocationTargetException e) {
+ Throwable t = e.getTargetException();
+ if (!mListener.onCatchException(m, args, t)) {
+ throw t;
+ }
+ } finally {
+ mListener.onFinally(m, args);
+ }
+ return result;
+ }
+}
diff --git a/core/java/android/hardware/photography/utils/UncheckedThrow.java b/core/java/android/hardware/photography/utils/UncheckedThrow.java
new file mode 100644
index 0000000..8eed6b1
--- /dev/null
+++ b/core/java/android/hardware/photography/utils/UncheckedThrow.java
@@ -0,0 +1,40 @@
+/*
+ * 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.hardware.photography.utils;
+
+/**
+ * @hide
+ */
+public class UncheckedThrow {
+
+ /**
+ * Throw any kind of exception without needing it to be checked
+ * @param e any instance of a Exception
+ */
+ public static void throwAnyException(Exception e) {
+ /**
+ * Abuse type erasure by making the compiler think we are throwing RuntimeException,
+ * which is unchecked, but then inserting any exception in there.
+ */
+ UncheckedThrow.<RuntimeException>throwAnyImpl(e);
+ }
+
+ @SuppressWarnings("unchecked")
+ private static<T extends Exception> void throwAnyImpl(Exception e) throws T {
+ throw (T) e;
+ }
+}
diff --git a/core/java/android/hardware/photography/utils/package.html b/core/java/android/hardware/photography/utils/package.html
new file mode 100644
index 0000000..783d0a1
--- /dev/null
+++ b/core/java/android/hardware/photography/utils/package.html
@@ -0,0 +1,3 @@
+<body>
+{@hide}
+</body>
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 7c09e89c..8e0935d 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1208,13 +1208,13 @@
pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
pw.print(uid); pw.print(',');
pw.print(category); pw.print(',');
- pw.print(type);
+ pw.print(type);
for (Object arg : args) {
- pw.print(',');
- pw.print(arg);
+ pw.print(',');
+ pw.print(arg);
}
- pw.print('\n');
+ pw.println();
}
/**
@@ -1407,7 +1407,11 @@
// Only log if we had at lease one wakelock...
if (sb.length() > 0) {
- dumpLine(pw, uid, category, WAKELOCK_DATA, ent.getKey(), sb.toString());
+ String name = ent.getKey();
+ if (name.indexOf(',') >= 0) {
+ name = name.replace(',', '_');
+ }
+ dumpLine(pw, uid, category, WAKELOCK_DATA, name, sb.toString());
}
}
}
@@ -2274,6 +2278,30 @@
}
oldState = rec.states;
}
+
+ public void printNextItemCheckin(PrintWriter pw, HistoryItem rec, long now) {
+ pw.print(rec.time-now);
+ pw.print(",");
+ if (rec.cmd == HistoryItem.CMD_START) {
+ pw.print("start");
+ } else if (rec.cmd == HistoryItem.CMD_OVERFLOW) {
+ pw.print("overflow");
+ } else {
+ pw.print(rec.batteryLevel);
+ pw.print(",");
+ pw.print(rec.states);
+ pw.print(",");
+ pw.print(rec.batteryStatus);
+ pw.print(",");
+ pw.print(rec.batteryHealth);
+ pw.print(",");
+ pw.print(rec.batteryPlugType);
+ pw.print(",");
+ pw.print((int)rec.batteryTemperature);
+ pw.print(",");
+ pw.print((int)rec.batteryVoltage);
+ }
+ }
}
/**
@@ -2351,6 +2379,21 @@
PrintWriter pw, List<ApplicationInfo> apps, boolean isUnpluggedOnly) {
prepareForDumpLocked();
+ long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
+
+ final HistoryItem rec = new HistoryItem();
+ if (startIteratingHistoryLocked()) {
+ HistoryPrinter hprinter = new HistoryPrinter();
+ while (getNextHistoryLocked(rec)) {
+ pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
+ pw.print(0); pw.print(',');
+ pw.print("h"); pw.print(',');
+ hprinter.printNextItemCheckin(pw, rec, now);
+ pw.println();
+ }
+ finishIteratingHistoryLocked();
+ }
+
if (apps != null) {
SparseArray<ArrayList<String>> uids = new SparseArray<ArrayList<String>>();
for (int i=0; i<apps.size(); i++) {
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index 362ae29..c5f473e 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -16,6 +16,7 @@
package android.os;
+import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.TypedProperties;
import android.util.Log;
@@ -476,7 +477,7 @@
PrintWriter outStream = null;
try {
FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE);
- outStream = new PrintWriter(new OutputStreamWriter(fos));
+ outStream = new FastPrintWriter(fos);
outStream.println("1");
} catch (Exception e) {
} finally {
@@ -504,7 +505,7 @@
PrintWriter outStream = null;
try {
FileOutputStream fos = new FileOutputStream(SYSFS_QEMU_TRACE_STATE);
- outStream = new PrintWriter(new OutputStreamWriter(fos));
+ outStream = new FastPrintWriter(fos);
outStream.println("0");
} catch (Exception e) {
// We could print an error message here but we probably want
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 9666d9a..97ea99d 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -60,6 +60,8 @@
public static native int setPermissions(String file, int mode, int uid, int gid);
+ public static native int getUid(String file);
+
/** returns the FAT file system volume ID for the volume mounted
* at the given mount point, or -1 for failure
* @param mountPoint point for FAT volume
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index a11358a..7589a5a 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -46,4 +46,7 @@
int userHandle);
Bundle getApplicationRestrictions(in String packageName);
Bundle getApplicationRestrictionsForUser(in String packageName, int userHandle);
+ boolean changeRestrictionsPin(in String newPin);
+ int checkRestrictionsPin(in String pin);
+ boolean hasRestrictionsPin();
}
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 93b1255..159d3eb 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -976,6 +976,8 @@
/** @hide */
public static final int PROC_PARENS = 0x200;
/** @hide */
+ public static final int PROC_QUOTES = 0x400;
+ /** @hide */
public static final int PROC_OUT_STRING = 0x1000;
/** @hide */
public static final int PROC_OUT_LONG = 0x2000;
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index a9abdc5..d794ca6 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -32,6 +32,7 @@
import com.android.internal.os.RuntimeInit;
+import com.android.internal.util.FastPrintWriter;
import dalvik.system.BlockGuard;
import dalvik.system.CloseGuard;
import dalvik.system.VMDebug;
@@ -1700,7 +1701,9 @@
/* package */ static void readAndHandleBinderCallViolations(Parcel p) {
// Our own stack trace to append
StringWriter sw = new StringWriter();
- new LogStackTrace().printStackTrace(new PrintWriter(sw));
+ PrintWriter pw = new FastPrintWriter(sw, false, 256);
+ new LogStackTrace().printStackTrace(pw);
+ pw.flush();
String ourStack = sw.toString();
int policyMask = getThreadPolicyMask();
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index cb5ed4f..c33a28a 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -140,6 +140,13 @@
*/
public static final String DISALLOW_REMOVE_USER = "no_remove_user";
+ /** @hide */
+ public static final int PIN_VERIFICATION_FAILED_INCORRECT = -3;
+ /** @hide */
+ public static final int PIN_VERIFICATION_FAILED_NOT_SET = -2;
+ /** @hide */
+ public static final int PIN_VERIFICATION_SUCCESS = -1;
+
private static UserManager sInstance = null;
/** @hide */
@@ -620,4 +627,55 @@
Log.w(TAG, "Could not set application restrictions for user " + user.getIdentifier());
}
}
+
+ /**
+ * @hide
+ * Sets a new restrictions PIN. This should only be called after verifying that there
+ * currently isn't a PIN set, or after the user successfully enters the current PIN.
+ * @param newPin
+ * @return Returns true if the PIN was changed successfully.
+ */
+ public boolean changeRestrictionsPin(String newPin) {
+ try {
+ return mService.changeRestrictionsPin(newPin);
+ } catch (RemoteException re) {
+ Log.w(TAG, "Could not change restrictions pin");
+ }
+ return false;
+ }
+
+ /**
+ * @hide
+ * @param pin The PIN to verify, or null to get the number of milliseconds to wait for before
+ * allowing the user to enter the PIN.
+ * @return Returns a positive number (including zero) for how many milliseconds before
+ * you can accept another PIN, when the input is null or the input doesn't match the saved PIN.
+ * Returns {@link #PIN_VERIFICATION_SUCCESS} if the input matches the saved PIN. Returns
+ * {@link #PIN_VERIFICATION_FAILED_NOT_SET} if there is no PIN set.
+ */
+ public int checkRestrictionsPin(String pin) {
+ try {
+ return mService.checkRestrictionsPin(pin);
+ } catch (RemoteException re) {
+ Log.w(TAG, "Could not check restrictions pin");
+ }
+ return PIN_VERIFICATION_FAILED_INCORRECT;
+ }
+
+ /**
+ * Checks whether the user has restrictions that are PIN-protected. An application that
+ * participates in restrictions can check if the owner has requested a PIN challenge for
+ * any restricted operations. If there is a PIN in effect, the application should launch
+ * the PIN challenge activity {@link android.content.Intent#ACTION_RESTRICTIONS_PIN_CHALLENGE}.
+ * @see android.content.Intent#ACTION_RESTRICTIONS_PIN_CHALLENGE
+ * @return whether a restrictions PIN is in effect.
+ */
+ public boolean hasRestrictionsPin() {
+ try {
+ return mService.hasRestrictionsPin();
+ } catch (RemoteException re) {
+ Log.w(TAG, "Could not change restrictions pin");
+ }
+ return false;
+ }
}
diff --git a/core/java/android/print/IPrintAdapter.aidl b/core/java/android/print/IPrintAdapter.aidl
index a9b4fb7..f3ff8c4 100644
--- a/core/java/android/print/IPrintAdapter.aidl
+++ b/core/java/android/print/IPrintAdapter.aidl
@@ -17,7 +17,7 @@
package android.print;
import android.os.ParcelFileDescriptor;
-import android.print.IPrintProgressListener;
+import android.print.IPrintResultCallback;
import android.print.PageRange;
import android.print.PrintAttributes;
@@ -30,6 +30,6 @@
void start();
void printAttributesChanged(in PrintAttributes attributes);
void print(in List<PageRange> pages, in ParcelFileDescriptor fd,
- IPrintProgressListener progressListener);
+ IPrintResultCallback callback);
void finish();
}
diff --git a/core/java/android/print/IPrintProgressListener.aidl b/core/java/android/print/IPrintResultCallback.aidl
similarity index 81%
rename from core/java/android/print/IPrintProgressListener.aidl
rename to core/java/android/print/IPrintResultCallback.aidl
index 2c0d607..838377e 100644
--- a/core/java/android/print/IPrintProgressListener.aidl
+++ b/core/java/android/print/IPrintResultCallback.aidl
@@ -26,8 +26,8 @@
*
* @hide
*/
-oneway interface IPrintProgressListener {
- void onWriteStarted(in PrintAdapterInfo info, ICancellationSignal cancellationSignal);
- void onWriteFinished(in List<PageRange> pages);
- void onWriteFailed(CharSequence error);
+oneway interface IPrintResultCallback {
+ void onPrintStarted(in PrintAdapterInfo info, ICancellationSignal cancellationSignal);
+ void onPrintFinished(in List<PageRange> pages);
+ void onPrintFailed(CharSequence error);
}
diff --git a/core/java/android/print/PageRange.java b/core/java/android/print/PageRange.java
index 044a715..60e6229 100644
--- a/core/java/android/print/PageRange.java
+++ b/core/java/android/print/PageRange.java
@@ -21,7 +21,7 @@
/**
* Represents a range of pages. The start and end page indices of
- * the range are zero based and are inclusive.
+ * the range are zero based and inclusive.
*/
public final class PageRange implements Parcelable {
diff --git a/core/java/android/print/PrintAdapter.java b/core/java/android/print/PrintAdapter.java
index a7f809b..6547c55 100644
--- a/core/java/android/print/PrintAdapter.java
+++ b/core/java/android/print/PrintAdapter.java
@@ -16,12 +16,11 @@
package android.print;
-import java.io.FileDescriptor;
-import java.io.IOException;
-import java.util.List;
-
import android.os.CancellationSignal;
+import java.io.FileDescriptor;
+import java.util.List;
+
/**
* Base class that provides data to be printed.
*
@@ -33,19 +32,23 @@
* This callback can be used to allocate resources.
* </li>
* <li>
- * Next you will get one or more calls to the pair
- * {@link #onPrintAttributesChanged(PrintAttributes)} and {@link #onPrint(List,
- * FileDescriptor, CancellationSignal, PrintProgressCallback)}. The first callback
- * informs you that the print attributes (page size, density, etc) changed giving
- * you an opportunity to re-layout the content. The second method asks you to write
- * a PDF file with the content for specific pages.
+ * Next you will get one or more calls to {@link #onPrintAttributesChanged(
+ * PrintAttributes) to informs you that the print attributes (page size, density,
+ * etc) changed giving you an opportunity to re-layout the content.
+ * </li>
+ * <li>
+ * After every {@link #onPrintAttributesChanged(PrintAttributes) you will receive
+ * one or more calls to {@link #onPrint(List, FileDescriptor, CancellationSignal,
+ * PrintResultCallback)} asking you to write a PDF file with the content for
+ * specific pages.
* </li>
* <li>
* Finally, you will receive a call on {@link #onFinish()} right after printing.
* You can use this callback to release resources.
* </li>
* <li>
- * You can receive calls to {@link #getInfo()} at any point which should return
+ * You can receive calls to {@link #getInfo()} at any point after a call to
+ * {@link #onPrintAttributesChanged(PrintAttributes)} which should return
* a {@link PrintAdapterInfo} describing your {@link PrintAdapter}.
* </li>
* </ul>
@@ -83,29 +86,28 @@
/**
* Called when specific pages of the content have to be printed in the from of
* a PDF file to the given file descriptor. You should <strong>not</strong>
- * close the file descriptor instead you have to invoke {@link PrintProgressCallback
- * #onWriteFinished()} or {@link PrintProgressCallback#onPrintFailed(CharSequence)}.
+ * close the file descriptor instead you have to invoke {@link PrintResultCallback
+ * #onPrintFinished()} or {@link PrintResultCallback#onPrintFailed(CharSequence)}.
* <p>
* <strong>Note:</strong> If the printed content is large, it is a good
* practice to schedule writing it on a dedicated thread and register a
- * callback in the provided {@link CancellationSignal} upon which to stop
- * writing data. The cancellation callback will not be made on the main
- * thread.
+ * callback in the provided {@link CancellationSignal} upon invocation of
+ * which you should stop writing data. The cancellation callback will not
+ * be made on the main thread.
* </p>
* <p>
* <strong>Note:</strong> Invoked on the main thread.
* </p>
- * <p>
*
- * @param pages The pages whose content to write.
+ * @param pages The pages whose content to print.
* @param destination The destination file descriptor to which to start writing.
- * @param cancellationSignal Signal for observing cancel write requests.
+ * @param cancellationSignal Signal for observing cancel print requests.
* @param progressListener Callback to inform the system with the write progress.
*
* @see CancellationSignal
*/
public abstract void onPrint(List<PageRange> pages, FileDescriptor destination,
- CancellationSignal cancellationSignal, PrintProgressCallback progressListener);
+ CancellationSignal cancellationSignal, PrintResultCallback progressListener);
/**
* Called when printing finished. You can use this callback to release
@@ -132,12 +134,12 @@
public abstract PrintAdapterInfo getInfo();
/**
- * Base class for implementing a listener for the printing progress
+ * Base class for implementing a listener for the print result
* of a {@link PrintAdapter}.
*/
- public static abstract class PrintProgressCallback {
+ public static abstract class PrintResultCallback {
- PrintProgressCallback() {
+ PrintResultCallback() {
/* do nothing - hide constructor */
}
diff --git a/core/java/android/print/PrintFileAdapter.java b/core/java/android/print/PrintFileAdapter.java
index bbfc394..dab9648 100644
--- a/core/java/android/print/PrintFileAdapter.java
+++ b/core/java/android/print/PrintFileAdapter.java
@@ -53,9 +53,9 @@
@Override
public void onPrint(List<PageRange> pages, FileDescriptor destination,
- CancellationSignal cancellationSignal, PrintProgressCallback progressListener) {
+ CancellationSignal cancellationSignal, PrintResultCallback callback) {
mWriteFileAsyncTask = new WriteFileAsyncTask(mFile, destination, cancellationSignal,
- progressListener);
+ callback);
mWriteFileAsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
(Void[]) null);
@@ -73,15 +73,15 @@
private final FileDescriptor mDestination;
- private final PrintProgressCallback mProgressListener;
+ private final PrintResultCallback mResultCallback;
private final CancellationSignal mCancellationSignal;
public WriteFileAsyncTask(File source, FileDescriptor destination,
- CancellationSignal cancellationSignal, PrintProgressCallback progressListener) {
+ CancellationSignal cancellationSignal, PrintResultCallback callback) {
mSource = source;
mDestination = destination;
- mProgressListener = progressListener;
+ mResultCallback = callback;
mCancellationSignal = cancellationSignal;
mCancellationSignal.setOnCancelListener(new OnCancelListener() {
@Override
@@ -113,9 +113,9 @@
if (!isCancelled()) {
List<PageRange> pages = new ArrayList<PageRange>();
pages.add(PageRange.ALL_PAGES);
- mProgressListener.onPrintFinished(pages);
+ mResultCallback.onPrintFinished(pages);
} else {
- mProgressListener.onPrintFailed("Cancelled");
+ mResultCallback.onPrintFailed("Cancelled");
}
}
return null;
diff --git a/core/java/android/print/PrintManager.java b/core/java/android/print/PrintManager.java
index 32a0f5a..be9b596 100644
--- a/core/java/android/print/PrintManager.java
+++ b/core/java/android/print/PrintManager.java
@@ -26,7 +26,7 @@
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
-import android.print.PrintAdapter.PrintProgressCallback;
+import android.print.PrintAdapter.PrintResultCallback;
import android.util.Log;
import com.android.internal.os.SomeArgs;
@@ -162,6 +162,8 @@
* @param pdfFile The PDF file to print.
* @param attributes The default print job attributes.
* @return The created print job.
+ *
+ * @see PrintJob
*/
public PrintJob print(String printJobName, File pdfFile, PrintAttributes attributes) {
PrintFileAdapter printable = new PrintFileAdapter(pdfFile);
@@ -176,6 +178,8 @@
* @param printAdapter The printable adapter to print.
* @param attributes The default print job attributes.
* @return The created print job.
+ *
+ * @see PrintJob
*/
public PrintJob print(String printJobName, PrintAdapter printAdapter,
PrintAttributes attributes) {
@@ -252,7 +256,7 @@
@Override
public void print(List<PageRange> pages, ParcelFileDescriptor fd,
- IPrintProgressListener progressListener) {
+ IPrintResultCallback callback) {
synchronized (mLock) {
if (isFinishedLocked()) {
return;
@@ -261,7 +265,7 @@
args.arg1 = mPrintAdapter;
args.arg2 = pages;
args.arg3 = fd.getFileDescriptor();
- args.arg4 = progressListener;
+ args.arg4 = callback;
mHandler.obtainMessage(MyHandler.MESSAGE_PRINT, args).sendToTarget();
}
}
@@ -318,16 +322,16 @@
@SuppressWarnings("unchecked")
List<PageRange> pages = (List<PageRange>) args.arg2;
final FileDescriptor fd = (FileDescriptor) args.arg3;
- IPrintProgressListener listener = (IPrintProgressListener) args.arg4;
+ IPrintResultCallback callback = (IPrintResultCallback) args.arg4;
args.recycle();
try {
ICancellationSignal remoteSignal = CancellationSignal.createTransport();
- listener.onWriteStarted(adapter.getInfo(), remoteSignal);
+ callback.onPrintStarted(adapter.getInfo(), remoteSignal);
CancellationSignal localSignal = CancellationSignal.fromTransport(
remoteSignal);
adapter.onPrint(pages, fd, localSignal,
- new PrintProgressListenerWrapper(listener) {
+ new PrintResultCallbackWrapper(callback) {
@Override
public void onPrintFinished(List<PageRange> pages) {
IoUtils.closeQuietly(fd);
@@ -363,29 +367,29 @@
}
}
- private static abstract class PrintProgressListenerWrapper extends PrintProgressCallback {
+ private static abstract class PrintResultCallbackWrapper extends PrintResultCallback {
- private final IPrintProgressListener mWrappedListener;
+ private final IPrintResultCallback mWrappedCallback;
- public PrintProgressListenerWrapper(IPrintProgressListener listener) {
- mWrappedListener = listener;
+ public PrintResultCallbackWrapper(IPrintResultCallback callback) {
+ mWrappedCallback = callback;
}
@Override
public void onPrintFinished(List<PageRange> pages) {
try {
- mWrappedListener.onWriteFinished(pages);
+ mWrappedCallback.onPrintFinished(pages);
} catch (RemoteException re) {
- Log.e(LOG_TAG, "Error calling onWriteFinished", re);
+ Log.e(LOG_TAG, "Error calling onPrintFinished", re);
}
}
@Override
public void onPrintFailed(CharSequence error) {
try {
- mWrappedListener.onWriteFailed(error);
+ mWrappedCallback.onPrintFailed(error);
} catch (RemoteException re) {
- Log.e(LOG_TAG, "Error calling onWriteFailed", re);
+ Log.e(LOG_TAG, "Error calling onPrintFailed", re);
}
}
}
diff --git a/core/java/android/print/pdf/PdfDocument.java b/core/java/android/print/pdf/PdfDocument.java
index 7fb170e..7ce036d 100644
--- a/core/java/android/print/pdf/PdfDocument.java
+++ b/core/java/android/print/pdf/PdfDocument.java
@@ -105,7 +105,7 @@
* is created you can draw arbitrary content on the page's canvas which
* you can get by calling {@link Page#getCanvas()}. After you are done
* drawing the content you should finish the page by calling
- * {@link #finishPage(Page). After the page is finished you should
+ * {@link #finishPage(Page)}. After the page is finished you should
* no longer access the page or its canvas.
* <p>
* <strong>Note:</strong> Do not call this method after {@link #close()}.
diff --git a/core/java/android/printservice/PrintJob.java b/core/java/android/printservice/PrintJob.java
index 9688761..f490f91 100644
--- a/core/java/android/printservice/PrintJob.java
+++ b/core/java/android/printservice/PrintJob.java
@@ -62,7 +62,7 @@
* <p>
* <strong>Node:</strong>The returned info object is a snapshot of the
* current print job state. Every call to this method returns a fresh
- * info object that reflects the current print jobs state.
+ * info object that reflects the current print job state.
* </p>
*
* @return The print job info.
@@ -100,7 +100,7 @@
*
* @see #complete()
* @see #cancel()
- * @see #fail()
+ * @see #fail(CharSequence)
*/
public boolean isStarted() {
return getInfo().getState() == PrintJobInfo.STATE_STARTED;
@@ -140,7 +140,8 @@
* Fails the print job. You should call this method if {@link
* #isStarted()} returns true you filed while printing.
*
- * @return Whether the job as failed.
+ * @param error The reason for the failure.
+ * @return Whether the job was failed.
*
* @see #isStarted()
*/
@@ -191,6 +192,9 @@
* Gets the data associated with this print job. It is a responsibility of
* the print service to open a stream to the returned file descriptor
* and fully read the content.
+ * <p>
+ * <strong>Note:</strong> It is your responsibility to close the file descriptor.
+ * </p>
*
* @return A file descriptor for reading the data or <code>null</code>.
*/
diff --git a/core/java/android/printservice/PrintService.java b/core/java/android/printservice/PrintService.java
index d5cadc0..9256966 100644
--- a/core/java/android/printservice/PrintService.java
+++ b/core/java/android/printservice/PrintService.java
@@ -52,7 +52,7 @@
* Calls to {@link #addDiscoveredPrinters(List)} and
* {@link #removeDiscoveredPrinters(List)} before a call to
* {@link #onStartPrinterDiscovery()} and after a call to
- * {@link #onStopPrinterDiscovery()} is a no-op.
+ * {@link #onStopPrinterDiscovery()} are a no-op.
* </p>
* <p>
* For every printer discovery period all printers have to be added. Each
@@ -68,7 +68,7 @@
* 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()}. A queued print
- * job is in a {@link PrintJobInfo#STATE_QUEUED} state.
+ * job is one whose {@link PrintJob#isQueued()} return true.
* </p>
* <p>
* A print service is responsible for setting the print job state as
@@ -200,7 +200,7 @@
/**
* 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
+ * {@link #onStopPrinterDiscovery()}. Discovered printers should be
* reported by calling #addDiscoveredPrinters(List) and reported ones
* that disappear should be reported by calling
* {@link #removeDiscoveredPrinters(List)}.
@@ -299,8 +299,7 @@
/**
* Called when canceling of a print job is requested. The service
* should do best effort to fulfill the request. After the print
- * job is canceled it state has to be set to
- * {@link PrintJobInfo#STATE_CANCELED}.
+ * job is canceled by calling {@link PrintJob#cancel()}.
*
* @param printJob The print job to be canceled.
*/
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 5dae599..9685fb0 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3983,6 +3983,14 @@
*/
public static final String VOICE_RECOGNITION_SERVICE = "voice_recognition_service";
+ /**
+ * Stores whether an user has consented to have apps verified through PAM.
+ * The value is boolean (1 or 0).
+ *
+ * @hide
+ */
+ public static final String PACKAGE_VERIFIER_USER_CONSENT =
+ "package_verifier_user_consent";
/**
* The {@link ComponentName} string of the selected spell checker service which is
diff --git a/core/java/android/util/Log.java b/core/java/android/util/Log.java
index 1c3709f..6a6f027 100644
--- a/core/java/android/util/Log.java
+++ b/core/java/android/util/Log.java
@@ -17,6 +17,7 @@
package android.util;
import com.android.internal.os.RuntimeInit;
+import com.android.internal.util.FastPrintWriter;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -315,8 +316,9 @@
}
StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
+ PrintWriter pw = new FastPrintWriter(sw, false, 256);
tr.printStackTrace(pw);
+ pw.flush();
return sw.toString();
}
diff --git a/core/java/android/view/CompatibilityInfoHolder.java b/core/java/android/view/CompatibilityInfoHolder.java
deleted file mode 100644
index fc8d684..0000000
--- a/core/java/android/view/CompatibilityInfoHolder.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.content.res.CompatibilityInfo;
-
-/** @hide */
-public class CompatibilityInfoHolder {
- private volatile CompatibilityInfo mCompatInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
-
- public void set(CompatibilityInfo compatInfo) {
- if (compatInfo != null && (compatInfo.isScalingRequired()
- || !compatInfo.supportsScreen())) {
- mCompatInfo = compatInfo;
- } else {
- mCompatInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
- }
- }
-
- public CompatibilityInfo get() {
- return mCompatInfo;
- }
-
- public CompatibilityInfo getIfNeeded() {
- CompatibilityInfo ci = mCompatInfo;
- if (ci == null || ci == CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO) {
- return null;
- }
- return ci;
- }
-}
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 4d984fd..0e34435 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -16,6 +16,7 @@
package android.view;
+import android.content.res.CompatibilityInfo;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
@@ -60,7 +61,7 @@
private final String mAddress;
private final int mOwnerUid;
private final String mOwnerPackageName;
- private final CompatibilityInfoHolder mCompatibilityInfo;
+ private final DisplayAdjustments mDisplayAdjustments;
private DisplayInfo mDisplayInfo; // never null
private boolean mIsValid;
@@ -203,11 +204,11 @@
*/
public Display(DisplayManagerGlobal global,
int displayId, DisplayInfo displayInfo /*not null*/,
- CompatibilityInfoHolder compatibilityInfo) {
+ DisplayAdjustments daj) {
mGlobal = global;
mDisplayId = displayId;
mDisplayInfo = displayInfo;
- mCompatibilityInfo = compatibilityInfo;
+ mDisplayAdjustments = daj;
mIsValid = true;
// Cache properties that cannot change as long as the display is valid.
@@ -348,11 +349,11 @@
/**
* Gets the compatibility info used by this display instance.
*
- * @return The compatibility info holder, or null if none is required.
+ * @return The display adjustments holder, or null if none is required.
* @hide
*/
- public CompatibilityInfoHolder getCompatibilityInfo() {
- return mCompatibilityInfo;
+ public DisplayAdjustments getDisplayAdjustments() {
+ return mDisplayAdjustments;
}
/**
@@ -393,7 +394,7 @@
public void getSize(Point outSize) {
synchronized (this) {
updateDisplayInfoLocked();
- mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo);
+ mDisplayInfo.getAppMetrics(mTempMetrics, mDisplayAdjustments);
outSize.x = mTempMetrics.widthPixels;
outSize.y = mTempMetrics.heightPixels;
}
@@ -408,7 +409,7 @@
public void getRectSize(Rect outSize) {
synchronized (this) {
updateDisplayInfoLocked();
- mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo);
+ mDisplayInfo.getAppMetrics(mTempMetrics, mDisplayAdjustments);
outSize.set(0, 0, mTempMetrics.widthPixels, mTempMetrics.heightPixels);
}
}
@@ -573,7 +574,7 @@
public void getMetrics(DisplayMetrics outMetrics) {
synchronized (this) {
updateDisplayInfoLocked();
- mDisplayInfo.getAppMetrics(outMetrics, mCompatibilityInfo);
+ mDisplayInfo.getAppMetrics(outMetrics, mDisplayAdjustments);
}
}
@@ -611,7 +612,9 @@
public void getRealMetrics(DisplayMetrics outMetrics) {
synchronized (this) {
updateDisplayInfoLocked();
- mDisplayInfo.getLogicalMetrics(outMetrics, null);
+ mDisplayInfo.getLogicalMetrics(outMetrics,
+ CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO,
+ mDisplayAdjustments.getActivityToken());
}
}
@@ -658,7 +661,7 @@
long now = SystemClock.uptimeMillis();
if (now > mLastCachedAppSizeUpdate + CACHED_APP_SIZE_DURATION_MILLIS) {
updateDisplayInfoLocked();
- mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo);
+ mDisplayInfo.getAppMetrics(mTempMetrics, mDisplayAdjustments);
mCachedAppWidthCompat = mTempMetrics.widthPixels;
mCachedAppHeightCompat = mTempMetrics.heightPixels;
mLastCachedAppSizeUpdate = now;
@@ -670,7 +673,7 @@
public String toString() {
synchronized (this) {
updateDisplayInfoLocked();
- mDisplayInfo.getAppMetrics(mTempMetrics, mCompatibilityInfo);
+ mDisplayInfo.getAppMetrics(mTempMetrics, mDisplayAdjustments);
return "Display id " + mDisplayId + ": " + mDisplayInfo
+ ", " + mTempMetrics + ", isValid=" + mIsValid;
}
diff --git a/core/java/android/view/DisplayAdjustments.java b/core/java/android/view/DisplayAdjustments.java
new file mode 100644
index 0000000..4a234ad
--- /dev/null
+++ b/core/java/android/view/DisplayAdjustments.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.content.res.CompatibilityInfo;
+import android.os.IBinder;
+
+import com.android.internal.util.Objects;
+
+/** @hide */
+public class DisplayAdjustments {
+ public static final boolean DEVELOPMENT_RESOURCES_DEPEND_ON_ACTIVITY_TOKEN = false;
+
+ public static final DisplayAdjustments DEFAULT_DISPLAY_ADJUSTMENTS = new DisplayAdjustments();
+
+ private volatile CompatibilityInfo mCompatInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
+ private volatile IBinder mActivityToken;
+
+ public DisplayAdjustments() {
+ }
+
+ public DisplayAdjustments(IBinder token) {
+ mActivityToken = token;
+ }
+
+ public DisplayAdjustments(CompatibilityInfo compatInfo, IBinder token) {
+ setCompatibilityInfo(compatInfo);
+ mActivityToken = token;
+ }
+
+ public void setCompatibilityInfo(CompatibilityInfo compatInfo) {
+ if (this == DEFAULT_DISPLAY_ADJUSTMENTS) {
+ throw new IllegalArgumentException(
+ "setCompatbilityInfo: Cannot modify DEFAULT_DISPLAY_ADJUSTMENTS");
+ }
+ if (compatInfo != null && (compatInfo.isScalingRequired()
+ || !compatInfo.supportsScreen())) {
+ mCompatInfo = compatInfo;
+ } else {
+ mCompatInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
+ }
+ }
+
+ public CompatibilityInfo getCompatibilityInfo() {
+ return mCompatInfo;
+ }
+
+ public void setActivityToken(IBinder token) {
+ if (this == DEFAULT_DISPLAY_ADJUSTMENTS) {
+ throw new IllegalArgumentException(
+ "setActivityToken: Cannot modify DEFAULT_DISPLAY_ADJUSTMENTS");
+ }
+ mActivityToken = token;
+ }
+
+ public IBinder getActivityToken() {
+ return mActivityToken;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 17;
+ hash = hash * 31 + mCompatInfo.hashCode();
+ if (DEVELOPMENT_RESOURCES_DEPEND_ON_ACTIVITY_TOKEN) {
+ hash = hash * 31 + (mActivityToken == null ? 0 : mActivityToken.hashCode());
+ }
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof DisplayAdjustments)) {
+ return false;
+ }
+ DisplayAdjustments daj = (DisplayAdjustments)o;
+ return Objects.equal(daj.mCompatInfo, mCompatInfo) &&
+ Objects.equal(daj.mActivityToken, mActivityToken);
+ }
+}
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 1442cb7..9a9c4cd 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -17,6 +17,7 @@
package android.view;
import android.content.res.CompatibilityInfo;
+import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Process;
@@ -343,12 +344,22 @@
return 0;
}
- public void getAppMetrics(DisplayMetrics outMetrics, CompatibilityInfoHolder cih) {
- getMetricsWithSize(outMetrics, cih, appWidth, appHeight);
+ public void getAppMetrics(DisplayMetrics outMetrics) {
+ getAppMetrics(outMetrics, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
}
- public void getLogicalMetrics(DisplayMetrics outMetrics, CompatibilityInfoHolder cih) {
- getMetricsWithSize(outMetrics, cih, logicalWidth, logicalHeight);
+ public void getAppMetrics(DisplayMetrics outMetrics, DisplayAdjustments displayAdjustments) {
+ getMetricsWithSize(outMetrics, displayAdjustments.getCompatibilityInfo(),
+ displayAdjustments.getActivityToken(), appWidth, appHeight);
+ }
+
+ public void getAppMetrics(DisplayMetrics outMetrics, CompatibilityInfo ci, IBinder token) {
+ getMetricsWithSize(outMetrics, ci, token, appWidth, appHeight);
+ }
+
+ public void getLogicalMetrics(DisplayMetrics outMetrics, CompatibilityInfo compatInfo,
+ IBinder token) {
+ getMetricsWithSize(outMetrics, compatInfo, token, logicalWidth, logicalHeight);
}
public int getNaturalWidth() {
@@ -368,8 +379,8 @@
return Display.hasAccess(uid, flags, ownerUid);
}
- private void getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfoHolder cih,
- int width, int height) {
+ private void getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfo compatInfo,
+ IBinder token, int width, int height) {
outMetrics.densityDpi = outMetrics.noncompatDensityDpi = logicalDensityDpi;
outMetrics.noncompatWidthPixels = outMetrics.widthPixels = width;
outMetrics.noncompatHeightPixels = outMetrics.heightPixels = height;
@@ -380,11 +391,8 @@
outMetrics.xdpi = outMetrics.noncompatXdpi = physicalXDpi;
outMetrics.ydpi = outMetrics.noncompatYdpi = physicalYDpi;
- if (cih != null) {
- CompatibilityInfo ci = cih.getIfNeeded();
- if (ci != null) {
- ci.applyToDisplayMetrics(outMetrics);
- }
+ if (!compatInfo.equals(CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO)) {
+ compatInfo.applyToDisplayMetrics(outMetrics);
}
}
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 1f35c1d..a441c39 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -781,7 +781,7 @@
int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
try {
final int nativePaint = paint == null ? 0 : paint.mNativePaint;
- nDrawPatch(mRenderer, bitmap.mNativeBitmap, patch.mChunk,
+ nDrawPatch(mRenderer, bitmap.mNativeBitmap, patch.mNativeChunk,
dst.left, dst.top, dst.right, dst.bottom, nativePaint);
} finally {
if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier);
@@ -796,14 +796,14 @@
int modifier = paint != null ? setupColorFilter(paint) : MODIFIER_NONE;
try {
final int nativePaint = paint == null ? 0 : paint.mNativePaint;
- nDrawPatch(mRenderer, bitmap.mNativeBitmap, patch.mChunk,
+ nDrawPatch(mRenderer, bitmap.mNativeBitmap, patch.mNativeChunk,
dst.left, dst.top, dst.right, dst.bottom, nativePaint);
} finally {
if (modifier != MODIFIER_NONE) nResetModifiers(mRenderer, modifier);
}
}
- private static native void nDrawPatch(int renderer, int bitmap, byte[] chunks,
+ private static native void nDrawPatch(int renderer, int bitmap, int chunk,
float left, float top, float right, float bottom, int paint);
@Override
diff --git a/core/java/android/view/GLES20DisplayList.java b/core/java/android/view/GLES20DisplayList.java
index 9c5b33d..8b2a2ef 100644
--- a/core/java/android/view/GLES20DisplayList.java
+++ b/core/java/android/view/GLES20DisplayList.java
@@ -16,9 +16,7 @@
package android.view;
-import android.graphics.Bitmap;
import android.graphics.Matrix;
-import android.graphics.NinePatch;
import java.util.ArrayList;
@@ -26,12 +24,6 @@
* An implementation of display list for OpenGL ES 2.0.
*/
class GLES20DisplayList extends DisplayList {
- // These lists ensure that any Bitmaps and DisplayLists recorded by a DisplayList are kept
- // alive as long as the DisplayList is alive. The Bitmap and DisplayList lists
- // are populated by the GLES20RecordingCanvas during appropriate drawing calls and are
- // cleared at the start of a new drawing frame or when the view is detached from the window.
- private ArrayList<Bitmap> mBitmaps;
- private ArrayList<NinePatch> mNinePatches;
private ArrayList<DisplayList> mChildDisplayLists;
private GLES20RecordingCanvas mCanvas;
@@ -89,21 +81,9 @@
}
void clearReferences() {
- if (mBitmaps != null) mBitmaps.clear();
- if (mNinePatches != null) mNinePatches.clear();
if (mChildDisplayLists != null) mChildDisplayLists.clear();
}
- ArrayList<Bitmap> getBitmaps() {
- if (mBitmaps == null) mBitmaps = new ArrayList<Bitmap>(5);
- return mBitmaps;
- }
-
- ArrayList<NinePatch> getNinePatches() {
- if (mNinePatches == null) mNinePatches = new ArrayList<NinePatch>(5);
- return mNinePatches;
- }
-
ArrayList<DisplayList> getChildDisplayLists() {
if (mChildDisplayLists == null) mChildDisplayLists = new ArrayList<DisplayList>();
return mChildDisplayLists;
diff --git a/core/java/android/view/GLES20RecordingCanvas.java b/core/java/android/view/GLES20RecordingCanvas.java
index 273947f..b6fc38d 100644
--- a/core/java/android/view/GLES20RecordingCanvas.java
+++ b/core/java/android/view/GLES20RecordingCanvas.java
@@ -16,15 +16,7 @@
package android.view;
-import android.graphics.Bitmap;
-import android.graphics.BitmapShader;
-import android.graphics.Matrix;
-import android.graphics.NinePatch;
-import android.graphics.Paint;
-import android.graphics.Path;
import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.Shader;
import android.util.Pools.SynchronizedPool;
/**
@@ -70,222 +62,10 @@
return getDisplayList(nativeDisplayList);
}
- private void recordShaderBitmap(Paint paint) {
- if (paint != null) {
- final Shader shader = paint.getShader();
- if (shader instanceof BitmapShader) {
- mDisplayList.getBitmaps().add(((BitmapShader) shader).mBitmap);
- }
- }
- }
-
- @Override
- public void drawPatch(NinePatch patch, RectF dst, Paint paint) {
- super.drawPatch(patch, dst, paint);
- mDisplayList.getBitmaps().add(patch.getBitmap());
- mDisplayList.getNinePatches().add(patch);
- // Shaders in the Paint are ignored when drawing a Bitmap
- }
-
- @Override
- public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
- super.drawBitmap(bitmap, left, top, paint);
- mDisplayList.getBitmaps().add(bitmap);
- // Shaders in the Paint are ignored when drawing a Bitmap
- }
-
- @Override
- public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) {
- super.drawBitmap(bitmap, matrix, paint);
- mDisplayList.getBitmaps().add(bitmap);
- // Shaders in the Paint are ignored when drawing a Bitmap
- }
-
- @Override
- public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) {
- super.drawBitmap(bitmap, src, dst, paint);
- mDisplayList.getBitmaps().add(bitmap);
- // Shaders in the Paint are ignored when drawing a Bitmap
- }
-
- @Override
- public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) {
- super.drawBitmap(bitmap, src, dst, paint);
- mDisplayList.getBitmaps().add(bitmap);
- // Shaders in the Paint are ignored when drawing a Bitmap
- }
-
- @Override
- public void drawBitmap(int[] colors, int offset, int stride, float x, float y, int width,
- int height, boolean hasAlpha, Paint paint) {
- super.drawBitmap(colors, offset, stride, x, y, width, height, hasAlpha, paint);
- // Shaders in the Paint are ignored when drawing a Bitmap
- }
-
- @Override
- public void drawBitmap(int[] colors, int offset, int stride, int x, int y, int width,
- int height, boolean hasAlpha, Paint paint) {
- super.drawBitmap(colors, offset, stride, x, y, width, height, hasAlpha, paint);
- // Shaders in the Paint are ignored when drawing a Bitmap
- }
-
- @Override
- public void drawBitmapMesh(Bitmap bitmap, int meshWidth, int meshHeight, float[] verts,
- int vertOffset, int[] colors, int colorOffset, Paint paint) {
- super.drawBitmapMesh(bitmap, meshWidth, meshHeight, verts, vertOffset,
- colors, colorOffset, paint);
- mDisplayList.getBitmaps().add(bitmap);
- // Shaders in the Paint are ignored when drawing a Bitmap
- }
-
- @Override
- public void drawCircle(float cx, float cy, float radius, Paint paint) {
- super.drawCircle(cx, cy, radius, paint);
- recordShaderBitmap(paint);
- }
-
@Override
public int drawDisplayList(DisplayList displayList, Rect dirty, int flags) {
int status = super.drawDisplayList(displayList, dirty, flags);
mDisplayList.getChildDisplayLists().add(displayList);
return status;
}
-
- @Override
- public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) {
- super.drawLine(startX, startY, stopX, stopY, paint);
- recordShaderBitmap(paint);
- }
-
- @Override
- public void drawLines(float[] pts, int offset, int count, Paint paint) {
- super.drawLines(pts, offset, count, paint);
- recordShaderBitmap(paint);
- }
-
- @Override
- public void drawLines(float[] pts, Paint paint) {
- super.drawLines(pts, paint);
- recordShaderBitmap(paint);
- }
-
- @Override
- public void drawOval(RectF oval, Paint paint) {
- super.drawOval(oval, paint);
- recordShaderBitmap(paint);
- }
-
- @Override
- public void drawPaint(Paint paint) {
- super.drawPaint(paint);
- recordShaderBitmap(paint);
- }
-
- @Override
- public void drawPath(Path path, Paint paint) {
- super.drawPath(path, paint);
- recordShaderBitmap(paint);
- }
-
- @Override
- public void drawPoint(float x, float y, Paint paint) {
- super.drawPoint(x, y, paint);
- recordShaderBitmap(paint);
- }
-
- @Override
- public void drawPoints(float[] pts, int offset, int count, Paint paint) {
- super.drawPoints(pts, offset, count, paint);
- recordShaderBitmap(paint);
- }
-
- @Override
- public void drawPoints(float[] pts, Paint paint) {
- super.drawPoints(pts, paint);
- recordShaderBitmap(paint);
- }
-
- @Override
- public void drawPosText(char[] text, int index, int count, float[] pos, Paint paint) {
- super.drawPosText(text, index, count, pos, paint);
- recordShaderBitmap(paint);
- }
-
- @Override
- public void drawPosText(String text, float[] pos, Paint paint) {
- super.drawPosText(text, pos, paint);
- recordShaderBitmap(paint);
- }
-
- @Override
- public void drawRect(float left, float top, float right, float bottom, Paint paint) {
- super.drawRect(left, top, right, bottom, paint);
- recordShaderBitmap(paint);
- }
-
- @Override
- public void drawRoundRect(RectF rect, float rx, float ry, Paint paint) {
- super.drawRoundRect(rect, rx, ry, paint);
- recordShaderBitmap(paint);
- }
-
- @Override
- public void drawText(char[] text, int index, int count, float x, float y, Paint paint) {
- super.drawText(text, index, count, x, y, paint);
- recordShaderBitmap(paint);
- }
-
- @Override
- public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) {
- super.drawText(text, start, end, x, y, paint);
- recordShaderBitmap(paint);
- }
-
- @Override
- public void drawText(String text, int start, int end, float x, float y, Paint paint) {
- super.drawText(text, start, end, x, y, paint);
- recordShaderBitmap(paint);
- }
-
- @Override
- public void drawText(String text, float x, float y, Paint paint) {
- super.drawText(text, x, y, paint);
- recordShaderBitmap(paint);
- }
-
- @Override
- public void drawTextOnPath(char[] text, int index, int count, Path path, float hOffset,
- float vOffset, Paint paint) {
- super.drawTextOnPath(text, index, count, path, hOffset, vOffset, paint);
- recordShaderBitmap(paint);
- }
-
- @Override
- public void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) {
- super.drawTextOnPath(text, path, hOffset, vOffset, paint);
- recordShaderBitmap(paint);
- }
-
- @Override
- public void drawTextRun(char[] text, int index, int count, int contextIndex, int contextCount,
- float x, float y, int dir, Paint paint) {
- super.drawTextRun(text, index, count, contextIndex, contextCount, x, y, dir, paint);
- recordShaderBitmap(paint);
- }
-
- @Override
- public void drawTextRun(CharSequence text, int start, int end, int contextStart,
- int contextEnd, float x, float y, int dir, Paint paint) {
- super.drawTextRun(text, start, end, contextStart, contextEnd, x, y, dir, paint);
- recordShaderBitmap(paint);
- }
-
- @Override
- public void drawVertices(VertexMode mode, int vertexCount, float[] verts, int vertOffset,
- float[] texs, int texOffset, int[] colors, int colorOffset, short[] indices,
- int indexOffset, int indexCount, Paint paint) {
- super.drawVertices(mode, vertexCount, verts, vertOffset, texs, texOffset, colors,
- colorOffset, indices, indexOffset, indexCount, paint);
- recordShaderBitmap(paint);
- }
}
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index bcefdba..281bd7e 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -1360,7 +1360,7 @@
@Override
boolean validate() {
- return checkCurrent() != SURFACE_STATE_ERROR;
+ return checkRenderContext() != SURFACE_STATE_ERROR;
}
@Override
@@ -1413,8 +1413,7 @@
return;
}
- final int surfaceState = checkCurrent();
- if (surfaceState != SURFACE_STATE_ERROR) {
+ if (checkRenderContext() != SURFACE_STATE_ERROR) {
int status = mCanvas.invokeFunctors(mRedrawClip);
handleFunctorStatus(attachInfo, status);
}
@@ -1433,7 +1432,8 @@
view.mPrivateFlags |= View.PFLAG_DRAWN;
- final int surfaceState = checkCurrent();
+ // We are already on the correct thread
+ final int surfaceState = checkRenderContextUnsafe();
if (surfaceState != SURFACE_STATE_ERROR) {
HardwareCanvas canvas = mCanvas;
attachInfo.mHardwareCanvas = canvas;
@@ -1446,6 +1446,13 @@
DisplayList displayList = buildDisplayList(view, canvas);
+ // buildDisplayList() calls into user code which can cause
+ // an eglMakeCurrent to happen with a different surface/context.
+ // We must therefore check again here.
+ if (checkRenderContextUnsafe() == SURFACE_STATE_ERROR) {
+ return;
+ }
+
int saveCount = 0;
int status = DisplayList.STATUS_DONE;
@@ -1500,9 +1507,6 @@
HardwareCanvas canvas, DisplayList displayList) {
if (mDebugOverdraw == OVERDRAW_TYPE_COUNT) {
- // TODO: Use an alpha layer allocated from a GraphicBuffer
- // The alpha format will help with rendering performance and
- // the GraphicBuffer will let us skip the read pixels step
if (mDebugOverdrawLayer == null) {
mDebugOverdrawLayer = createHardwareLayer(mWidth, mHeight, true);
} else if (mDebugOverdrawLayer.getWidth() != mWidth ||
@@ -1725,21 +1729,39 @@
}
/**
- * Ensures the current EGL context is the one we expect.
+ * Ensures the current EGL context and surface are the ones we expect.
+ * This method throws an IllegalStateException if invoked from a thread
+ * that did not initialize EGL.
*
* @return {@link #SURFACE_STATE_ERROR} if the correct EGL context cannot be made current,
* {@link #SURFACE_STATE_UPDATED} if the EGL context was changed or
* {@link #SURFACE_STATE_SUCCESS} if the EGL context was the correct one
+ *
+ * @see #checkRenderContextUnsafe()
*/
- int checkCurrent() {
+ int checkRenderContext() {
if (mEglThread != Thread.currentThread()) {
throw new IllegalStateException("Hardware acceleration can only be used with a " +
"single UI thread.\nOriginal thread: " + mEglThread + "\n" +
"Current thread: " + Thread.currentThread());
}
- if (!mEglContext.equals(sEgl.eglGetCurrentContext()) ||
- !mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL_DRAW))) {
+ return checkRenderContextUnsafe();
+ }
+
+ /**
+ * Ensures the current EGL context and surface are the ones we expect.
+ * This method does not check the current thread.
+ *
+ * @return {@link #SURFACE_STATE_ERROR} if the correct EGL context cannot be made current,
+ * {@link #SURFACE_STATE_UPDATED} if the EGL context was changed or
+ * {@link #SURFACE_STATE_SUCCESS} if the EGL context was the correct one
+ *
+ * @see #checkRenderContext()
+ */
+ private int checkRenderContextUnsafe() {
+ if (!mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL_DRAW)) ||
+ !mEglContext.equals(sEgl.eglGetCurrentContext())) {
if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
Log.e(LOG_TAG, "eglMakeCurrent failed " +
GLUtils.getEGLErrorString(sEgl.eglGetError()));
@@ -2193,8 +2215,7 @@
@Override
boolean safelyRun(Runnable action) {
- boolean needsContext = true;
- if (isEnabled() && checkCurrent() != SURFACE_STATE_ERROR) needsContext = false;
+ boolean needsContext = !isEnabled() || checkRenderContext() == SURFACE_STATE_ERROR;
if (needsContext) {
Gl20RendererEglContext managedContext =
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 525b58f..0c1b192 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -10063,8 +10063,10 @@
* is inside the view, where the area of the view is expanded by the slop factor.
* This method is called while processing touch-move events to determine if the event
* is still within the view.
+ *
+ * @hide
*/
- private boolean pointInView(float localX, float localY, float slop) {
+ public boolean pointInView(float localX, float localY, float slop) {
return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
localY < ((mBottom - mTop) + slop);
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 9bc66be..50dbd5f4 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -239,7 +239,7 @@
boolean mAdded;
boolean mAddedTouchMode;
- final CompatibilityInfoHolder mCompatibilityInfo;
+ final DisplayAdjustments mDisplayAdjustments;
// These are accessed by multiple threads.
final Rect mWinFrame; // frame given by window manager.
@@ -336,8 +336,7 @@
mDisplay = display;
mBasePackageName = context.getBasePackageName();
- CompatibilityInfoHolder cih = display.getCompatibilityInfo();
- mCompatibilityInfo = cih != null ? cih : new CompatibilityInfoHolder();
+ mDisplayAdjustments = display.getDisplayAdjustments();
mThread = Thread.currentThread();
mLocation = new WindowLeaked(null);
@@ -423,6 +422,8 @@
synchronized (this) {
if (mView == null) {
mView = view;
+ Slog.d(TAG, "setView: b9404689 setting mView to " + view + " mAdded=" + mAdded
+ + " Callers=" + Debug.getCallers(4));
mViewLayoutDirectionInitial = mView.getRawLayoutDirection();
mFallbackEventHandler.setView(view);
mWindowAttributes.copyFrom(attrs);
@@ -444,8 +445,9 @@
}
}
- CompatibilityInfo compatibilityInfo = mCompatibilityInfo.get();
+ CompatibilityInfo compatibilityInfo = mDisplayAdjustments.getCompatibilityInfo();
mTranslator = compatibilityInfo.getTranslator();
+ mDisplayAdjustments.setActivityToken(attrs.token);
// If the application owns the surface, don't enable hardware acceleration
if (mSurfaceHolder == null) {
@@ -478,6 +480,8 @@
= panelParentView.getApplicationWindowToken();
}
mAdded = true;
+ Slog.d(TAG, "setView: b9404689 setting mAdded=true mView=" + mView
+ + " Callers=" + Debug.getCallers(4));
int res; /* = WindowManagerImpl.ADD_OKAY; */
// Schedule the first layout -before- adding to the window
@@ -503,6 +507,8 @@
mFallbackEventHandler.setView(null);
unscheduleTraversals();
setAccessibilityFocus(null, null);
+ Slog.d(TAG, "setView: b9404689 threw exception e=" + e
+ + " Callers=" + Debug.getCallers(4));
throw new RuntimeException("Adding window failed", e);
} finally {
if (restore) {
@@ -1136,7 +1142,7 @@
surfaceChanged = true;
params = lp;
}
- CompatibilityInfo compatibilityInfo = mCompatibilityInfo.get();
+ CompatibilityInfo compatibilityInfo = mDisplayAdjustments.getCompatibilityInfo();
if (compatibilityInfo.supportsScreen() == mLastInCompatMode) {
params = lp;
mFullRedrawNeeded = true;
@@ -2847,8 +2853,8 @@
+ mWindowAttributes.getTitle()
+ ": " + config);
- CompatibilityInfo ci = mCompatibilityInfo.getIfNeeded();
- if (ci != null) {
+ CompatibilityInfo ci = mDisplayAdjustments.getCompatibilityInfo();
+ if (!ci.equals(CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO)) {
config = new Configuration(config);
ci.applyToConfiguration(mNoncompatDensity, config);
}
@@ -5158,11 +5164,14 @@
return;
}
mRemoved = true;
+ Slog.d(TAG, "doDie: b9404689 mAdded==true mView=" + mView
+ + " Callers=" + Debug.getCallers(4));
if (mAdded) {
dispatchDetachedFromWindow();
}
if (mAdded && !mFirst) {
+ Slog.d(TAG, "doDie: b9404689 mAdded && !mFirst");
invalidateDisplayLists();
destroyHardwareRenderer();
@@ -5186,6 +5195,8 @@
}
}
+ Slog.d(TAG, "doDie: b9404689 setting mAdded=false mView=" + mView
+ + " Callers=" + Debug.getCallers(4));
mAdded = false;
}
WindowManagerGlobal.getInstance().doRemoveView(this);
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 7cda01c..6666545 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -21,6 +21,7 @@
import android.content.ComponentCallbacks2;
import android.content.res.Configuration;
import android.opengl.ManagedEGLContext;
+import android.os.Debug;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -28,7 +29,9 @@
import android.util.AndroidRuntimeException;
import android.util.ArraySet;
import android.util.Log;
+import android.util.Slog;
import android.view.inputmethod.InputMethodManager;
+import com.android.internal.util.FastPrintWriter;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
@@ -224,6 +227,7 @@
if (index >= 0) {
if (mDyingViews.contains(view)) {
// Don't wait for MSG_DIE to make it's way through root's queue.
+ Slog.d(TAG, "addView: b9404689 mDying contains view=" + view);
mRoots.get(index).doDie();
} else {
throw new IllegalStateException("View " + view
@@ -248,6 +252,7 @@
view.setLayoutParams(wparams);
+ Slog.d(TAG, "addView: b9404689 adding view=" + view + " root=" + root);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
@@ -346,6 +351,8 @@
if (view != null) {
view.assignParent(null);
if (deferred) {
+ Slog.d(TAG, "removeViewLocked: b9404689 mDyingViews adding view=" + view
+ + " root=" + root + " Callers=" + Debug.getCallers(4));
mDyingViews.add(view);
}
}
@@ -355,10 +362,15 @@
synchronized (mLock) {
final int index = mRoots.indexOf(root);
if (index >= 0) {
+ Slog.d(TAG, "doRemoveView: b9404689 removing view=" + mViews.get(index)
+ + " Callers=" + Debug.getCallers(4));
mRoots.remove(index);
mParams.remove(index);
final View view = mViews.remove(index);
mDyingViews.remove(view);
+ } else {
+ Slog.d(TAG, "doRemoveView: b9404689 couldn't find root=" + root
+ + " Callers=" + Debug.getCallers(4));
}
}
}
@@ -414,7 +426,7 @@
public void dumpGfxInfo(FileDescriptor fd) {
FileOutputStream fout = new FileOutputStream(fd);
- PrintWriter pw = new PrintWriter(fout);
+ PrintWriter pw = new FastPrintWriter(fout);
try {
synchronized (mLock) {
final int count = mViews.size();
diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
index 312af71..fea6be6 100644
--- a/core/java/android/webkit/CallbackProxy.java
+++ b/core/java/android/webkit/CallbackProxy.java
@@ -296,7 +296,12 @@
// in the UI thread. The WebViewClient and WebChromeClient functions
// that check for a non-null callback are ok because java ensures atomic
// 32-bit reads and writes.
- if (messagesBlocked()) return;
+ if (messagesBlocked()) {
+ synchronized (this) {
+ notify();
+ }
+ return;
+ }
switch (msg.what) {
case PAGE_STARTED:
String startedUrl = msg.getData().getString("url");
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index bb1f954..1e20ab2 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -3369,68 +3369,62 @@
}
private void onTouchDown(MotionEvent ev) {
- View v;
- switch (mTouchMode) {
- case TOUCH_MODE_OVERFLING: {
+ mActivePointerId = ev.getPointerId(0);
+
+ if (mTouchMode == TOUCH_MODE_OVERFLING) {
+ // Stopped the fling. It is a scroll.
mFlingRunnable.endFling();
if (mPositionScroller != null) {
mPositionScroller.stop();
}
mTouchMode = TOUCH_MODE_OVERSCROLL;
mMotionX = (int) ev.getX();
- mMotionY = mLastY = (int) ev.getY();
+ mMotionY = (int) ev.getY();
+ mLastY = mMotionY;
mMotionCorrection = 0;
- mActivePointerId = ev.getPointerId(0);
mDirection = 0;
- break;
- }
-
- default: {
- mActivePointerId = ev.getPointerId(0);
+ } else {
final int x = (int) ev.getX();
final int y = (int) ev.getY();
int motionPosition = pointToPosition(x, y);
+
if (!mDataChanged) {
- if ((mTouchMode != TOUCH_MODE_FLING) && (motionPosition >= 0)
- && (getAdapter().isEnabled(motionPosition))) {
- // User clicked on an actual view (and was not stopping a fling).
- // It might be a click or a scroll. Assume it is a click until
- // proven otherwise
+ if (mTouchMode == TOUCH_MODE_FLING) {
+ // Stopped a fling. It is a scroll.
+ createScrollingCache();
+ mTouchMode = TOUCH_MODE_SCROLL;
+ mMotionCorrection = 0;
+ motionPosition = findMotionRow(y);
+ mFlingRunnable.flywheelTouch();
+ } else if ((motionPosition >= 0) && getAdapter().isEnabled(motionPosition)) {
+ // User clicked on an actual view (and was not stopping a
+ // fling). It might be a click or a scroll. Assume it is a
+ // click until proven otherwise.
mTouchMode = TOUCH_MODE_DOWN;
+
// FIXME Debounce
if (mPendingCheckForTap == null) {
mPendingCheckForTap = new CheckForTap();
}
+
postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
- } else {
- if (mTouchMode == TOUCH_MODE_FLING) {
- // Stopped a fling. It is a scroll.
- createScrollingCache();
- mTouchMode = TOUCH_MODE_SCROLL;
- mMotionCorrection = 0;
- motionPosition = findMotionRow(y);
- mFlingRunnable.flywheelTouch();
- }
}
}
if (motionPosition >= 0) {
// Remember where the motion event started
- v = getChildAt(motionPosition - mFirstPosition);
+ final View v = getChildAt(motionPosition - mFirstPosition);
mMotionViewOriginalTop = v.getTop();
}
+
mMotionX = x;
mMotionY = y;
mMotionPosition = motionPosition;
mLastY = Integer.MIN_VALUE;
- break;
- }
}
- if (performButtonActionOnTouchDown(ev)) {
- if (mTouchMode == TOUCH_MODE_DOWN) {
- removeCallbacks(mPendingCheckForTap);
- }
+ if (performButtonActionOnTouchDown(ev) && (mTouchMode == TOUCH_MODE_DOWN)) {
+ removeCallbacks(mPendingCheckForTap);
}
}
@@ -3460,10 +3454,8 @@
}
// Otherwise, check containment within list bounds. If we're
// outside bounds, cancel any active presses.
- final float x = ev.getX();
- final boolean inList = (x > mListPadding.left)
- && (x < getWidth() - mListPadding.right);
- if (!inList) {
+ final float x = ev.getX(pointerIndex);
+ if (!pointInView(x, y, mTouchSlop)) {
setPressed(false);
final View motionView = getChildAt(mMotionPosition - mFirstPosition);
if (motionView != null) {
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index 62e15786..d452f58 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -274,9 +274,14 @@
mPreviewPadding = res.getDimensionPixelSize(R.dimen.fastscroll_overlay_padding);
+ final int textMinSize = Math.max(0, previewSize - mPreviewPadding);
mPrimaryText = createPreviewTextView(context, ta);
+ mPrimaryText.setMinimumWidth(textMinSize);
+ mPrimaryText.setMinimumHeight(textMinSize);
mOverlay.add(mPrimaryText);
mSecondaryText = createPreviewTextView(context, ta);
+ mSecondaryText.setMinimumWidth(textMinSize);
+ mSecondaryText.setMinimumHeight(textMinSize);
mOverlay.add(mSecondaryText);
mPreviewResId[PREVIEW_LEFT] = ta.getResourceId(PREVIEW_BACKGROUND_LEFT, 0);
@@ -598,7 +603,11 @@
transitionToVisible();
break;
case STATE_DRAGGING:
- transitionToDragging();
+ if (transitionPreviewLayout(mCurrentSection)) {
+ transitionToDragging();
+ } else {
+ transitionToVisible();
+ }
break;
}
@@ -673,10 +682,6 @@
mDecorAnimation = new AnimatorSet();
mDecorAnimation.playTogether(fadeIn, slideIn);
mDecorAnimation.start();
-
- // Ensure the preview text is correct.
- final String previewText = getPreviewText();
- transitionPreviewLayout(previewText);
}
private boolean isLongList(int visibleItemCount, int totalItemCount) {
@@ -853,42 +858,35 @@
sectionIndex = -1;
}
- if (sectionIndex >= 0 && sectionIndex < sections.length) {
- // If we moved sections, display section.
- if (mCurrentSection != sectionIndex) {
- mCurrentSection = sectionIndex;
- final String section = sections[sectionIndex].toString();
+ if (mCurrentSection != sectionIndex) {
+ mCurrentSection = sectionIndex;
+
+ if (transitionPreviewLayout(sectionIndex)) {
transitionToDragging();
- transitionPreviewLayout(section);
+ } else {
+ transitionToVisible();
}
- } else {
- // No current section, transition out of preview.
- transitionPreviewLayout(null);
- transitionToVisible();
}
}
- private String getPreviewText() {
- final Object[] sections = mSections;
- if (sections == null) {
- return null;
- }
-
- final int sectionIndex = mCurrentSection;
- if (sectionIndex < 0 || sectionIndex >= sections.length) {
- return null;
- }
-
- return sections[sectionIndex].toString();
- }
-
/**
- * Transitions the preview text to a new value. Handles animation,
- * measurement, and layout.
+ * Transitions the preview text to a new section. Handles animation,
+ * measurement, and layout. If the new preview text is empty, returns false.
*
- * @param text The preview text to transition to.
+ * @param sectionIndex The section index to which the preview should
+ * transition.
+ * @return False if the new preview text is empty.
*/
- private void transitionPreviewLayout(CharSequence text) {
+ private boolean transitionPreviewLayout(int sectionIndex) {
+ final Object[] sections = mSections;
+ String text = null;
+ if (sections != null && sectionIndex >= 0 && sectionIndex < sections.length) {
+ final Object section = sections[sectionIndex];
+ if (section != null) {
+ text = section.toString();
+ }
+ }
+
final Rect bounds = mTempBounds;
final ImageView preview = mPreviewImage;
final TextView showing;
@@ -952,6 +950,8 @@
}
mPreviewAnimation.start();
+
+ return (text != null && text.length() > 0);
}
/**
@@ -1012,26 +1012,46 @@
final boolean hasSections = mSectionIndexer != null && mSections != null
&& mSections.length > 0;
if (!hasSections || !mMatchDragPosition) {
- return firstVisibleItem / (totalItemCount - visibleItemCount);
+ return (float) firstVisibleItem / (totalItemCount - visibleItemCount);
}
+ // Ignore headers.
firstVisibleItem -= mHeaderCount;
if (firstVisibleItem < 0) {
return 0;
}
-
totalItemCount -= mHeaderCount;
+ // Hidden portion of the first visible row.
+ final View child = mList.getChildAt(0);
+ final float incrementalPos;
+ if (child == null || child.getHeight() == 0) {
+ incrementalPos = 0;
+ } else {
+ incrementalPos = (float) (mList.getPaddingTop() - child.getTop()) / child.getHeight();
+ }
+
+ // Number of rows in this section.
final int section = mSectionIndexer.getSectionForPosition(firstVisibleItem);
final int sectionPos = mSectionIndexer.getPositionForSection(section);
- final int nextSectionPos = mSectionIndexer.getPositionForSection(section + 1);
final int sectionCount = mSections.length;
- final int positionsInSection = Math.max(1, nextSectionPos - sectionPos);
+ final int positionsInSection;
+ if (section < sectionCount - 1) {
+ final int nextSectionPos = mSectionIndexer.getPositionForSection(section + 1);
+ positionsInSection = nextSectionPos - sectionPos;
+ } else {
+ positionsInSection = totalItemCount - sectionPos;
+ }
- final View child = mList.getChildAt(0);
- final float incrementalPos = child == null ? 0 : firstVisibleItem +
- (float) (mList.getPaddingTop() - child.getTop()) / Math.max(1, child.getHeight());
- final float posWithinSection = (incrementalPos - sectionPos) / positionsInSection;
+ // Position within this section.
+ final float posWithinSection;
+ if (positionsInSection == 0) {
+ posWithinSection = 0;
+ } else {
+ posWithinSection = (firstVisibleItem + incrementalPos - sectionPos)
+ / positionsInSection;
+ }
+
return (section + posWithinSection) / sectionCount;
}
diff --git a/core/java/com/android/internal/app/AlertActivity.java b/core/java/com/android/internal/app/AlertActivity.java
index 7251256..7456def 100644
--- a/core/java/com/android/internal/app/AlertActivity.java
+++ b/core/java/com/android/internal/app/AlertActivity.java
@@ -36,18 +36,18 @@
* @see #mAlertParams
*/
protected AlertController mAlert;
-
+
/**
* The parameters for the alert.
*/
protected AlertController.AlertParams mAlertParams;
-
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
+
mAlert = new AlertController(this, this, getWindow());
- mAlertParams = new AlertController.AlertParams(this);
+ mAlertParams = new AlertController.AlertParams(this);
}
public void cancel() {
@@ -65,7 +65,7 @@
/**
* Sets up the alert, including applying the parameters to the alert model,
* and installing the alert's content.
- *
+ *
* @see #mAlert
* @see #mAlertParams
*/
@@ -73,7 +73,7 @@
mAlertParams.apply(mAlert);
mAlert.installContent();
}
-
+
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (mAlert.onKeyDown(keyCode, event)) return true;
@@ -85,6 +85,4 @@
if (mAlert.onKeyUp(keyCode, event)) return true;
return super.onKeyUp(keyCode, event);
}
-
-
}
diff --git a/core/java/com/android/internal/app/RestrictionsPinActivity.java b/core/java/com/android/internal/app/RestrictionsPinActivity.java
new file mode 100644
index 0000000..57436f7
--- /dev/null
+++ b/core/java/com/android/internal/app/RestrictionsPinActivity.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.app;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.os.UserManager;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.TextView.OnEditorActionListener;
+
+import com.android.internal.R;
+
+/**
+ * This activity is launched by Settings and other apps to either create a new PIN or
+ * challenge for an existing PIN. The PIN is maintained by UserManager.
+ */
+public class RestrictionsPinActivity extends AlertActivity
+ implements DialogInterface.OnClickListener, TextWatcher, OnEditorActionListener {
+
+ private UserManager mUserManager;
+
+ private EditText mPin1Text;
+ private EditText mPin2Text;
+ private TextView mPinErrorMessage;
+ private TextView mPinMessage;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ AlertController.AlertParams ap = mAlertParams;
+ ap.mTitle = getString(R.string.restr_pin_enter_pin);
+ ap.mPositiveButtonText = getString(R.string.ok);
+ ap.mNegativeButtonText = getString(R.string.cancel);
+ ap.mPositiveButtonListener = this;
+ ap.mNegativeButtonListener = this;
+ LayoutInflater inflater =
+ (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ ap.mView = inflater.inflate(R.layout.pin_challenge, null);
+
+ mPinMessage = (TextView) ap.mView.findViewById(R.id.pin_message);
+ mPin1Text = (EditText) ap.mView.findViewById(R.id.pin1_text);
+ mPin2Text = (EditText) ap.mView.findViewById(R.id.pin2_text);
+ mPinErrorMessage = (TextView) ap.mView.findViewById(R.id.pin_error_message);
+ mPin1Text.addTextChangedListener(this);
+ mPin2Text.addTextChangedListener(this);
+
+ mUserManager = (UserManager) getSystemService(Context.USER_SERVICE);
+
+ setupAlert();
+ }
+
+ protected boolean verifyingPin() {
+ return true;
+ }
+
+ public void onResume() {
+ super.onResume();
+
+ setPositiveButtonState(false);
+ boolean hasPin = mUserManager.hasRestrictionsPin();
+ if (verifyingPin()) {
+ if (hasPin) {
+ mPinMessage.setVisibility(View.GONE);
+ mPinErrorMessage.setVisibility(View.GONE);
+ mPin2Text.setVisibility(View.GONE);
+ mPin1Text.setOnEditorActionListener(this);
+ updatePinTimer(-1);
+ } else {
+ setResult(RESULT_OK);
+ finish();
+ }
+ } else if (hasPin) {
+ // Shouldn't really be in this state, exit
+ setResult(RESULT_OK);
+ finish();
+ }
+ }
+
+ private void setPositiveButtonState(boolean enabled) {
+ mAlert.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(enabled);
+ }
+
+ private void updatePinTimer(int pinTimerMs) {
+ if (pinTimerMs < 0) {
+ pinTimerMs = mUserManager.checkRestrictionsPin(null);
+ }
+ if (pinTimerMs >= 200) {
+ final int seconds = (pinTimerMs + 200) / 1000;
+ final String formatString = getResources().getQuantityString(
+ R.plurals.restr_pin_countdown,
+ seconds);
+ mPinErrorMessage.setText(String.format(formatString, seconds));
+ mPinErrorMessage.setVisibility(View.VISIBLE);
+ mPin1Text.setEnabled(false);
+ mPin1Text.setText("");
+ setPositiveButtonState(false);
+ mPin1Text.postDelayed(mCountdownRunnable, Math.min(1000, pinTimerMs));
+ } else {
+ mPinErrorMessage.setVisibility(View.INVISIBLE);
+ mPin1Text.setEnabled(true);
+ mPin1Text.setText("");
+ }
+ }
+
+ public void onClick(DialogInterface dialog, int which) {
+ setResult(RESULT_CANCELED);
+ if (which == AlertDialog.BUTTON_POSITIVE) {
+ performPositiveButtonAction();
+ } else if (which == AlertDialog.BUTTON_NEGATIVE) {
+ finish();
+ }
+ }
+
+ private void performPositiveButtonAction() {
+ if (verifyingPin()) {
+ int result = mUserManager.checkRestrictionsPin(mPin1Text.getText().toString());
+ if (result == UserManager.PIN_VERIFICATION_SUCCESS) {
+ setResult(RESULT_OK);
+ finish();
+ } else if (result >= 0) {
+ updatePinTimer(result);
+ }
+ } else {
+ if (mUserManager.changeRestrictionsPin(mPin1Text.getText().toString())) {
+ setResult(RESULT_OK);
+ finish();
+ }
+ }
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ CharSequence pin1 = mPin1Text.getText();
+ if (!verifyingPin()) {
+ CharSequence pin2 = mPin2Text.getText();
+ boolean match = pin1 != null && pin2 != null && pin1.length() >= 4
+ && pin1.toString().equals(pin2.toString());
+ setPositiveButtonState(match);
+ mPinErrorMessage.setVisibility(match ? View.INVISIBLE : View.VISIBLE);
+ } else {
+ setPositiveButtonState(pin1 != null && pin1.length() >= 4);
+ }
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ }
+
+ @Override
+ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+ performPositiveButtonAction();
+ return true;
+ }
+
+ private Runnable mCountdownRunnable = new Runnable() {
+ public void run() {
+ updatePinTimer(-1);
+ }
+ };
+}
diff --git a/core/java/com/android/internal/app/RestrictionsPinSetupActivity.java b/core/java/com/android/internal/app/RestrictionsPinSetupActivity.java
new file mode 100644
index 0000000..35f2967
--- /dev/null
+++ b/core/java/com/android/internal/app/RestrictionsPinSetupActivity.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.app;
+
+/**
+ * This activity is launched by Settings and other apps to either create a new PIN or
+ * challenge for an existing PIN. The PIN is maintained by UserManager.
+ */
+public class RestrictionsPinSetupActivity extends RestrictionsPinActivity {
+
+ protected boolean verifyingPin() {
+ return false;
+ }
+}
diff --git a/core/java/com/android/internal/logging/AndroidHandler.java b/core/java/com/android/internal/logging/AndroidHandler.java
index 12f6a4f..f55a31f 100644
--- a/core/java/com/android/internal/logging/AndroidHandler.java
+++ b/core/java/com/android/internal/logging/AndroidHandler.java
@@ -17,6 +17,7 @@
package com.android.internal.logging;
import android.util.Log;
+import com.android.internal.util.FastPrintWriter;
import dalvik.system.DalvikLogging;
import dalvik.system.DalvikLogHandler;
@@ -91,7 +92,7 @@
Throwable thrown = r.getThrown();
if (thrown != null) {
StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
+ PrintWriter pw = new FastPrintWriter(sw, false, 256);
sw.write(r.getMessage());
sw.write("\n");
thrown.printStackTrace(pw);
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 949a499..061bf17 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -47,6 +47,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.net.NetworkStatsFactory;
+import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.JournaledFile;
import com.google.android.collect.Sets;
@@ -301,7 +302,8 @@
private static int sKernelWakelockUpdateVersion = 0;
private static final int[] PROC_WAKELOCKS_FORMAT = new int[] {
- Process.PROC_TAB_TERM|Process.PROC_OUT_STRING, // 0: name
+ Process.PROC_TAB_TERM|Process.PROC_OUT_STRING| // 0: name
+ Process.PROC_QUOTES,
Process.PROC_TAB_TERM|Process.PROC_OUT_LONG, // 1: count
Process.PROC_TAB_TERM,
Process.PROC_TAB_TERM,
@@ -4461,12 +4463,13 @@
Slog.w(TAG, "New history ends before old history!");
} else if (!out.same(mHistoryReadTmp)) {
long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
- PrintWriter pw = new PrintWriter(new LogWriter(android.util.Log.WARN, TAG));
+ PrintWriter pw = new FastPrintWriter(new LogWriter(android.util.Log.WARN, TAG));
pw.println("Histories differ!");
pw.println("Old history:");
(new HistoryPrinter()).printNextItem(pw, out, now);
pw.println("New history:");
(new HistoryPrinter()).printNextItem(pw, mHistoryReadTmp, now);
+ pw.flush();
}
}
return true;
diff --git a/core/java/com/android/internal/os/ProcessStats.java b/core/java/com/android/internal/os/ProcessStats.java
index bd0914d..874bc0e 100644
--- a/core/java/com/android/internal/os/ProcessStats.java
+++ b/core/java/com/android/internal/os/ProcessStats.java
@@ -18,10 +18,12 @@
import static android.os.Process.*;
+import android.os.FileUtils;
import android.os.Process;
import android.os.StrictMode;
import android.os.SystemClock;
import android.util.Slog;
+import com.android.internal.util.FastPrintWriter;
import java.io.File;
import java.io.FileInputStream;
@@ -173,12 +175,15 @@
public static class Stats {
public final int pid;
+ public final int uid;
final String statFile;
final String cmdlineFile;
final String threadsDir;
final ArrayList<Stats> threadStats;
final ArrayList<Stats> workingThreads;
-
+
+ public BatteryStatsImpl.Uid.Proc batteryStats;
+
public boolean interesting;
public String baseName;
@@ -228,6 +233,7 @@
threadStats = null;
workingThreads = null;
}
+ uid = FileUtils.getUid(statFile.toString());
}
}
@@ -675,13 +681,14 @@
final public String printCurrentLoad() {
StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
+ PrintWriter pw = new FastPrintWriter(sw, false, 128);
pw.print("Load: ");
pw.print(mLoad1);
pw.print(" / ");
pw.print(mLoad5);
pw.print(" / ");
pw.println(mLoad15);
+ pw.flush();
return sw.toString();
}
@@ -689,7 +696,7 @@
buildWorkingProcs();
StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
+ PrintWriter pw = new FastPrintWriter(sw, false, 1024);
pw.print("CPU usage from ");
if (now > mLastSampleTime) {
@@ -740,7 +747,8 @@
printProcessCPU(pw, "", -1, "TOTAL", totalTime, mRelUserTime, mRelSystemTime,
mRelIoWaitTime, mRelIrqTime, mRelSoftIrqTime, 0, 0);
-
+
+ pw.flush();
return sw.toString();
}
diff --git a/core/java/com/android/internal/util/DumpUtils.java b/core/java/com/android/internal/util/DumpUtils.java
index 7b8c582..65b56ec 100644
--- a/core/java/com/android/internal/util/DumpUtils.java
+++ b/core/java/com/android/internal/util/DumpUtils.java
@@ -40,7 +40,7 @@
if (handler.runWithScissors(new Runnable() {
@Override
public void run() {
- PrintWriter lpw = new PrintWriter(sw);
+ PrintWriter lpw = new FastPrintWriter(sw);
dump.dump(lpw);
lpw.close();
}
diff --git a/core/java/com/android/internal/util/FastPrintWriter.java b/core/java/com/android/internal/util/FastPrintWriter.java
index 6ad8e66..fa53cfa 100644
--- a/core/java/com/android/internal/util/FastPrintWriter.java
+++ b/core/java/com/android/internal/util/FastPrintWriter.java
@@ -1,7 +1,5 @@
package com.android.internal.util;
-import java.io.File;
-import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
@@ -15,14 +13,39 @@
import java.nio.charset.CodingErrorAction;
public class FastPrintWriter extends PrintWriter {
- private static final int BUFFER_LEN = 8192;
+ private static Writer sDummyWriter = new Writer() {
+ @Override
+ public void close() throws IOException {
+ UnsupportedOperationException ex
+ = new UnsupportedOperationException("Shouldn't be here");
+ throw ex;
+ }
- private final char[] mText = new char[BUFFER_LEN];
+ @Override
+ public void flush() throws IOException {
+ close();
+ }
+
+ @Override
+ public void write(char[] buf, int offset, int count) throws IOException {
+ close();
+ }
+ };
+
+ private final int mBufferLen;
+ private final char[] mText;
private int mPos;
final private OutputStream mOutputStream;
+ final private boolean mAutoFlush;
+ final private String mSeparator;
+
+ final private Writer mWriter;
+
private CharsetEncoder mCharset;
- final private ByteBuffer mBytes = ByteBuffer.allocate(BUFFER_LEN);
+ final private ByteBuffer mBytes;
+
+ private boolean mIoError;
/**
* Constructs a new {@code PrintWriter} with {@code out} as its target
@@ -35,9 +58,7 @@
* if {@code out} is {@code null}.
*/
public FastPrintWriter(OutputStream out) {
- super(out);
- mOutputStream = out;
- initDefaultEncoder();
+ this(out, false, 8192);
}
/**
@@ -55,8 +76,38 @@
* if {@code out} is {@code null}.
*/
public FastPrintWriter(OutputStream out, boolean autoFlush) {
- super(out, autoFlush);
+ this(out, autoFlush, 8192);
+ }
+
+ /**
+ * Constructs a new {@code PrintWriter} with {@code out} as its target
+ * stream and a custom buffer size. The parameter {@code autoFlush} determines
+ * if the print writer automatically flushes its contents to the target stream
+ * when a newline is encountered.
+ *
+ * @param out
+ * the target output stream.
+ * @param autoFlush
+ * indicates whether contents are flushed upon encountering a
+ * newline sequence.
+ * @param bufferLen
+ * specifies the size of the FastPrintWriter's internal buffer; the
+ * default is 8192.
+ * @throws NullPointerException
+ * if {@code out} is {@code null}.
+ */
+ public FastPrintWriter(OutputStream out, boolean autoFlush, int bufferLen) {
+ super(sDummyWriter, autoFlush);
+ if (out == null) {
+ throw new NullPointerException("out is null");
+ }
+ mBufferLen = bufferLen;
+ mText = new char[bufferLen];
+ mBytes = ByteBuffer.allocate(mBufferLen);
mOutputStream = out;
+ mWriter = null;
+ mAutoFlush = autoFlush;
+ mSeparator = System.lineSeparator();
initDefaultEncoder();
}
@@ -65,15 +116,17 @@
* writer. By default, the new print writer does not automatically flush its
* contents to the target writer when a newline is encountered.
*
+ * <p>NOTE: Unlike PrintWriter, this version will still do buffering inside of
+ * FastPrintWriter before sending data to the Writer. This means you must call
+ * flush() before retrieving any data from the Writer.</p>
+ *
* @param wr
* the target writer.
* @throws NullPointerException
* if {@code wr} is {@code null}.
*/
public FastPrintWriter(Writer wr) {
- super(wr);
- mOutputStream = null;
- initDefaultEncoder();
+ this(wr, false, 8192);
}
/**
@@ -91,99 +144,41 @@
* if {@code out} is {@code null}.
*/
public FastPrintWriter(Writer wr, boolean autoFlush) {
- super(wr, autoFlush);
- mOutputStream = null;
- initDefaultEncoder();
+ this(wr, autoFlush, 8192);
}
/**
- * Constructs a new {@code PrintWriter} with {@code file} as its target. The
- * VM's default character set is used for character encoding.
- * The print writer does not automatically flush its contents to the target
- * file when a newline is encountered. The output to the file is buffered.
+ * Constructs a new {@code PrintWriter} with {@code out} as its target
+ * writer and a custom buffer size. The parameter {@code autoFlush} determines
+ * if the print writer automatically flushes its contents to the target writer
+ * when a newline is encountered.
*
- * @param file
- * the target file. If the file already exists, its contents are
- * removed, otherwise a new file is created.
- * @throws java.io.FileNotFoundException
- * if an error occurs while opening or creating the target file.
- */
- public FastPrintWriter(File file) throws FileNotFoundException {
- super(file);
- mOutputStream = null;
- initDefaultEncoder();
- }
-
- /**
- * Constructs a new {@code PrintWriter} with {@code file} as its target. The
- * character set named {@code csn} is used for character encoding.
- * The print writer does not automatically flush its contents to the target
- * file when a newline is encountered. The output to the file is buffered.
- *
- * @param file
- * the target file. If the file already exists, its contents are
- * removed, otherwise a new file is created.
- * @param csn
- * the name of the character set used for character encoding.
- * @throws FileNotFoundException
- * if an error occurs while opening or creating the target file.
+ * @param wr
+ * the target writer.
+ * @param autoFlush
+ * indicates whether to flush contents upon encountering a
+ * newline sequence.
+ * @param bufferLen
+ * specifies the size of the FastPrintWriter's internal buffer; the
+ * default is 8192.
* @throws NullPointerException
- * if {@code csn} is {@code null}.
- * @throws java.io.UnsupportedEncodingException
- * if the encoding specified by {@code csn} is not supported.
+ * if {@code wr} is {@code null}.
*/
- public FastPrintWriter(File file, String csn) throws FileNotFoundException,
- UnsupportedEncodingException {
- super(file, csn);
+ public FastPrintWriter(Writer wr, boolean autoFlush, int bufferLen) {
+ super(sDummyWriter, autoFlush);
+ if (wr == null) {
+ throw new NullPointerException("wr is null");
+ }
+ mBufferLen = bufferLen;
+ mText = new char[bufferLen];
+ mBytes = null;
mOutputStream = null;
- initEncoder(csn);
- }
-
- /**
- * Constructs a new {@code PrintWriter} with the file identified by {@code
- * fileName} as its target. The VM's default character set is
- * used for character encoding. The print writer does not automatically
- * flush its contents to the target file when a newline is encountered. The
- * output to the file is buffered.
- *
- * @param fileName
- * the target file's name. If the file already exists, its
- * contents are removed, otherwise a new file is created.
- * @throws FileNotFoundException
- * if an error occurs while opening or creating the target file.
- */
- public FastPrintWriter(String fileName) throws FileNotFoundException {
- super(fileName);
- mOutputStream = null;
+ mWriter = wr;
+ mAutoFlush = autoFlush;
+ mSeparator = System.lineSeparator();
initDefaultEncoder();
}
- /**
- * Constructs a new {@code PrintWriter} with the file identified by {@code
- * fileName} as its target. The character set named {@code csn} is used for
- * character encoding. The print writer does not automatically flush its
- * contents to the target file when a newline is encountered. The output to
- * the file is buffered.
- *
- * @param fileName
- * the target file's name. If the file already exists, its
- * contents are removed, otherwise a new file is created.
- * @param csn
- * the name of the character set used for character encoding.
- * @throws FileNotFoundException
- * if an error occurs while opening or creating the target file.
- * @throws NullPointerException
- * if {@code csn} is {@code null}.
- * @throws UnsupportedEncodingException
- * if the encoding specified by {@code csn} is not supported.
- */
- public FastPrintWriter(String fileName, String csn)
- throws FileNotFoundException, UnsupportedEncodingException {
- super(fileName, csn);
- mOutputStream = null;
- initEncoder(csn);
- }
-
private final void initEncoder(String csn) throws UnsupportedEncodingException {
try {
mCharset = Charset.forName(csn).newEncoder();
@@ -194,61 +189,97 @@
mCharset.onUnmappableCharacter(CodingErrorAction.REPLACE);
}
+ /**
+ * Flushes this writer and returns the value of the error flag.
+ *
+ * @return {@code true} if either an {@code IOException} has been thrown
+ * previously or if {@code setError()} has been called;
+ * {@code false} otherwise.
+ * @see #setError()
+ */
+ public boolean checkError() {
+ flush();
+ synchronized (lock) {
+ return mIoError;
+ }
+ }
+
+ /**
+ * Sets the error state of the stream to false.
+ * @since 1.6
+ */
+ protected void clearError() {
+ synchronized (lock) {
+ mIoError = false;
+ }
+ }
+
+ /**
+ * Sets the error flag of this writer to true.
+ */
+ protected void setError() {
+ synchronized (lock) {
+ mIoError = true;
+ }
+ }
+
private final void initDefaultEncoder() {
mCharset = Charset.defaultCharset().newEncoder();
mCharset.onMalformedInput(CodingErrorAction.REPLACE);
mCharset.onUnmappableCharacter(CodingErrorAction.REPLACE);
}
- private void appendInner(char c) throws IOException {
+ private void appendLocked(char c) throws IOException {
int pos = mPos;
- if (pos >= (BUFFER_LEN-1)) {
- flush();
+ if (pos >= (mBufferLen-1)) {
+ flushLocked();
pos = mPos;
}
mText[pos] = c;
mPos = pos+1;
}
- private void appendInner(String str, int i, final int length) throws IOException {
+ private void appendLocked(String str, int i, final int length) throws IOException {
+ final int BUFFER_LEN = mBufferLen;
if (length > BUFFER_LEN) {
final int end = i + length;
while (i < end) {
int next = i + BUFFER_LEN;
- appendInner(str, i, next<end ? BUFFER_LEN : (end-i));
+ appendLocked(str, i, next < end ? BUFFER_LEN : (end - i));
i = next;
}
return;
}
int pos = mPos;
if ((pos+length) > BUFFER_LEN) {
- flush();
+ flushLocked();
pos = mPos;
}
str.getChars(i, i + length, mText, pos);
mPos = pos + length;
}
- private void appendInner(char[] buf, int i, final int length) throws IOException {
+ private void appendLocked(char[] buf, int i, final int length) throws IOException {
+ final int BUFFER_LEN = mBufferLen;
if (length > BUFFER_LEN) {
final int end = i + length;
while (i < end) {
int next = i + BUFFER_LEN;
- appendInner(buf, i, next < end ? BUFFER_LEN : (end - i));
+ appendLocked(buf, i, next < end ? BUFFER_LEN : (end - i));
i = next;
}
return;
}
int pos = mPos;
if ((pos+length) > BUFFER_LEN) {
- flush();
+ flushLocked();
pos = mPos;
}
System.arraycopy(buf, i, mText, pos, length);
mPos = pos + length;
}
- private void flushBytesInner() throws IOException {
+ private void flushBytesLocked() throws IOException {
int position;
if ((position = mBytes.position()) > 0) {
mBytes.flip();
@@ -257,7 +288,7 @@
}
}
- private void flushInner() throws IOException {
+ private void flushLocked() throws IOException {
//Log.i("PackageManager", "flush mPos=" + mPos);
if (mPos > 0) {
if (mOutputStream != null) {
@@ -267,17 +298,17 @@
if (result.isError()) {
throw new IOException(result.toString());
} else if (result.isOverflow()) {
- flushBytesInner();
+ flushBytesLocked();
result = mCharset.encode(charBuffer, mBytes, true);
continue;
}
break;
}
- flushBytesInner();
+ flushBytesLocked();
mOutputStream.flush();
} else {
- out.write(mText, 0, mPos);
- out.flush();
+ mWriter.write(mText, 0, mPos);
+ mWriter.flush();
}
mPos = 0;
}
@@ -290,11 +321,34 @@
*/
@Override
public void flush() {
- try {
- flushInner();
- } catch (IOException e) {
+ synchronized (lock) {
+ try {
+ flushLocked();
+ if (mOutputStream != null) {
+ mOutputStream.flush();
+ } else {
+ mWriter.flush();
+ }
+ } catch (IOException e) {
+ setError();
+ }
}
- super.flush();
+ }
+
+ @Override
+ public void close() {
+ synchronized (lock) {
+ try {
+ flushLocked();
+ if (mOutputStream != null) {
+ mOutputStream.close();
+ } else {
+ mWriter.close();
+ }
+ } catch (IOException e) {
+ setError();
+ }
+ }
}
/**
@@ -306,9 +360,11 @@
* @see #print(String)
*/
public void print(char[] charArray) {
- try {
- appendInner(charArray, 0, charArray.length);
- } catch (IOException e) {
+ synchronized (lock) {
+ try {
+ appendLocked(charArray, 0, charArray.length);
+ } catch (IOException e) {
+ }
}
}
@@ -321,9 +377,11 @@
* @see #print(String)
*/
public void print(char ch) {
- try {
- appendInner(ch);
- } catch (IOException e) {
+ synchronized (lock) {
+ try {
+ appendLocked(ch);
+ } catch (IOException e) {
+ }
}
}
@@ -342,9 +400,65 @@
if (str == null) {
str = String.valueOf((Object) null);
}
- try {
- appendInner(str, 0, str.length());
- } catch (IOException e) {
+ synchronized (lock) {
+ try {
+ appendLocked(str, 0, str.length());
+ } catch (IOException e) {
+ setError();
+ }
+ }
+ }
+
+
+ @Override
+ public void print(int inum) {
+ if (inum == 0) {
+ print("0");
+ } else {
+ super.print(inum);
+ }
+ }
+
+ @Override
+ public void print(long lnum) {
+ if (lnum == 0) {
+ print("0");
+ } else {
+ super.print(lnum);
+ }
+ }
+
+ /**
+ * Prints a newline. Flushes this writer if the autoFlush flag is set to {@code true}.
+ */
+ public void println() {
+ synchronized (lock) {
+ try {
+ appendLocked(mSeparator, 0, mSeparator.length());
+ if (mAutoFlush) {
+ flushLocked();
+ }
+ } catch (IOException e) {
+ setError();
+ }
+ }
+ }
+
+ @Override
+ public void println(int inum) {
+ if (inum == 0) {
+ println("0");
+ } else {
+ super.println(inum);
+ }
+ }
+
+ @Override
+ public void println(long lnum) {
+ if (lnum == 0) {
+ println("0");
+ } else {
+ super.print(lnum);
}
}
@@ -385,9 +499,11 @@
*/
@Override
public void write(char[] buf, int offset, int count) {
- try {
- appendInner(buf, offset, count);
- } catch (IOException e) {
+ synchronized (lock) {
+ try {
+ appendLocked(buf, offset, count);
+ } catch (IOException e) {
+ }
}
}
@@ -403,9 +519,11 @@
*/
@Override
public void write(int oneChar) {
- try {
- appendInner((char) oneChar);
- } catch (IOException e) {
+ synchronized (lock) {
+ try {
+ appendLocked((char) oneChar);
+ } catch (IOException e) {
+ }
}
}
@@ -417,9 +535,11 @@
*/
@Override
public void write(String str) {
- try {
- appendInner(str, 0, str.length());
- } catch (IOException e) {
+ synchronized (lock) {
+ try {
+ appendLocked(str, 0, str.length());
+ } catch (IOException e) {
+ }
}
}
@@ -439,9 +559,11 @@
*/
@Override
public void write(String str, int offset, int count) {
- try {
- appendInner(str, offset, count);
- } catch (IOException e) {
+ synchronized (lock) {
+ try {
+ appendLocked(str, offset, count);
+ } catch (IOException e) {
+ }
}
}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index faaf588..0a694c7 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -131,6 +131,7 @@
android_media_RemoteDisplay.cpp \
android_media_ToneGenerator.cpp \
android_hardware_Camera.cpp \
+ android_hardware_photography_CameraMetadata.cpp \
android_hardware_SensorManager.cpp \
android_hardware_SerialPort.cpp \
android_hardware_UsbDevice.cpp \
@@ -164,6 +165,7 @@
$(call include-path-for, libhardware)/hardware \
$(call include-path-for, libhardware_legacy)/hardware_legacy \
$(TOP)/frameworks/av/include \
+ $(TOP)/system/media/camera/include \
external/skia/src/core \
external/skia/src/pdf \
external/skia/src/images \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 144cc84..1299579 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -76,6 +76,7 @@
extern int register_android_opengl_jni_GLES30(JNIEnv* env);
extern int register_android_hardware_Camera(JNIEnv *env);
+extern int register_android_hardware_photography_CameraMetadata(JNIEnv *env);
extern int register_android_hardware_SensorManager(JNIEnv *env);
extern int register_android_hardware_SerialPort(JNIEnv *env);
extern int register_android_hardware_UsbDevice(JNIEnv *env);
@@ -1191,6 +1192,7 @@
REG_JNI(register_android_os_MemoryFile),
REG_JNI(register_com_android_internal_os_ZygoteInit),
REG_JNI(register_android_hardware_Camera),
+ REG_JNI(register_android_hardware_photography_CameraMetadata),
REG_JNI(register_android_hardware_SensorManager),
REG_JNI(register_android_hardware_SerialPort),
REG_JNI(register_android_hardware_UsbDevice),
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index a7a9266..016c11e 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -296,23 +296,11 @@
SkAutoTDelete<SkBitmap> adb(outputBitmap == NULL ? new SkBitmap : NULL);
if (outputBitmap == NULL) outputBitmap = adb.get();
- SkAutoTDelete<SkImageDecoder> add(decoder);
-
NinePatchPeeker peeker(decoder);
decoder->setPeeker(&peeker);
- AutoDecoderCancel adc(options, decoder);
-
- // To fix the race condition in case "requestCancelDecode"
- // happens earlier than AutoDecoderCancel object is added
- // to the gAutoDecoderCancelMutex linked list.
- if (options != NULL && env->GetBooleanField(options, gOptions_mCancelID)) {
- return nullObjectReturn("gOptions_mCancelID");
- }
-
SkImageDecoder::Mode decodeMode = isPurgeable ? SkImageDecoder::kDecodeBounds_Mode : mode;
-
JavaPixelAllocator javaAllocator(env);
RecyclingPixelAllocator recyclingAllocator(outputBitmap->pixelRef(), existingBufferSize);
ScaleCheckingAllocator scaleCheckingAllocator(scale, existingBufferSize);
@@ -328,6 +316,20 @@
}
}
+ // Only setup the decoder to be deleted after its stack-based, refcounted
+ // components (allocators, peekers, etc) are declared. This prevents RefCnt
+ // asserts from firing due to the order objects are deleted from the stack.
+ SkAutoTDelete<SkImageDecoder> add(decoder);
+
+ AutoDecoderCancel adc(options, decoder);
+
+ // To fix the race condition in case "requestCancelDecode"
+ // happens earlier than AutoDecoderCancel object is added
+ // to the gAutoDecoderCancelMutex linked list.
+ if (options != NULL && env->GetBooleanField(options, gOptions_mCancelID)) {
+ return nullObjectReturn("gOptions_mCancelID");
+ }
+
SkBitmap decodingBitmap;
if (!decoder->decode(stream, &decodingBitmap, prefConfig, decodeMode)) {
return nullObjectReturn("decoder->decode returned false");
diff --git a/core/jni/android/graphics/NinePatch.cpp b/core/jni/android/graphics/NinePatch.cpp
index 684b1c1..7e6aeae 100644
--- a/core/jni/android/graphics/NinePatch.cpp
+++ b/core/jni/android/graphics/NinePatch.cpp
@@ -21,22 +21,30 @@
#include <androidfw/ResourceTypes.h>
#include <utils/Log.h>
+#include <Caches.h>
+
#include "SkCanvas.h"
#include "SkRegion.h"
#include "GraphicsJNI.h"
#include "JNIHelp.h"
-extern void NinePatch_Draw(SkCanvas* canvas, const SkRect& bounds,
- const SkBitmap& bitmap, const android::Res_png_9patch& chunk,
- const SkPaint* paint, SkRegion** outRegion);
+extern void NinePatch_Draw(SkCanvas* canvas, const SkRect& bounds, const SkBitmap& bitmap,
+ const android::Res_png_9patch& chunk, const SkPaint* paint, SkRegion** outRegion);
using namespace android;
+/**
+ * IMPORTANT NOTE: 9patch chunks can be manipuated either as an array of bytes
+ * or as a Res_png_9patch instance. It is important to note that the size of the
+ * array required to hold a 9patch chunk is greater than sizeof(Res_png_9patch).
+ * The code below manipulates chunks as Res_png_9patch* types to draw and as
+ * int8_t* to allocate and free the backing storage.
+ */
+
class SkNinePatchGlue {
public:
- static jboolean isNinePatchChunk(JNIEnv* env, jobject, jbyteArray obj)
- {
+ static jboolean isNinePatchChunk(JNIEnv* env, jobject, jbyteArray obj) {
if (NULL == obj) {
return false;
}
@@ -45,126 +53,110 @@
}
const jbyte* array = env->GetByteArrayElements(obj, 0);
if (array != NULL) {
- const Res_png_9patch* chunk =
- reinterpret_cast<const Res_png_9patch*>(array);
+ const Res_png_9patch* chunk = reinterpret_cast<const Res_png_9patch*>(array);
int8_t wasDeserialized = chunk->wasDeserialized;
- env->ReleaseByteArrayElements(obj, const_cast<jbyte*>(array),
- JNI_ABORT);
+ env->ReleaseByteArrayElements(obj, const_cast<jbyte*>(array), JNI_ABORT);
return wasDeserialized != -1;
}
return false;
}
- static void validateNinePatchChunk(JNIEnv* env, jobject, jint, jbyteArray obj)
- {
- if (env->GetArrayLength(obj) < (int) (sizeof(Res_png_9patch))) {
+ static int8_t* validateNinePatchChunk(JNIEnv* env, jobject, jint, jbyteArray obj) {
+ size_t chunkSize = env->GetArrayLength(obj);
+ if (chunkSize < (int) (sizeof(Res_png_9patch))) {
jniThrowRuntimeException(env, "Array too small for chunk.");
- return;
+ return NULL;
}
- // XXX Also check that dimensions are correct.
+ int8_t* storage = new int8_t[chunkSize];
+ // This call copies the content of the jbyteArray
+ env->GetByteArrayRegion(obj, 0, chunkSize, reinterpret_cast<jbyte*>(storage));
+ // Deserialize in place, return the array we just allocated
+ return (int8_t*) Res_png_9patch::deserialize(storage);
}
- static void draw(JNIEnv* env, SkCanvas* canvas, SkRect& bounds,
- const SkBitmap* bitmap, jbyteArray chunkObj, const SkPaint* paint,
- jint destDensity, jint srcDensity)
- {
- size_t chunkSize = env->GetArrayLength(chunkObj);
- void* storage = alloca(chunkSize);
- env->GetByteArrayRegion(chunkObj, 0, chunkSize,
- reinterpret_cast<jbyte*>(storage));
- if (!env->ExceptionCheck()) {
- // need to deserialize the chunk
- Res_png_9patch* chunk = static_cast<Res_png_9patch*>(storage);
- assert(chunkSize == chunk->serializedSize());
- // this relies on deserialization being done in place
- Res_png_9patch::deserialize(chunk);
+ static void finalize(JNIEnv* env, jobject, int8_t* patch) {
+#ifdef USE_OPENGL_RENDERER
+ if (android::uirenderer::Caches::hasInstance()) {
+ Res_png_9patch* p = (Res_png_9patch*) patch;
+ android::uirenderer::Caches::getInstance().resourceCache.destructor(p);
+ return;
+ }
+#endif // USE_OPENGL_RENDERER
+ delete[] patch;
+ }
- if (destDensity == srcDensity || destDensity == 0
- || srcDensity == 0) {
- ALOGV("Drawing unscaled 9-patch: (%g,%g)-(%g,%g)",
- SkScalarToFloat(bounds.fLeft), SkScalarToFloat(bounds.fTop),
- SkScalarToFloat(bounds.fRight), SkScalarToFloat(bounds.fBottom));
- NinePatch_Draw(canvas, bounds, *bitmap, *chunk, paint, NULL);
- } else {
- canvas->save();
+ static void draw(JNIEnv* env, SkCanvas* canvas, SkRect& bounds, const SkBitmap* bitmap,
+ Res_png_9patch* chunk, const SkPaint* paint, jint destDensity, jint srcDensity) {
+ if (destDensity == srcDensity || destDensity == 0 || srcDensity == 0) {
+ ALOGV("Drawing unscaled 9-patch: (%g,%g)-(%g,%g)",
+ SkScalarToFloat(bounds.fLeft), SkScalarToFloat(bounds.fTop),
+ SkScalarToFloat(bounds.fRight), SkScalarToFloat(bounds.fBottom));
+ NinePatch_Draw(canvas, bounds, *bitmap, *chunk, paint, NULL);
+ } else {
+ canvas->save();
- SkScalar scale = SkFloatToScalar(destDensity / (float)srcDensity);
- canvas->translate(bounds.fLeft, bounds.fTop);
- canvas->scale(scale, scale);
+ SkScalar scale = SkFloatToScalar(destDensity / (float)srcDensity);
+ canvas->translate(bounds.fLeft, bounds.fTop);
+ canvas->scale(scale, scale);
- bounds.fRight = SkScalarDiv(bounds.fRight-bounds.fLeft, scale);
- bounds.fBottom = SkScalarDiv(bounds.fBottom-bounds.fTop, scale);
- bounds.fLeft = bounds.fTop = 0;
+ bounds.fRight = SkScalarDiv(bounds.fRight-bounds.fLeft, scale);
+ bounds.fBottom = SkScalarDiv(bounds.fBottom-bounds.fTop, scale);
+ bounds.fLeft = bounds.fTop = 0;
- ALOGV("Drawing scaled 9-patch: (%g,%g)-(%g,%g) srcDensity=%d destDensity=%d",
- SkScalarToFloat(bounds.fLeft), SkScalarToFloat(bounds.fTop),
- SkScalarToFloat(bounds.fRight), SkScalarToFloat(bounds.fBottom),
- srcDensity, destDensity);
+ ALOGV("Drawing scaled 9-patch: (%g,%g)-(%g,%g) srcDensity=%d destDensity=%d",
+ SkScalarToFloat(bounds.fLeft), SkScalarToFloat(bounds.fTop),
+ SkScalarToFloat(bounds.fRight), SkScalarToFloat(bounds.fBottom),
+ srcDensity, destDensity);
- NinePatch_Draw(canvas, bounds, *bitmap, *chunk, paint, NULL);
+ NinePatch_Draw(canvas, bounds, *bitmap, *chunk, paint, NULL);
- canvas->restore();
- }
+ canvas->restore();
}
}
static void drawF(JNIEnv* env, jobject, SkCanvas* canvas, jobject boundsRectF,
- const SkBitmap* bitmap, jbyteArray chunkObj, const SkPaint* paint,
- jint destDensity, jint srcDensity)
- {
+ const SkBitmap* bitmap, Res_png_9patch* chunk, const SkPaint* paint,
+ jint destDensity, jint srcDensity) {
SkASSERT(canvas);
SkASSERT(boundsRectF);
SkASSERT(bitmap);
- SkASSERT(chunkObj);
+ SkASSERT(chunk);
// paint is optional
- SkRect bounds;
+ SkRect bounds;
GraphicsJNI::jrectf_to_rect(env, boundsRectF, &bounds);
- draw(env, canvas, bounds, bitmap, chunkObj, paint, destDensity, srcDensity);
+ draw(env, canvas, bounds, bitmap, chunk, paint, destDensity, srcDensity);
}
static void drawI(JNIEnv* env, jobject, SkCanvas* canvas, jobject boundsRect,
- const SkBitmap* bitmap, jbyteArray chunkObj, const SkPaint* paint,
- jint destDensity, jint srcDensity)
- {
+ const SkBitmap* bitmap, Res_png_9patch* chunk, const SkPaint* paint,
+ jint destDensity, jint srcDensity) {
SkASSERT(canvas);
SkASSERT(boundsRect);
SkASSERT(bitmap);
- SkASSERT(chunkObj);
+ SkASSERT(chunk);
// paint is optional
- SkRect bounds;
+ SkRect bounds;
GraphicsJNI::jrect_to_rect(env, boundsRect, &bounds);
- draw(env, canvas, bounds, bitmap, chunkObj, paint, destDensity, srcDensity);
+ draw(env, canvas, bounds, bitmap, chunk, paint, destDensity, srcDensity);
}
- static jint getTransparentRegion(JNIEnv* env, jobject,
- const SkBitmap* bitmap, jbyteArray chunkObj,
- jobject boundsRect)
- {
+ static jint getTransparentRegion(JNIEnv* env, jobject, const SkBitmap* bitmap,
+ Res_png_9patch* chunk, jobject boundsRect) {
SkASSERT(bitmap);
- SkASSERT(chunkObj);
+ SkASSERT(chunk);
SkASSERT(boundsRect);
- SkRect bounds;
+ SkRect bounds;
GraphicsJNI::jrect_to_rect(env, boundsRect, &bounds);
- size_t chunkSize = env->GetArrayLength(chunkObj);
- void* storage = alloca(chunkSize);
- env->GetByteArrayRegion(chunkObj, 0, chunkSize,
- reinterpret_cast<jbyte*>(storage));
- if (!env->ExceptionCheck()) {
- // need to deserialize the chunk
- Res_png_9patch* chunk = static_cast<Res_png_9patch*>(storage);
- assert(chunkSize == chunk->serializedSize());
- // this relies on deserialization being done in place
- Res_png_9patch::deserialize(chunk);
- SkRegion* region = NULL;
- NinePatch_Draw(NULL, bounds, *bitmap, *chunk, NULL, ®ion);
- return (jint)region;
- }
- return 0;
+
+ SkRegion* region = NULL;
+ NinePatch_Draw(NULL, bounds, *bitmap, *chunk, NULL, ®ion);
+
+ return (jint) region;
}
};
@@ -174,18 +166,16 @@
#include <android_runtime/AndroidRuntime.h>
static JNINativeMethod gNinePatchMethods[] = {
- { "isNinePatchChunk", "([B)Z", (void*)SkNinePatchGlue::isNinePatchChunk },
- { "validateNinePatchChunk", "(I[B)V", (void*)SkNinePatchGlue::validateNinePatchChunk },
- { "nativeDraw", "(ILandroid/graphics/RectF;I[BIII)V", (void*)SkNinePatchGlue::drawF },
- { "nativeDraw", "(ILandroid/graphics/Rect;I[BIII)V", (void*)SkNinePatchGlue::drawI },
- { "nativeGetTransparentRegion", "(I[BLandroid/graphics/Rect;)I",
- (void*)SkNinePatchGlue::getTransparentRegion }
+ { "isNinePatchChunk", "([B)Z", (void*) SkNinePatchGlue::isNinePatchChunk },
+ { "validateNinePatchChunk", "(I[B)I", (void*) SkNinePatchGlue::validateNinePatchChunk },
+ { "nativeFinalize", "(I)V", (void*) SkNinePatchGlue::finalize },
+ { "nativeDraw", "(ILandroid/graphics/RectF;IIIII)V", (void*) SkNinePatchGlue::drawF },
+ { "nativeDraw", "(ILandroid/graphics/Rect;IIIII)V", (void*) SkNinePatchGlue::drawI },
+ { "nativeGetTransparentRegion", "(IILandroid/graphics/Rect;)I",
+ (void*) SkNinePatchGlue::getTransparentRegion }
};
-int register_android_graphics_NinePatch(JNIEnv* env)
-{
+int register_android_graphics_NinePatch(JNIEnv* env) {
return android::AndroidRuntime::registerNativeMethods(env,
- "android/graphics/NinePatch",
- gNinePatchMethods,
- SK_ARRAY_COUNT(gNinePatchMethods));
+ "android/graphics/NinePatch", gNinePatchMethods, SK_ARRAY_COUNT(gNinePatchMethods));
}
diff --git a/core/jni/android_hardware_photography_CameraMetadata.cpp b/core/jni/android_hardware_photography_CameraMetadata.cpp
new file mode 100644
index 0000000..fa363f3
--- /dev/null
+++ b/core/jni/android_hardware_photography_CameraMetadata.cpp
@@ -0,0 +1,271 @@
+/*
+**
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+// #define LOG_NDEBUG 0
+#define LOG_TAG "CameraMetadata-JNI"
+#include <utils/Log.h>
+
+#include "jni.h"
+#include "JNIHelp.h"
+#include "android_os_Parcel.h"
+#include "android_runtime/AndroidRuntime.h"
+
+#include <camera/CameraMetadata.h>
+
+// fully-qualified class name
+#define CAMERA_METADATA_CLASS_NAME "android/hardware/photography/CameraMetadata"
+
+using namespace android;
+
+struct fields_t {
+ jfieldID metadata_ptr;
+};
+
+static fields_t fields;
+
+extern "C" {
+
+static void CameraMetadata_classInit(JNIEnv *env, jobject thiz);
+
+// Less safe access to native pointer. Does NOT throw any Java exceptions if NULL.
+static CameraMetadata* CameraMetadata_getPointerNoThrow(JNIEnv *env, jobject thiz) {
+
+ if (thiz == NULL) {
+ return NULL;
+ }
+
+ return reinterpret_cast<CameraMetadata*>(env->GetLongField(thiz, fields.metadata_ptr));
+}
+
+// Safe access to native pointer from object. Throws if not possible to access.
+static CameraMetadata* CameraMetadata_getPointerThrow(JNIEnv *env, jobject thiz,
+ const char* argName = "this") {
+
+ if (thiz == NULL) {
+ ALOGV("%s: Throwing java.lang.NullPointerException for null reference",
+ __FUNCTION__);
+ jniThrowNullPointerException(env, argName);
+ return NULL;
+ }
+
+ CameraMetadata* metadata = CameraMetadata_getPointerNoThrow(env, thiz);
+ if (metadata == NULL) {
+ ALOGV("%s: Throwing java.lang.IllegalStateException for closed object",
+ __FUNCTION__);
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Metadata object was already closed");
+ return NULL;
+ }
+
+ return metadata;
+}
+
+static jlong CameraMetadata_allocate(JNIEnv *env, jobject thiz) {
+ ALOGV("%s", __FUNCTION__);
+
+ return reinterpret_cast<jlong>(new CameraMetadata());
+}
+
+static jboolean CameraMetadata_isEmpty(JNIEnv *env, jobject thiz) {
+ ALOGV("%s", __FUNCTION__);
+
+ CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
+
+ if (metadata == NULL) {
+ ALOGW("%s: Returning early due to exception being thrown",
+ __FUNCTION__);
+ return JNI_TRUE; // actually throws java exc.
+ }
+
+ jboolean empty = metadata->isEmpty();
+
+ ALOGV("%s: Empty returned %d, entry count was %d",
+ __FUNCTION__, empty, metadata->entryCount());
+
+ return empty;
+}
+
+static jint CameraMetadata_getEntryCount(JNIEnv *env, jobject thiz) {
+ ALOGV("%s", __FUNCTION__);
+
+ CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
+
+ if (metadata == NULL) return 0; // actually throws java exc.
+
+ return metadata->entryCount();
+}
+
+// idempotent. calling more than once has no effect.
+static void CameraMetadata_close(JNIEnv *env, jobject thiz) {
+ ALOGV("%s", __FUNCTION__);
+
+ CameraMetadata* metadata = CameraMetadata_getPointerNoThrow(env, thiz);
+
+ if (metadata != NULL) {
+ delete metadata;
+ env->SetLongField(thiz, fields.metadata_ptr, 0);
+ }
+
+ LOG_ALWAYS_FATAL_IF(CameraMetadata_getPointerNoThrow(env, thiz) != NULL,
+ "Expected the native ptr to be 0 after #close");
+}
+
+static void CameraMetadata_swap(JNIEnv *env, jobject thiz, jobject other) {
+ ALOGV("%s", __FUNCTION__);
+
+ CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
+
+ // order is important: we can't call another JNI method
+ // if there is an exception pending
+ if (metadata == NULL) return;
+
+ CameraMetadata* otherMetadata = CameraMetadata_getPointerThrow(env, other, "other");
+
+ if (otherMetadata == NULL) return;
+
+ metadata->swap(*otherMetadata);
+}
+
+static void CameraMetadata_readFromParcel(JNIEnv *env, jobject thiz, jobject parcel) {
+ ALOGV("%s", __FUNCTION__);
+ CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
+ if (metadata == NULL) {
+ return;
+ }
+
+ Parcel* parcelNative = parcelForJavaObject(env, parcel);
+ if (parcelNative == NULL) {
+ jniThrowNullPointerException(env, "parcel");
+ return;
+ }
+
+ status_t err;
+ if ((err = metadata->readFromParcel(parcelNative)) != OK) {
+ jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
+ "Failed to read from parcel (error code %d)", err);
+ return;
+ }
+}
+
+static void CameraMetadata_writeToParcel(JNIEnv *env, jobject thiz, jobject parcel) {
+ ALOGV("%s", __FUNCTION__);
+ CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
+ if (metadata == NULL) {
+ return;
+ }
+
+ Parcel* parcelNative = parcelForJavaObject(env, parcel);
+ if (parcelNative == NULL) {
+ jniThrowNullPointerException(env, "parcel");
+ return;
+ }
+
+ status_t err;
+ if ((err = metadata->writeToParcel(parcelNative)) != OK) {
+ jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
+ "Failed to write to parcel (error code %d)", err);
+ return;
+ }
+}
+
+} // extern "C"
+
+//-------------------------------------------------
+
+static JNINativeMethod gCameraMetadataMethods[] = {
+ { "nativeClassInit",
+ "()V",
+ (void *)CameraMetadata_classInit },
+ { "nativeAllocate",
+ "()J",
+ (void*)CameraMetadata_allocate },
+ { "nativeIsEmpty",
+ "()Z",
+ (void*)CameraMetadata_isEmpty },
+ { "nativeGetEntryCount",
+ "()I",
+ (void*)CameraMetadata_getEntryCount },
+ { "nativeClose",
+ "()V",
+ (void*)CameraMetadata_close },
+ { "nativeSwap",
+ "(L" CAMERA_METADATA_CLASS_NAME ";)V",
+ (void *)CameraMetadata_swap },
+ { "nativeReadFromParcel",
+ "(Landroid/os/Parcel;)V",
+ (void *)CameraMetadata_readFromParcel },
+ { "nativeWriteToParcel",
+ "(Landroid/os/Parcel;)V",
+ (void *)CameraMetadata_writeToParcel },
+};
+
+struct field {
+ const char *class_name;
+ const char *field_name;
+ const char *field_type;
+ jfieldID *jfield;
+};
+
+static int find_fields(JNIEnv *env, field *fields, int count)
+{
+ for (int i = 0; i < count; i++) {
+ field *f = &fields[i];
+ jclass clazz = env->FindClass(f->class_name);
+ if (clazz == NULL) {
+ ALOGE("Can't find %s", f->class_name);
+ return -1;
+ }
+
+ jfieldID field = env->GetFieldID(clazz, f->field_name, f->field_type);
+ if (field == NULL) {
+ ALOGE("Can't find %s.%s", f->class_name, f->field_name);
+ return -1;
+ }
+
+ *(f->jfield) = field;
+ }
+
+ return 0;
+}
+
+// Get all the required offsets in java class and register native functions
+int register_android_hardware_photography_CameraMetadata(JNIEnv *env)
+{
+ // Register native functions
+ return AndroidRuntime::registerNativeMethods(env,
+ CAMERA_METADATA_CLASS_NAME,
+ gCameraMetadataMethods,
+ NELEM(gCameraMetadataMethods));
+}
+
+extern "C" {
+static void CameraMetadata_classInit(JNIEnv *env, jobject thiz) {
+ // XX: Why do this separately instead of doing it in the register function?
+ ALOGV("%s", __FUNCTION__);
+
+ field fields_to_find[] = {
+ { CAMERA_METADATA_CLASS_NAME, "mMetadataPtr", "J", &fields.metadata_ptr },
+ };
+
+ // Do this here instead of in register_native_methods,
+ // since otherwise it will fail to find the fields.
+ if (find_fields(env, fields_to_find, NELEM(fields_to_find)) < 0)
+ return;
+
+ jclass clazz = env->FindClass(CAMERA_METADATA_CLASS_NAME);
+}
+} // extern "C"
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 0827f7c..67c2cfd 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -271,6 +271,17 @@
return (jint) AudioSystem::getPrimaryOutputFrameCount();
}
+static jint
+android_media_AudioSystem_getOutputLatency(JNIEnv *env, jobject clazz, jint stream)
+{
+ uint32_t afLatency;
+ if (AudioSystem::getOutputLatency(&afLatency, static_cast <audio_stream_type_t>(stream))
+ != NO_ERROR) {
+ afLatency = -1;
+ }
+ return (jint) afLatency;
+}
+
// ----------------------------------------------------------------------------
static JNINativeMethod gMethods[] = {
@@ -296,6 +307,7 @@
{"getDevicesForStream", "(I)I", (void *)android_media_AudioSystem_getDevicesForStream},
{"getPrimaryOutputSamplingRate", "()I", (void *)android_media_AudioSystem_getPrimaryOutputSamplingRate},
{"getPrimaryOutputFrameCount", "()I", (void *)android_media_AudioSystem_getPrimaryOutputFrameCount},
+ {"getOutputLatency", "(I)I", (void *)android_media_AudioSystem_getOutputLatency},
};
int register_android_media_AudioSystem(JNIEnv *env)
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index e2d34c9..3ff9dda 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -728,6 +728,19 @@
// ----------------------------------------------------------------------------
+static jint android_media_AudioTrack_get_latency(JNIEnv *env, jobject thiz) {
+ sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
+
+ if (lpTrack == NULL) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Unable to retrieve AudioTrack pointer for latency()");
+ return AUDIOTRACK_ERROR;
+ }
+ return (jint)lpTrack->latency();
+}
+
+
+// ----------------------------------------------------------------------------
static jint android_media_AudioTrack_set_loop(JNIEnv *env, jobject thiz,
jint loopStart, jint loopEnd, jint loopCount) {
sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
@@ -854,6 +867,7 @@
"()I", (void *)android_media_AudioTrack_get_pos_update_period},
{"native_set_position", "(I)I", (void *)android_media_AudioTrack_set_position},
{"native_get_position", "()I", (void *)android_media_AudioTrack_get_position},
+ {"native_get_latency", "()I", (void *)android_media_AudioTrack_get_latency},
{"native_set_loop", "(III)I", (void *)android_media_AudioTrack_set_loop},
{"native_reload_static", "()I", (void *)android_media_AudioTrack_reload},
{"native_get_output_sample_rate",
diff --git a/core/jni/android_os_FileUtils.cpp b/core/jni/android_os_FileUtils.cpp
index a07f5b7..0aaa2b1 100644
--- a/core/jni/android_os_FileUtils.cpp
+++ b/core/jni/android_os_FileUtils.cpp
@@ -55,6 +55,24 @@
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) {
@@ -78,6 +96,7 @@
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/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 61eb31b..33ded03 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -678,6 +678,7 @@
PROC_SPACE_TERM = ' ',
PROC_COMBINE = 0x100,
PROC_PARENS = 0x200,
+ PROC_QUOTES = 0x400,
PROC_OUT_STRING = 0x1000,
PROC_OUT_LONG = 0x2000,
PROC_OUT_FLOAT = 0x4000,
@@ -719,9 +720,15 @@
jboolean res = JNI_TRUE;
for (jsize fi=0; fi<NF; fi++) {
- const jint mode = formatData[fi];
+ jint mode = formatData[fi];
if ((mode&PROC_PARENS) != 0) {
i++;
+ } else if ((mode&PROC_QUOTES != 0)) {
+ if (buffer[i] == '"') {
+ i++;
+ } else {
+ mode &= ~PROC_QUOTES;
+ }
}
const char term = (char)(mode&PROC_TERM_MASK);
const jsize start = i;
@@ -737,6 +744,12 @@
}
end = i;
i++;
+ } else if ((mode&PROC_QUOTES) != 0) {
+ while (buffer[i] != '"' && i < endIndex) {
+ i++;
+ }
+ end = i;
+ i++;
}
while (buffer[i] != term && i < endIndex) {
i++;
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 5b6cff0..87ebbd2 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -432,15 +432,9 @@
}
static void android_view_GLES20Canvas_drawPatch(JNIEnv* env, jobject clazz,
- OpenGLRenderer* renderer, SkBitmap* bitmap, jbyteArray chunks,
+ OpenGLRenderer* renderer, SkBitmap* bitmap, Res_png_9patch* patch,
float left, float top, float right, float bottom, SkPaint* paint) {
- jbyte* storage = env->GetByteArrayElements(chunks, NULL);
- Res_png_9patch* patch = reinterpret_cast<Res_png_9patch*>(storage);
- Res_png_9patch::deserialize(patch);
-
renderer->drawPatch(bitmap, patch, left, top, right, bottom, paint);
-
- env->ReleaseByteArrayElements(chunks, storage, 0);
}
static void android_view_GLES20Canvas_drawColor(JNIEnv* env, jobject clazz,
@@ -1031,7 +1025,7 @@
{ "nDrawBitmapMesh", "(IIII[FI[III)V", (void*) android_view_GLES20Canvas_drawBitmapMesh },
- { "nDrawPatch", "(II[BFFFFI)V", (void*) android_view_GLES20Canvas_drawPatch },
+ { "nDrawPatch", "(IIIFFFFI)V", (void*) android_view_GLES20Canvas_drawPatch },
{ "nDrawColor", "(III)V", (void*) android_view_GLES20Canvas_drawColor },
{ "nDrawRect", "(IFFFFI)V", (void*) android_view_GLES20Canvas_drawRect },
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index ca274e3..7ddb0dc 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -185,6 +185,7 @@
<protected-broadcast android:name="com.android.server.WifiManager.action.DELAYED_DRIVER_STOP" />
<protected-broadcast android:name="android.net.wifi.WIFI_STATE_CHANGED" />
<protected-broadcast android:name="android.net.wifi.WIFI_AP_STATE_CHANGED" />
+ <protected-broadcast android:name="android.net.wifi.WIFI_SCAN_AVAILABLE" />
<protected-broadcast android:name="android.net.wifi.SCAN_RESULTS" />
<protected-broadcast android:name="android.net.wifi.RSSI_CHANGED" />
<protected-broadcast android:name="android.net.wifi.STATE_CHANGE" />
@@ -1221,6 +1222,13 @@
android:label="@string/permlab_removeTasks"
android:description="@string/permdesc_removeTasks" />
+ <!-- @hide Allows an application to create/manage/remove stacks -->
+ <permission android:name="android.permission.MANAGE_ACTIVITY_STACKS"
+ android:permissionGroup="android.permission-group.APP_INFO"
+ android:protectionLevel="signature"
+ android:label="@string/permlab_manageActivityStacks"
+ android:description="@string/permdesc_manageActivityStacks" />
+
<!-- Allows an application to start any activity, regardless of permission
protection or exported state. @hide -->
<permission android:name="android.permission.START_ANY_ACTIVITY"
@@ -2432,6 +2440,29 @@
android:process=":ui">
</activity>
+ <activity android:name="com.android.internal.app.RestrictionsPinSetupActivity"
+ android:theme="@style/Theme.Holo.Dialog.Alert"
+ android:permission="android.permission.MANAGE_USERS"
+ android:excludeFromRecents="true"
+ android:windowSoftInputMode="adjustPan"
+ android:process=":ui">
+ <intent-filter android:priority="100">
+ <action android:name="android.intent.action.RESTRICTIONS_PIN_CREATE" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
+ <activity android:name="com.android.internal.app.RestrictionsPinActivity"
+ android:theme="@style/Theme.Holo.Dialog.Alert"
+ android:excludeFromRecents="true"
+ android:windowSoftInputMode="adjustPan"
+ android:process=":ui">
+ <intent-filter android:priority="100">
+ <action android:name="android.intent.action.RESTRICTIONS_PIN_CHALLENGE" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
<receiver android:name="com.android.server.BootReceiver"
android:primaryUserOnly="true">
<intent-filter>
@@ -2470,9 +2501,9 @@
</receiver>
<receiver android:name="com.android.server.MasterClearReceiver"
- android:permission="android.permission.MASTER_CLEAR"
- android:priority="100" >
- <intent-filter>
+ android:permission="android.permission.MASTER_CLEAR">
+ <intent-filter
+ android:priority="100" >
<!-- For Checkin, Settings, etc.: action=MASTER_CLEAR -->
<action android:name="android.intent.action.MASTER_CLEAR" />
diff --git a/core/res/res/layout/pin_challenge.xml b/core/res/res/layout/pin_challenge.xml
new file mode 100644
index 0000000..2cb14b4
--- /dev/null
+++ b/core/res/res/layout/pin_challenge.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- Layout used as the dialog's content View for EditTextPreference. -->
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginTop="48dp"
+ android:layout_marginBottom="48dp"
+ android:overScrollMode="ifContentScrolls">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="8dip"
+ android:orientation="vertical">
+
+ <TextView android:id="@+id/pin_message"
+ style="?android:attr/textAppearanceMedium"
+ android:layout_marginTop="16dp"
+ android:layout_marginBottom="16dp"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/restr_pin_create_pin"
+ android:textColor="?android:attr/textColorSecondary" />
+
+ <!-- TextView android:id="@+id/pin1_label"
+ style="?android:attr/textAppearanceSmall"
+ android:layout_marginBottom="16dp"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/restr_pin_enter_pin"
+ android:textColor="?android:attr/textColorSecondary" /-->
+
+ <EditText android:id="@+id/pin1_text"
+ style="?android:attr/textAppearanceMedium"
+ android:layout_marginBottom="16dp"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:hint="@string/restr_pin_enter_pin"
+ android:inputType="textPassword"
+ android:textColor="?android:attr/textColorPrimary" />
+
+ <!-- TextView android:id="@+id/pin2_label"
+ style="?android:attr/textAppearanceSmall"
+ android:layout_marginBottom="16dp"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/restr_pin_confirm_pin"
+ android:textColor="?android:attr/textColorSecondary" /-->
+
+ <EditText android:id="@+id/pin2_text"
+ style="?android:attr/textAppearanceMedium"
+ android:layout_marginBottom="16dp"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:hint="@string/restr_pin_confirm_pin"
+ android:inputType="textPassword"
+ android:textColor="?android:attr/textColorPrimary" />
+
+ <TextView android:id="@+id/pin_error_message"
+ style="?android:attr/textAppearanceSmall"
+ android:layout_marginBottom="16dp"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/restr_pin_error_doesnt_match"
+ android:textColor="#FFFF0000" />
+
+ </LinearLayout>
+
+</ScrollView>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 2512fd7..c0c71f9 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Dit laat die houer toe om aan die topvlak-koppelvlak van \'n invoermetode te bind. Dit moet nooit vir normale programme nodig wees nie."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"verbind aan \'n toeganklikheidsdiens"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Dit laat die houer toe om aan die top-koppelvlak van \'n toeganklikheidsdiens te verbind. Behoort nooit vir gewone programme nodig te wees nie."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<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>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Hierdie program werk nie met rekeninge vir beperkte profiele nie"</string>
<string name="app_not_found" msgid="3429141853498927379">"Geen program gevind om hierdie handeling te hanteer nie"</string>
<string name="revoke" msgid="5404479185228271586">"Herroep"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 7cb0ad1..51fb415 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"ያዡ ግቤት ስልቱን ወደ ከፍተኛ-ደረጃ በይነገጽ ለመጠረዝ ይፈቅዳሉ። ለመደበኛ ትግበራዎች በፍፁም አያስፈልግም።"</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"ከአንድ የተደራሽነት አገልግሎት ጋር እሰር"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"ያዢው ወደ የአንድ ተደራሽነት አገልግሎት ከፍተኛ-ደረጃ በይነገጽ እንዲያስር ይፈቅድለታል። ለመደበኛ መተግበሪያዎች መቼም ቢሆን ሊያስፈልግ አይገባም።"</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"ለፅሁፍ አገልግሎት አሰረ"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"ያዡ ግቤት ለከፍተኛ-ደረጃ የፅሁፍ አገልግሎት ገፅታ ለመጠረዝ ይፈቅዳል። ለመደበኛ ትግበራዎች በፍፁም አያስፈልግም።"</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"ለVPN አገልግሎት ተገዛ"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"ይህ መተግበሪያ የተገደቡ መገለጫዎች መለያዎችን አይደግፍም"</string>
<string name="app_not_found" msgid="3429141853498927379">"ይህን እርምጃ የሚያከናውን ምንም መተግበሪያ አልተገኘም"</string>
<string name="revoke" msgid="5404479185228271586">"ሻር"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 40a0320..18fd4c9 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"للسماح للمالك بالالتزام بواجهة المستوى العلوي لأسلوب الإدخال. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"الالتزام بخدمة إمكانية الدخول"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"للسماح للمالك بالالتزام بواجهة المستوى العلوي لخدمة إمكانية الدخول. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"الالتزام بخدمة إدخال النصوص"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"للسماح للمالك بالالتزام بواجهة المستوى العلوي لخدمة إدخال النصوص (على سبيل المثال، SpellCheckerService). لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"الالتزام بخدمة VPN"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"لا يتوافق هذا التطبيق مع حسابات الملفات الشخصية المقيدة"</string>
<string name="app_not_found" msgid="3429141853498927379">"لم يتم العثور على تطبيق يمكنه التعامل مع هذا الإجراء."</string>
<string name="revoke" msgid="5404479185228271586">"إلغاء"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 9ef8bba..9d87725 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Дазваляе ўладальніку прывязвацца да інтэрфейсу верхняга ўзроўню метада ўводу. Не патрабуецца для звычайных прыкладанняў."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"прывязацца да службы доступу"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Дазваляе ўладальніку прывязвацца да інтэрфейсу верхняга ўзроўню службы доступу. Не патрабуецца для звычайных прыкладанняў."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"звязаць з тэкставай службай"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Дазваляе ўладальніку прывязвацца да інтэрфейсу верхняга ўзроўню тэкставай паслугі (напрыклад, SpellCheckerService). Ніколі не патрабуецца для звычайных прыкладанняў."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"звязвацца з VPN сэрвісам"</string>
@@ -1503,4 +1511,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Гэта прыкладанне не падтрымлівае ўліковыя запісы для профiляў з абмежаваннямі"</string>
<string name="app_not_found" msgid="3429141853498927379">"Прыкладанне для гэтага дзеяння не знойдзенае"</string>
<string name="revoke" msgid="5404479185228271586">"Ануляваць"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 5f11579..d1b4737 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Разрешава на притежателя да се обвърже с интерфейса от най-високото ниво на метод на въвеждане. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"обвързване с услуга за достъпност"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Разрешава на притежателя да се обвърже с интерфейса от най-високото ниво на услуга за достъпност. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"обвързване с текстова услуга"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Разрешава на притежателя да се обвърже с интерфейса от най-високото ниво на текстова услуга (напр. SpellCheckerService). Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"обвързване с услуга за VPN"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Това приложение не поддържа профили за потребителски профили с ограничена функционалност"</string>
<string name="app_not_found" msgid="3429141853498927379">"Няма намерено приложение за извършване на това действие"</string>
<string name="revoke" msgid="5404479185228271586">"Отмяна"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index b87296b..40db5d2 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Permet que el titular vinculi a la interfície de nivell superior d\'un mètode d\'entrada. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"vincular amb un servei d\'accessibilitat"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Permet vincular amb la interfície de nivell superior d\'un servei d\'accessibilitat. Les aplicacions normals no haurien de necessitar-ho."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"vincula a un servei de text"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Permet al titular vincular amb la interfície de nivell superior d\'un servei de text (per exemple, SpellCheckerService). Les aplicacions normals mai no ho haurien de necessitar."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"vincula a un servei de VPN"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"L\'aplicació no és compatible amb comptes de perfils restringits"</string>
<string name="app_not_found" msgid="3429141853498927379">"No s\'ha trobat cap aplicació per processar aquesta acció"</string>
<string name="revoke" msgid="5404479185228271586">"Revoca"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index b43deec..33a68bd 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Umožňuje držiteli vázat se na nejvyšší úroveň rozhraní pro zadávání dat. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"navázat se na službu usnadnění přístupu"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Umožňuje držiteli navázat se na nejvyšší úroveň rozhraní služby usnadnění přístupu. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<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>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Tato aplikace nepodporuje účty pro omezené profily"</string>
<string name="app_not_found" msgid="3429141853498927379">"Aplikace potřebná k provedení této akce nebyla nalezena"</string>
<string name="revoke" msgid="5404479185228271586">"Zrušit"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 9806779..aacf74ad 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Tillader, at brugeren kan forpligter sig til en inputmetodes grænseflade på øverste niveau. Bør aldrig være nødvendigt til almindelige apps."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"bind dig til en tilgængelighedstjeneste"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Tillader, at brugeren binder sig til en grænseflade for en tilgængelighedstjeneste på øverste niveau. Bør aldrig være nødvendigt til almindelige apps."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"forpligte sig til en sms-tjeneste"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Tillader, at ejeren kan binde en teksttjenestes grænseflade (f. eks. SpellCheckerService) på øverste niveau. Dette bør aldrig være nødvendigt til normale apps."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"bind til en VPN-tjeneste"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Denne applikation understøtter ikke konti for begrænsede profiler"</string>
<string name="app_not_found" msgid="3429141853498927379">"Der blev ikke fundet nogen applikation, der kan håndtere denne handling"</string>
<string name="revoke" msgid="5404479185228271586">"Tilbagekald"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index d8ded2a..a35a41a 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Ermöglicht dem Halter, sich an die Oberfläche einer Eingabemethode auf oberster Ebene zu binden. Sollte nie für normale Apps benötigt werden."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"An eine Bedienungshilfe binden"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Ermöglicht dem Halter, sich an die Oberfläche einer Bedienungshilfe auf oberster Ebene zu binden. Sollte nie für normale Apps benötigt werden."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"An einen Textdienst binden"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Ermöglicht dem Halter, sich an die Oberfläche eines Textdienstes auf oberster Ebene zu binden, z. B. eines Rechtschreibprüfungsdienstes. Sollte nie für normale Apps benötigt werden."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"An einen VPN-Dienst binden"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Diese App unterstützt keine Konten für eingeschränkte Profile."</string>
<string name="app_not_found" msgid="3429141853498927379">"Für diese Aktion wurde keine App gefunden."</string>
<string name="revoke" msgid="5404479185228271586">"Aufheben"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index db6d161..6592bde 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανωτάτου επιπέδου μιας μεθόδου εισόδου. Δεν απαιτείται για συνήθεις εφαρμογές."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"δέσμευση σε υπηρεσία προσβασιμότητας"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανώτατου επιπέδου μιας υπηρεσίας προσβασιμότητας. Δεν απαιτείται σε κανονικές εφαρμογές."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"δέσμευση σε υπηρεσία ανταλλαγής μηνυμάτων"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Επιτρέπει στον κάτοχο τη σύνδεση με τη διεπαφή ανωτέρου επιπέδου μιας υπηρεσίας ανταλλαγής μηνυμάτων (π.χ. SpellCheckerService). Δεν είναι απαραίτητο για κανονικές εφαρμογές."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"δέσμευση σε υπηρεσία VPN"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Αυτή η εφαρμογή δεν υποστηρίζει λογαριασμούς για περιορισμένα προφίλ"</string>
<string name="app_not_found" msgid="3429141853498927379">"Δεν υπάρχει εφαρμογή για τη διαχείριση αυτής της ενέργειας"</string>
<string name="revoke" msgid="5404479185228271586">"Ανάκληση"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 5a32c1e..8ad86c2 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Allows the holder to bind to the top-level interface of an input method. Should never be needed for normal apps."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"bind to an accessibility service"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Allows the holder to bind to the top-level interface of an accessibility service. Should never be needed for normal apps."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"bind to a text service"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Allows the holder to bind to the top-level interface of a text service (e.g. SpellCheckerService). Should never be needed for normal applications."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"bind to a VPN service"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"This app doesn\'t support accounts for restricted profiles"</string>
<string name="app_not_found" msgid="3429141853498927379">"No application found to handle this action"</string>
<string name="revoke" msgid="5404479185228271586">"Revoke"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 991e9e0..5756a31 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Permite al propietario vincularse a la interfaz de nivel superior de un método de entrada. Las aplicaciones normales no deberían necesitar este permiso."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"vincular a un servicio de accesibilidad"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Permite al propietario vincularse a la interfaz de nivel superior de un servicio de accesibilidad. Las aplicaciones normales no deberían necesitar este permiso."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"vincular a un servicio de texto"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Permite al titular vincularse a la interfaz de nivel superior de un servicio de texto (p. ej., SpellCheckerService). Las aplicaciones normales no deberían necesitar este permiso."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"vincular con un servicio de VPN"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Esta aplicación no admite cuentas de perfiles restringidos."</string>
<string name="app_not_found" msgid="3429141853498927379">"No se encontró una aplicación para manejar esta acción."</string>
<string name="revoke" msgid="5404479185228271586">"Revocar"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 72e5694..2c7ca39 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Permite que se enlace con la interfaz de nivel superior de un método de introducción de texto. Las aplicaciones normales no deberían necesitar este permiso."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"enlazar con un servicio de accesibilidad"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Permite enlazar con la interfaz de nivel superior de un servicio de accesibilidad. Las aplicaciones normales no deberían necesitar este permiso."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"enlazar con un servicio de texto"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Permite enlazar con la interfaz de nivel superior de un servicio de texto (por ejemplo, SpellCheckerService). Las aplicaciones normales no deberían necesitar este permiso."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"enlazar con un servicio VPN"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Esta aplicación no admite cuentas de perfiles restringidos"</string>
<string name="app_not_found" msgid="3429141853498927379">"No se ha encontrado ninguna aplicación que pueda realizar esta acción."</string>
<string name="revoke" msgid="5404479185228271586">"Revocar"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 89851e8..5c31f97 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Lubab omanikul siduda sisestusmeetodi ülataseme liidesega. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"sidumine juurdepääsuteenusega"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Lubab omanikul luua sideme juurdepääsuteenuse ülataseme liidesega. Tavarakenduste puhul ei tohiks seda kunagi vaja minna."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"tekstiteenusega sidumine"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Võimaldab omanikul siduda tekstiteenuse (nt SpellCheckerService) ülataseme liidesega. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"seo VPN-teenusega"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"See rakendus ei toeta piiratud profiilide kontosid"</string>
<string name="app_not_found" msgid="3429141853498927379">"Selle toimingu käsitlemiseks ei leitud ühtegi rakendust"</string>
<string name="revoke" msgid="5404479185228271586">"Tühista"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 65853a1..c62b131 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"به دارنده این دستگاه اجازه میدهد تا به رابط سطح بالای یک روش ورودی متصل شود. این ویژگی هیچگاه برای برنامههای معمولی ضروری نمیباشد."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"اتصال به سرویس دسترسی"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"به دارنده اجازه میدهد که به رابط سطح بالای سرویس دسترسی متصل شود. هرگز برای برنامههای معمولی مورد نیاز نیست."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"اتصال به یک سرویس متنی"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"به دارنده اجازه میدهد خود را به یک رابط سطح بالای خدمات متنی مرتبط کند (برای مثال SpellCheckerService). هرگز برای برنامههای عادی لازم نیست."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"اتصال به یک سرویس VPN"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"این برنامه از حسابهای متعلق به نمایههای محدود پشتیبانی نمیکند"</string>
<string name="app_not_found" msgid="3429141853498927379">"برنامهای برای انجام این عملکرد موجود نیست"</string>
<string name="revoke" msgid="5404479185228271586">"لغو"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index c29ed64..ded0f00 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Antaa sovelluksen sitoutua syötetavan ylätason käyttöliittymään. Ei tavallisten sovellusten käyttöön."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"sitoudu esteettömyyspalveluun"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Antaa sovelluksen sitoutua esteettömyyspalvelun ylemmän tason käyttöliittymään. Ei tavallisten sovelluksien käyttöön."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"tekstipalveluun sitoutuminen"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Antaa sovelluksen sitoutua tekstipalvelun (kuten SpellCheckerServicen) ylätason liittymään. Ei tavallisten sovellusten käyttöön."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"sitoudu VPN-palveluun"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Tämä sovellus ei tue rajoitettujen profiilien tilejä"</string>
<string name="app_not_found" msgid="3429141853498927379">"Tätä toimintoa käsittelevää sovellusta ei löydy"</string>
<string name="revoke" msgid="5404479185228271586">"Peruuta"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 6df108f..c162cf1 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un mode de saisie. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"associer à un service d\'accessibilité"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un service d\'accessibilité. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<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>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Les comptes des profils en accès limité ne sont pas compatibles avec cette application."</string>
<string name="app_not_found" msgid="3429141853498927379">"Aucune application trouvée pour gérer cette action."</string>
<string name="revoke" msgid="5404479185228271586">"Révoquer"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 76c62ea..218cb89 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"धारक को किसी इनपुट विधि के शीर्ष-स्तर इंटरफ़ेस से आबद्ध होने देता है. सामान्य एप्लिकेशन के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"पहुंच-योग्यता सेवा से आबद्ध करें"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"धारक को किसी पहुंच-योग्यता सेवा के शीर्ष-स्तर इंटरफ़ेस से आबद्ध होने देता है. सामान्य एप्लिकेशन के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"किसी पाठ सेवा पर बने रहें"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"धारक को किसी पाठ सेवा (उदा. SpellCheckerService) के शीर्ष-स्तर इंटरफ़ेस पर आबद्ध होने देता है. सामान्य एप्लिकेशन के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"किसी VPN सेवा से आबद्ध करें"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"यह एप्लिकेशन प्रतिबंधित प्रोफ़ाइल के खातों का समर्थन नहीं करता है"</string>
<string name="app_not_found" msgid="3429141853498927379">"इस कार्यवाही को प्रबंधित करने के लिए कोई एप्लिकेशन नहीं मिला"</string>
<string name="revoke" msgid="5404479185228271586">"निरस्त करें"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index e53fb2d..bda36de 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Nositelju omogućuje povezivanje sučelja najviše razine načina unosa. Ne bi smjelo biti potrebno za normalne aplikacije."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"vezivanje uz uslugu dostupnosti"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Nositelju omogućuje vezanje uz sučelje najviše razine usluge dostupnosti. Ne bi smjelo biti potrebno za normalne aplikacije."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"vezanje na tekstualnu uslugu"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Omogućuje korisniku povezivanje s najvišom razinom sučelja tekstualne usluge (npr. SpellCheckerService). Ne bi smjelo biti potrebno za normalne aplikacije."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"vezanje na VPN uslugu"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Aplikacija ne podržava račune za ograničene profile"</string>
<string name="app_not_found" msgid="3429141853498927379">"Nije pronađena aplikacija za upravljanje ovom radnjom"</string>
<string name="revoke" msgid="5404479185228271586">"Opozovi"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index c4c7f0a..9efb6b3 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Lehetővé teszi, hogy a tulajdonos kötelezővé tegye egy beviteli mód legfelső szintű felületét. A normál alkalmazásoknak erre soha nincs szüksége."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"csatlakozás egy kisegítő szolgáltatáshoz"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Lehetővé teszi a használó számára, hogy csatlakozzon egy kisegítő szolgáltatás legfelső szintű kezelőfelületéhez. A normál alkalmazásoknak erre soha nincs szükségük."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"csatlakozás szövegszolgáltatáshoz"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Lehetővé teszi, hogy a tulajdonos egy szöveges szolgáltatás felső szintjéhez kapcsolódjon (pl. SpellCheckerService). A normál alkalmazásoknak erre soha nincs szüksége."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"csatlakozás egy VPN-szolgáltatáshoz"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Ez az alkalmazás nem támogatja a korlátozott profilokkal rendelkező fiókokat"</string>
<string name="app_not_found" msgid="3429141853498927379">"Nincs megfelelő alkalmazás a művelet elvégzésére."</string>
<string name="revoke" msgid="5404479185228271586">"Visszavonás"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index e0e3fca..de45c42 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Mengizinkan pemegang mengikat antarmuka tingkat tinggi dari suatu metode masukan. Tidak pernah diperlukan oleh apl normal."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"mengikat ke layanan aksesibilitas"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Mengizinkan pemegang untuk mengikat antarmuka tingkat tinggi dari suatu layanan. Tidak pernah diperlukan oleh aplikasi normal."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<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>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Aplikasi ini tidak mendukung akun untuk profil yang dibatasi"</string>
<string name="app_not_found" msgid="3429141853498927379">"Tidak ada aplikasi yang ditemukan untuk menangani tindakan ini"</string>
<string name="revoke" msgid="5404479185228271586">"Cabut"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 8079b41..5861679 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Consente l\'associazione di un metodo di inserimento all\'interfaccia principale. Non dovrebbe mai essere necessaria per le normali applicazioni."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"collegamento a un servizio di accessibilità"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Consente al titolare di collegarsi all\'interfaccia di primo livello di un servizio di accessibilità. Non dovrebbe essere mai necessaria per le normali applicazioni."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"associazione a un servizio di testo"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Consente al titolare di collegarsi all\'interfaccia di primo livello di un servizio di testo (ad esempio SpellCheckerService). Non dovrebbe essere mai necessaria per le normali applicazioni."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"associazione a un servizio VPN"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Questa app non supporta account relativi a profili con limitazioni"</string>
<string name="app_not_found" msgid="3429141853498927379">"Nessuna applicazione trovata in grado di gestire questa azione"</string>
<string name="revoke" msgid="5404479185228271586">"Revoca"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 4926a11..37444e9 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"מאפשר למשתמש לבצע איגוד לממשק ברמה עליונה של שיטת קלט. הרשאה זו לעולם אינה נחוצה ליישומים רגילים."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"הכפפה לשירות נגישות"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"מתיר לבעלים להכפיף לממשק ברמה העליונה של שירות זמינות. הרשאה זו אף פעם אינה אמורה להיות נחוצה ליישומים רגילים."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"הכפפה לשירות טקסט"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"מאפשר למשתמש ליצור איגוד לממשק הרמה העליונה של שירות טקסט (למשל, SpellCheckerService). הרשאה זו לעולם אינה נחוצה ליישומים רגילים."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"אגד לשירות VPN"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"האפליקציה הזו לא תומכת בחשבונות עבור פרופילים מוגבלים"</string>
<string name="app_not_found" msgid="3429141853498927379">"לא נמצא יישום שתומך בפעולה זו"</string>
<string name="revoke" msgid="5404479185228271586">"בטל"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 89354bf..5fd3105 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"入力方法のトップレベルインターフェースにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"ユーザー補助サービスにバインド"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"ユーザー補助サービスのトップレベルインターフェースにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"テキストサービスにバインド"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"テキストサービス(SpellCheckerServiceなど)のトップレベルインターフェースにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"VPNサービスにバインド"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"このアプリでは制限付きプロフィールのアカウントはサポートしていません"</string>
<string name="app_not_found" msgid="3429141853498927379">"この操作を行うアプリが見つかりません"</string>
<string name="revoke" msgid="5404479185228271586">"取り消し"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index b9f2459..a15e777 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"권한을 가진 프로그램이 입력 방법에 대한 최상위 인터페이스를 사용하도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"접근성 서비스와 연결"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"권한을 가진 프로그램이 접근성 서비스에 대한 최상위 인터페이스를 사용하도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"텍스트 서비스 연결"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"권한을 가진 프로그램이 텍스트 서비스(예: SpellCheckerService)에 대한 최상위 인터페이스를 사용하도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"VPN 서비스와 연결"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"이 앱은 제한된 프로필의 계정을 지원하지 않습니다."</string>
<string name="app_not_found" msgid="3429141853498927379">"이 작업을 처리하는 애플리케이션을 찾을 수 없습니다."</string>
<string name="revoke" msgid="5404479185228271586">"취소"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index bcd82a9..267171c 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Leidžiama savininką susaistyti su įvesties metodo aukščiausio lygio sąsaja. Įprastoms programoms to neturėtų prireikti."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"susisaistyti su pasiekiamumo paslauga"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Savininkui leidžiama susisaistyti su aukščiausio lygio pasiekiamumo paslaugos sąsaja. Įprastoms programoms to neturėtų prireikti."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"priskirti teksto paslaugą"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Leidžiama savininkui priskirti aukščiausio lygio teksto paslaugos (pvz., „SpellCheckerService“) sąsają. Įprastoms programoms to neturėtų prireikti."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"susaistyti su VPN paslauga"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Ši programa nepalaiko apribotų profilių paskyrų"</string>
<string name="app_not_found" msgid="3429141853498927379">"Nerasta programa šiam veiksmui apdoroti"</string>
<string name="revoke" msgid="5404479185228271586">"Anuliuoti"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 3e35a45..79eb3ec 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Ļauj īpašniekam izveidot saiti ar ievades metodes augstākā līmeņa saskarni. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"saistīt ar pieejamības pakalpojumu"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Ļauj īpašniekam izveidot saiti ar pieejamības pakalpojuma augšējā līmeņa saskarni. Parastajām lietotnēm šī atļauja nav nepieciešama."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"saistīt ar īsziņu pakalpojumu"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Ļauj īpašniekam veikt saistīšanu ar īsziņu pakalpojuma augstākā līmeņa saskarni (piem., SpellCheckerService). Parastajām lietotnēm tas nekad nav nepieciešams."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"saistīt ar VPN pakalpojumu"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Šajā lietotnē netiek atbalstīti ierobežotu profilu konti."</string>
<string name="app_not_found" msgid="3429141853498927379">"Netika atrasta neviena lietojumprogramma, kas var veikt šo darbību."</string>
<string name="revoke" msgid="5404479185228271586">"Atsaukt"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 45ed50f..cd27bba 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi kaedah input itu. Tidak sekali-kali diperlukan untuk apl biasa."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"terikat kepada perkhidmatan yang boleh diakses"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi perkhidmatan yang boleh diakses. Tidak sekali-kali diperlukan untuk apl biasa."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<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>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Apl ini tidak menyokong akaun untuk profil yang disekat"</string>
<string name="app_not_found" msgid="3429141853498927379">"Tidak menemui aplikasi untuk mengendalikan tindakan ini"</string>
<string name="revoke" msgid="5404479185228271586">"Batalkan"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 5aa260d..8bc91eda 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -356,6 +356,14 @@
<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>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"binde seg til en tilgjengelighetstjeneste"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Gir innehaveren tillatelse til å bindes til det øverste nivået av grensesnittet for en tilgjengelighetstjeneste. Skal aldri være nødvendig for vanlige apper."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"binde til en teksttjeneste"</string>
<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>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Denne appen støtter ikke kontoer for begrensede profiler"</string>
<string name="app_not_found" msgid="3429141853498927379">"Finner ingen apper som kan utføre denne handlingen"</string>
<string name="revoke" msgid="5404479185228271586">"Opphev"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 7f902b2..4101c47 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Hiermee kan de houder zich verbinden met de hoofdinterface van een invoermethode. Nooit vereist voor normale apps."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"koppelen aan een toegankelijkheidsservice"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Hiermee wordt de houder toegestaan verbinding te maken met de hoofdinterface van een toegankelijkheidsservice. Nooit vereist voor normale apps."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"koppelen aan een sms-service"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Hiermee kan de gebruiker koppelen met de hoofdinterface van een tekstservice (zoals SpellCheckerService). Dit is niet nodig voor normale apps."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"koppelen aan een VPN-service"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Deze app biedt geen ondersteuning voor accounts voor beperkte profielen"</string>
<string name="app_not_found" msgid="3429141853498927379">"Er is geen app gevonden om deze actie uit te voeren"</string>
<string name="revoke" msgid="5404479185228271586">"Intrekken"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index e0daead..9623ab9 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Pozwala na powiązanie wybranego sposobu wprowadzania tekstu z interfejsem najwyższego poziomu. To uprawnienie nie powinno być nigdy wymagane przez zwykłe aplikacje."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"tworzenie powiązania z usługą ułatwień dostępu"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Zezwala na tworzenie powiązania z interfejsem najwyższego poziomu usługi ułatwień dostępu. Nieprzeznaczone dla zwykłych aplikacji."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"tworzenie powiązania z usługą tekstową"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Pozwala na tworzenie powiązania z interfejsem najwyższego poziomu usługi tekstowej (np. SpellCheckerService). Nie powinno być nigdy potrzebne w przypadku zwykłych aplikacji."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"tworzenie powiązania z usługą VPN"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Ta aplikacja nie obsługuje kont w profilach z ograniczeniami"</string>
<string name="app_not_found" msgid="3429141853498927379">"Nie znaleziono aplikacji do obsługi tej akcji"</string>
<string name="revoke" msgid="5404479185228271586">"Cofnij"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index bbf6f84..b139363 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Permite ao titular vincular-se à interface de nível superior de um método de entrada. Nunca deve ser necessário para aplicações normais."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"vincular a um serviço de acessibilidade"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Permite que o titular vincule a interface de nível superior de um serviço de acessibilidade. Nunca deverá ser necessário para aplicações normais."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"vincular a um serviço de texto"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Permite ao titular ligar-se à interface de nível superior de um serviço de texto (por exemplo SpellCheckerService). Nunca deverá ser necessário para aplicações normais."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"vincular a um serviço VPN"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Esta aplicação não suporta contas de perfis restritos"</string>
<string name="app_not_found" msgid="3429141853498927379">"Não foram encontradas aplicações para executar esta ação"</string>
<string name="revoke" msgid="5404479185228271586">"Revogar"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index c5fe686..457a7a6 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Permite que o proprietário utilize a interface de nível superior de um método de entrada. Nunca deve ser necessário para aplicativos normais."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"usar um serviço de acessibilidade"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Permite que o proprietário use a interface de nível superior de um serviço de acessibilidade. Nunca deve ser necessário para aplicativos comuns."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"sujeitar-se a um serviço de texto"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Permite que o proprietário utilize interface de nível superior de um serviço de texto (por exemplo, SpellCheckerService). Nunca deve ser necessário para aplicativos normais."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"se ligam a um serviço de VPN"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Este aplicativo não suporta contas para perfis restritos"</string>
<string name="app_not_found" msgid="3429141853498927379">"Nenhum aplicativo encontrado para executar a ação"</string>
<string name="revoke" msgid="5404479185228271586">"Revogar"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index 787c92b..b124437 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -553,6 +553,14 @@
<skip />
<!-- no translation found for permdesc_bindAccessibilityService (7034615928609331368) -->
<skip />
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<!-- no translation found for permlab_bindTextService (7358378401915287938) -->
<skip />
<!-- no translation found for permdesc_bindTextService (8151968910973998670) -->
@@ -2443,4 +2451,82 @@
<skip />
<!-- no translation found for revoke (5404479185228271586) -->
<skip />
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index f5d8b9e..708b632 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Permite proprietarului să se conecteze la interfaţa de nivel superior a unei metode de introducere. Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"conectare la un serviciu de accesibilitate"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Permite proprietarului să se conecteze la interfaţa de nivel superior a unui serviciu de accesibilitate. Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<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>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Această aplicație nu acceptă conturi pentru profilurile cu permisiuni limitate"</string>
<string name="app_not_found" msgid="3429141853498927379">"Nicio aplicație pentru gestionarea acestei acțiuni"</string>
<string name="revoke" msgid="5404479185228271586">"Revocați"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 70da18e..66136de 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Приложение сможет подключаться к базовому интерфейсу системы ввода. Это разрешение не используется обычными приложениями."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"Подключение к службе специальных возможностей"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Приложение сможет подключаться к базовому интерфейсу службы специальных возможностей. Это разрешение не используется обычными приложениями."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"Подключение к службе текстовых сообщений"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Позволяет подключаться к базовому интерфейсу службы текстовых сообщений (например, SpellCheckerService). Это разрешение не используется обычными приложениями."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"Подключение к VPN-службе"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Это приложение не поддерживается в аккаунтах для профилей с ограниченным доступом"</string>
<string name="app_not_found" msgid="3429141853498927379">"Невозможно обработать это действие"</string>
<string name="revoke" msgid="5404479185228271586">"Отменить"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index fde5bbb..aa24702 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania metódy vstupu. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"viazať na službu zjednodušeného ovládania"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania služby zjednodušeného ovládania. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"väzba na textovú službu"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania textovej služby (napr. SpellCheckerService). Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"Zaviazať k službe VPN"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Táto aplikácia nepodporuje účty pre profily s obmedzením"</string>
<string name="app_not_found" msgid="3429141853498927379">"Aplikácia potrebná na spracovanie tejto akcie sa nenašla"</string>
<string name="revoke" msgid="5404479185228271586">"Odvolať"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 6166e2f..298d0cc 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Lastniku omogoča, da se poveže z vmesnikom načina vnosa najvišje ravni. Tega nikoli ni treba uporabiti za navadne programe."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"povezovanje s storitvijo za ljudi s posebnimi potrebami"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Lastniku omogoča povezovanje z vmesnikom najvišje ravni storitve za ljudi s posebnimi potrebami. Tega nikoli ni treba uporabiti za navadne aplikacije."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"poveži z besedilno storitvijo"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Dovoljuje, da se lastnik poveže z vmesnikom besedilne storitve najvišje ravni (npr. SpellCheckerService). Tega nikoli ni treba uporabiti za navadne programe."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"povezava s storitvijo navideznega zasebnega omrežja"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Ta aplikacija ne podpira računov za profile z omejitvami"</string>
<string name="app_not_found" msgid="3429141853498927379">"Najdena ni bila nobena aplikacija za izvedbo tega dejanja"</string>
<string name="revoke" msgid="5404479185228271586">"Prekliči"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 616787a..a762056 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Омогућава да се власник обавеже на интерфејс методе уноса највишег нивоа. Уобичајене апликације никада не би требало да је користе."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"повезивање са услугом приступачности"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Дозвољава власнику да се повеже са интерфејсом услуге приступачности највишег нивоа. Уобичајене апликације никада не би требало да је користе."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"обавезивање на текстуалну услугу"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Омогућава власнику да се обавеже на интерфејс текстуалне услуге највишег нивоа (нпр. SpellCheckerService). Обичне апликације никада не би требало да је користе."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"везивање за VPN услугу"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Ова апликација не подржава налоге за ограничене профиле"</string>
<string name="app_not_found" msgid="3429141853498927379">"Није пронађена ниједна апликација која би могла да обави ову радњу"</string>
<string name="revoke" msgid="5404479185228271586">"Опозови"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 89426d1..9e4b548 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en inmatningsmetod. Ska inte behövas för vanliga appar."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"bind till en tillgänglighetstjänst"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en tillgänglighetstjänst. Ska inte behövas för vanliga appar."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"bind till en texttjänst"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Tillåter innehavaren att binda mot den högsta gränssnittsnivån i en texttjänst (t.ex. SpellCheckerService). Bör aldrig behövas för normala appar."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"bind till en VPN-tjänst"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Den här appen stöder inte konton för begränsade profiler"</string>
<string name="app_not_found" msgid="3429141853498927379">"Ingen app som kan hantera åtgärden hittades"</string>
<string name="revoke" msgid="5404479185228271586">"Återkalla"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 7f5144f..2e21886 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Inaruhusu mmiliki kushurutisha kwenye kusano ya kiwango cha juu ya mbinu ya ingizo. Haipaswi kuhitajika kwa programu za kawaida."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"funga kwa huduma ya ufikiaji"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Inamuruhusu mmiliki kufunga kipengee kinachojitokeza katika nyanja mbalimbali za kiwango cha juu cha huduma ya afikiaji. Hapaswi kuhitajika kwa programu za kawaida."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<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>
@@ -795,8 +803,8 @@
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Hakuna SIM kadi katika kompyuta ndogo."</string>
<string name="lockscreen_missing_sim_message" product="default" msgid="2186920585695169078">"Hakuna SIM kadi kwenye simu."</string>
<string name="lockscreen_missing_sim_instructions" msgid="5372787138023272615">"Ingiza SIM kadi."</string>
- <string name="lockscreen_missing_sim_instructions_long" msgid="3526573099019319472">"Kadi ya SIM haiko au haisomeki. Tafadhali ingiza SIM kadi."</string>
- <string name="lockscreen_permanent_disabled_sim_message_short" msgid="5096149665138916184">"Kadi ya SIM isiyotumika."</string>
+ <string name="lockscreen_missing_sim_instructions_long" msgid="3526573099019319472">"SIM kadi haipatikani au haisomeki. Tafadhali ingiza SIM kadi."</string>
+ <string name="lockscreen_permanent_disabled_sim_message_short" msgid="5096149665138916184">"SIM kadi isiyotumika."</string>
<string name="lockscreen_permanent_disabled_sim_instructions" msgid="910904643433151371">"SIM kadi yako imelemezwa kabisa."\n" Wasiliana na mtoa huduma wako wa pasi waya ili upate SIM kadi nyingine."</string>
<string name="lockscreen_transport_prev_description" msgid="201594905152746886">"Kitufe cha awali cha wimbo"</string>
<string name="lockscreen_transport_next_description" msgid="6089297650481292363">"Kitufe cha wimbo unaofuata"</string>
@@ -805,9 +813,9 @@
<string name="lockscreen_transport_stop_description" msgid="4562318378766987601">"Kitufe cha kusitisha"</string>
<string name="emergency_calls_only" msgid="6733978304386365407">"Simu za dharura pekee"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"Mtandao umefungwa"</string>
- <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"Kadi ya SIM imefungwa na PUK."</string>
+ <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM kadi imefungwa kwa PUK."</string>
<string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"Angalia Mwongozo wa Mtumiaji au wasiliana na Huduma ya Wateja."</string>
- <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"Kadi ya SIM imefungwa."</string>
+ <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"SIM kadi imefungwa."</string>
<string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"Inafungua SIM kadi..."</string>
<string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"Umekosea katika kuchora ruwaza yako ya kufungua mara <xliff:g id="NUMBER_0">%d</xliff:g>. "\n\n" Jaribu tena kwa sekunde <xliff:g id="NUMBER_1">%d</xliff:g>."</string>
<string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"Umekosea mara <xliff:g id="NUMBER_0">%d</xliff:g> katika kuingiza nenosiri lako. "\n\n" Jaribu tena katika sekunde <xliff:g id="NUMBER_1">%d</xliff:g>."</string>
@@ -1172,10 +1180,10 @@
<string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"Unaweza kubadilisha hii baadaye kwenye Mipangilio > Programu"</string>
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"Ruhusu Kila mara"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"Usiruhusu Kamwe"</string>
- <string name="sim_removed_title" msgid="6227712319223226185">"Kadi ya SIM imeondolewa"</string>
+ <string name="sim_removed_title" msgid="6227712319223226185">"SIM kadi imeondolewa"</string>
<string name="sim_removed_message" msgid="2333164559970958645">"mtandao wa simu hutapatika hadi uanzishe upya na SIM kadi halali iliyoingizwa."</string>
<string name="sim_done_button" msgid="827949989369963775">"Kwisha"</string>
- <string name="sim_added_title" msgid="3719670512889674693">"Kadi ya SIM imeongezwa"</string>
+ <string name="sim_added_title" msgid="3719670512889674693">"SIM kadi imeongezwa"</string>
<string name="sim_added_message" msgid="6599945301141050216">"Anzisha upya kifaa chako ili kufikia mtandao wa simu."</string>
<string name="sim_restart_button" msgid="4722407842815232347">"Anza upya"</string>
<string name="time_picker_dialog_title" msgid="8349362623068819295">"Weka muda"</string>
@@ -1467,7 +1475,7 @@
<string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM sasa imelemazwa. Ingiza msimbo wa PUK ili kuendelea. Wasiliana na mtoa huduma kwa maelezo."</string>
<string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Ingiza msimbo wa PIN unaopendelewa"</string>
<string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Thibitisha msimbo wa PIN unaopendelewa"</string>
- <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Inafungua kadi ya SIM..."</string>
+ <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Inafungua SIM kadi..."</string>
<string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Msimbo wa PIN usio sahihi."</string>
<string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Charaza PIN iliyo na tarakimu kati ya 4 na 8."</string>
<string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"Msimbo wa PUK unafaa kuwa na nambari 8 au zaidi."</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Programu hii haiwezi kutumiwa na akaunti za wasifu zilizowekewa vikwazo"</string>
<string name="app_not_found" msgid="3429141853498927379">"Hakuna programu iliyopatikana ili kushughulikia kitendo hiki"</string>
<string name="revoke" msgid="5404479185228271586">"Batilisha"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 8d730a5..60c22ea 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"อนุญาตให้ผู้ใช้เชื่อมโยงกับส่วนติดต่อผู้ใช้ระดับสูงสุดของวิธีการป้อนข้อมูล ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"เชื่อมโยงกับบริการการเข้าถึง"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"อนุญาตให้เจ้าของเชื่อมโยงกับส่วนติดต่อระดับบนสุดของบริการการเข้าถึง ซึ่งแอปพลิเคชันทั่วไปไม่จำเป็นต้องใช้"</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"เชื่อมโยงกับบริการข้อความ"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"อนุญาตให้ผู้ใช้เชื่อมโยงกับส่วนติดต่อผู้ใช้ระดับสูงสุดของบริการข้อความ (เช่น บริการเครื่องตรวจตัวสะกด) ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"เชื่อมโยงกับบริการ VPN"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"แอปนี้ไม่สนับสนุนบัญชีที่โปรไฟล์ถูกจำกัด"</string>
<string name="app_not_found" msgid="3429141853498927379">"ไม่พบแอปพลิเคชันสำหรับการทำงานนี้"</string>
<string name="revoke" msgid="5404479185228271586">"เพิกถอน"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index ac771173..e1dfbad 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Pinapayagan ang may-hawak na sumailalim sa nangungunang interface ng pamamaraan ng pag-input. Hindi kailanman dapat na kailanganin para sa normal na apps."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"sumailalim sa isang serbisyo sa accessibility"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Binibigyang-daan ang may-ari na sumailalim sa nasa nangungunang antas na interface ng isang serbisyo sa accessibility. Hindi dapat kailanman kailanganin para sa normal na apps."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"sumailalim sa serbisyo ng teksto"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Pinapayagan ang may-hawak na sumailalim sa nangungunang antas na interface (hal. SpellCheckerService). Hindi kailanman dapat na kailanganin para sa normal na apps."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"sumailalim sa isang serbisyo ng VPN"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Hindi sinusuportahan ng app na ito ang mga account para sa mga pinaghihigpitang profile"</string>
<string name="app_not_found" msgid="3429141853498927379">"Walang nakitang application na mangangasiwa sa pagkilos na ito"</string>
<string name="revoke" msgid="5404479185228271586">"Bawiin"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 0e7710d..419d1ca 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Cihazın sahibine, bir giriş yönteminin en üst düzey arayüzüne bağlanma izni verir. Normal uygulamalarda hiçbir zaman gerek duyulmaz."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"erişilebilirlik hizmetine bağlan"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"İzin sahibine bir erişilebilirlik hizmetinin en üst düzey arayüzüne bağlanma izni verir. Normal uygulamalarda hiçbir zaman gerek duyulmaz."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"kısa mesaj hizmetine bağla"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Cihazın sahibine, bir metin hizmetinin (ör. SpellCheckerService) en üst düzey arayüzüne bağlanma izni verir. Normal uygulamalarda hiçbir zaman gerekmez."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"VPN hizmetine bağlan"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Bu uygulama, kısıtlanmış profillerin hesaplarını desteklemez"</string>
<string name="app_not_found" msgid="3429141853498927379">"Bu eylemi gerçekleştirecek bir uygulama bulunamadı"</string>
<string name="revoke" msgid="5404479185228271586">"İptal et"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index d3e8b2e..047e288 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Дозволяє власнику прив’язуватися до інтерфейсу верхнього рівня методу введення. Ніколи не застосовується для звичайних програм."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"прив’язуватися до служби доступності"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Дозволяє власникові прив’язуватися до інтерфейсу верхнього рівня служби доступності. Ніколи не застосовується для звичайних програм."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"прив’язати до текстової служби"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Дозволяє власникові прив’язуватися до інтерфейсу верхнього рівня текстової служби (напр. SpellCheckerService). Ніколи не застосовується для звичайних програм."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"прив’язуватися до служби VPN"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Ця програма не підтримує облікові записи для обмежених профілів"</string>
<string name="app_not_found" msgid="3429141853498927379">"Не знайдено програму для обробки цієї дії"</string>
<string name="revoke" msgid="5404479185228271586">"Анулювати"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 871a244e..4f1f931 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Cho phép chủ sở hữu liên kết với giao diện cấp cao nhất của phương thức nhập. Không cần thiết cho các ứng dụng thông thường."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"liên kết với dịch vụ truy cập"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"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ụ truy cập. Không cần thiết cho các ứng dụng thông thường."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"liên kết với dịch vụ văn bản"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"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ụ văn bản (ví dụ: SpellCheckerService). Không cần thiết cho các ứng dụng thông thường."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"liên kết với dịch vụ VPN"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Ứng dụng này không hỗ trợ tài khoản đối với các tiểu sử bị hạn chế"</string>
<string name="app_not_found" msgid="3429141853498927379">"Không tìm thấy ứng dụng nào để xử lý tác vụ này"</string>
<string name="revoke" msgid="5404479185228271586">"Thu hồi"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index c04017a..685e43f 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"允许用户绑定至输入法的顶级接口。普通应用绝不需要此权限。"</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"绑定至辅助服务"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"允许应用绑定至辅助服务的顶级接口。普通应用绝不需要此权限。"</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"绑定至文字服务"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"允许用户绑定至文字服务(如 SpellCheckerService)的顶级接口。普通应用绝不需要此权限。"</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"绑定到 VPN 服务"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"此应用不支持受限个人资料的帐户"</string>
<string name="app_not_found" msgid="3429141853498927379">"找不到可处理此操作的应用"</string>
<string name="revoke" msgid="5404479185228271586">"撤消"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index a7df755..50af84b 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"允許應用程式繫結至輸入法的頂層介面 (一般應用程式不需使用)。"</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"繫結至協助工具服務"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"允許應用程式繫結至協助工具服務的頂層介面 (一般應用程式不需使用)。"</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"繫結至文字服務"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"允許應用程式繫結至文字服務 (例如 SpellCheckerService) 的頂層介面 (一般應用程式不需使用)。"</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"繫結至 VPN 服務"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"這個應用程式不支援設有限制的個人資料所屬帳戶"</string>
<string name="app_not_found" msgid="3429141853498927379">"找不到支援此操作的應用程式"</string>
<string name="revoke" msgid="5404479185228271586">"撤銷"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 6d3e3ad..127743e 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -356,6 +356,14 @@
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"Ivumela isimeli ukuhlanganisa uxhumano nomsebenzisi wezinga eliphezulu lendlela yokufaka. Ayisoze yadingeka kwizinhlelo ezivamile."</string>
<string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"hlanganisa kusevisi yokufinyeleleka"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"Ivumela isibambi ukuhlanganisa uxhumo nomsebenzisi kwezinga eliphezulu lesevisi yesinqunjwana. Akusoze kwadingekela izinhlelo zokusebenza ezivamile."</string>
+ <!-- no translation found for permlab_bindPrintService (8462815179572748761) -->
+ <skip />
+ <!-- no translation found for permdesc_bindPrintService (7960067623209111135) -->
+ <skip />
+ <!-- no translation found for permlab_accessAllPrintJobs (1120792468465711159) -->
+ <skip />
+ <!-- no translation found for permdesc_accessAllPrintJobs (2978185311041864762) -->
+ <skip />
<string name="permlab_bindTextService" msgid="7358378401915287938">"bophezela kunsizakalo yombhalo"</string>
<string name="permdesc_bindTextService" msgid="8151968910973998670">"Ivumela umbambi ukuhlanganisa uxhumano nomsebenzisi kwezinga eliphezulu lwesixhumi esibonakalayo sensizakalo yombhalo(isb. InsizakaloYokuhlolaUkubhala). Akusoze kwadingeka kwezinhlelo zokusebenza ezivamile."</string>
<string name="permlab_bindVpnService" msgid="4708596021161473255">"hlanganisa kwinsizakalo ye-VPN"</string>
@@ -1502,4 +1510,82 @@
<string name="app_no_restricted_accounts" msgid="5739463249673727736">"Lolu hlelo lokusebenza alusekeli ama-akhawunti wamaphrofayela akhawulelwe"</string>
<string name="app_not_found" msgid="3429141853498927379">"Alukho uhlelo lokusebenza olutholakele lokuphatha lesi senzo"</string>
<string name="revoke" msgid="5404479185228271586">"Chitha"</string>
+ <!-- no translation found for mediaSize_iso_a0 (7875427489420821793) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a1 (3760734499050875356) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a2 (5973266378020144382) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a3 (1373407105687300884) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a4 (6689772807982597254) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a5 (5353549652015741040) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a6 (8585038048674911907) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a7 (6641836716963839119) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a8 (7571139437465693355) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a9 (1378455891957115079) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_a10 (2480747457429475344) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b0 (3965935097661108039) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b1 (2505753285010115437) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b2 (8763874709859458453) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b3 (4210506688191764076) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b4 (5749404165888526034) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b5 (7640627414621904733) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b6 (7342988864712748544) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b7 (5069844065235382429) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b8 (7316818922278779774) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b9 (5414727094026532341) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_b10 (5251253731832048185) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c0 (4003138342671964217) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c1 (1935188063393553008) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c2 (3197307969712069904) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c3 (4335826087321913508) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c4 (3745639598281015005) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c5 (8269457765822791013) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c6 (566666105260346930) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c7 (8678413180782608498) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c8 (8392376206627041730) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c9 (9191613372324845405) -->
+ <skip />
+ <!-- no translation found for mediaSize_iso_c10 (7327709699184920822) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_letter (4191805615829472953) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_gvrnmt_letter (7853382192649405507) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_legal (6697982988283823150) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_junior_legal (3727743969902758948) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_ledger (281871464896601236) -->
+ <skip />
+ <!-- no translation found for mediaSize_na_tabloid (5775966416333578127) -->
+ <skip />
</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 4bd1c9b..d844076 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -123,6 +123,17 @@
of them. This should not normally be modified. -->
<bool name="config_closeDialogWhenTouchOutside">true</bool>
+ <!-- Device configuration indicating this is a device with limited RAM, so heavier-weight
+ features should be turned off. -->
+ <bool name="config_lowRamDevice">false</bool>
+
+ <!-- Device configuration indicating whether we should avoid using accelerated graphics
+ in certain places to reduce RAM footprint. This is ignored if config_lowRamDevice
+ is true (in that case this is assumed true as well). It can allow you to tune down
+ your device's memory use without going to the point of causing applications to turn
+ off features. -->
+ <bool name="config_avoidGfxAccel">false</bool>
+
<!-- The duration (in milliseconds) that the radio will scan for a signal
when there's no network connection. If the scan doesn't timeout, use zero -->
<integer name="config_radioScanningTimeout">0</integer>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 1938b88..75ff8b2 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -712,6 +712,15 @@
tasks and kill their apps. Malicious apps may disrupt
the behavior of other apps.</string>
+ <!-- [CHAR LIMIT=NONE] Title of an application permission, allowing an application to create,
+ change, remove activity stacks. -->
+ <string name="permlab_manageActivityStacks">manage activity stacks</string>
+ <!-- [CHAR LIMIT=NONE] Description of an application permission, allowing an application to create,
+ change, remove activity stacks. -->
+ <string name="permdesc_manageActivityStacks">Allows the app to add, remove, and
+ modify the activity stacks in which other apps run. Malicious apps may disrupt
+ the behavior of other apps.</string>
+
<!-- Title of an application permission, allowing an application to start any activity, regardless of permission protection or exported state. -->
<string name="permlab_startAnyActivity">start any activity</string>
<!-- Description of an application permission, allowing an application to start any activity, regardless of permission protection or exported state. -->
@@ -4018,7 +4027,7 @@
<!-- Message shown when user enters wrong PIN -->
<string name="kg_wrong_pin">Wrong PIN</string>
<!-- Countdown message shown after too many failed unlock attempts -->
- <string name="kg_too_many_failed_attempts_countdown">Try again in <xliff:g id="number">%d</xliff:g> seconds.</string>
+ <string name="kg_too_many_failed_attempts_countdown">Try again in <xliff:g id="number">%1$d</xliff:g> seconds.</string>
<!-- Instructions for using the pattern unlock screen -->
<string name="kg_pattern_instructions">Draw your pattern</string>
<!-- Instructions for using the SIM PIN unlock screen -->
@@ -4227,4 +4236,20 @@
<!-- North America Tabloid media size: 11" × 17" -->
<string name="mediaSize_na_tabloid">Tabloid</string>
+ <!-- PIN creation dialog message [CHAR LIMIT=none] -->
+ <string name="restr_pin_create_pin">Create a PIN for modifying restrictions</string>
+ <!-- PIN entry dialog label for PIN [CHAR LIMIT=none] -->
+ <string name="restr_pin_enter_pin">Enter PIN</string>
+ <!-- PIN entry dialog label for PIN confirmation [CHAR LIMIT=none] -->
+ <string name="restr_pin_confirm_pin">Confirm PIN</string>
+ <!-- PIN entry dialog error when PINs are not the same [CHAR LIMIT=none] -->
+ <string name="restr_pin_error_doesnt_match">PINs don\'t match. Try again.</string>
+ <!-- PIN entry dialog error when PIN is too short [CHAR LIMIT=none] -->
+ <string name="restr_pin_error_too_short">PIN is too short. Must be at least 4 digits.</string>
+ <!-- PIN entry dialog countdown message for next chance to enter the PIN [CHAR LIMIT=none] -->
+ <!-- Phrase describing a time duration using seconds [CHAR LIMIT=16] -->
+ <plurals name="restr_pin_countdown">
+ <item quantity="one">Incorrect PIN. Try again in 1 second.</item>
+ <item quantity="other">Incorrect PIN. Try again in <xliff:g id="count">%d</xliff:g> seconds.</item>
+ </plurals>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 7f39364..38aa2a0 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -213,6 +213,10 @@
<java-symbol type="id" name="sms_short_code_remember_undo_instruction" />
<java-symbol type="id" name="breadcrumb_section" />
<java-symbol type="id" name="action_bar_spinner" />
+ <java-symbol type="id" name="pin_message" />
+ <java-symbol type="id" name="pin1_text" />
+ <java-symbol type="id" name="pin2_text" />
+ <java-symbol type="id" name="pin_error_message" />
<java-symbol type="attr" name="actionModeShareDrawable" />
<java-symbol type="attr" name="alertDialogCenterButtons" />
@@ -239,6 +243,7 @@
<java-symbol type="bool" name="action_bar_embed_tabs" />
<java-symbol type="bool" name="action_bar_embed_tabs_pre_jb" />
<java-symbol type="bool" name="action_bar_expanded_action_views_exclusive" />
+ <java-symbol type="bool" name="config_avoidGfxAccel" />
<java-symbol type="bool" name="config_allowActionMenuItemTextWithIcon" />
<java-symbol type="bool" name="config_bluetooth_address_validation" />
<java-symbol type="bool" name="config_bluetooth_sco_off_call" />
@@ -246,6 +251,7 @@
<java-symbol type="bool" name="config_duplicate_port_omadm_wappush" />
<java-symbol type="bool" name="config_enable_emergency_call_while_sim_locked" />
<java-symbol type="bool" name="config_enable_puk_unlock_screen" />
+ <java-symbol type="bool" name="config_lowRamDevice" />
<java-symbol type="bool" name="config_mms_content_disposition_support" />
<java-symbol type="bool" name="config_showMenuShortcutsWhenKeyboardPresent" />
<java-symbol type="bool" name="config_sip_wifi_only" />
@@ -898,6 +904,7 @@
<java-symbol type="string" name="mediaSize_na_junior_legal" />
<java-symbol type="string" name="mediaSize_na_ledger" />
<java-symbol type="string" name="mediaSize_na_tabloid" />
+ <java-symbol type="string" name="restr_pin_enter_pin" />
<java-symbol type="plurals" name="abbrev_in_num_days" />
<java-symbol type="plurals" name="abbrev_in_num_hours" />
@@ -920,6 +927,7 @@
<java-symbol type="plurals" name="num_hours_ago" />
<java-symbol type="plurals" name="num_minutes_ago" />
<java-symbol type="plurals" name="num_seconds_ago" />
+ <java-symbol type="plurals" name="restr_pin_countdown" />
<java-symbol type="array" name="carrier_properties" />
<java-symbol type="array" name="config_data_usage_network_types" />
@@ -1145,6 +1153,7 @@
<java-symbol type="layout" name="sms_short_code_confirmation_dialog" />
<java-symbol type="layout" name="action_bar_up_container" />
<java-symbol type="layout" name="app_not_authorized" />
+ <java-symbol type="layout" name="pin_challenge" />
<java-symbol type="anim" name="slide_in_child_bottom" />
<java-symbol type="anim" name="slide_in_right" />
diff --git a/docs/html/training/location/activity-recognition.jd b/docs/html/training/location/activity-recognition.jd
index 79804db..47ba5f8 100644
--- a/docs/html/training/location/activity-recognition.jd
+++ b/docs/html/training/location/activity-recognition.jd
@@ -171,11 +171,9 @@
return true;
// Google Play services was not available for some reason
} else {
- // Get the error code
- int errorCode = connectionResult.getErrorCode();
// Get the error dialog from Google Play services
Dialog errorDialog = GooglePlayServicesUtil.getErrorDialog(
- errorCode,
+ resultCode,
this,
CONNECTION_FAILURE_RESOLUTION_REQUEST);
@@ -649,7 +647,7 @@
public class MainActivity extends FragmentActivity implements
ConnectionCallbacks, OnConnectionFailedListener {
...
- public enum REQUEST_TYPE = {START, STOP}
+ public enum REQUEST_TYPE {START, STOP}
private REQUEST_TYPE mRequestType;
...
}
@@ -664,7 +662,7 @@
...
public void startUpdates() {
// Set the request type to START
- mRequestType = START;
+ mRequestType = REQUEST_TYPE.START;
/*
* Test for Google Play services after setting the request type.
* If Google Play services isn't present, the proper request type
@@ -686,9 +684,16 @@
*/
mActivityRecognitionClient.requestActivityUpdates(
DETECTION_INTERVAL_MILLISECONDS,
- mActivityRecognitionPendingIntent());
+ mActivityRecognitionPendingIntent);
break;
- ...
+ ...
+ /*
+ * An enum was added to the definition of REQUEST_TYPE,
+ * but it doesn't match a known case. Throw an exception.
+ */
+ default :
+ throw new Exception("Unknown request type in onConnected().");
+ break;
}
...
}
@@ -712,7 +717,7 @@
*/
public void stopUpdates() {
// Set the request type to STOP
- mRequestType = STOP;
+ mRequestType = REQUEST_TYPE.STOP;
/*
* Test for Google Play services after setting the request type.
* If Google Play services isn't present, the request can be
@@ -760,7 +765,7 @@
mActivityRecognitionClient.removeActivityUpdates(
mActivityRecognitionPendingIntent);
break;
-
+ ...
}
...
}
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index bd871c4..14ac901 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -61,6 +61,7 @@
protected int mScreenDensity = Bitmap.DENSITY_NONE;
// Used by native code
+ @SuppressWarnings("UnusedDeclaration")
private int mSurfaceFormat;
/**
@@ -381,8 +382,8 @@
*/
public int saveLayer(RectF bounds, Paint paint, int saveFlags) {
return native_saveLayer(mNativeCanvas, bounds,
- paint != null ? paint.mNativePaint : 0,
- saveFlags);
+ paint != null ? paint.mNativePaint : 0,
+ saveFlags);
}
/**
@@ -391,8 +392,8 @@
public int saveLayer(float left, float top, float right, float bottom, Paint paint,
int saveFlags) {
return native_saveLayer(mNativeCanvas, left, top, right, bottom,
- paint != null ? paint.mNativePaint : 0,
- saveFlags);
+ paint != null ? paint.mNativePaint : 0,
+ saveFlags);
}
/**
@@ -1039,7 +1040,7 @@
throw new NullPointerException();
}
native_drawArc(mNativeCanvas, oval, startAngle, sweepAngle,
- useCenter, paint.mNativePaint);
+ useCenter, paint.mNativePaint);
}
/**
@@ -1079,8 +1080,6 @@
/**
* Draws the specified bitmap as an N-patch (most often, a 9-patches.)
*
- * Note: Only supported by hardware accelerated canvas at the moment.
- *
* @param patch The ninepatch object to render
* @param dst The destination rectangle.
* @param paint The paint to draw the bitmap with. may be null
@@ -1088,13 +1087,12 @@
* @hide
*/
public void drawPatch(NinePatch patch, Rect dst, Paint paint) {
+ patch.drawSoftware(this, dst, paint);
}
/**
* Draws the specified bitmap as an N-patch (most often, a 9-patches.)
*
- * Note: Only supported by hardware accelerated canvas at the moment.
- *
* @param patch The ninepatch object to render
* @param dst The destination rectangle.
* @param paint The paint to draw the bitmap with. may be null
@@ -1102,6 +1100,7 @@
* @hide
*/
public void drawPatch(NinePatch patch, RectF dst, Paint paint) {
+ patch.drawSoftware(this, dst, paint);
}
/**
@@ -1188,7 +1187,7 @@
}
throwIfRecycled(bitmap);
native_drawBitmap(mNativeCanvas, bitmap.ni(), src, dst,
- paint != null ? paint.mNativePaint : 0, mScreenDensity, bitmap.mDensity);
+ paint != null ? paint.mNativePaint : 0, mScreenDensity, bitmap.mDensity);
}
/**
@@ -1309,8 +1308,8 @@
checkRange(colors.length, colorOffset, count);
}
nativeDrawBitmapMesh(mNativeCanvas, bitmap.ni(), meshWidth, meshHeight,
- verts, vertOffset, colors, colorOffset,
- paint != null ? paint.mNativePaint : 0);
+ verts, vertOffset, colors, colorOffset,
+ paint != null ? paint.mNativePaint : 0);
}
public enum VertexMode {
@@ -1372,8 +1371,8 @@
checkRange(indices.length, indexOffset, indexCount);
}
nativeDrawVertices(mNativeCanvas, mode.nativeInt, vertexCount, verts,
- vertOffset, texs, texOffset, colors, colorOffset,
- indices, indexOffset, indexCount, paint.mNativePaint);
+ vertOffset, texs, texOffset, colors, colorOffset,
+ indices, indexOffset, indexCount, paint.mNativePaint);
}
/**
@@ -1444,10 +1443,10 @@
if (text instanceof String || text instanceof SpannedString ||
text instanceof SpannableString) {
native_drawText(mNativeCanvas, text.toString(), start, end, x, y,
- paint.mBidiFlags, paint.mNativePaint);
+ paint.mBidiFlags, paint.mNativePaint);
} else if (text instanceof GraphicsOperations) {
((GraphicsOperations) text).drawText(this, start, end, x, y,
- paint);
+ paint);
} else {
char[] buf = TemporaryBuffer.obtain(end - start);
TextUtils.getChars(text, start, end, buf, 0);
@@ -1568,7 +1567,7 @@
throw new IndexOutOfBoundsException();
}
native_drawPosText(mNativeCanvas, text, index, count, pos,
- paint.mNativePaint);
+ paint.mNativePaint);
}
/**
@@ -1609,8 +1608,8 @@
throw new ArrayIndexOutOfBoundsException();
}
native_drawTextOnPath(mNativeCanvas, text, index, count,
- path.ni(), hOffset, vOffset,
- paint.mBidiFlags, paint.mNativePaint);
+ path.ni(), hOffset, vOffset,
+ paint.mBidiFlags, paint.mNativePaint);
}
/**
diff --git a/graphics/java/android/graphics/NinePatch.java b/graphics/java/android/graphics/NinePatch.java
index 932e474..528d9de 100644
--- a/graphics/java/android/graphics/NinePatch.java
+++ b/graphics/java/android/graphics/NinePatch.java
@@ -18,11 +18,8 @@
/**
- * The NinePatch class permits drawing a bitmap in nine sections.
- * The four corners are unscaled; the four edges are scaled in one axis,
- * and the middle is scaled in both axes. Normally, the middle is
- * transparent so that the patch can provide a selection about a rectangle.
- * Essentially, it allows the creation of custom graphics that will scale the
+ * The NinePatch class permits drawing a bitmap in nine or more sections.
+ * Essentially, it allows the creation of custom graphics that will scale the
* way that you define, when content added within the image exceeds the normal
* bounds of the graphic. For a thorough explanation of a NinePatch image,
* read the discussion in the
@@ -36,19 +33,23 @@
*/
public class NinePatch {
private final Bitmap mBitmap;
+
/**
+ * Used by native code. This pointer is an instance of Res_png_9patch*.
+ *
* @hide
*/
- public final byte[] mChunk;
+ public final int mNativeChunk;
+
private Paint mPaint;
- private String mSrcName; // Useful for debugging
+ private String mSrcName;
/**
* Create a drawable projection from a bitmap to nine patches.
*
- * @param bitmap The bitmap describing the patches.
- * @param chunk The 9-patch data chunk describing how the underlying
- * bitmap is split apart and drawn.
+ * @param bitmap The bitmap describing the patches.
+ * @param chunk The 9-patch data chunk describing how the underlying bitmap
+ * is split apart and drawn.
*/
public NinePatch(Bitmap bitmap, byte[] chunk) {
this(bitmap, chunk, null);
@@ -57,16 +58,15 @@
/**
* Create a drawable projection from a bitmap to nine patches.
*
- * @param bitmap The bitmap describing the patches.
- * @param chunk The 9-patch data chunk describing how the underlying
- * bitmap is split apart and drawn.
- * @param srcName The name of the source for the bitmap. Might be null.
+ * @param bitmap The bitmap describing the patches.
+ * @param chunk The 9-patch data chunk describing how the underlying
+ * bitmap is split apart and drawn.
+ * @param srcName The name of the source for the bitmap. Might be null.
*/
public NinePatch(Bitmap bitmap, byte[] chunk, String srcName) {
mBitmap = bitmap;
- mChunk = chunk;
mSrcName = srcName;
- validateNinePatchChunk(mBitmap.ni(), chunk);
+ mNativeChunk = validateNinePatchChunk(mBitmap.ni(), chunk);
}
/**
@@ -74,74 +74,103 @@
*/
public NinePatch(NinePatch patch) {
mBitmap = patch.mBitmap;
- mChunk = patch.mChunk;
mSrcName = patch.mSrcName;
if (patch.mPaint != null) {
mPaint = new Paint(patch.mPaint);
}
- validateNinePatchChunk(mBitmap.ni(), mChunk);
+ // No need to validate the 9patch chunk again, it was done by
+ // the instance we're copying from
+ mNativeChunk = patch.mNativeChunk;
}
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ nativeFinalize(mNativeChunk);
+ } finally {
+ super.finalize();
+ }
+ }
+
+ /**
+ * Returns the name of this NinePatch object if one was specified
+ * when calling the constructor.
+ */
+ public String getName() {
+ return mSrcName;
+ }
+
+ /**
+ * Returns the paint used to draw this NinePatch. The paint can be null.
+ *
+ * @see #setPaint(Paint)
+ * @see #draw(Canvas, Rect)
+ * @see #draw(Canvas, RectF)
+ */
+ public Paint getPaint() {
+ return mPaint;
+ }
+
+ /**
+ * Sets the paint to use when drawing the NinePatch.
+ *
+ * @param p The paint that will be used to draw this NinePatch.
+ *
+ * @see #getPaint()
+ * @see #draw(Canvas, Rect)
+ * @see #draw(Canvas, RectF)
+ */
public void setPaint(Paint p) {
mPaint = p;
}
/**
- * @hide
+ * Returns the bitmap used to draw this NinePatch.
*/
public Bitmap getBitmap() {
return mBitmap;
}
/**
- * Draw a bitmap of nine patches.
+ * Draws the NinePatch. This method will use the paint returned by {@link #getPaint()}.
*
- * @param canvas A container for the current matrix and clip used to draw the bitmap.
- * @param location Where to draw the bitmap.
+ * @param canvas A container for the current matrix and clip used to draw the NinePatch.
+ * @param location Where to draw the NinePatch.
*/
public void draw(Canvas canvas, RectF location) {
- if (canvas.isHardwareAccelerated()) {
- canvas.drawPatch(this, location, mPaint);
- } else {
- nativeDraw(canvas.mNativeCanvas, location,
- mBitmap.ni(), mChunk,
- mPaint != null ? mPaint.mNativePaint : 0,
- canvas.mDensity, mBitmap.mDensity);
- }
- }
-
- /**
- * Draw a bitmap of nine patches.
- *
- * @param canvas A container for the current matrix and clip used to draw the bitmap.
- * @param location Where to draw the bitmap.
- */
- public void draw(Canvas canvas, Rect location) {
- if (canvas.isHardwareAccelerated()) {
- canvas.drawPatch(this, location, mPaint);
- } else {
- nativeDraw(canvas.mNativeCanvas, location,
- mBitmap.ni(), mChunk,
- mPaint != null ? mPaint.mNativePaint : 0,
- canvas.mDensity, mBitmap.mDensity);
- }
+ canvas.drawPatch(this, location, mPaint);
}
/**
- * Draw a bitmap of nine patches.
+ * Draws the NinePatch. This method will use the paint returned by {@link #getPaint()}.
*
- * @param canvas A container for the current matrix and clip used to draw the bitmap.
- * @param location Where to draw the bitmap.
- * @param paint The Paint to draw through.
+ * @param canvas A container for the current matrix and clip used to draw the NinePatch.
+ * @param location Where to draw the NinePatch.
+ */
+ public void draw(Canvas canvas, Rect location) {
+ canvas.drawPatch(this, location, mPaint);
+ }
+
+ /**
+ * Draws the NinePatch. This method will ignore the paint returned
+ * by {@link #getPaint()} and use the specified paint instead.
+ *
+ * @param canvas A container for the current matrix and clip used to draw the NinePatch.
+ * @param location Where to draw the NinePatch.
+ * @param paint The Paint to draw through.
*/
public void draw(Canvas canvas, Rect location, Paint paint) {
- if (canvas.isHardwareAccelerated()) {
- canvas.drawPatch(this, location, paint);
- } else {
- nativeDraw(canvas.mNativeCanvas, location,
- mBitmap.ni(), mChunk, paint != null ? paint.mNativePaint : 0,
- canvas.mDensity, mBitmap.mDensity);
- }
+ canvas.drawPatch(this, location, paint);
+ }
+
+ void drawSoftware(Canvas canvas, RectF location, Paint paint) {
+ nativeDraw(canvas.mNativeCanvas, location, mBitmap.ni(), mNativeChunk,
+ paint != null ? paint.mNativePaint : 0, canvas.mDensity, mBitmap.mDensity);
+ }
+
+ void drawSoftware(Canvas canvas, Rect location, Paint paint) {
+ nativeDraw(canvas.mNativeCanvas, location, mBitmap.ni(), mNativeChunk,
+ paint != null ? paint.mNativePaint : 0, canvas.mDensity, mBitmap.mDensity);
}
/**
@@ -151,32 +180,67 @@
public int getDensity() {
return mBitmap.mDensity;
}
-
+
+ /**
+ * Returns the intrinsic width, in pixels, of this NinePatch. This is equivalent
+ * to querying the width of the underlying bitmap returned by {@link #getBitmap()}.
+ */
public int getWidth() {
return mBitmap.getWidth();
}
+ /**
+ * Returns the intrinsic height, in pixels, of this NinePatch. This is equivalent
+ * to querying the height of the underlying bitmap returned by {@link #getBitmap()}.
+ */
public int getHeight() {
return mBitmap.getHeight();
}
+ /**
+ * Indicates whether this NinePatch contains transparent or translucent pixels.
+ * This is equivalent to calling <code>getBitmap().hasAlpha()</code> on this
+ * NinePatch.
+ */
public final boolean hasAlpha() {
return mBitmap.hasAlpha();
}
- public final Region getTransparentRegion(Rect location) {
- int r = nativeGetTransparentRegion(mBitmap.ni(), mChunk, location);
+ /**
+ * Returns a {@link Region} representing the parts of the NinePatch that are
+ * completely transparent.
+ *
+ * @param bounds The location and size of the NinePatch.
+ *
+ * @return null if the NinePatch has no transparent region to
+ * report, else a {@link Region} holding the parts of the specified bounds
+ * that are transparent.
+ */
+ public final Region getTransparentRegion(Rect bounds) {
+ int r = nativeGetTransparentRegion(mBitmap.ni(), mNativeChunk, bounds);
return r != 0 ? new Region(r) : null;
}
-
+
+ /**
+ * Verifies that the specified byte array is a valid 9-patch data chunk.
+ *
+ * @param chunk A byte array representing a 9-patch data chunk.
+ *
+ * @return True if the specified byte array represents a 9-patch data chunk,
+ * false otherwise.
+ */
public native static boolean isNinePatchChunk(byte[] chunk);
- private static native void validateNinePatchChunk(int bitmap, byte[] chunk);
+ /**
+ * Validates the 9-patch chunk and throws an exception if the chunk is invalid.
+ * If validation is successful, this method returns a native Res_png_9patch*
+ * object used by the renderers.
+ */
+ private static native int validateNinePatchChunk(int bitmap, byte[] chunk);
+ private static native void nativeFinalize(int chunk);
private static native void nativeDraw(int canvas_instance, RectF loc, int bitmap_instance,
- byte[] c, int paint_instance_or_null,
- int destDensity, int srcDensity);
+ int c, int paint_instance_or_null, int destDensity, int srcDensity);
private static native void nativeDraw(int canvas_instance, Rect loc, int bitmap_instance,
- byte[] c, int paint_instance_or_null,
- int destDensity, int srcDensity);
- private static native int nativeGetTransparentRegion(int bitmap, byte[] chunk, Rect location);
+ int c, int paint_instance_or_null, int destDensity, int srcDensity);
+ private static native int nativeGetTransparentRegion(int bitmap, int chunk, Rect location);
}
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 1089b7c..6de8c8c 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -286,6 +286,7 @@
void Caches::clearGarbage() {
textureCache.clearGarbage();
pathCache.clearGarbage();
+ patchCache.clearGarbage();
Vector<DisplayList*> displayLists;
Vector<Layer*> layers;
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index 0d4dd1a..cebfd26 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -100,6 +100,10 @@
caches.resourceCache.decrementRefcountLocked(mFilterResources.itemAt(i));
}
+ for (size_t i = 0; i < mPatchResources.size(); i++) {
+ caches.resourceCache.decrementRefcountLocked(mPatchResources.itemAt(i));
+ }
+
for (size_t i = 0; i < mShaders.size(); i++) {
caches.resourceCache.decrementRefcountLocked(mShaders.itemAt(i));
caches.resourceCache.destructorLocked(mShaders.itemAt(i));
@@ -134,6 +138,7 @@
mBitmapResources.clear();
mOwnedBitmapResources.clear();
mFilterResources.clear();
+ mPatchResources.clear();
mShaders.clear();
mSourcePaths.clear();
mPaints.clear();
@@ -201,6 +206,13 @@
caches.resourceCache.incrementRefcountLocked(resource);
}
+ const Vector<Res_png_9patch*>& patchResources = recorder.getPatchResources();
+ for (size_t i = 0; i < patchResources.size(); i++) {
+ Res_png_9patch* resource = patchResources.itemAt(i);
+ mPatchResources.add(resource);
+ caches.resourceCache.incrementRefcountLocked(resource);
+ }
+
const Vector<SkiaShader*>& shaders = recorder.getShaders();
for (size_t i = 0; i < shaders.size(); i++) {
SkiaShader* resource = shaders.itemAt(i);
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index 1417df7..194be9e 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -30,8 +30,11 @@
#include <utils/SortedVector.h>
#include <utils/String8.h>
#include <utils/Vector.h>
+
#include <cutils/compiler.h>
+#include <androidfw/ResourceTypes.h>
+
#include "utils/LinearAllocator.h"
#include "Debug.h"
@@ -484,6 +487,7 @@
Vector<SkBitmap*> mBitmapResources;
Vector<SkBitmap*> mOwnedBitmapResources;
Vector<SkiaColorFilter*> mFilterResources;
+ Vector<Res_png_9patch*> mPatchResources;
Vector<SkPaint*> mPaints;
Vector<SkPath*> mPaths;
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 5d23e1d..9113092 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -57,6 +57,10 @@
mCaches.resourceCache.decrementRefcountLocked(mFilterResources.itemAt(i));
}
+ for (size_t i = 0; i < mPatchResources.size(); i++) {
+ mCaches.resourceCache.decrementRefcountLocked(mPatchResources.itemAt(i));
+ }
+
for (size_t i = 0; i < mShaders.size(); i++) {
mCaches.resourceCache.decrementRefcountLocked(mShaders.itemAt(i));
}
@@ -74,6 +78,7 @@
mBitmapResources.clear();
mOwnedBitmapResources.clear();
mFilterResources.clear();
+ mPatchResources.clear();
mSourcePaths.clear();
mShaders.clear();
@@ -318,6 +323,7 @@
status_t DisplayListRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch,
float left, float top, float right, float bottom, SkPaint* paint) {
bitmap = refBitmap(bitmap);
+ patch = refPatch(patch);
paint = refPaint(paint);
addDrawOp(new (alloc()) DrawPatchOp(bitmap, patch, left, top, right, bottom, paint));
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 85d6107..03f50c8 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -156,6 +156,10 @@
return mFilterResources;
}
+ const Vector<Res_png_9patch*>& getPatchResources() const {
+ return mPatchResources;
+ }
+
const Vector<SkiaShader*>& getShaders() const {
return mShaders;
}
@@ -315,9 +319,16 @@
return colorFilter;
}
+ inline Res_png_9patch* refPatch(Res_png_9patch* patch) {
+ mPatchResources.add(patch);
+ mCaches.resourceCache.incrementRefcount(patch);
+ return patch;
+ }
+
Vector<SkBitmap*> mBitmapResources;
Vector<SkBitmap*> mOwnedBitmapResources;
Vector<SkiaColorFilter*> mFilterResources;
+ Vector<Res_png_9patch*> mPatchResources;
Vector<SkPaint*> mPaints;
DefaultKeyedVector<SkPaint*, SkPaint*> mPaintMap;
diff --git a/libs/hwui/Patch.cpp b/libs/hwui/Patch.cpp
index 9e3e701..7656f85 100644
--- a/libs/hwui/Patch.cpp
+++ b/libs/hwui/Patch.cpp
@@ -79,8 +79,8 @@
uint32_t maxVertices = ((xCount + 1) * (yCount + 1) - emptyQuads) * 4;
if (maxVertices == 0) return NULL;
- vertices = new TextureVertex[maxVertices];
- TextureVertex* vertex = vertices;
+ TextureVertex* tempVertices = new TextureVertex[maxVertices];
+ TextureVertex* vertex = tempVertices;
const int32_t* xDivs = patch->xDivs;
const int32_t* yDivs = patch->yDivs;
@@ -159,6 +159,14 @@
width, bitmapWidth, quadCount);
}
+ if (verticesCount == maxVertices) {
+ vertices = tempVertices;
+ } else {
+ vertices = new TextureVertex[verticesCount];
+ memcpy(vertices, tempVertices, verticesCount * sizeof(TextureVertex));
+ delete[] tempVertices;
+ }
+
return vertices;
}
diff --git a/libs/hwui/PatchCache.cpp b/libs/hwui/PatchCache.cpp
index dc69d7f..dc0d98c 100644
--- a/libs/hwui/PatchCache.cpp
+++ b/libs/hwui/PatchCache.cpp
@@ -32,7 +32,7 @@
PatchCache::PatchCache():
mSize(0), mCache(LruCache<PatchDescription, Patch*>::kUnlimitedCapacity),
- mMeshBuffer(0), mGenerationId(0) {
+ mMeshBuffer(0), mFreeBlocks(NULL), mGenerationId(0) {
char property[PROPERTY_VALUE_MAX];
if (property_get(PROPERTY_PATCH_CACHE_SIZE, property, NULL) > 0) {
INIT_LOGD(" Setting patch cache size to %skB", property);
@@ -97,14 +97,130 @@
delete i.value();
}
mCache.clear();
+
+ BufferBlock* block = mFreeBlocks;
+ while (block) {
+ BufferBlock* next = block->next;
+ delete block;
+ block = next;
+ }
+ mFreeBlocks = NULL;
+}
+
+void PatchCache::remove(Vector<patch_pair_t>& patchesToRemove, Res_png_9patch* patch) {
+ LruCache<PatchDescription, Patch*>::Iterator i(mCache);
+ while (i.next()) {
+ const PatchDescription& key = i.key();
+ if (key.getPatch() == patch) {
+ patchesToRemove.push(patch_pair_t(&key, i.value()));
+ }
+ }
+}
+
+void PatchCache::removeDeferred(Res_png_9patch* patch) {
+ Mutex::Autolock _l(mLock);
+ mGarbage.push(patch);
+}
+
+void PatchCache::clearGarbage() {
+ Vector<patch_pair_t> patchesToRemove;
+
+ { // scope for the mutex
+ Mutex::Autolock _l(mLock);
+ size_t count = mGarbage.size();
+ for (size_t i = 0; i < count; i++) {
+ remove(patchesToRemove, mGarbage[i]);
+ }
+ mGarbage.clear();
+ }
+
+ // TODO: We could sort patchesToRemove by offset to merge
+ // adjacent free blocks
+ for (size_t i = 0; i < patchesToRemove.size(); i++) {
+ const patch_pair_t& pair = patchesToRemove[i];
+
+ // Add a new free block to the list
+ const Patch* patch = pair.getSecond();
+ BufferBlock* block = new BufferBlock(patch->offset, patch->getSize());
+ block->next = mFreeBlocks;
+ mFreeBlocks = block;
+
+ mSize -= patch->getSize();
+
+ mCache.remove(*pair.getFirst());
+ }
+
+#if DEBUG_PATCHES
+ if (patchesToRemove.size() > 0) {
+ dumpFreeBlocks("Removed garbage");
+ }
+#endif
}
void PatchCache::createVertexBuffer() {
glBufferData(GL_ARRAY_BUFFER, mMaxSize, NULL, GL_DYNAMIC_DRAW);
mSize = 0;
+ mFreeBlocks = new BufferBlock(0, mMaxSize);
mGenerationId++;
}
+/**
+ * Sets the mesh's offsets and copies its associated vertices into
+ * the mesh buffer (VBO).
+ */
+void PatchCache::setupMesh(Patch* newMesh, TextureVertex* vertices) {
+ // This call ensures the VBO exists and that it is bound
+ init(Caches::getInstance());
+
+ // If we're running out of space, let's clear the entire cache
+ uint32_t size = newMesh->getSize();
+ if (mSize + size > mMaxSize) {
+ clearCache();
+ createVertexBuffer();
+ }
+
+ // Find a block where we can fit the mesh
+ BufferBlock* previous = NULL;
+ BufferBlock* block = mFreeBlocks;
+ while (block) {
+ // The mesh fits
+ if (block->size >= size) {
+ break;
+ }
+ previous = block;
+ block = block->next;
+ }
+
+ // We have enough space left in the buffer, but it's
+ // too fragmented, let's clear the cache
+ if (!block) {
+ clearCache();
+ createVertexBuffer();
+ previous = NULL;
+ block = mFreeBlocks;
+ }
+
+ // Copy the 9patch mesh in the VBO
+ newMesh->offset = (GLintptr) (block->offset);
+ newMesh->textureOffset = newMesh->offset + gMeshTextureOffset;
+ glBufferSubData(GL_ARRAY_BUFFER, newMesh->offset, size, vertices);
+
+ // Remove the block since we've used it entirely
+ if (block->size == size) {
+ if (previous) {
+ previous->next = block->next;
+ } else {
+ mFreeBlocks = block->next;
+ }
+ } else {
+ // Resize the block now that it's occupied
+ block->offset += size;
+ block->size -= size;
+ }
+
+ mSize += size;
+}
+
const Patch* PatchCache::get(const AssetAtlas::Entry* entry,
const uint32_t bitmapWidth, const uint32_t bitmapHeight,
const float pixelWidth, const float pixelHeight, const Res_png_9patch* patch) {
@@ -117,6 +233,7 @@
TextureVertex* vertices;
if (entry) {
+ // An atlas entry has a UV mapper
vertices = newMesh->createMesh(bitmapWidth, bitmapHeight,
pixelWidth, pixelHeight, entry->uvMapper, patch);
} else {
@@ -125,24 +242,13 @@
}
if (vertices) {
- // This call ensures the VBO exists and that it is bound
- init(Caches::getInstance());
-
- // TODO: Simply remove the oldest items until we have enough room
- // This will require to keep a list of free blocks in the VBO
- uint32_t size = newMesh->getSize();
- if (mSize + size > mMaxSize) {
- clearCache();
- createVertexBuffer();
- }
-
- newMesh->offset = (GLintptr) mSize;
- newMesh->textureOffset = newMesh->offset + gMeshTextureOffset;
- mSize += size;
-
- glBufferSubData(GL_ARRAY_BUFFER, newMesh->offset, size, vertices);
+ setupMesh(newMesh, vertices);
}
+#if DEBUG_PATCHES
+ dumpFreeBlocks("Adding patch");
+#endif
+
mCache.put(description, newMesh);
return newMesh;
}
@@ -150,5 +256,17 @@
return mesh;
}
+#if DEBUG_PATCHES
+void PatchCache::dumpFreeBlocks(const char* prefix) {
+ String8 dump;
+ BufferBlock* block = mFreeBlocks;
+ while (block) {
+ dump.appendFormat("->(%d, %d)", block->offset, block->size);
+ block = block->next;
+ }
+ ALOGD("%s: Free blocks%s", prefix, dump.string());
+}
+#endif
+
}; // namespace uirenderer
}; // namespace android
diff --git a/libs/hwui/PatchCache.h b/libs/hwui/PatchCache.h
index 1829b89..9f2c9a5 100644
--- a/libs/hwui/PatchCache.h
+++ b/libs/hwui/PatchCache.h
@@ -26,6 +26,7 @@
#include "AssetAtlas.h"
#include "Debug.h"
#include "Patch.h"
+#include "utils/Pair.h"
namespace android {
namespace uirenderer {
@@ -74,10 +75,20 @@
return mGenerationId;
}
-private:
- void clearCache();
- void createVertexBuffer();
+ /**
+ * Removes the entries associated with the specified 9-patch. This is meant
+ * to be called from threads that are not the EGL context thread (GC thread
+ * on the VM side for instance.)
+ */
+ void removeDeferred(Res_png_9patch* patch);
+ /**
+ * Process deferred removals.
+ */
+ void clearGarbage();
+
+
+private:
struct PatchDescription {
PatchDescription(): mPatch(NULL), mBitmapWidth(0), mBitmapHeight(0),
mPixelWidth(0), mPixelHeight(0) {
@@ -91,6 +102,8 @@
hash_t hash() const;
+ const Res_png_9patch* getPatch() const { return mPatch; }
+
static int compare(const PatchDescription& lhs, const PatchDescription& rhs);
bool operator==(const PatchDescription& other) const {
@@ -124,14 +137,50 @@
}; // struct PatchDescription
+ /**
+ * A buffer block represents an empty range in the mesh buffer
+ * that can be used to store vertices.
+ *
+ * The patch cache maintains a linked-list of buffer blocks
+ * to track available regions of memory in the VBO.
+ */
+ struct BufferBlock {
+ BufferBlock(uint32_t offset, uint32_t size): offset(offset), size(size), next(NULL) {
+ }
+
+ uint32_t offset;
+ uint32_t size;
+
+ BufferBlock* next;
+ }; // struct BufferBlock
+
+ typedef Pair<const PatchDescription*, Patch*> patch_pair_t;
+
+ void clearCache();
+ void createVertexBuffer();
+
+ void setupMesh(Patch* newMesh, TextureVertex* vertices);
+
+ void remove(Vector<patch_pair_t>& patchesToRemove, Res_png_9patch* patch);
+
+#if DEBUG_PATCHES
+ void dumpFreeBlocks(const char* prefix);
+#endif
+
uint32_t mMaxSize;
uint32_t mSize;
LruCache<PatchDescription, Patch*> mCache;
GLuint mMeshBuffer;
+ // First available free block inside the mesh buffer
+ BufferBlock* mFreeBlocks;
uint32_t mGenerationId;
+
+ // Garbage tracking, required to handle GC events on the VM side
+ Vector<Res_png_9patch*> mGarbage;
+ mutable Mutex mLock;
}; // class PatchCache
}; // namespace uirenderer
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index 3ab40da..70ab6e7 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -350,8 +350,7 @@
// Paths
///////////////////////////////////////////////////////////////////////////////
-void PathCache::remove(const path_pair_t& pair) {
- Vector<PathDescription> pathsToRemove;
+void PathCache::remove(Vector<PathDescription>& pathsToRemove, const path_pair_t& pair) {
LruCache<PathDescription, PathTexture*>::Iterator i(mCache);
while (i.next()) {
@@ -362,10 +361,6 @@
pathsToRemove.push(key);
}
}
-
- for (size_t i = 0; i < pathsToRemove.size(); i++) {
- mCache.remove(pathsToRemove.itemAt(i));
- }
}
void PathCache::removeDeferred(SkPath* path) {
@@ -374,12 +369,20 @@
}
void PathCache::clearGarbage() {
- Mutex::Autolock l(mLock);
- size_t count = mGarbage.size();
- for (size_t i = 0; i < count; i++) {
- remove(mGarbage.itemAt(i));
+ Vector<PathDescription> pathsToRemove;
+
+ { // scope for the mutex
+ Mutex::Autolock l(mLock);
+ size_t count = mGarbage.size();
+ for (size_t i = 0; i < count; i++) {
+ remove(pathsToRemove, mGarbage.itemAt(i));
+ }
+ mGarbage.clear();
}
- mGarbage.clear();
+
+ for (size_t i = 0; i < pathsToRemove.size(); i++) {
+ mCache.remove(pathsToRemove.itemAt(i));
+ }
}
/**
diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h
index a191f0e..16d20a8 100644
--- a/libs/hwui/PathCache.h
+++ b/libs/hwui/PathCache.h
@@ -269,7 +269,7 @@
* Removes an entry.
* The pair must define first=path, second=sourcePath
*/
- void remove(const path_pair_t& pair);
+ void remove(Vector<PathDescription>& pathsToRemove, const path_pair_t& pair);
/**
* Ensures there is enough space in the cache for a texture of the specified
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 347bd78..58fa21c 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#define LOG_TAG "OpenGLRenderer"
+
#include <SkPixelRef.h>
#include "ResourceCache.h"
#include "Caches.h"
@@ -79,6 +81,10 @@
incrementRefcount((void*) filterResource, kColorFilter);
}
+void ResourceCache::incrementRefcount(Res_png_9patch* patchResource) {
+ incrementRefcount((void*) patchResource, kNinePatch);
+}
+
void ResourceCache::incrementRefcount(Layer* layerResource) {
incrementRefcount((void*) layerResource, kLayer);
}
@@ -113,6 +119,10 @@
incrementRefcountLocked((void*) filterResource, kColorFilter);
}
+void ResourceCache::incrementRefcountLocked(Res_png_9patch* patchResource) {
+ incrementRefcountLocked((void*) patchResource, kNinePatch);
+}
+
void ResourceCache::incrementRefcountLocked(Layer* layerResource) {
incrementRefcountLocked((void*) layerResource, kLayer);
}
@@ -142,6 +152,10 @@
decrementRefcount((void*) filterResource);
}
+void ResourceCache::decrementRefcount(Res_png_9patch* patchResource) {
+ decrementRefcount((void*) patchResource);
+}
+
void ResourceCache::decrementRefcount(Layer* layerResource) {
decrementRefcount((void*) layerResource);
}
@@ -179,6 +193,10 @@
decrementRefcountLocked((void*) filterResource);
}
+void ResourceCache::decrementRefcountLocked(Res_png_9patch* patchResource) {
+ decrementRefcountLocked((void*) patchResource);
+}
+
void ResourceCache::decrementRefcountLocked(Layer* layerResource) {
decrementRefcountLocked((void*) layerResource);
}
@@ -265,6 +283,30 @@
}
}
+void ResourceCache::destructor(Res_png_9patch* resource) {
+ Mutex::Autolock _l(mLock);
+ destructorLocked(resource);
+}
+
+void ResourceCache::destructorLocked(Res_png_9patch* resource) {
+ ssize_t index = mCache->indexOfKey(resource);
+ ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
+ if (ref == NULL) {
+ if (Caches::hasInstance()) {
+ Caches::getInstance().patchCache.removeDeferred(resource);
+ }
+ // If we're not tracking this resource, just delete it
+ // A Res_png_9patch is actually an array of byte that's larger
+ // than sizeof(Res_png_9patch). It must be freed as an array.
+ delete[] (int8_t*) resource;
+ return;
+ }
+ ref->destroyed = true;
+ if (ref->refCount == 0) {
+ deleteResourceReferenceLocked(resource, ref);
+ }
+}
+
/**
* Return value indicates whether resource was actually recycled, which happens when RefCnt
* reaches 0.
@@ -335,6 +377,16 @@
delete filter;
}
break;
+ case kNinePatch: {
+ if (Caches::hasInstance()) {
+ Caches::getInstance().patchCache.removeDeferred((Res_png_9patch*) resource);
+ }
+ // A Res_png_9patch is actually an array of byte that's larger
+ // than sizeof(Res_png_9patch). It must be freed as an array.
+ int8_t* patch = (int8_t*) resource;
+ delete[] patch;
+ }
+ break;
case kLayer: {
Layer* layer = (Layer*) resource;
Caches::getInstance().deleteLayerDeferred(layer);
diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h
index ab493e5..ea0c1b5 100644
--- a/libs/hwui/ResourceCache.h
+++ b/libs/hwui/ResourceCache.h
@@ -22,7 +22,11 @@
#include <SkBitmap.h>
#include <SkiaColorFilter.h>
#include <SkiaShader.h>
+
#include <utils/KeyedVector.h>
+
+#include <androidfw/ResourceTypes.h>
+
#include "Layer.h"
namespace android {
@@ -35,6 +39,7 @@
kBitmap,
kShader,
kColorFilter,
+ kNinePatch,
kPath,
kLayer
};
@@ -69,35 +74,41 @@
void incrementRefcount(SkBitmap* resource);
void incrementRefcount(SkiaShader* resource);
void incrementRefcount(SkiaColorFilter* resource);
+ void incrementRefcount(Res_png_9patch* resource);
void incrementRefcount(Layer* resource);
void incrementRefcountLocked(SkPath* resource);
void incrementRefcountLocked(SkBitmap* resource);
void incrementRefcountLocked(SkiaShader* resource);
void incrementRefcountLocked(SkiaColorFilter* resource);
+ void incrementRefcountLocked(Res_png_9patch* resource);
void incrementRefcountLocked(Layer* resource);
void decrementRefcount(SkBitmap* resource);
void decrementRefcount(SkPath* resource);
void decrementRefcount(SkiaShader* resource);
void decrementRefcount(SkiaColorFilter* resource);
+ void decrementRefcount(Res_png_9patch* resource);
void decrementRefcount(Layer* resource);
void decrementRefcountLocked(SkBitmap* resource);
void decrementRefcountLocked(SkPath* resource);
void decrementRefcountLocked(SkiaShader* resource);
void decrementRefcountLocked(SkiaColorFilter* resource);
+ void decrementRefcountLocked(Res_png_9patch* resource);
void decrementRefcountLocked(Layer* resource);
void destructor(SkPath* resource);
void destructor(SkBitmap* resource);
void destructor(SkiaShader* resource);
void destructor(SkiaColorFilter* resource);
+ void destructor(Res_png_9patch* resource);
void destructorLocked(SkPath* resource);
void destructorLocked(SkBitmap* resource);
void destructorLocked(SkiaShader* resource);
void destructorLocked(SkiaColorFilter* resource);
+ void destructorLocked(Res_png_9patch* resource);
bool recycle(SkBitmap* resource);
bool recycleLocked(SkBitmap* resource);
diff --git a/location/lib/java/com/android/location/provider/LocationProviderBase.java b/location/lib/java/com/android/location/provider/LocationProviderBase.java
index 8a5a739..150c289 100644
--- a/location/lib/java/com/android/location/provider/LocationProviderBase.java
+++ b/location/lib/java/com/android/location/provider/LocationProviderBase.java
@@ -35,6 +35,7 @@
import com.android.internal.location.ILocationProvider;
import com.android.internal.location.ProviderProperties;
import com.android.internal.location.ProviderRequest;
+import com.android.internal.util.FastPrintWriter;
/**
* Base class for location providers implemented as unbundled services.
@@ -106,7 +107,7 @@
}
@Override
public void dump(FileDescriptor fd, String[] args) {
- PrintWriter pw = new PrintWriter(new FileOutputStream(fd));
+ PrintWriter pw = new FastPrintWriter(new FileOutputStream(fd));
onDump(fd, pw, args);
pw.flush();
}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 32e5446..3144e8a 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2556,4 +2556,15 @@
}
}
+ /**
+ * Returns the estimated latency for the given stream type in milliseconds.
+ *
+ * DO NOT UNHIDE. The existing approach for doing A/V sync has too many problems. We need
+ * a better solution.
+ * @hide
+ */
+ public int getOutputLatency(int streamType) {
+ return AudioSystem.getOutputLatency(streamType);
+ }
+
}
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 4a33743..d42bfd44 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -401,5 +401,6 @@
// helpers for android.media.AudioManager.getProperty(), see description there for meaning
public static native int getPrimaryOutputSamplingRate();
public static native int getPrimaryOutputFrameCount();
+ public static native int getOutputLatency(int stream);
}
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 60eaa92..7322716 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -651,6 +651,18 @@
}
/**
+ * Returns this track's estimated latency in milliseconds. This includes the latency due
+ * to AudioTrack buffer size, AudioMixer (if any) and audio hardware driver.
+ *
+ * DO NOT UNHIDE. The existing approach for doing A/V sync has too many problems. We need
+ * a better solution.
+ * @hide
+ */
+ public int getLatency() {
+ return native_get_latency();
+ }
+
+ /**
* Returns the output sample rate in Hz for the specified stream type.
*/
static public int getNativeOutputSampleRate(int streamType) {
@@ -1315,6 +1327,8 @@
private native final int native_set_position(int position);
private native final int native_get_position();
+ private native final int native_get_latency();
+
private native final int native_set_loop(int start, int end, int loopCount);
static private native final int native_get_output_sample_rate(int streamType);
diff --git a/media/java/android/media/Image.java b/media/java/android/media/Image.java
index eb94346..f55756c 100644
--- a/media/java/android/media/Image.java
+++ b/media/java/android/media/Image.java
@@ -44,7 +44,7 @@
*
* @see ImageReader
*/
-public abstract class Image implements AutoCloseable {
+public interface Image extends AutoCloseable {
/**
* Get the format for this image. This format determines the number of
* ByteBuffers needed to represent the image, and the general layout of the
@@ -87,25 +87,19 @@
*
* @see android.graphics.ImageFormat
*/
- public int getFormat() {
- return ImageFormat.UNKNOWN;
- }
+ public int getFormat();
/**
* The width of the image in pixels. For formats where some color channels
* are subsampled, this is the width of the largest-resolution plane.
*/
- public int getWidth() {
- return 0;
- }
+ public int getWidth();
/**
* The height of the image in pixels. For formats where some color channels
* are subsampled, this is the height of the largest-resolution plane.
*/
- public int getHeight() {
- return 0;
- }
+ public int getHeight();
/**
* Get the timestamp associated with this frame. The timestamp is measured
@@ -113,17 +107,13 @@
* and whether the timestamp can be compared against other sources of time
* or images depend on the source of this image.
*/
- public long getTimestamp() {
- return 0;
- }
+ public long getTimestamp();
/**
* Get the array of pixel planes for this Image. The number of planes is
* determined by the format of the Image.
*/
- public Plane[] getPlanes() {
- return null;
- }
+ public Plane[] getPlanes();
/**
* Free up this frame for reuse. After calling this method, calling any
@@ -131,11 +121,7 @@
* attempting to read from ByteBuffers returned by an earlier
* {@code Plane#getBuffer} call will have undefined behavior.
*/
- public abstract void close();
-
- protected final void finalize() {
- close();
- }
+ public void close();
/**
* <p>A single color plane of image data.</p>
@@ -148,17 +134,14 @@
*
* @see #getFormat
*/
- public static final class Plane {
+ public interface Plane {
/**
* <p>The row stride for this color plane, in bytes.
*
* <p>This is the distance between the start of two consecutive rows of
* pixels in the image.</p>
*/
- public int getRowStride() {
- return 0;
- }
-
+ public int getRowStride();
/**
* <p>The distance between adjacent pixel samples, in bytes.</p>
*
@@ -166,19 +149,14 @@
* of pixels. It may be larger than the size of a single pixel to
* account for interleaved image data or padded formats.</p>
*/
- public int getPixelStride() {
- return 0;
- }
-
+ public int getPixelStride();
/**
* <p>Get a set of direct {@link java.nio.ByteBuffer byte buffers}
* containing the frame data.</p>
*
* @return the byte buffer containing the image data for this plane.
*/
- public ByteBuffer getBuffer() {
- return null;
- }
+ public ByteBuffer getBuffer();
}
}
diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java
index 9384c14..8f09b54 100644
--- a/media/java/android/media/ImageReader.java
+++ b/media/java/android/media/ImageReader.java
@@ -16,8 +16,15 @@
package android.media;
+import android.graphics.ImageFormat;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
import android.view.Surface;
-import java.lang.AutoCloseable;
+
+import java.lang.ref.WeakReference;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
/**
* <p>The ImageReader class allows direct application access to image data
@@ -39,7 +46,7 @@
* ImageReader does not obtain and release Images at a rate equal to the
* production rate.</p>
*/
-public final class ImageReader {
+public final class ImageReader implements AutoCloseable {
/**
* <p>Create a new reader for images of the desired size and format.</p>
@@ -62,7 +69,7 @@
* access simultaneously. This should be as small as possible to limit
* memory use. Once maxImages Images are obtained by the user, one of them
* has to be released before a new Image will become available for access
- * through getImage(). Must be greater than 0.
+ * through getNextImage(). Must be greater than 0.
*
* @see Image
*/
@@ -80,6 +87,12 @@
throw new IllegalArgumentException(
"Maximum outstanding image count must be at least 1");
}
+
+ mNumPlanes = getNumPlanesFromFormat();
+
+ nativeInit(new WeakReference<ImageReader>(this), width, height, format, maxImages);
+
+ mSurface = nativeGetSurface();
}
public int getWidth() {
@@ -111,7 +124,7 @@
* @return A Surface to use for a drawing target for various APIs.
*/
public Surface getSurface() {
- return null;
+ return mSurface;
}
/**
@@ -122,6 +135,13 @@
* available.
*/
public Image getNextImage() {
+ SurfaceImage si = new SurfaceImage();
+ if (nativeImageSetup(si)) {
+ // create SurfacePlane objects
+ si.createSurfacePlanes();
+ si.setImageValid(true);
+ return si;
+ }
return null;
}
@@ -138,34 +158,307 @@
throw new IllegalArgumentException(
"This image was not produced by this ImageReader");
}
+
+ si.clearSurfacePlanes();
+ nativeReleaseImage(i);
+ si.setImageValid(false);
}
- public void setOnImageAvailableListener(OnImageAvailableListener l) {
- mImageListener = l;
+ /**
+ * Register a listener to be invoked when a new image becomes available
+ * from the ImageReader.
+ * @param listener the listener that will be run
+ * @param handler The handler on which the listener should be invoked, or null
+ * if the listener should be invoked on the calling thread's looper.
+ */
+ public void setImageAvailableListener(OnImageAvailableListener listener, Handler handler) {
+ mImageListener = listener;
+
+ Looper looper;
+ mHandler = handler;
+ if (mHandler == null) {
+ if ((looper = Looper.myLooper()) != null) {
+ mHandler = new Handler();
+ } else {
+ throw new IllegalArgumentException(
+ "Looper doesn't exist in the calling thread");
+ }
+ }
}
+ /**
+ * Callback interface for being notified that a new image is available.
+ * The onImageAvailable is called per image basis, that is, callback fires for every new frame
+ * available from ImageReader.
+ */
public interface OnImageAvailableListener {
+ /**
+ * Callback that is called when a new image is available from ImageReader.
+ * @param reader the ImageReader the callback is associated with.
+ * @see ImageReader
+ * @see Image
+ */
void onImageAvailable(ImageReader reader);
}
+ /**
+ * Free up all the resources associated with this ImageReader. After
+ * Calling this method, this ImageReader can not be used. calling
+ * any methods on this ImageReader and Images previously provided by {@link #getNextImage}
+ * will result in an IllegalStateException, and attempting to read from
+ * ByteBuffers returned by an earlier {@code Plane#getBuffer} call will
+ * have undefined behavior.
+ */
+ @Override
+ public void close() {
+ nativeClose();
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ close();
+ } finally {
+ super.finalize();
+ }
+ }
+
+ private int getNumPlanesFromFormat() {
+ switch (mFormat) {
+ case ImageFormat.YV12:
+ case ImageFormat.YUV_420_888:
+ case ImageFormat.NV21:
+ return 3;
+ case ImageFormat.NV16:
+ return 2;
+ case ImageFormat.RGB_565:
+ case ImageFormat.JPEG:
+ case ImageFormat.YUY2:
+ case ImageFormat.Y8:
+ case ImageFormat.Y16:
+ case ImageFormat.RAW_SENSOR:
+ return 1;
+ default:
+ throw new UnsupportedOperationException(
+ String.format("Invalid format specified %d", mFormat));
+ }
+ }
+
+ /**
+ * Called from Native code when an Event happens.
+ */
+ private static void postEventFromNative(Object selfRef) {
+ WeakReference weakSelf = (WeakReference)selfRef;
+ final ImageReader ir = (ImageReader)weakSelf.get();
+ if (ir == null) {
+ return;
+ }
+
+ if (ir.mHandler != null) {
+ ir.mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ ir.mImageListener.onImageAvailable(ir);
+ }
+ });
+ }
+ }
+
private final int mWidth;
private final int mHeight;
private final int mFormat;
private final int mMaxImages;
+ private final int mNumPlanes;
+ private final Surface mSurface;
+ private Handler mHandler;
private OnImageAvailableListener mImageListener;
- private class SurfaceImage extends android.media.Image {
+ /**
+ * This field is used by native code, do not access or modify.
+ */
+ private long mNativeContext;
+
+ private class SurfaceImage implements android.media.Image {
public SurfaceImage() {
+ mIsImageValid = false;
}
@Override
public void close() {
- ImageReader.this.releaseImage(this);
+ if (mIsImageValid) {
+ ImageReader.this.releaseImage(this);
+ }
}
public ImageReader getReader() {
return ImageReader.this;
}
+
+ @Override
+ public int getFormat() {
+ if (mIsImageValid) {
+ return ImageReader.this.mFormat;
+ } else {
+ throw new IllegalStateException("Image is already released");
+ }
+ }
+
+ @Override
+ public int getWidth() {
+ if (mIsImageValid) {
+ return ImageReader.this.mWidth;
+ } else {
+ throw new IllegalStateException("Image is already released");
+ }
+ }
+
+ @Override
+ public int getHeight() {
+ if (mIsImageValid) {
+ return ImageReader.this.mHeight;
+ } else {
+ throw new IllegalStateException("Image is already released");
+ }
+ }
+
+ @Override
+ public long getTimestamp() {
+ if (mIsImageValid) {
+ return mTimestamp;
+ } else {
+ throw new IllegalStateException("Image is already released");
+ }
+ }
+
+ @Override
+ public Plane[] getPlanes() {
+ if (mIsImageValid) {
+ // Shallow copy is fine.
+ return mPlanes.clone();
+ } else {
+ throw new IllegalStateException("Image is already released");
+ }
+ }
+
+ @Override
+ protected final void finalize() throws Throwable {
+ try {
+ close();
+ } finally {
+ super.finalize();
+ }
+ }
+
+ private void setImageValid(boolean isValid) {
+ mIsImageValid = isValid;
+ }
+
+ private boolean isImageValid() {
+ return mIsImageValid;
+ }
+
+ private void clearSurfacePlanes() {
+ if (mIsImageValid) {
+ for (int i = 0; i < mPlanes.length; i++) {
+ if (mPlanes[i] != null) {
+ mPlanes[i].clearBuffer();
+ mPlanes[i] = null;
+ }
+ }
+ }
+ }
+
+ private void createSurfacePlanes() {
+ mPlanes = new SurfacePlane[ImageReader.this.mNumPlanes];
+ for (int i = 0; i < ImageReader.this.mNumPlanes; i++) {
+ mPlanes[i] = nativeCreatePlane(i);
+ }
+ }
+ private class SurfacePlane implements android.media.Image.Plane {
+ // SurfacePlane instance is created by native code when a new SurfaceImage is created
+ private SurfacePlane(int index, int rowStride, int pixelStride) {
+ mIndex = index;
+ mRowStride = rowStride;
+ mPixelStride = pixelStride;
+ }
+
+ @Override
+ public ByteBuffer getBuffer() {
+ if (SurfaceImage.this.isImageValid() == false) {
+ throw new IllegalStateException("Image is already released");
+ }
+ if (mBuffer != null) {
+ return mBuffer;
+ } else {
+ mBuffer = SurfaceImage.this.nativeImageGetBuffer(mIndex);
+ // Set the byteBuffer order according to host endianness (native order),
+ // otherwise, the byteBuffer order defaults to ByteOrder.BIG_ENDIAN.
+ return mBuffer.order(ByteOrder.nativeOrder());
+ }
+ }
+
+ @Override
+ public int getPixelStride() {
+ if (SurfaceImage.this.isImageValid()) {
+ return mPixelStride;
+ } else {
+ throw new IllegalStateException("Image is already released");
+ }
+ }
+
+ @Override
+ public int getRowStride() {
+ if (SurfaceImage.this.isImageValid()) {
+ return mRowStride;
+ } else {
+ throw new IllegalStateException("Image is already released");
+ }
+ }
+
+ private void clearBuffer() {
+ mBuffer = null;
+ }
+
+ final private int mIndex;
+ final private int mPixelStride;
+ final private int mRowStride;
+
+ private ByteBuffer mBuffer;
+ }
+
+ /**
+ * This field is used to keep track of native object and used by native code only.
+ * Don't modify.
+ */
+ private long mLockedBuffer;
+
+ /**
+ * This field is set by native code during nativeImageSetup().
+ */
+ private long mTimestamp;
+
+ private SurfacePlane[] mPlanes;
+ private boolean mIsImageValid;
+
+ private synchronized native ByteBuffer nativeImageGetBuffer(int idx);
+ private synchronized native SurfacePlane nativeCreatePlane(int idx);
+ }
+
+ private synchronized native void nativeInit(Object weakSelf, int w, int h,
+ int fmt, int maxImgs);
+ private synchronized native void nativeClose();
+ private synchronized native void nativeReleaseImage(Image i);
+ private synchronized native Surface nativeGetSurface();
+ private synchronized native boolean nativeImageSetup(Image i);
+
+ /*
+ * We use a class initializer to allow the native code to cache some
+ * field offsets.
+ */
+ private static native void nativeClassInit();
+ static {
+ System.loadLibrary("media_jni");
+ nativeClassInit();
}
}
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index d703642c..8cf0b4b 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -164,7 +164,8 @@
*
* The following is a partial list of defined mime types and their semantics:
* <ul>
- * <li>"video/x-vnd.on2.vp8" - VPX video (i.e. video in .webm)
+ * <li>"video/x-vnd.on2.vp8" - VP8 video (i.e. video in .webm)
+ * <li>"video/x-vnd.on2.vp9" - VP9 video (i.e. video in .webm)
* <li>"video/avc" - H.264/AVC video
* <li>"video/mp4v-es" - MPEG4 video
* <li>"video/3gpp" - H.263 video
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index 416a2a1..01b3174 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -2,6 +2,7 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
+ android_media_ImageReader.cpp \
android_media_MediaCrypto.cpp \
android_media_MediaCodec.cpp \
android_media_MediaCodecList.cpp \
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
new file mode 100644
index 0000000..bdb07a6
--- /dev/null
+++ b/media/jni/android_media_ImageReader.cpp
@@ -0,0 +1,747 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ImageReader_JNI"
+#include <utils/Log.h>
+#include <utils/misc.h>
+#include <utils/List.h>
+
+#include <cstdio>
+
+#include <gui/CpuConsumer.h>
+#include <gui/Surface.h>
+
+#include <android_runtime/AndroidRuntime.h>
+#include <android_runtime/android_view_Surface.h>
+
+#include <jni.h>
+#include <JNIHelp.h>
+
+#define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )
+
+#define ANDROID_MEDIA_IMAGEREADER_JNI_ID "mCpuConsumer"
+#define ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID "mNativeContext"
+#define ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID "mLockedBuffer"
+#define ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID "mTimestamp"
+
+// ----------------------------------------------------------------------------
+
+using namespace android;
+
+enum {
+ IMAGE_READER_MAX_NUM_PLANES = 3,
+};
+
+struct fields_t {
+ // For ImageReader class
+ jfieldID imageReaderContext;
+ jmethodID postEvent;
+ // For SurfaceImage class
+ jfieldID buffer;
+ jfieldID timeStamp;
+};
+
+struct classInfo_t {
+ jclass clazz;
+ jmethodID ctor;
+};
+
+static fields_t fields;
+static classInfo_t surfPlaneClassInfo;
+
+// ----------------------------------------------------------------------------
+
+class JNIImageReaderContext : public CpuConsumer::FrameAvailableListener
+{
+public:
+ JNIImageReaderContext(JNIEnv* env, jobject weakThiz, jclass clazz, int maxImages);
+
+ virtual ~JNIImageReaderContext();
+
+ virtual void onFrameAvailable();
+
+ CpuConsumer::LockedBuffer* getLockedBuffer();
+
+ void returnLockedBuffer(CpuConsumer::LockedBuffer* buffer);
+
+ CpuConsumer* getCpuConsumer() { return mConsumer.get(); }
+
+ void setCpuConsumer(sp<CpuConsumer> consumer) { mConsumer = consumer; }
+
+ void setBufferFormat(int format) { mFormat = format; }
+ int getBufferFormat() { return mFormat; }
+
+ void setBufferWidth(int width) { mWidth = width; }
+ int getBufferWidth() { return mWidth; }
+
+ void setBufferHeight(int height) { mHeight = height; }
+ int getBufferHeight() { return mHeight; }
+
+private:
+ static JNIEnv* getJNIEnv(bool* needsDetach);
+ static void detachJNI();
+
+ List<CpuConsumer::LockedBuffer*> mBuffers;
+ sp<CpuConsumer> mConsumer;
+ jobject mWeakThiz;
+ jclass mClazz;
+ int mFormat;
+ int mWidth;
+ int mHeight;
+};
+
+JNIImageReaderContext::JNIImageReaderContext(JNIEnv* env,
+ jobject weakThiz, jclass clazz, int maxImages) :
+ mWeakThiz(env->NewGlobalRef(weakThiz)),
+ mClazz((jclass)env->NewGlobalRef(clazz)) {
+ for (int i = 0; i < maxImages; i++) {
+ CpuConsumer::LockedBuffer *buffer = new CpuConsumer::LockedBuffer;
+ mBuffers.push_back(buffer);
+ }
+}
+
+JNIEnv* JNIImageReaderContext::getJNIEnv(bool* needsDetach) {
+ LOG_ALWAYS_FATAL_IF(needsDetach == NULL, "needsDetach is null!!!");
+ *needsDetach = false;
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ if (env == NULL) {
+ JavaVMAttachArgs args = {JNI_VERSION_1_4, NULL, NULL};
+ JavaVM* vm = AndroidRuntime::getJavaVM();
+ int result = vm->AttachCurrentThread(&env, (void*) &args);
+ if (result != JNI_OK) {
+ ALOGE("thread attach failed: %#x", result);
+ return NULL;
+ }
+ *needsDetach = true;
+ }
+ return env;
+}
+
+void JNIImageReaderContext::detachJNI() {
+ JavaVM* vm = AndroidRuntime::getJavaVM();
+ int result = vm->DetachCurrentThread();
+ if (result != JNI_OK) {
+ ALOGE("thread detach failed: %#x", result);
+ }
+}
+
+CpuConsumer::LockedBuffer* JNIImageReaderContext::getLockedBuffer() {
+ if (mBuffers.empty()) {
+ return NULL;
+ }
+ // Return a LockedBuffer pointer and remove it from the list
+ List<CpuConsumer::LockedBuffer*>::iterator it = mBuffers.begin();
+ CpuConsumer::LockedBuffer* buffer = *it;
+ mBuffers.erase(it);
+ return buffer;
+}
+
+void JNIImageReaderContext::returnLockedBuffer(CpuConsumer::LockedBuffer * buffer) {
+ mBuffers.push_back(buffer);
+}
+
+JNIImageReaderContext::~JNIImageReaderContext() {
+ bool needsDetach = false;
+ JNIEnv* env = getJNIEnv(&needsDetach);
+ if (env != NULL) {
+ env->DeleteGlobalRef(mWeakThiz);
+ env->DeleteGlobalRef(mClazz);
+ } else {
+ ALOGW("leaking JNI object references");
+ }
+ if (needsDetach) {
+ detachJNI();
+ }
+
+ // Delete LockedBuffers
+ for (List<CpuConsumer::LockedBuffer *>::iterator it = mBuffers.begin();
+ it != mBuffers.end(); it++) {
+ delete *it;
+ }
+ mBuffers.clear();
+ mConsumer.clear();
+}
+
+void JNIImageReaderContext::onFrameAvailable()
+{
+ ALOGV("%s: frame available", __FUNCTION__);
+ bool needsDetach = false;
+ JNIEnv* env = getJNIEnv(&needsDetach);
+ if (env != NULL) {
+ env->CallStaticVoidMethod(mClazz, fields.postEvent, mWeakThiz);
+ } else {
+ ALOGW("onFrameAvailable event will not posted");
+ }
+ if (needsDetach) {
+ detachJNI();
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+extern "C" {
+
+static JNIImageReaderContext* ImageReader_getContext(JNIEnv* env, jobject thiz)
+{
+ JNIImageReaderContext *ctx;
+ ctx = reinterpret_cast<JNIImageReaderContext *>
+ (env->GetLongField(thiz, fields.imageReaderContext));
+ return ctx;
+}
+
+static CpuConsumer* ImageReader_getCpuConsumer(JNIEnv* env, jobject thiz)
+{
+ ALOGV("%s:", __FUNCTION__);
+ JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz);
+ if (ctx == NULL) {
+ jniThrowRuntimeException(env, "ImageReaderContext is not initialized");
+ return NULL;
+ }
+ return ctx->getCpuConsumer();
+}
+
+static void ImageReader_setNativeContext(JNIEnv* env,
+ jobject thiz, sp<JNIImageReaderContext> ctx)
+{
+ ALOGV("%s:", __FUNCTION__);
+ JNIImageReaderContext* const p = ImageReader_getContext(env, thiz);
+ if (ctx != 0) {
+ ctx->incStrong((void*)ImageReader_setNativeContext);
+ }
+ if (p) {
+ p->decStrong((void*)ImageReader_setNativeContext);
+ }
+ env->SetLongField(thiz, fields.imageReaderContext, reinterpret_cast<jlong>(ctx.get()));
+}
+
+static CpuConsumer::LockedBuffer* Image_getLockedBuffer(JNIEnv* env, jobject image)
+{
+ return reinterpret_cast<CpuConsumer::LockedBuffer*>(env->GetLongField(image, fields.buffer));
+}
+
+static void Image_setBuffer(JNIEnv* env, jobject thiz,
+ const CpuConsumer::LockedBuffer* buffer)
+{
+ env->SetLongField(thiz, fields.buffer, reinterpret_cast<jlong>(buffer));
+}
+
+// Some formats like JPEG defined with different values between android.graphics.ImageFormat and
+// graphics.h, need convert to the one defined in graphics.h here.
+static int Image_getPixelFormat(JNIEnv* env, int format)
+{
+ int jpegFormat, rawSensorFormat;
+ jfieldID fid;
+
+ ALOGV("%s: format = 0x%x", __FUNCTION__, format);
+
+ jclass imageFormatClazz = env->FindClass("android/graphics/ImageFormat");
+ ALOG_ASSERT(imageFormatClazz != NULL);
+
+ fid = env->GetStaticFieldID(imageFormatClazz, "JPEG", "I");
+ jpegFormat = env->GetStaticIntField(imageFormatClazz, fid);
+ fid = env->GetStaticFieldID(imageFormatClazz, "RAW_SENSOR", "I");
+ rawSensorFormat = env->GetStaticIntField(imageFormatClazz, fid);
+
+ // Translate the JPEG to BLOB for camera purpose, an add more if more mismatch is found.
+ if (format == jpegFormat) {
+ format = HAL_PIXEL_FORMAT_BLOB;
+ }
+ // Same thing for RAW_SENSOR format
+ if (format == rawSensorFormat) {
+ format = HAL_PIXEL_FORMAT_RAW_SENSOR;
+ }
+
+ return format;
+}
+
+static void Image_getLockedBufferInfo(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx,
+ uint8_t **base, uint32_t *size)
+{
+ ALOG_ASSERT(buffer != NULL, "Input buffer is NULL!!!");
+ ALOG_ASSERT(base != NULL, "base is NULL!!!");
+ ALOG_ASSERT(size != NULL, "size is NULL!!!");
+ ALOG_ASSERT((idx < IMAGE_READER_MAX_NUM_PLANES) && (idx >= 0));
+
+ ALOGV("%s: buffer: 0x%p", __FUNCTION__, buffer);
+
+ uint32_t dataSize, ySize, cSize, cStride;
+ uint8_t *cb, *cr;
+ uint8_t *pData = NULL;
+
+ dataSize = ySize = cSize = cStride = 0;
+ int32_t fmt = buffer->format;
+ switch (fmt) {
+ case HAL_PIXEL_FORMAT_YCbCr_420_888:
+ pData =
+ (idx == 0) ?
+ buffer->data :
+ (idx == 1) ?
+ buffer->dataCb :
+ buffer->dataCr;
+ if (idx == 0) {
+ dataSize = buffer->stride * buffer->height;
+ } else {
+ dataSize = buffer->chromaStride * buffer->height / 2;
+ }
+ break;
+ // NV21
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ cr = buffer->data + (buffer->stride * buffer->height);
+ cb = cr + 1;
+ ySize = buffer->width * buffer->height;
+ cSize = buffer->width * buffer->height / 2;
+
+ pData =
+ (idx == 0) ?
+ buffer->data :
+ (idx == 1) ?
+ cb:
+ cr;
+
+ dataSize = (idx == 0) ? ySize : cSize;
+ break;
+ case HAL_PIXEL_FORMAT_YV12:
+ // Y and C stride need to be 16 pixel aligned.
+ LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
+ "Stride is not 16 pixel aligned %d", buffer->stride);
+
+ ySize = buffer->stride * buffer->height;
+ cStride = ALIGN(buffer->stride / 2, 16);
+ cr = buffer->data + ySize;
+ cSize = cStride * buffer->height / 2;
+ cb = cr + cSize;
+
+ pData =
+ (idx == 0) ?
+ buffer->data :
+ (idx == 1) ?
+ cb :
+ cr;
+ dataSize = (idx == 0) ? ySize : cSize;
+ break;
+ case HAL_PIXEL_FORMAT_Y8:
+ // Single plane, 8bpp.
+ ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+
+ pData = buffer->data;
+ dataSize = buffer->stride * buffer->height;
+ break;
+ case HAL_PIXEL_FORMAT_Y16:
+ // Single plane, 16bpp, strides are specified in pixels, not in bytes
+ ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+
+ pData = buffer->data;
+ dataSize = buffer->stride * buffer->height * 2;
+ break;
+ case HAL_PIXEL_FORMAT_BLOB:
+ // Used for JPEG data, height must be 1, width == size, single plane.
+ ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+ ALOG_ASSERT(buffer->height == 1, "JPEG should has height value %d", buffer->height);
+
+ pData = buffer->data;
+ dataSize = buffer->width;
+ break;
+ case HAL_PIXEL_FORMAT_RAW_SENSOR:
+ // Single plane 16bpp bayer data.
+ ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+ pData = buffer->data;
+ dataSize = buffer->width * 2 * buffer->height;
+ break;
+ default:
+ jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException",
+ "Pixel format: 0x%x is unsupported", fmt);
+ break;
+ }
+
+ *base = pData;
+ *size = dataSize;
+}
+
+static jint Image_imageGetPixelStride(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx)
+{
+ ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
+ ALOG_ASSERT((idx < IMAGE_READER_MAX_NUM_PLANES) && (idx >= 0), "Index is out of range:%d", idx);
+
+ int pixelStride = 0;
+ ALOG_ASSERT(buffer != NULL, "buffer is NULL");
+
+ int32_t fmt = buffer->format;
+ switch (fmt) {
+ case HAL_PIXEL_FORMAT_YCbCr_420_888:
+ pixelStride = (idx == 0) ? 1 : buffer->chromaStep;
+ break;
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ pixelStride = (idx == 0) ? 1 : 2;
+ break;
+ case HAL_PIXEL_FORMAT_Y8:
+ // Single plane 8bpp data.
+ ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+ pixelStride;
+ break;
+ case HAL_PIXEL_FORMAT_YV12:
+ pixelStride = 1;
+ break;
+ case HAL_PIXEL_FORMAT_BLOB:
+ // Used for JPEG data, single plane, row and pixel strides are 0
+ ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+ pixelStride = 0;
+ break;
+ case HAL_PIXEL_FORMAT_Y16:
+ case HAL_PIXEL_FORMAT_RAW_SENSOR:
+ // Single plane 16bpp data.
+ ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+ pixelStride = 2;
+ break;
+ default:
+ jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException",
+ "Pixel format: 0x%x is unsupported", fmt);
+ break;
+ }
+
+ return pixelStride;
+}
+
+static jint Image_imageGetRowStride(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx)
+{
+ ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
+ ALOG_ASSERT((idx < IMAGE_READER_MAX_NUM_PLANES) && (idx >= 0));
+
+ int rowStride = 0;
+ ALOG_ASSERT(buffer != NULL, "buffer is NULL");
+
+ int32_t fmt = buffer->format;
+
+ switch (fmt) {
+ case HAL_PIXEL_FORMAT_YCbCr_420_888:
+ rowStride = (idx == 0) ? buffer->stride : buffer->chromaStride;
+ break;
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ rowStride = buffer->width;
+ break;
+ case HAL_PIXEL_FORMAT_YV12:
+ LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
+ "Stride is not 16 pixel aligned %d", buffer->stride);
+ rowStride = (idx == 0) ? buffer->stride : ALIGN(buffer->stride / 2, 16);
+ break;
+ case HAL_PIXEL_FORMAT_BLOB:
+ // Used for JPEG data, single plane, row and pixel strides are 0
+ ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+ rowStride = 0;
+ break;
+ case HAL_PIXEL_FORMAT_Y8:
+ ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+ LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
+ "Stride is not 16 pixel aligned %d", buffer->stride);
+ rowStride = buffer->stride;
+ break;
+ case HAL_PIXEL_FORMAT_Y16:
+ case HAL_PIXEL_FORMAT_RAW_SENSOR:
+ // In native side, strides are specified in pixels, not in bytes.
+ // Single plane 16bpp bayer data. even width/height,
+ // row stride multiple of 16 pixels (32 bytes)
+ ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+ LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
+ "Stride is not 16 pixel aligned %d", buffer->stride);
+ rowStride = buffer->stride * 2;
+ break;
+ default:
+ ALOGE("%s Pixel format: 0x%x is unsupported", __FUNCTION__, fmt);
+ jniThrowException(env, "java/lang/UnsupportedOperationException",
+ "unsupported buffer format");
+ break;
+ }
+
+ return rowStride;
+}
+
+// ----------------------------------------------------------------------------
+
+static void ImageReader_classInit(JNIEnv* env, jclass clazz)
+{
+ ALOGV("%s:", __FUNCTION__);
+
+ jclass imageClazz = env->FindClass("android/media/ImageReader$SurfaceImage");
+ LOG_ALWAYS_FATAL_IF(imageClazz == NULL,
+ "can't find android/graphics/ImageReader$SurfaceImage");
+ fields.buffer = env->GetFieldID(imageClazz, ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID, "J");
+ LOG_ALWAYS_FATAL_IF(fields.buffer == NULL,
+ "can't find android/graphics/ImageReader.%s",
+ ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID);
+
+ fields.timeStamp = env->GetFieldID(imageClazz, ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID, "J");
+ LOG_ALWAYS_FATAL_IF(fields.timeStamp == NULL,
+ "can't find android/graphics/ImageReader.%s",
+ ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID);
+
+ fields.imageReaderContext = env->GetFieldID(clazz, ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID, "J");
+ LOG_ALWAYS_FATAL_IF(fields.imageReaderContext == NULL,
+ "can't find android/graphics/ImageReader.%s",
+ ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID);
+
+ fields.postEvent = env->GetStaticMethodID(clazz, "postEventFromNative",
+ "(Ljava/lang/Object;)V");
+ LOG_ALWAYS_FATAL_IF(fields.postEvent == NULL,
+ "can't find android/graphics/ImageReader.postEventFromNative");
+
+ jclass planeClazz = env->FindClass("android/media/ImageReader$SurfaceImage$SurfacePlane");
+ LOG_ALWAYS_FATAL_IF(planeClazz == NULL, "Can not find SurfacePlane class");
+ // FindClass only gives a local reference of jclass object.
+ surfPlaneClassInfo.clazz = (jclass) env->NewGlobalRef(planeClazz);
+ surfPlaneClassInfo.ctor = env->GetMethodID(surfPlaneClassInfo.clazz, "<init>",
+ "(Landroid/media/ImageReader$SurfaceImage;III)V");
+ LOG_ALWAYS_FATAL_IF(surfPlaneClassInfo.ctor == NULL, "Can not find SurfacePlane constructor");
+}
+
+static void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz,
+ jint width, jint height, jint format, jint maxImages)
+{
+ status_t res;
+ int nativeFormat;
+
+ ALOGV("%s: width:%d, height: %d, format: 0x%x, maxImages:%d",
+ __FUNCTION__, width, height, format, maxImages);
+
+ nativeFormat = Image_getPixelFormat(env, format);
+
+ sp<CpuConsumer> consumer = new CpuConsumer(maxImages);
+ // TODO: throw dvm exOutOfMemoryError?
+ if (consumer == NULL) {
+ jniThrowRuntimeException(env, "Failed to allocate native CpuConsumer");
+ return;
+ }
+
+ jclass clazz = env->GetObjectClass(thiz);
+ if (clazz == NULL) {
+ jniThrowRuntimeException(env, "Can't find android/graphics/ImageReader");
+ return;
+ }
+ sp<JNIImageReaderContext> ctx(new JNIImageReaderContext(env, weakThiz, clazz, maxImages));
+ ctx->setCpuConsumer(consumer);
+ consumer->setFrameAvailableListener(ctx);
+ ImageReader_setNativeContext(env, thiz, ctx);
+ ctx->setBufferFormat(nativeFormat);
+ ctx->setBufferWidth(width);
+ ctx->setBufferHeight(height);
+
+ // Set the width/height/format to the CpuConsumer
+ res = consumer->setDefaultBufferSize(width, height);
+ if (res != OK) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Failed to set CpuConsumer buffer size");
+ return;
+ }
+ res = consumer->setDefaultBufferFormat(nativeFormat);
+ if (res != OK) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Failed to set CpuConsumer buffer format");
+ }
+}
+
+static void ImageReader_close(JNIEnv* env, jobject thiz)
+{
+ ALOGV("%s:", __FUNCTION__);
+
+ JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz);
+ if (ctx == NULL) {
+ // ImageReader is already closed.
+ return;
+ }
+
+ CpuConsumer* consumer = ImageReader_getCpuConsumer(env, thiz);
+ if (consumer != NULL) {
+ consumer->abandon();
+ consumer->setFrameAvailableListener(NULL);
+ }
+ ImageReader_setNativeContext(env, thiz, NULL);
+}
+
+static void ImageReader_imageRelease(JNIEnv* env, jobject thiz, jobject image)
+{
+ ALOGV("%s:", __FUNCTION__);
+ JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz);
+ if (ctx == NULL) {
+ ALOGW("ImageReader#close called before Image#close, consider calling Image#close first");
+ return;
+ }
+
+ CpuConsumer* consumer = ctx->getCpuConsumer();
+ CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, image);
+ if (!buffer) {
+ ALOGW("Image already released!!!");
+ return;
+ }
+ consumer->unlockBuffer(*buffer);
+ Image_setBuffer(env, image, NULL);
+ ctx->returnLockedBuffer(buffer);
+}
+
+static jboolean ImageReader_imageSetup(JNIEnv* env, jobject thiz,
+ jobject image)
+{
+ ALOGV("%s:", __FUNCTION__);
+ JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz);
+ if (ctx == NULL) {
+ jniThrowRuntimeException(env, "ImageReaderContext is not initialized");
+ return false;
+ }
+
+ CpuConsumer* consumer = ctx->getCpuConsumer();
+ CpuConsumer::LockedBuffer* buffer = ctx->getLockedBuffer();
+ if (buffer == NULL) {
+ ALOGE("Unable to acquire a lockedBuffer, very likely client tries to lock more than"
+ "maxImages buffers");
+ return false;
+ }
+ status_t res = consumer->lockNextBuffer(buffer);
+ if (res != NO_ERROR) {
+ ALOGE("%s Fail to lockNextBuffer with error: 0x%x ", __FUNCTION__, res);
+ return false;
+ }
+
+
+ // Check if the left-top corner of the crop rect is origin, we currently assume this point is
+ // zero, will revist this once this assumption turns out problematic.
+ Point lt = buffer->crop.leftTop();
+ if (lt.x != 0 || lt.y != 0) {
+ ALOGE("crop left: %d, top = %d", lt.x, lt.y);
+ jniThrowException(env, "java/lang/UnsupportedOperationException",
+ "crop left top corner need to at origin");
+ }
+
+ // Check if the producer buffer configurations match what ImageReader configured.
+ // We want to fail for the very first image because this case is too bad.
+ int outputWidth = buffer->crop.getWidth() + 1;
+ int outputHeight = buffer->crop.getHeight() + 1;
+ int imageReaderWidth = ctx->getBufferWidth();
+ int imageReaderHeight = ctx->getBufferHeight();
+ if ((imageReaderWidth != outputWidth) ||
+ (imageReaderHeight != outputHeight)) {
+ // Spew warning for now, since MediaCodec decoder has a bug to setup the right crop
+ // TODO: make it throw exception once the decoder bug is fixed.
+ ALOGW("Producer buffer size: %dx%d, doesn't match ImageReader configured size: %dx%d",
+ outputWidth, outputHeight, imageReaderWidth, imageReaderHeight);
+ }
+
+ if (ctx->getBufferFormat() != buffer->format) {
+ // Return the buffer to the queue.
+ consumer->unlockBuffer(*buffer);
+ ctx->returnLockedBuffer(buffer);
+
+ // Throw exception
+ ALOGE("Producer output buffer format: 0x%x, ImageReader configured format: 0x%x",
+ buffer->format, ctx->getBufferFormat());
+ jniThrowException(env, "java/lang/UnsupportedOperationException",
+ "The producer output buffer configuration doesn't match the ImageReader"
+ "configured");
+ return false;
+ }
+ // Set SurfaceImage instance member variables
+ Image_setBuffer(env, image, buffer);
+ env->SetLongField(image, fields.timeStamp, static_cast<jlong>(buffer->timestamp));
+
+ return true;
+}
+
+static jobject ImageReader_getSurface(JNIEnv* env, jobject thiz)
+{
+ ALOGV("%s: ", __FUNCTION__);
+
+ CpuConsumer* consumer = ImageReader_getCpuConsumer(env, thiz);
+ if (consumer == NULL) {
+ jniThrowRuntimeException(env, "CpuConsumer is uninitialized");
+ return NULL;
+ }
+
+ // Wrap the IGBP in a Java-language Surface.
+ return android_view_Surface_createFromIGraphicBufferProducer(env,
+ consumer->getProducerInterface());
+}
+
+static jobject Image_createSurfacePlane(JNIEnv* env, jobject thiz, int idx)
+{
+ int rowStride, pixelStride;
+ ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
+
+ CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz);
+
+ ALOG_ASSERT(buffer != NULL);
+ if (buffer == NULL) {
+ jniThrowException(env, "java/lang/IllegalStateException", "Image was released");
+ }
+ rowStride = Image_imageGetRowStride(env, buffer, idx);
+ pixelStride = Image_imageGetPixelStride(env, buffer, idx);
+
+ jobject surfPlaneObj = env->NewObject(surfPlaneClassInfo.clazz, surfPlaneClassInfo.ctor,
+ thiz, idx, rowStride, pixelStride);
+
+ return surfPlaneObj;
+}
+
+static jobject Image_getByteBuffer(JNIEnv* env, jobject thiz, int idx)
+{
+ uint8_t *base = NULL;
+ uint32_t size = 0;
+ jobject byteBuffer;
+
+ ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
+
+ CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz);
+
+ if (buffer == NULL) {
+ jniThrowException(env, "java/lang/IllegalStateException", "Image was released");
+ }
+
+ // Create byteBuffer from native buffer
+ Image_getLockedBufferInfo(env, buffer, idx, &base, &size);
+ byteBuffer = env->NewDirectByteBuffer(base, size);
+ // TODO: throw dvm exOutOfMemoryError?
+ if ((byteBuffer == NULL) && (env->ExceptionCheck() == false)) {
+ jniThrowException(env, "java/lang/IllegalStateException", "Failed to allocate ByteBuffer");
+ }
+
+ return byteBuffer;
+}
+
+} // extern "C"
+
+// ----------------------------------------------------------------------------
+
+static JNINativeMethod gImageReaderMethods[] = {
+ {"nativeClassInit", "()V", (void*)ImageReader_classInit },
+ {"nativeInit", "(Ljava/lang/Object;IIII)V", (void*)ImageReader_init },
+ {"nativeClose", "()V", (void*)ImageReader_close },
+ {"nativeReleaseImage", "(Landroid/media/Image;)V", (void*)ImageReader_imageRelease },
+ {"nativeImageSetup", "(Landroid/media/Image;)Z", (void*)ImageReader_imageSetup },
+ {"nativeGetSurface", "()Landroid/view/Surface;", (void*)ImageReader_getSurface },
+};
+
+static JNINativeMethod gImageMethods[] = {
+ {"nativeImageGetBuffer", "(I)Ljava/nio/ByteBuffer;", (void*)Image_getByteBuffer },
+ {"nativeCreatePlane", "(I)Landroid/media/ImageReader$SurfaceImage$SurfacePlane;",
+ (void*)Image_createSurfacePlane },
+};
+
+int register_android_media_ImageReader(JNIEnv *env) {
+
+ int ret1 = AndroidRuntime::registerNativeMethods(env,
+ "android/media/ImageReader", gImageReaderMethods, NELEM(gImageReaderMethods));
+
+ int ret2 = AndroidRuntime::registerNativeMethods(env,
+ "android/media/ImageReader$SurfaceImage", gImageMethods, NELEM(gImageMethods));
+
+ return (ret1 || ret2);
+}
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 0f78649..9b66c06 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -896,6 +896,7 @@
"android/media/MediaPlayer", gMethods, NELEM(gMethods));
}
+extern int register_android_media_ImageReader(JNIEnv *env);
extern int register_android_media_Crypto(JNIEnv *env);
extern int register_android_media_Drm(JNIEnv *env);
extern int register_android_media_MediaCodec(JNIEnv *env);
@@ -923,6 +924,11 @@
}
assert(env != NULL);
+ if (register_android_media_ImageReader(env) < 0) {
+ ALOGE("ERROR: ImageReader native registration failed");
+ goto bail;
+ }
+
if (register_android_media_MediaPlayer(env) < 0) {
ALOGE("ERROR: MediaPlayer native registration failed\n");
goto bail;
diff --git a/media/tests/MediaFrameworkTest/Android.mk b/media/tests/MediaFrameworkTest/Android.mk
index c9afa19..1e6b2e7 100644
--- a/media/tests/MediaFrameworkTest/Android.mk
+++ b/media/tests/MediaFrameworkTest/Android.mk
@@ -7,7 +7,7 @@
LOCAL_JAVA_LIBRARIES := android.test.runner
-LOCAL_STATIC_JAVA_LIBRARIES := easymocklib
+LOCAL_STATIC_JAVA_LIBRARIES := easymocklib mockito-target
LOCAL_PACKAGE_NAME := mediaframeworktest
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkIntegrationTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkIntegrationTestRunner.java
index 88c5b0c..7751fcc 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkIntegrationTestRunner.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkIntegrationTestRunner.java
@@ -19,8 +19,10 @@
import android.os.Bundle;
import android.test.InstrumentationTestRunner;
import android.test.InstrumentationTestSuite;
+import android.util.Log;
import com.android.mediaframeworktest.integration.CameraBinderTest;
+import com.android.mediaframeworktest.integration.CameraDeviceBinderTest;
import junit.framework.TestSuite;
@@ -34,11 +36,15 @@
public class MediaFrameworkIntegrationTestRunner extends InstrumentationTestRunner {
+ private static final String TAG = "MediaFrameworkIntegrationTestRunner";
+
+ public static int mCameraId = 0;
@Override
public TestSuite getAllTests() {
TestSuite suite = new InstrumentationTestSuite(this);
suite.addTestSuite(CameraBinderTest.class);
+ suite.addTestSuite(CameraDeviceBinderTest.class);
return suite;
}
@@ -50,5 +56,17 @@
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
+
+ String cameraId = (String) icicle.get("camera_id");
+ if (cameraId != null) {
+ try {
+ Log.v(TAG,
+ String.format("Reading camera_id from icicle: '%s'", cameraId));
+ mCameraId = Integer.parseInt(cameraId);
+ }
+ catch (NumberFormatException e) {
+ Log.e(TAG, String.format("Failed to convert camera_id to integer"));
+ }
+ }
}
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java
index 62af3f3..ecdc287 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkUnitTestRunner.java
@@ -48,6 +48,7 @@
addMediaRecorderStateUnitTests(suite);
addMediaPlayerStateUnitTests(suite);
addMediaScannerUnitTests(suite);
+ addCameraUnitTests(suite);
return suite;
}
@@ -56,6 +57,14 @@
return MediaFrameworkUnitTestRunner.class.getClassLoader();
}
+ private void addCameraUnitTests(TestSuite suite) {
+ suite.addTestSuite(CameraUtilsDecoratorTest.class);
+ suite.addTestSuite(CameraUtilsRuntimeExceptionTest.class);
+ suite.addTestSuite(CameraUtilsUncheckedThrowTest.class);
+ suite.addTestSuite(CameraUtilsBinderDecoratorTest.class);
+ suite.addTestSuite(CameraMetadataTest.class);
+ }
+
// Running all unit tests checking the state machine may be time-consuming.
private void addMediaMetadataRetrieverStateUnitTests(TestSuite suite) {
suite.addTestSuite(MediaMetadataRetrieverTest.class);
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
index ba2859b..bc3adc9 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
@@ -16,122 +16,72 @@
package com.android.mediaframeworktest.integration;
-import android.content.Context;
-import android.content.pm.FeatureInfo;
-import android.content.pm.PackageManager;
import android.hardware.CameraInfo;
import android.hardware.ICamera;
import android.hardware.ICameraClient;
-import android.hardware.ICameraService;
import android.hardware.ICameraServiceListener;
import android.hardware.IProCameraCallbacks;
import android.hardware.IProCameraUser;
+import android.hardware.photography.CameraMetadata;
+import android.hardware.photography.ICameraDeviceCallbacks;
+import android.hardware.photography.ICameraDeviceUser;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
-import android.os.ServiceManager;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
/**
+ * <p>
* Junit / Instrumentation test case for the camera2 api
+ * </p>
+ * <p>
+ * To run only tests in this class:
+ * </p>
*
- * To run only tests in
- * this class:
- *
+ * <pre>
* adb shell am instrument \
- * -e class com.android.mediaframeworktest.integration.CameraBinderTest \
- * -w com.android.mediaframeworktest/.MediaFrameworkIntegrationTestRunner
+ * -e class com.android.mediaframeworktest.integration.CameraBinderTest \
+ * -w com.android.mediaframeworktest/.MediaFrameworkIntegrationTestRunner
+ * </pre>
*/
public class CameraBinderTest extends AndroidTestCase {
- private static String TAG = "CameraBinderTest";
+ static String TAG = "CameraBinderTest";
- private static final String CAMERA_SERVICE_BINDER_NAME = "media.camera";
- private static final int NO_ERROR = 0;
- private static final int ALREADY_EXISTS = -17;
- private static final int BAD_VALUE = -22;
-
- private static final int USE_CALLING_UID = -1;
-
- private ICameraService mCameraService;
- private int mGuessedNumCameras = 0;
+ protected CameraBinderTestUtils mUtils;
public CameraBinderTest() {
}
- private final static boolean isFeatureAvailable(Context context, String feature) {
- final PackageManager packageManager = context.getPackageManager();
- final FeatureInfo[] featuresList = packageManager.getSystemAvailableFeatures();
- for (FeatureInfo f : featuresList) {
- if (f.name != null && f.name.equals(feature)) {
- return true;
- }
- }
-
- return false;
- }
-
- // Guess the lower bound for how many cameras there are
- private void guessNumCameras() {
-
- /**
- * Why do we need this? This way we have no dependency on getNumCameras
- * actually working. On most systems there are only 0, 1, or 2 cameras,
- * and this covers that 'usual case'. On other systems there might be 3+
- * cameras, but this will at least check the first 2.
- */
- mGuessedNumCameras = 0;
-
- // Front facing camera
- if (isFeatureAvailable(getContext(), PackageManager.FEATURE_CAMERA_FRONT)) {
- mGuessedNumCameras++;
- }
-
- // Back facing camera
- if (isFeatureAvailable(getContext(), PackageManager.FEATURE_CAMERA)) {
- mGuessedNumCameras++;
- }
-
- // Any facing camera
- if (mGuessedNumCameras == 0
- && isFeatureAvailable(getContext(), PackageManager.FEATURE_CAMERA_ANY)) {
- mGuessedNumCameras++;
- }
-
- Log.v(TAG, "Guessing there are at least " + mGuessedNumCameras + " cameras");
- }
-
+ @Override
protected void setUp() throws Exception {
super.setUp();
- guessNumCameras();
-
- IBinder cameraServiceBinder = ServiceManager.getService(CAMERA_SERVICE_BINDER_NAME);
- assertNotNull("Camera service IBinder should not be null", cameraServiceBinder);
-
- mCameraService = ICameraService.Stub.asInterface(cameraServiceBinder);
- assertNotNull("Camera service should not be null", mCameraService);
+ mUtils = new CameraBinderTestUtils(getContext());
}
@SmallTest
public void testNumberOfCameras() throws Exception {
- int numCameras = mCameraService.getNumberOfCameras();
- assertTrue("At least this many cameras: " + mGuessedNumCameras,
- numCameras >= mGuessedNumCameras);
+
+ int numCameras = mUtils.getCameraService().getNumberOfCameras();
+ assertTrue("At least this many cameras: " + mUtils.getGuessedNumCameras(),
+ numCameras >= mUtils.getGuessedNumCameras());
Log.v(TAG, "Number of cameras " + numCameras);
}
@SmallTest
public void testCameraInfo() throws Exception {
- for (int cameraId = 0; cameraId < mGuessedNumCameras; ++cameraId) {
+ for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
CameraInfo info = new CameraInfo();
info.info.facing = -1;
info.info.orientation = -1;
- assertTrue("Camera service returned info for camera " + cameraId,
- mCameraService.getCameraInfo(cameraId, info) == NO_ERROR);
+ assertTrue(
+ "Camera service returned info for camera " + cameraId,
+ mUtils.getCameraService().getCameraInfo(cameraId, info) ==
+ CameraBinderTestUtils.NO_ERROR);
assertTrue("Facing was not set for camera " + cameraId, info.info.facing != -1);
assertTrue("Orientation was not set for camera " + cameraId,
info.info.orientation != -1);
@@ -153,14 +103,15 @@
@SmallTest
public void testConnect() throws Exception {
- for (int cameraId = 0; cameraId < mGuessedNumCameras; ++cameraId) {
+ for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
ICameraClient dummyCallbacks = new DummyCameraClient();
String clientPackageName = getContext().getPackageName();
- ICamera cameraUser = mCameraService.connect(dummyCallbacks, cameraId, clientPackageName,
- USE_CALLING_UID);
+ ICamera cameraUser = mUtils.getCameraService().connect(dummyCallbacks, cameraId,
+ clientPackageName,
+ CameraBinderTestUtils.USE_CALLING_UID);
assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
Log.v(TAG, String.format("Camera %s connected", cameraId));
@@ -174,14 +125,45 @@
@SmallTest
public void testConnectPro() throws Exception {
- for (int cameraId = 0; cameraId < mGuessedNumCameras; ++cameraId) {
+ for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
IProCameraCallbacks dummyCallbacks = new DummyProCameraCallbacks();
String clientPackageName = getContext().getPackageName();
- IProCameraUser cameraUser = mCameraService.connectPro(dummyCallbacks, cameraId,
- clientPackageName, USE_CALLING_UID);
+ IProCameraUser cameraUser = mUtils.getCameraService().connectPro(dummyCallbacks,
+ cameraId,
+ clientPackageName, CameraBinderTestUtils.USE_CALLING_UID);
+ assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
+
+ Log.v(TAG, String.format("Camera %s connected", cameraId));
+
+ cameraUser.disconnect();
+ }
+ }
+
+ static class DummyCameraDeviceCallbacks extends DummyBase implements ICameraDeviceCallbacks {
+
+ @Override
+ public void notifyCallback(int msgType, int ext1, int ext2) throws RemoteException {
+ }
+
+ @Override
+ public void onResultReceived(int frameId, CameraMetadata result) throws RemoteException {
+ }
+ }
+
+ @SmallTest
+ public void testConnectDevice() throws Exception {
+ for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
+
+ ICameraDeviceCallbacks dummyCallbacks = new DummyCameraDeviceCallbacks();
+
+ String clientPackageName = getContext().getPackageName();
+
+ ICameraDeviceUser cameraUser = mUtils.getCameraService().connectDevice(dummyCallbacks,
+ cameraId,
+ clientPackageName, CameraBinderTestUtils.USE_CALLING_UID);
assertNotNull(String.format("Camera %s was null", cameraId), cameraUser);
Log.v(TAG, String.format("Camera %s connected", cameraId));
@@ -199,27 +181,39 @@
}
/**
+ * <pre>
* adb shell am instrument \
- * -e class 'com.android.mediaframeworktest.integration.CameraBinderTest#testAddRemoveListeners' \
- * -w com.android.mediaframeworktest/.MediaFrameworkIntegrationTestRunner
+ * -e class 'com.android.mediaframeworktest.integration.CameraBinderTest#testAddRemoveListeners' \
+ * -w com.android.mediaframeworktest/.MediaFrameworkIntegrationTestRunner
+ * </pre>
*/
@SmallTest
public void testAddRemoveListeners() throws Exception {
- for (int cameraId = 0; cameraId < mGuessedNumCameras; ++cameraId) {
+ for (int cameraId = 0; cameraId < mUtils.getGuessedNumCameras(); ++cameraId) {
ICameraServiceListener listener = new DummyCameraServiceListener();
- assertTrue("Listener was removed before added",
- mCameraService.removeListener(listener) == BAD_VALUE);
+ assertTrue(
+ "Listener was removed before added",
+ mUtils.getCameraService().removeListener(listener) ==
+ CameraBinderTestUtils.BAD_VALUE);
- assertTrue("Listener was not added", mCameraService.addListener(listener) == NO_ERROR);
- assertTrue("Listener was wrongly added again",
- mCameraService.addListener(listener) == ALREADY_EXISTS);
+ assertTrue("Listener was not added",
+ mUtils.getCameraService().addListener(listener) ==
+ CameraBinderTestUtils.NO_ERROR);
+ assertTrue(
+ "Listener was wrongly added again",
+ mUtils.getCameraService().addListener(listener) ==
+ CameraBinderTestUtils.ALREADY_EXISTS);
- assertTrue("Listener was not removed",
- mCameraService.removeListener(listener) == NO_ERROR);
- assertTrue("Listener was wrongly removed again",
- mCameraService.removeListener(listener) == BAD_VALUE);
+ assertTrue(
+ "Listener was not removed",
+ mUtils.getCameraService().removeListener(listener) ==
+ CameraBinderTestUtils.NO_ERROR);
+ assertTrue(
+ "Listener was wrongly removed again",
+ mUtils.getCameraService().removeListener(listener) ==
+ CameraBinderTestUtils.BAD_VALUE);
}
}
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTestUtils.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTestUtils.java
new file mode 100644
index 0000000..f0fc817
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTestUtils.java
@@ -0,0 +1,92 @@
+
+package com.android.mediaframeworktest.integration;
+
+import static org.junit.Assert.assertNotNull;
+
+import android.content.Context;
+import android.content.pm.FeatureInfo;
+import android.content.pm.PackageManager;
+import android.hardware.ICameraService;
+import android.os.IBinder;
+import android.os.ServiceManager;
+import android.util.Log;
+
+public class CameraBinderTestUtils {
+ private final ICameraService mCameraService;
+ private int mGuessedNumCameras;
+
+ static final String CAMERA_SERVICE_BINDER_NAME = "media.camera";
+
+ protected static final int USE_CALLING_UID = -1;
+ protected static final int BAD_VALUE = -22;
+ protected static final int ALREADY_EXISTS = -17;
+ protected static final int NO_ERROR = 0;
+ private final Context mContext;
+
+ public CameraBinderTestUtils(Context context) {
+
+ mContext = context;
+
+ guessNumCameras();
+
+ IBinder cameraServiceBinder = ServiceManager
+ .getService(CameraBinderTestUtils.CAMERA_SERVICE_BINDER_NAME);
+ assertNotNull("Camera service IBinder should not be null", cameraServiceBinder);
+
+ this.mCameraService = ICameraService.Stub.asInterface(cameraServiceBinder);
+ assertNotNull("Camera service should not be null", getCameraService());
+ }
+
+ private void guessNumCameras() {
+
+ /**
+ * Why do we need this? This way we have no dependency on getNumCameras
+ * actually working. On most systems there are only 0, 1, or 2 cameras,
+ * and this covers that 'usual case'. On other systems there might be 3+
+ * cameras, but this will at least check the first 2.
+ */
+ this.mGuessedNumCameras = 0;
+
+ // Front facing camera
+ if (CameraBinderTestUtils.isFeatureAvailable(mContext,
+ PackageManager.FEATURE_CAMERA_FRONT)) {
+ this.mGuessedNumCameras = getGuessedNumCameras() + 1;
+ }
+
+ // Back facing camera
+ if (CameraBinderTestUtils.isFeatureAvailable(mContext,
+ PackageManager.FEATURE_CAMERA)) {
+ this.mGuessedNumCameras = getGuessedNumCameras() + 1;
+ }
+
+ // Any facing camera
+ if (getGuessedNumCameras() == 0
+ && CameraBinderTestUtils.isFeatureAvailable(mContext,
+ PackageManager.FEATURE_CAMERA_ANY)) {
+ this.mGuessedNumCameras = getGuessedNumCameras() + 1;
+ }
+
+ Log.v(CameraBinderTest.TAG, "Guessing there are at least " + getGuessedNumCameras()
+ + " cameras");
+ }
+
+ final static public boolean isFeatureAvailable(Context context, String feature) {
+ final PackageManager packageManager = context.getPackageManager();
+ final FeatureInfo[] featuresList = packageManager.getSystemAvailableFeatures();
+ for (FeatureInfo f : featuresList) {
+ if (f.name != null && f.name.equals(feature)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ ICameraService getCameraService() {
+ return mCameraService;
+ }
+
+ int getGuessedNumCameras() {
+ return mGuessedNumCameras;
+ }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
new file mode 100644
index 0000000..0cbb989
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mediaframeworktest.integration;
+
+import android.graphics.SurfaceTexture;
+import android.hardware.photography.CameraMetadata;
+import android.hardware.photography.CaptureRequest;
+import android.hardware.photography.ICameraDeviceCallbacks;
+import android.hardware.photography.ICameraDeviceUser;
+import android.os.RemoteException;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+import android.view.Surface;
+
+import static android.hardware.photography.CameraDevice.TEMPLATE_PREVIEW;
+
+import com.android.mediaframeworktest.MediaFrameworkIntegrationTestRunner;
+import com.android.mediaframeworktest.integration.CameraBinderTest.DummyBase;
+
+public class CameraDeviceBinderTest extends AndroidTestCase {
+ private static String TAG = "CameraDeviceBinderTest";
+
+ private int mCameraId;
+ private ICameraDeviceUser mCameraUser;
+ private CameraBinderTestUtils mUtils;
+
+ public CameraDeviceBinderTest() {
+ }
+
+ static class DummyCameraDeviceCallbacks extends DummyBase implements ICameraDeviceCallbacks {
+
+ @Override
+ public void notifyCallback(int msgType, int ext1, int ext2) throws RemoteException {
+ }
+
+ @Override
+ public void onResultReceived(int frameId, CameraMetadata result) throws RemoteException {
+ }
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mUtils = new CameraBinderTestUtils(getContext());
+
+ // This cannot be set in the constructor, since the onCreate isn't
+ // called yet
+ mCameraId = MediaFrameworkIntegrationTestRunner.mCameraId;
+
+ ICameraDeviceCallbacks dummyCallbacks = new DummyCameraDeviceCallbacks();
+
+ String clientPackageName = getContext().getPackageName();
+
+ mCameraUser = mUtils.getCameraService().connectDevice(dummyCallbacks, mCameraId,
+ clientPackageName, CameraBinderTestUtils.USE_CALLING_UID);
+ assertNotNull(String.format("Camera %s was null", mCameraId), mCameraUser);
+
+ Log.v(TAG, String.format("Camera %s connected", mCameraId));
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ mCameraUser.disconnect();
+ mCameraUser = null;
+ }
+
+ @SmallTest
+ public void testCreateDefaultRequest() throws Exception {
+ CameraMetadata metadata = new CameraMetadata();
+ assertTrue(metadata.isEmpty());
+
+ int status = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW, /* out */metadata);
+ assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+ assertFalse(metadata.isEmpty());
+
+ metadata.close();
+ }
+
+ @SmallTest
+ public void testCreateStream() throws Exception {
+ SurfaceTexture surfaceTexture = new SurfaceTexture(/* ignored */0);
+ surfaceTexture.setDefaultBufferSize(640, 480);
+ Surface surface = new Surface(surfaceTexture);
+
+ int streamId = mCameraUser.createStream(/* ignored */10, /* ignored */20, /* ignored */30,
+ surface);
+
+ assertEquals(0, streamId);
+
+ assertEquals(CameraBinderTestUtils.ALREADY_EXISTS,
+ mCameraUser.createStream(/* ignored */0, /* ignored */0, /* ignored */0, surface));
+
+ assertEquals(CameraBinderTestUtils.NO_ERROR, mCameraUser.deleteStream(streamId));
+ }
+
+ @SmallTest
+ public void testDeleteInvalidStream() throws Exception {
+ assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(-1));
+ assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(0));
+ assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(1));
+ assertEquals(CameraBinderTestUtils.BAD_VALUE, mCameraUser.deleteStream(0xC0FFEE));
+ }
+
+ @SmallTest
+ public void testCreateStreamTwo() throws Exception {
+
+ // Create first stream
+
+ SurfaceTexture surfaceTexture = new SurfaceTexture(/* ignored */0);
+ surfaceTexture.setDefaultBufferSize(640, 480);
+ Surface surface = new Surface(surfaceTexture);
+
+ int streamId = mCameraUser.createStream(/* ignored */0, /* ignored */0, /* ignored */0,
+ surface);
+
+ assertEquals(0, streamId);
+
+ assertEquals(CameraBinderTestUtils.ALREADY_EXISTS,
+ mCameraUser.createStream(/* ignored */0, /* ignored */0, /* ignored */0, surface));
+
+ // Create second stream.
+
+ SurfaceTexture surfaceTexture2 = new SurfaceTexture(/* ignored */0);
+ surfaceTexture2.setDefaultBufferSize(640, 480);
+ Surface surface2 = new Surface(surfaceTexture2);
+
+ int streamId2 = mCameraUser.createStream(/* ignored */0, /* ignored */0, /* ignored */0,
+ surface2);
+
+ assertEquals(1, streamId2);
+
+ // Clean up streams
+
+ assertEquals(CameraBinderTestUtils.NO_ERROR, mCameraUser.deleteStream(streamId));
+ assertEquals(CameraBinderTestUtils.NO_ERROR, mCameraUser.deleteStream(streamId2));
+ }
+
+ @SmallTest
+ public void testSubmitBadRequest() throws Exception {
+
+ CameraMetadata metadata = new CameraMetadata();
+ assertTrue(metadata.isEmpty());
+
+ CaptureRequest request = new CaptureRequest();
+ assertTrue(request.isEmpty());
+
+ int status = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW, /* out */metadata);
+ assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+ assertFalse(metadata.isEmpty());
+
+ request.swap(metadata);
+ assertFalse(request.isEmpty());
+ assertTrue(metadata.isEmpty());
+
+ status = mCameraUser.submitRequest(request, /* streaming */false);
+ assertEquals("Expected submitRequest to return BAD_VALUE " +
+ "since we had 0 surface targets set.", CameraBinderTestUtils.BAD_VALUE, status);
+
+ SurfaceTexture surfaceTexture = new SurfaceTexture(/* ignored */0);
+ surfaceTexture.setDefaultBufferSize(640, 480);
+ Surface surface = new Surface(surfaceTexture);
+ request.addTarget(surface);
+
+ status = mCameraUser.submitRequest(request, /* streaming */false);
+ assertEquals("Expected submitRequest to return BAD_VALUE since " +
+ "the target surface wasn't registered with createStream.",
+ CameraBinderTestUtils.BAD_VALUE, status);
+
+ request.close();
+ metadata.close();
+ surface.release();
+ }
+
+ @SmallTest
+ public void testSubmitGoodRequest() throws Exception {
+
+ CameraMetadata metadata = new CameraMetadata();
+ assertTrue(metadata.isEmpty());
+
+ CaptureRequest request = new CaptureRequest();
+ assertTrue(request.isEmpty());
+
+ // Create default request from template.
+
+ int status = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW, /* out */metadata);
+ assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+ assertFalse(metadata.isEmpty());
+
+ request.swap(metadata);
+ assertFalse(request.isEmpty());
+ assertTrue(metadata.isEmpty());
+
+ SurfaceTexture surfaceTexture = new SurfaceTexture(/* ignored */0);
+ surfaceTexture.setDefaultBufferSize(640, 480);
+ Surface surface = new Surface(surfaceTexture);
+
+ // Create stream first. Pre-requisite to submitting a request using that
+ // stream.
+
+ int streamId = mCameraUser.createStream(/* ignored */10, /* ignored */20, /* ignored */30,
+ surface);
+ assertEquals(0, streamId);
+
+ request.addTarget(surface);
+
+ // Submit valid request twice.
+
+ int requestId1;
+ requestId1 = mCameraUser.submitRequest(request, /* streaming */false);
+ assertTrue("Request IDs should be non-negative", requestId1 >= 0);
+
+ int requestId2 = mCameraUser.submitRequest(request, /* streaming */false);
+ assertTrue("Request IDs should be non-negative", requestId2 >= 0);
+ assertNotSame("Request IDs should be unique for multiple requests", requestId1, requestId2);
+
+ surface.release();
+ request.close();
+ metadata.close();
+ }
+
+ @SmallTest
+ public void testSubmitStreamingRequest() throws Exception {
+
+ CameraMetadata metadata = new CameraMetadata();
+ assertTrue(metadata.isEmpty());
+
+ CaptureRequest request = new CaptureRequest();
+ assertTrue(request.isEmpty());
+
+ // Create default request from template.
+
+ int status = mCameraUser.createDefaultRequest(TEMPLATE_PREVIEW, /* out */metadata);
+ assertEquals(CameraBinderTestUtils.NO_ERROR, status);
+ assertFalse(metadata.isEmpty());
+
+ request.swap(metadata);
+ assertFalse(request.isEmpty());
+ assertTrue(metadata.isEmpty());
+
+ SurfaceTexture surfaceTexture = new SurfaceTexture(/* ignored */0);
+ surfaceTexture.setDefaultBufferSize(640, 480);
+ Surface surface = new Surface(surfaceTexture);
+
+ // Create stream first. Pre-requisite to submitting a request using that
+ // stream.
+
+ int streamId = mCameraUser.createStream(/* ignored */10, /* ignored */20, /* ignored */30,
+ surface);
+ assertEquals(0, streamId);
+
+ request.addTarget(surface);
+
+ // Submit valid request once (non-streaming), and another time
+ // (streaming)
+
+ int requestId1;
+ requestId1 = mCameraUser.submitRequest(request, /* streaming */true);
+ assertTrue("Request IDs should be non-negative", requestId1 >= 0);
+
+ int requestIdStreaming = mCameraUser.submitRequest(request, /* streaming */false);
+ assertTrue("Request IDs should be non-negative", requestIdStreaming >= 0);
+ assertNotSame("Request IDs should be unique for multiple requests", requestId1,
+ requestIdStreaming);
+
+ status = mCameraUser.cancelRequest(-1);
+ assertEquals("Invalid request IDs should not be cancellable",
+ CameraBinderTestUtils.BAD_VALUE, status);
+
+ status = mCameraUser.cancelRequest(requestId1);
+ assertEquals("Non-streaming request IDs should not be cancellable",
+ CameraBinderTestUtils.BAD_VALUE, status);
+
+ status = mCameraUser.cancelRequest(requestIdStreaming);
+ assertEquals("Streaming request IDs should be cancellable", CameraBinderTestUtils.NO_ERROR,
+ status);
+
+ surface.release();
+ request.close();
+ metadata.close();
+ }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
new file mode 100644
index 0000000..3400434
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import android.os.Parcel;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.hardware.photography.CameraMetadata;
+
+/**
+ * <pre>
+ * adb shell am instrument \
+ * -e class 'com.android.mediaframeworktest.unit.CameraMetadataTest' \
+ * -w com.android.mediaframeworktest/.MediaFrameworkUnitTestRunner
+ * </pre>
+ */
+public class CameraMetadataTest extends junit.framework.TestCase {
+
+ CameraMetadata mMetadata;
+ Parcel mParcel;
+
+ @Override
+ public void setUp() {
+ mMetadata = new CameraMetadata();
+ mParcel = Parcel.obtain();
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ mMetadata.close();
+ mMetadata = null;
+
+ mParcel.recycle();
+ mParcel = null;
+ }
+
+ @SmallTest
+ public void testNew() {
+ assertEquals(0, mMetadata.getEntryCount());
+ assertTrue(mMetadata.isEmpty());
+ }
+
+ @SmallTest
+ public void testClose() throws Exception {
+ mMetadata.isEmpty(); // no throw
+
+ assertFalse(mMetadata.isClosed());
+
+ mMetadata.close();
+
+ assertTrue(mMetadata.isClosed());
+
+ // OK: second close should not throw
+ mMetadata.close();
+
+ assertTrue(mMetadata.isClosed());
+
+ // All other calls after close should throw IllegalStateException
+
+ try {
+ mMetadata.isEmpty();
+ fail("Unreachable -- isEmpty after close should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // good: we expect calling this method after close to fail
+ }
+
+ try {
+ mMetadata.getEntryCount();
+ fail("Unreachable -- getEntryCount after close should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // good: we expect calling this method after close to fail
+ }
+
+
+ try {
+ mMetadata.swap(mMetadata);
+ fail("Unreachable -- swap after close should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // good: we expect calling this method after close to fail
+ }
+
+ try {
+ mMetadata.readFromParcel(mParcel);
+ fail("Unreachable -- readFromParcel after close should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // good: we expect calling this method after close to fail
+ }
+
+ try {
+ mMetadata.writeToParcel(mParcel, /*flags*/0);
+ fail("Unreachable -- writeToParcel after close should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // good: we expect calling this method after close to fail
+ }
+ }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsBinderDecoratorTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsBinderDecoratorTest.java
new file mode 100644
index 0000000..7c48992
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsBinderDecoratorTest.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import android.hardware.photography.CameraAccessException;
+import android.hardware.photography.utils.CameraBinderDecorator;
+import android.hardware.photography.utils.CameraRuntimeException;
+import android.os.DeadObjectException;
+import android.os.RemoteException;
+import android.os.TransactionTooLargeException;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import static org.mockito.Mockito.*;
+import static android.hardware.photography.utils.CameraBinderDecorator.*;
+import static android.hardware.photography.CameraAccessException.*;
+
+import junit.framework.Assert;
+
+public class CameraUtilsBinderDecoratorTest extends junit.framework.TestCase {
+
+ private interface ICameraBinderStereotype {
+
+ double doNothing();
+
+ // int is a 'status_t'
+ int doSomethingPositive();
+
+ int doSomethingNoError();
+
+ int doSomethingPermissionDenied();
+
+ int doSomethingAlreadyExists();
+
+ int doSomethingBadValue();
+
+ int doSomethingDeadObject() throws CameraRuntimeException;
+
+ int doSomethingBadPolicy() throws CameraRuntimeException;
+
+ int doSomethingDeviceBusy() throws CameraRuntimeException;
+
+ int doSomethingNoSuchDevice() throws CameraRuntimeException;
+
+ int doSomethingUnknownErrorCode();
+
+ int doSomethingThrowDeadObjectException() throws RemoteException;
+
+ int doSomethingThrowTransactionTooLargeException() throws RemoteException;
+ }
+
+ private static final double SOME_ARBITRARY_DOUBLE = 1.0;
+ private static final int SOME_ARBITRARY_POSITIVE_INT = 5;
+ private static final int SOME_ARBITRARY_NEGATIVE_INT = -0xC0FFEE;
+
+ @SmallTest
+ public void testStereotypes() {
+
+ ICameraBinderStereotype mock = mock(ICameraBinderStereotype.class);
+ try {
+ when(mock.doNothing()).thenReturn(SOME_ARBITRARY_DOUBLE);
+ when(mock.doSomethingPositive()).thenReturn(SOME_ARBITRARY_POSITIVE_INT);
+ when(mock.doSomethingNoError()).thenReturn(NO_ERROR);
+ when(mock.doSomethingPermissionDenied()).thenReturn(PERMISSION_DENIED);
+ when(mock.doSomethingAlreadyExists()).thenReturn(ALREADY_EXISTS);
+ when(mock.doSomethingBadValue()).thenReturn(BAD_VALUE);
+ when(mock.doSomethingDeadObject()).thenReturn(DEAD_OBJECT);
+ when(mock.doSomethingBadPolicy()).thenReturn(EACCES);
+ when(mock.doSomethingDeviceBusy()).thenReturn(EBUSY);
+ when(mock.doSomethingNoSuchDevice()).thenReturn(ENODEV);
+ when(mock.doSomethingUnknownErrorCode()).thenReturn(SOME_ARBITRARY_NEGATIVE_INT);
+ when(mock.doSomethingThrowDeadObjectException()).thenThrow(new DeadObjectException());
+ when(mock.doSomethingThrowTransactionTooLargeException()).thenThrow(
+ new TransactionTooLargeException());
+ } catch (RemoteException e) {
+ Assert.fail("Unreachable");
+ }
+
+ ICameraBinderStereotype decoratedMock = CameraBinderDecorator.newInstance(mock);
+
+ // ignored by decorator because return type is double, not int
+ assertEquals(SOME_ARBITRARY_DOUBLE, decoratedMock.doNothing());
+
+ // pass through for positive values
+ assertEquals(SOME_ARBITRARY_POSITIVE_INT, decoratedMock.doSomethingPositive());
+
+ // pass through NO_ERROR
+ assertEquals(NO_ERROR, decoratedMock.doSomethingNoError());
+
+ try {
+ decoratedMock.doSomethingPermissionDenied();
+ Assert.fail("Should've thrown SecurityException");
+ } catch (SecurityException e) {
+ }
+
+ assertEquals(ALREADY_EXISTS, decoratedMock.doSomethingAlreadyExists());
+
+ try {
+ decoratedMock.doSomethingBadValue();
+ Assert.fail("Should've thrown IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ }
+
+ try {
+ decoratedMock.doSomethingDeadObject();
+ Assert.fail("Should've thrown CameraRuntimeException");
+ } catch (CameraRuntimeException e) {
+ assertEquals(CAMERA_DISCONNECTED, e.getReason());
+ }
+
+ try {
+ decoratedMock.doSomethingBadPolicy();
+ Assert.fail("Should've thrown CameraRuntimeException");
+ } catch (CameraRuntimeException e) {
+ assertEquals(CAMERA_DISABLED, e.getReason());
+ }
+
+ try {
+ decoratedMock.doSomethingDeviceBusy();
+ Assert.fail("Should've thrown CameraRuntimeException");
+ } catch (CameraRuntimeException e) {
+ assertEquals(CAMERA_IN_USE, e.getReason());
+ }
+
+ try {
+ decoratedMock.doSomethingNoSuchDevice();
+ Assert.fail("Should've thrown CameraRuntimeException");
+ } catch (CameraRuntimeException e) {
+ assertEquals(CAMERA_DISCONNECTED, e.getReason());
+ }
+
+ try {
+ decoratedMock.doSomethingUnknownErrorCode();
+ Assert.fail("Should've thrown UnsupportedOperationException");
+ } catch (UnsupportedOperationException e) {
+ assertEquals(String.format("Unknown error %d",
+ SOME_ARBITRARY_NEGATIVE_INT), e.getMessage());
+ }
+
+ try {
+ decoratedMock.doSomethingThrowDeadObjectException();
+ Assert.fail("Should've thrown CameraRuntimeException");
+ } catch (CameraRuntimeException e) {
+ assertEquals(CAMERA_DISCONNECTED, e.getReason());
+ } catch (RemoteException e) {
+ Assert.fail("Should not throw a DeadObjectException directly, but rethrow");
+ }
+
+ try {
+ decoratedMock.doSomethingThrowTransactionTooLargeException();
+ Assert.fail("Should've thrown UnsupportedOperationException");
+ } catch (UnsupportedOperationException e) {
+ assertTrue(e.getCause() instanceof TransactionTooLargeException);
+ } catch (RemoteException e) {
+ Assert.fail("Should not throw a TransactionTooLargeException directly, but rethrow");
+ }
+ }
+
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsDecoratorTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsDecoratorTest.java
new file mode 100644
index 0000000..bae17fa
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsDecoratorTest.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import android.test.suitebuilder.annotation.SmallTest;
+import android.hardware.photography.utils.*;
+import android.hardware.photography.utils.Decorator.DecoratorListener;
+
+import junit.framework.Assert;
+
+import java.lang.reflect.Method;
+
+/**
+ * adb shell am instrument -e class 'com.android.mediaframeworktest.unit.CameraUtilsDecoratorTest' \
+ * -w com.android.mediaframeworktest/.MediaFrameworkUnitTestRunner
+ */
+public class CameraUtilsDecoratorTest extends junit.framework.TestCase {
+ private DummyListener mDummyListener;
+ private DummyInterface mIface;
+
+ @Override
+ public void setUp() {
+ mDummyListener = new DummyListener();
+ mIface = Decorator.newInstance(new DummyImpl(), mDummyListener);
+ }
+
+ interface DummyInterface {
+ int addValues(int x, int y, int z);
+
+ void raiseException() throws Exception;
+
+ void raiseUnsupportedOperationException() throws UnsupportedOperationException;
+ }
+
+ class DummyImpl implements DummyInterface {
+ @Override
+ public int addValues(int x, int y, int z) {
+ return x + y + z;
+ }
+
+ @Override
+ public void raiseException() throws Exception {
+ throw new Exception("Test exception");
+ }
+
+ @Override
+ public void raiseUnsupportedOperationException() throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("Test exception");
+ }
+ }
+
+ class DummyListener implements DecoratorListener {
+
+ public boolean beforeCalled = false;
+ public boolean afterCalled = false;
+ public boolean catchCalled = false;
+ public boolean finallyCalled = false;
+ public Object resultValue = null;
+
+ public boolean raiseException = false;
+
+ @Override
+ public void onBeforeInvocation(Method m, Object[] args) {
+ beforeCalled = true;
+ }
+
+ @Override
+ public void onAfterInvocation(Method m, Object[] args, Object result) {
+ afterCalled = true;
+ resultValue = result;
+
+ if (raiseException) {
+ throw new UnsupportedOperationException("Test exception");
+ }
+ }
+
+ @Override
+ public boolean onCatchException(Method m, Object[] args, Throwable t) {
+ catchCalled = true;
+ return false;
+ }
+
+ @Override
+ public void onFinally(Method m, Object[] args) {
+ finallyCalled = true;
+ }
+
+ };
+
+ @SmallTest
+ public void testDecorator() {
+
+ // TODO rewrite this using mocks
+
+ assertTrue(mIface.addValues(1, 2, 3) == 6);
+ assertTrue(mDummyListener.beforeCalled);
+ assertTrue(mDummyListener.afterCalled);
+
+ int resultValue = (Integer)mDummyListener.resultValue;
+ assertTrue(resultValue == 6);
+ assertTrue(mDummyListener.finallyCalled);
+ assertFalse(mDummyListener.catchCalled);
+ }
+
+ @SmallTest
+ public void testDecoratorExceptions() {
+
+ boolean gotExceptions = false;
+ try {
+ mIface.raiseException();
+ } catch (Exception e) {
+ gotExceptions = true;
+ assertTrue(e.getMessage() == "Test exception");
+ }
+ assertTrue(gotExceptions);
+ assertTrue(mDummyListener.beforeCalled);
+ assertFalse(mDummyListener.afterCalled);
+ assertTrue(mDummyListener.catchCalled);
+ assertTrue(mDummyListener.finallyCalled);
+ }
+
+ @SmallTest
+ public void testDecoratorUnsupportedOperationException() {
+
+ boolean gotExceptions = false;
+ try {
+ mIface.raiseUnsupportedOperationException();
+ } catch (UnsupportedOperationException e) {
+ gotExceptions = true;
+ assertTrue(e.getMessage() == "Test exception");
+ }
+ assertTrue(gotExceptions);
+ assertTrue(mDummyListener.beforeCalled);
+ assertFalse(mDummyListener.afterCalled);
+ assertTrue(mDummyListener.catchCalled);
+ assertTrue(mDummyListener.finallyCalled);
+ }
+
+ @SmallTest
+ public void testDecoratorRaisesException() {
+
+ boolean gotExceptions = false;
+ try {
+ mDummyListener.raiseException = true;
+ mIface.addValues(1, 2, 3);
+ Assert.fail("unreachable");
+ } catch (UnsupportedOperationException e) {
+ gotExceptions = true;
+ assertTrue(e.getMessage() == "Test exception");
+ }
+ assertTrue(gotExceptions);
+ assertTrue(mDummyListener.beforeCalled);
+ assertTrue(mDummyListener.afterCalled);
+ assertFalse(mDummyListener.catchCalled);
+ assertTrue(mDummyListener.finallyCalled);
+ }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsRuntimeExceptionTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsRuntimeExceptionTest.java
new file mode 100644
index 0000000..8c2dd4d
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsRuntimeExceptionTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import android.hardware.photography.CameraAccessException;
+import android.hardware.photography.utils.CameraRuntimeException;
+import android.hardware.photography.utils.UncheckedThrow;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import junit.framework.Assert;
+
+public class CameraUtilsRuntimeExceptionTest extends junit.framework.TestCase {
+
+ @SmallTest
+ public void testCameraRuntimeException1() {
+ try {
+ CameraRuntimeException runtimeExc = new CameraRuntimeException(12345);
+ throw runtimeExc.asChecked();
+ } catch (CameraAccessException e) {
+ assertEquals(12345, e.getReason());
+ assertNull(e.getMessage());
+ assertNull(e.getCause());
+ }
+ }
+
+ @SmallTest
+ public void testCameraRuntimeException2() {
+ try {
+ CameraRuntimeException runtimeExc = new CameraRuntimeException(12345, "Hello");
+ throw runtimeExc.asChecked();
+ } catch (CameraAccessException e) {
+ assertEquals(12345, e.getReason());
+ assertEquals("Hello", e.getMessage());
+ assertNull(e.getCause());
+ }
+ }
+
+ @SmallTest
+ public void testCameraRuntimeException3() {
+ Throwable cause = new IllegalStateException("For great justice");
+ try {
+ CameraRuntimeException runtimeExc = new CameraRuntimeException(12345, cause);
+ throw runtimeExc.asChecked();
+ } catch (CameraAccessException e) {
+ assertEquals(12345, e.getReason());
+ assertNull(e.getMessage());
+ assertEquals(cause, e.getCause());
+ }
+ }
+
+ @SmallTest
+ public void testCameraRuntimeException4() {
+ Throwable cause = new IllegalStateException("For great justice");
+ try {
+ CameraRuntimeException runtimeExc = new CameraRuntimeException(12345, "Hello", cause);
+ throw runtimeExc.asChecked();
+ } catch (CameraAccessException e) {
+ assertEquals(12345, e.getReason());
+ assertEquals("Hello", e.getMessage());
+ assertEquals(cause, e.getCause());
+ }
+ }
+}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsUncheckedThrowTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsUncheckedThrowTest.java
new file mode 100644
index 0000000..cbe123c
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraUtilsUncheckedThrowTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import android.hardware.photography.CameraAccessException;
+import android.hardware.photography.utils.UncheckedThrow;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import junit.framework.Assert;
+
+public class CameraUtilsUncheckedThrowTest extends junit.framework.TestCase {
+
+ private void fakeNeverThrowsCameraAccess() throws CameraAccessException {
+ }
+
+ @SmallTest
+ public void testUncheckedThrow() {
+ try {
+ UncheckedThrow.throwAnyException(new CameraAccessException(
+ CameraAccessException.CAMERA_DISCONNECTED));
+ Assert.fail("unreachable");
+ fakeNeverThrowsCameraAccess();
+ } catch (CameraAccessException e) {
+ }
+ }
+}
diff --git a/packages/Keyguard/res/values-sw/strings.xml b/packages/Keyguard/res/values-sw/strings.xml
index a022655..014c732 100644
--- a/packages/Keyguard/res/values-sw/strings.xml
+++ b/packages/Keyguard/res/values-sw/strings.xml
@@ -104,7 +104,7 @@
<string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"SIM sasa imelemazwa. Ingiza msimbo wa PUK ili kuendelea. Wasiliana na mtoa huduma kwa maelezo."</string>
<string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"Ingiza msimbo wa PIN unaopendelewa"</string>
<string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"Thibitisha msimbo wa PIN unaopendelewa"</string>
- <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Inafungua kadi ya SIM..."</string>
+ <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"Inafungua SIM kadi..."</string>
<string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"Msimbo wa PIN usio sahihi."</string>
<string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"Charaza PIN iliyo na tarakimu kati ya 4 na 8."</string>
<string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"Msimbo wa PUK unafaa kuwa na nambari 8 au zaidi."</string>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/RemotePrintAdapter.java b/packages/PrintSpooler/src/com/android/printspooler/RemotePrintAdapter.java
index 7537218..c81b00c 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/RemotePrintAdapter.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/RemotePrintAdapter.java
@@ -20,7 +20,7 @@
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.print.IPrintAdapter;
-import android.print.IPrintProgressListener;
+import android.print.IPrintResultCallback;
import android.print.PageRange;
import android.print.PrintAdapterInfo;
import android.print.PrintAttributes;
@@ -50,7 +50,7 @@
private final File mFile;
- private final IPrintProgressListener mIPrintProgressListener;
+ private final IPrintResultCallback mIPrintProgressListener;
private PrintAdapterInfo mInfo;
@@ -61,12 +61,12 @@
public RemotePrintAdapter(IPrintAdapter printAdatper, File file) {
mRemoteInterface = printAdatper;
mFile = file;
- mIPrintProgressListener = new IPrintProgressListener.Stub() {
+ mIPrintProgressListener = new IPrintResultCallback.Stub() {
@Override
- public void onWriteStarted(PrintAdapterInfo info,
+ public void onPrintStarted(PrintAdapterInfo info,
ICancellationSignal cancellationSignal) {
if (DEBUG) {
- Log.i(LOG_TAG, "IPrintProgressListener#onWriteStarted()");
+ Log.i(LOG_TAG, "IPrintProgressListener#onPrintStarted()");
}
synchronized (mLock) {
mInfo = info;
@@ -75,9 +75,9 @@
}
@Override
- public void onWriteFinished(List<PageRange> pages) {
+ public void onPrintFinished(List<PageRange> pages) {
if (DEBUG) {
- Log.i(LOG_TAG, "IPrintProgressListener#onWriteFinished(" + pages + ")");
+ Log.i(LOG_TAG, "IPrintProgressListener#onPrintFinished(" + pages + ")");
}
synchronized (mLock) {
if (isPrintingLocked()) {
@@ -88,9 +88,9 @@
}
@Override
- public void onWriteFailed(CharSequence error) {
+ public void onPrintFailed(CharSequence error) {
if (DEBUG) {
- Log.i(LOG_TAG, "IPrintProgressListener#onWriteFailed(" + error + ")");
+ Log.i(LOG_TAG, "IPrintProgressListener#onPrintFailed(" + error + ")");
}
synchronized (mLock) {
if (isPrintingLocked()) {
diff --git a/packages/SystemUI/Android.mk b/packages/SystemUI/Android.mk
index fc70f7a..f8f064a 100644
--- a/packages/SystemUI/Android.mk
+++ b/packages/SystemUI/Android.mk
@@ -6,7 +6,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src) \
src/com/android/systemui/EventLogTags.logtags
-LOCAL_JAVA_LIBRARIES := services telephony-common
+LOCAL_JAVA_LIBRARIES := telephony-common
LOCAL_PACKAGE_NAME := SystemUI
LOCAL_CERTIFICATE := platform
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 4bb44af..dfc68f4 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -38,7 +38,6 @@
<uses-permission android:name="android.permission.MANAGE_USB" />
<uses-permission android:name="android.permission.DEVICE_POWER" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
- <uses-permission android:name="android.permission.UPDATE_DEVICE_STATS" />
<uses-permission android:name="android.permission.MASTER_CLEAR" />
<uses-permission android:name="android.permission.VIBRATE" />
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 7d5959c..aa66811 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -199,8 +199,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."\n"Sleep weer af vir stelselkontroles."</string>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <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>
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index e66149e..a0d2960 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -199,8 +199,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"Swipe የስርዓት መቆጣጠሪያዎችን ለማምጣት እንደገና ወደ ታች ያንሸራትቱ።"</string>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <string name="hideybar_confirmation_message" msgid="9050869548951044371">"አሞሌውን ለማሳየት የማያ ገጹን ጠርዝ ላይ ያንሸራትቱ"</string>
+ <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"አሞሌውን ለማሳየት ከማያ ገጹ ጠርዝ ጀምረው ያንሸራትቱ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 20347db..1571531 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -199,8 +199,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>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <string name="hideybar_confirmation_message" msgid="9050869548951044371">"مرر سريعًا لحافة الشاشة لإظهار الشريط"</string>
+ <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"مرر سريعًا من حافة الشاشة لإظهار شريط النظام"</string>
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 6cd66e3..6cce40b 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -199,8 +199,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>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Прекарайте пръст по ръба на екрана, за да се покаже лентата"</string>
+ <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Прекарайте пръст от ръба на екрана, за да се покаже системната лента"</string>
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 34b39e2..cf34d5a 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -199,8 +199,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."\n"Stryg ned igen for at komme til systemindstillingerne."</string>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <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>
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 16968e5..43cde46 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -201,8 +201,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."\n"Wischen Sie für Systemeinstellungen erneut nach unten."</string>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <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>
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index f7aa31c..6a04819 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -201,8 +201,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>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Σύρετε από την άκρη της οθόνης για να εμφανίσετε τη γραμμή"</string>
+ <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Σύρετε από την άκρη της οθόνης για να εμφανίσετε τη γραμμή συστήματος"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 68da06a..2f8e0cf 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -199,8 +199,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."\n"Swipe down again for system controls."</string>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <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>
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 770b440..d8ea0d4 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -201,8 +201,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."\n"Vuelve a deslizar el dedo hacia abajo para acceder a los controles del sistema."</string>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <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>
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 5295079..3ae2401 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -199,8 +199,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."\n"Vuelve a deslizar el dedo hacia abajo para acceder a los controles del sistema."</string>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <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>
</resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index f084d2d..4dcf12c 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -199,8 +199,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."\n"Süsteemi juhtnuppude jaoks pühkige uuesti alla."</string>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <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>
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 6c48bed..62b9bd7 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -199,8 +199,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>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <string name="hideybar_confirmation_message" msgid="9050869548951044371">"برای نمایش نوار، انگشت خود را از لبه صفحه به داخل بکشید"</string>
+ <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"برای نمایش نوار سیستم، انگشت خود را از لبه صفحه به داخل بکشید"</string>
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 9f97fdb..a7915a6 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -199,8 +199,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."\n"Voit palauttaa järjestelmän ohjaimet näkyviin liu\'uttamalla sormea alas uudelleen."</string>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <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>
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index aefcfe0..dd2cee6 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -201,8 +201,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."\n"Répétez l\'opération pour accéder aux commandes du système."</string>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <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>
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index e8c07dd..702469e 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -199,8 +199,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>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <string name="hideybar_confirmation_message" msgid="9050869548951044371">"बार दिखाने के लिए स्क्रीन के किनारे को स्वाइप करें"</string>
+ <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"सिस्टम बार दिखाने के लिए स्क्रीन के किनारे से स्वाइप करें"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index a91eda5..ebdc5dd 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -199,8 +199,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. "\n"Ponovo prstom trznite prema dolje za kontrole sustava."</string>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <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>
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index a26575c..9b05a07 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -199,8 +199,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."\n"Húzza le az ujját még egyszer a rendszerbeállítások eléréséhez."</string>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <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>
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 93cfd86..f8b03c6 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -199,8 +199,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."\n"Gesek ke bawah sekali lagi untuk kontrol sistem."</string>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <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>
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index cef3733..5a6b285 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -201,8 +201,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."\n"Fai scorrere di nuovo verso il basso per visualizzare i controlli del sistema."</string>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <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>
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index d352972..653bb78 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -199,8 +199,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>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <string name="hideybar_confirmation_message" msgid="9050869548951044371">"החלק מקצה המסך כדי להציג את הסרגל"</string>
+ <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"החלק מקצה המסך כדי להציג את סרגל המערכת"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index b57898a..a57938d 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -201,8 +201,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>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <string name="hideybar_confirmation_message" msgid="9050869548951044371">"バーを表示するには、画面の端からスワイプします"</string>
+ <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"システムバーを表示するには、画面の端からスワイプします"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index c9585fc..ba9bcbf 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -199,8 +199,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>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <string name="hideybar_confirmation_message" msgid="9050869548951044371">"화면 가장자리에서 스와이프하여 표시줄 표시"</string>
+ <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"화면 가장자리에서 스와이프하여 시스템 표시줄 표시"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 9c57358..4947298 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -199,8 +199,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."\n"Jei norite naudoti sistemos valdiklius, perbraukite žemyn dar kartą."</string>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <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>
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 65cadd5..c8a1a1d 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -199,8 +199,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."\n"Vēlreiz velciet, lai tiktu parādītas sistēmas vadīklas."</string>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <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>
</resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 1bbe4df..4b71cb4 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -199,8 +199,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."\n"Leret ke bawah sekali lagi untuk mendapatkan kawalan sistem."</string>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <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>
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index acda153..4764da6 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -199,8 +199,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."\n"Sveip nedover igjen for å gå til systemkontrollene."</string>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <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>
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 90faf36..5e18d0a 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -199,8 +199,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."\n"Veeg nogmaals met uw vinger omlaag om de systeembesturingselementen weer te geven."</string>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <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>
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index a7eb487..13374ae 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -199,8 +199,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ół."\n"Przesuń jeszcze raz w dół, by otworzyć ustawienia systemowe."</string>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <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>
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 93a47b0..a55aaa4 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -199,8 +199,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."\n"Deslize novamente para baixo para aceder aos controlos do sistema."</string>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <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>
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 5d326d1..37b1819 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -199,8 +199,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."\n"Glisaţi în jos din nou pentru comenzile sistemului."</string>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <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>
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index f09e192..e2abc0c 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -203,8 +203,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>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Чтобы открыть панель, проведите пальцем от края к центру экрана"</string>
+ <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Чтобы открыть панель навигации, проведите пальцем от края к центру экрана"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 4396daa..e9aec22 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -201,8 +201,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."\n"Ak posuniete prstom nadol ešte raz, zobrazia sa ovládacie prvky systému."</string>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <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>
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 4a67b94..a4ad396 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -199,8 +199,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."\n"Za prikaz sistemskih kontrolnikov znova povlecite navzdol."</string>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <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>
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index d37800f..e1a585d 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -199,8 +199,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>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Превуците по ивици екрана да би се приказала трака"</string>
+ <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Превуците од ивице екрана да би се приказала системска трака"</string>
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 0e81a4b..d39c533 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -199,8 +199,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."\n"Dra nedåt igen om du vill visa systemkontroller."</string>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <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>
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 85bcfb9..4e29d81 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -197,8 +197,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."\n"Telezesha chini tena kupata vidhibiti vya mfumo."</string>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <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>
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 18ed6e0..a0cd9a6 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -199,8 +199,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>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <string name="hideybar_confirmation_message" msgid="9050869548951044371">"กวาดขอบของหน้าจอเพื่อแสดงแถบ"</string>
+ <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"กวาดจากขอบของหน้าจอเพื่อแสดงแถบระบบ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 043a23e..4ba399a 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -199,8 +199,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."\n"Muling mag-swipe pababa para sa mga kontrol ng system."</string>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <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>
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 96c64d3..6808f30 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -199,8 +199,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."\n"Sistem denetimleri için tekrar hızlıca aşağı kaydırın."</string>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <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>
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index d470e64..bb507d9 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -199,8 +199,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>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <string name="hideybar_confirmation_message" msgid="9050869548951044371">"Гортайте від краю екрана, щоб з’явилась панель"</string>
+ <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"Проведіть пальцем від краю екрана, щоб з’явилась навігаційна панель"</string>
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index a4eee9d..59e5d1d 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -199,8 +199,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."\n"Vuốt lại xuống để hiển thị các điều khiển hệ thống."</string>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <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>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index ee8de82..af2228b 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -201,8 +201,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>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <string name="hideybar_confirmation_message" msgid="9050869548951044371">"从边缘向里滑可显示系统栏"</string>
+ <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"从屏幕边缘向里滑动即可显示系统栏"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 299f255..c0e5bac 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -201,8 +201,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>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <string name="hideybar_confirmation_message" msgid="9050869548951044371">"滑動螢幕邊緣即可顯示導覽列"</string>
+ <string name="hideybar_confirmation_message_long" msgid="7117692795163620626">"從螢幕邊緣向內滑動即可顯示導覽列"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 53837be..295db6e 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -199,8 +199,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."\n"Swayiphela phansi futhi ngezilawuli zesistimu."</string>
- <!-- no translation found for hideybar_confirmation_message (9050869548951044371) -->
- <skip />
- <!-- no translation found for hideybar_confirmation_message_long (7117692795163620626) -->
- <skip />
+ <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>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
new file mode 100644
index 0000000..323905f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui;
+
+import android.view.Display;
+import android.view.View;
+
+public interface RecentsComponent {
+ void toggleRecents(Display display, int layoutDirection, View statusBarView);
+
+ void preloadRecentTasksList();
+
+ void cancelPreloadingRecentTasksList();
+
+ void closeRecents();
+}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUI.java b/packages/SystemUI/src/com/android/systemui/SystemUI.java
index 6c38cea..fec7329 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUI.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUI.java
@@ -21,9 +21,11 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.Map;
public abstract class SystemUI {
public Context mContext;
+ public Map<Class<?>, Object> mComponents;
public abstract void start();
@@ -32,4 +34,15 @@
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
}
+
+ @SuppressWarnings("unchecked")
+ public <T> T getComponent(Class<T> interfaceType) {
+ return (T) (mComponents != null ? mComponents.get(interfaceType) : null);
+ }
+
+ public <T, C extends T> void putComponent(Class<T> interfaceType, C component) {
+ if (mComponents != null) {
+ mComponents.put(interfaceType, component);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index f130993..ca5f7d1 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -24,6 +24,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.HashMap;
public class SystemUIService extends Service {
private static final String TAG = "SystemUIService";
@@ -32,7 +33,9 @@
* The classes of the stuff to start.
*/
private final Class<?>[] SERVICES = new Class[] {
+ com.android.systemui.recent.Recents.class,
com.android.systemui.statusbar.SystemBars.class,
+ com.android.systemui.usb.StorageNotification.class,
com.android.systemui.power.PowerUI.class,
com.android.systemui.media.RingtonePlayer.class,
com.android.systemui.settings.SettingsUI.class,
@@ -45,6 +48,7 @@
@Override
public void onCreate() {
+ HashMap<Class<?>, Object> components = new HashMap<Class<?>, Object>();
final int N = SERVICES.length;
for (int i=0; i<N; i++) {
Class<?> cl = SERVICES[i];
@@ -57,6 +61,7 @@
throw new RuntimeException(ex);
}
mServices[i].mContext = this;
+ mServices[i].mComponents = components;
Log.d(TAG, "running: " + mServices[i]);
mServices[i].start();
}
diff --git a/packages/SystemUI/src/com/android/systemui/recent/Recents.java b/packages/SystemUI/src/com/android/systemui/recent/Recents.java
new file mode 100644
index 0000000..f51e34b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recent/Recents.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recent;
+
+import android.app.ActivityOptions;
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Paint;
+import android.os.UserHandle;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.Display;
+import android.view.View;
+
+import com.android.systemui.R;
+import com.android.systemui.RecentsComponent;
+import com.android.systemui.SystemUI;
+
+public class Recents extends SystemUI implements RecentsComponent {
+ private static final String TAG = "Recents";
+ private static final boolean DEBUG = false;
+
+ @Override
+ public void start() {
+ putComponent(RecentsComponent.class, this);
+ }
+
+ @Override
+ public void toggleRecents(Display display, int layoutDirection, View statusBarView) {
+ if (DEBUG) Log.d(TAG, "toggle recents panel");
+ try {
+ TaskDescription firstTask = RecentTasksLoader.getInstance(mContext).getFirstTask();
+
+ Intent intent = new Intent(RecentsActivity.TOGGLE_RECENTS_INTENT);
+ intent.setClassName("com.android.systemui",
+ "com.android.systemui.recent.RecentsActivity");
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+
+ if (firstTask == null) {
+ if (RecentsActivity.forceOpaqueBackground(mContext)) {
+ ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
+ R.anim.recents_launch_from_launcher_enter,
+ R.anim.recents_launch_from_launcher_exit);
+ mContext.startActivityAsUser(intent, opts.toBundle(), new UserHandle(
+ UserHandle.USER_CURRENT));
+ } else {
+ // The correct window animation will be applied via the activity's style
+ mContext.startActivityAsUser(intent, new UserHandle(
+ UserHandle.USER_CURRENT));
+ }
+
+ } else {
+ Bitmap first = firstTask.getThumbnail();
+ final Resources res = mContext.getResources();
+
+ float thumbWidth = res
+ .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_width);
+ float thumbHeight = res
+ .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_height);
+ if (first == null) {
+ throw new RuntimeException("Recents thumbnail is null");
+ }
+ if (first.getWidth() != thumbWidth || first.getHeight() != thumbHeight) {
+ first = Bitmap.createScaledBitmap(first, (int) thumbWidth, (int) thumbHeight,
+ true);
+ if (first == null) {
+ throw new RuntimeException("Recents thumbnail is null");
+ }
+ }
+
+
+ DisplayMetrics dm = new DisplayMetrics();
+ display.getMetrics(dm);
+ // calculate it here, but consider moving it elsewhere
+ // first, determine which orientation you're in.
+ final Configuration config = res.getConfiguration();
+ int x, y;
+
+ if (config.orientation == Configuration.ORIENTATION_PORTRAIT) {
+ float appLabelLeftMargin = res.getDimensionPixelSize(
+ R.dimen.status_bar_recents_app_label_left_margin);
+ float appLabelWidth = res.getDimensionPixelSize(
+ R.dimen.status_bar_recents_app_label_width);
+ float thumbLeftMargin = res.getDimensionPixelSize(
+ R.dimen.status_bar_recents_thumbnail_left_margin);
+ float thumbBgPadding = res.getDimensionPixelSize(
+ R.dimen.status_bar_recents_thumbnail_bg_padding);
+
+ float width = appLabelLeftMargin +
+ +appLabelWidth
+ + thumbLeftMargin
+ + thumbWidth
+ + 2 * thumbBgPadding;
+
+ x = (int) ((dm.widthPixels - width) / 2f + appLabelLeftMargin + appLabelWidth
+ + thumbBgPadding + thumbLeftMargin);
+ y = (int) (dm.heightPixels
+ - res.getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_height)
+ - thumbBgPadding);
+ if (layoutDirection == View.LAYOUT_DIRECTION_RTL) {
+ x = dm.widthPixels - x - res.getDimensionPixelSize(
+ R.dimen.status_bar_recents_thumbnail_width);
+ }
+
+ } else { // if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
+ float thumbTopMargin = res.getDimensionPixelSize(
+ R.dimen.status_bar_recents_thumbnail_top_margin);
+ float thumbBgPadding = res.getDimensionPixelSize(
+ R.dimen.status_bar_recents_thumbnail_bg_padding);
+ float textPadding = res.getDimensionPixelSize(
+ R.dimen.status_bar_recents_text_description_padding);
+ float labelTextSize = res.getDimensionPixelSize(
+ R.dimen.status_bar_recents_app_label_text_size);
+ Paint p = new Paint();
+ p.setTextSize(labelTextSize);
+ float labelTextHeight = p.getFontMetricsInt().bottom
+ - p.getFontMetricsInt().top;
+ float descriptionTextSize = res.getDimensionPixelSize(
+ R.dimen.status_bar_recents_app_description_text_size);
+ p.setTextSize(descriptionTextSize);
+ float descriptionTextHeight = p.getFontMetricsInt().bottom
+ - p.getFontMetricsInt().top;
+
+ float statusBarHeight = res.getDimensionPixelSize(
+ com.android.internal.R.dimen.status_bar_height);
+ float recentsItemTopPadding = statusBarHeight;
+
+ float height = thumbTopMargin
+ + thumbHeight
+ + 2 * thumbBgPadding + textPadding + labelTextHeight
+ + recentsItemTopPadding + textPadding + descriptionTextHeight;
+ float recentsItemRightPadding = res
+ .getDimensionPixelSize(R.dimen.status_bar_recents_item_padding);
+ float recentsScrollViewRightPadding = res
+ .getDimensionPixelSize(R.dimen.status_bar_recents_right_glow_margin);
+ x = (int) (dm.widthPixels - res
+ .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_width)
+ - thumbBgPadding - recentsItemRightPadding
+ - recentsScrollViewRightPadding);
+ y = (int) ((dm.heightPixels - statusBarHeight - height) / 2f + thumbTopMargin
+ + recentsItemTopPadding + thumbBgPadding + statusBarHeight);
+ }
+
+ ActivityOptions opts = ActivityOptions.makeThumbnailScaleDownAnimation(
+ statusBarView,
+ first, x, y,
+ new ActivityOptions.OnAnimationStartedListener() {
+ public void onAnimationStarted() {
+ Intent intent =
+ new Intent(RecentsActivity.WINDOW_ANIMATION_START_INTENT);
+ intent.setPackage("com.android.systemui");
+ mContext.sendBroadcastAsUser(intent,
+ new UserHandle(UserHandle.USER_CURRENT));
+ }
+ });
+ intent.putExtra(RecentsActivity.WAITING_FOR_WINDOW_ANIMATION_PARAM, true);
+ mContext.startActivityAsUser(intent, opts.toBundle(), new UserHandle(
+ UserHandle.USER_CURRENT));
+ }
+ } catch (ActivityNotFoundException e) {
+ Log.e(TAG, "Failed to launch RecentAppsIntent", e);
+ }
+ }
+
+ @Override
+ public void preloadRecentTasksList() {
+ if (DEBUG) Log.d(TAG, "preloading recents");
+ Intent intent = new Intent(RecentsActivity.PRELOAD_INTENT);
+ intent.setClassName("com.android.systemui",
+ "com.android.systemui.recent.RecentsPreloadReceiver");
+ mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+
+ RecentTasksLoader.getInstance(mContext).preloadFirstTask();
+ }
+
+ @Override
+ public void cancelPreloadingRecentTasksList() {
+ if (DEBUG) Log.d(TAG, "cancel preloading recents");
+ Intent intent = new Intent(RecentsActivity.CANCEL_PRELOAD_INTENT);
+ intent.setClassName("com.android.systemui",
+ "com.android.systemui.recent.RecentsPreloadReceiver");
+ mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+
+ RecentTasksLoader.getInstance(mContext).cancelPreloadingFirstTask();
+ }
+
+ @Override
+ public void closeRecents() {
+ if (DEBUG) Log.d(TAG, "closing recents panel");
+ Intent intent = new Intent(RecentsActivity.CLOSE_RECENTS_INTENT);
+ intent.setPackage("com.android.systemui");
+ mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index bf82466..3583081 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -1,4 +1,3 @@
-
/*
* Copyright (C) 2010 The Android Open Source Project
*
@@ -19,11 +18,9 @@
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
-import android.app.ActivityOptions;
import android.app.KeyguardManager;
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
-import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -31,10 +28,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
-import android.content.res.Resources;
import android.database.ContentObserver;
-import android.graphics.Bitmap;
-import android.graphics.Paint;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Build;
@@ -47,7 +41,6 @@
import android.provider.Settings;
import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
-import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.IWindowManager;
@@ -70,11 +63,9 @@
import com.android.internal.statusbar.StatusBarIconList;
import com.android.internal.widget.SizeAdaptiveLayout;
import com.android.systemui.R;
+import com.android.systemui.RecentsComponent;
import com.android.systemui.SearchPanelView;
import com.android.systemui.SystemUI;
-import com.android.systemui.recent.RecentTasksLoader;
-import com.android.systemui.recent.RecentsActivity;
-import com.android.systemui.recent.TaskDescription;
import com.android.systemui.statusbar.policy.NotificationRowLayout;
import java.util.ArrayList;
@@ -142,6 +133,8 @@
private boolean mDeviceProvisioned = false;
+ private RecentsComponent mRecents;
+
public IStatusBarService getStatusBarService() {
return mBarService;
}
@@ -219,6 +212,8 @@
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
+ mRecents = getComponent(RecentsComponent.class);
+
mLocale = mContext.getResources().getConfiguration().locale;
mLayoutDirection = TextUtils.getLayoutDirectionFromLocale(mLocale);
@@ -442,9 +437,6 @@
mHandler.sendEmptyMessage(msg);
}
- protected abstract WindowManager.LayoutParams getRecentsLayoutParams(
- LayoutParams layoutParams);
-
protected abstract WindowManager.LayoutParams getSearchLayoutParams(
LayoutParams layoutParams);
@@ -488,140 +480,6 @@
protected abstract View getStatusBarView();
- protected void toggleRecentsActivity() {
- try {
-
- TaskDescription firstTask = RecentTasksLoader.getInstance(mContext).getFirstTask();
-
- Intent intent = new Intent(RecentsActivity.TOGGLE_RECENTS_INTENT);
- intent.setClassName("com.android.systemui",
- "com.android.systemui.recent.RecentsActivity");
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
-
- if (firstTask == null) {
- if (RecentsActivity.forceOpaqueBackground(mContext)) {
- ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
- R.anim.recents_launch_from_launcher_enter,
- R.anim.recents_launch_from_launcher_exit);
- mContext.startActivityAsUser(intent, opts.toBundle(), new UserHandle(
- UserHandle.USER_CURRENT));
- } else {
- // The correct window animation will be applied via the activity's style
- mContext.startActivityAsUser(intent, new UserHandle(
- UserHandle.USER_CURRENT));
- }
-
- } else {
- Bitmap first = firstTask.getThumbnail();
- final Resources res = mContext.getResources();
-
- float thumbWidth = res
- .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_width);
- float thumbHeight = res
- .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_height);
- if (first == null) {
- throw new RuntimeException("Recents thumbnail is null");
- }
- if (first.getWidth() != thumbWidth || first.getHeight() != thumbHeight) {
- first = Bitmap.createScaledBitmap(first, (int) thumbWidth, (int) thumbHeight,
- true);
- if (first == null) {
- throw new RuntimeException("Recents thumbnail is null");
- }
- }
-
-
- DisplayMetrics dm = new DisplayMetrics();
- mDisplay.getMetrics(dm);
- // calculate it here, but consider moving it elsewhere
- // first, determine which orientation you're in.
- final Configuration config = res.getConfiguration();
- int x, y;
-
- if (config.orientation == Configuration.ORIENTATION_PORTRAIT) {
- float appLabelLeftMargin = res
- .getDimensionPixelSize(R.dimen.status_bar_recents_app_label_left_margin);
- float appLabelWidth = res
- .getDimensionPixelSize(R.dimen.status_bar_recents_app_label_width);
- float thumbLeftMargin = res
- .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_left_margin);
- float thumbBgPadding = res
- .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_bg_padding);
-
- float width = appLabelLeftMargin +
- +appLabelWidth
- + thumbLeftMargin
- + thumbWidth
- + 2 * thumbBgPadding;
-
- x = (int) ((dm.widthPixels - width) / 2f + appLabelLeftMargin + appLabelWidth
- + thumbBgPadding + thumbLeftMargin);
- y = (int) (dm.heightPixels
- - res.getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_height) - thumbBgPadding);
- if (mLayoutDirection == View.LAYOUT_DIRECTION_RTL) {
- x = dm.widthPixels - x - res
- .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_width);
- }
-
- } else { // if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
- float thumbTopMargin = res
- .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_top_margin);
- float thumbBgPadding = res
- .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_bg_padding);
- float textPadding = res
- .getDimensionPixelSize(R.dimen.status_bar_recents_text_description_padding);
- float labelTextSize = res
- .getDimensionPixelSize(R.dimen.status_bar_recents_app_label_text_size);
- Paint p = new Paint();
- p.setTextSize(labelTextSize);
- float labelTextHeight = p.getFontMetricsInt().bottom
- - p.getFontMetricsInt().top;
- float descriptionTextSize = res
- .getDimensionPixelSize(R.dimen.status_bar_recents_app_description_text_size);
- p.setTextSize(descriptionTextSize);
- float descriptionTextHeight = p.getFontMetricsInt().bottom
- - p.getFontMetricsInt().top;
-
- float statusBarHeight = res
- .getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
- float recentsItemTopPadding = statusBarHeight;
-
- float height = thumbTopMargin
- + thumbHeight
- + 2 * thumbBgPadding + textPadding + labelTextHeight
- + recentsItemTopPadding + textPadding + descriptionTextHeight;
- float recentsItemRightPadding = res
- .getDimensionPixelSize(R.dimen.status_bar_recents_item_padding);
- float recentsScrollViewRightPadding = res
- .getDimensionPixelSize(R.dimen.status_bar_recents_right_glow_margin);
- x = (int) (dm.widthPixels - res
- .getDimensionPixelSize(R.dimen.status_bar_recents_thumbnail_width)
- - thumbBgPadding - recentsItemRightPadding - recentsScrollViewRightPadding);
- y = (int) ((dm.heightPixels - statusBarHeight - height) / 2f + thumbTopMargin
- + recentsItemTopPadding + thumbBgPadding + statusBarHeight);
- }
-
- ActivityOptions opts = ActivityOptions.makeThumbnailScaleDownAnimation(
- getStatusBarView(),
- first, x, y,
- new ActivityOptions.OnAnimationStartedListener() {
- public void onAnimationStarted() {
- Intent intent = new Intent(RecentsActivity.WINDOW_ANIMATION_START_INTENT);
- intent.setPackage("com.android.systemui");
- mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
- }
- });
- intent.putExtra(RecentsActivity.WAITING_FOR_WINDOW_ANIMATION_PARAM, true);
- mContext.startActivityAsUser(intent, opts.toBundle(), new UserHandle(
- UserHandle.USER_CURRENT));
- }
- return;
- } catch (ActivityNotFoundException e) {
- Log.e(TAG, "Failed to launch RecentAppsIntent", e);
- }
- }
-
protected View.OnTouchListener mRecentsPreloadOnTouchListener = new View.OnTouchListener() {
// additional optimization when we have software system buttons - start loading the recent
// tasks on touch down
@@ -642,24 +500,28 @@
}
};
- protected void preloadRecentTasksList() {
- if (DEBUG) Log.d(TAG, "preloading recents");
- Intent intent = new Intent(RecentsActivity.PRELOAD_INTENT);
- intent.setClassName("com.android.systemui",
- "com.android.systemui.recent.RecentsPreloadReceiver");
- mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+ protected void toggleRecentsActivity() {
+ if (mRecents != null) {
+ mRecents.toggleRecents(mDisplay, mLayoutDirection, getStatusBarView());
+ }
+ }
- RecentTasksLoader.getInstance(mContext).preloadFirstTask();
+ protected void preloadRecentTasksList() {
+ if (mRecents != null) {
+ mRecents.preloadRecentTasksList();
+ }
}
protected void cancelPreloadingRecentTasksList() {
- if (DEBUG) Log.d(TAG, "cancel preloading recents");
- Intent intent = new Intent(RecentsActivity.CANCEL_PRELOAD_INTENT);
- intent.setClassName("com.android.systemui",
- "com.android.systemui.recent.RecentsPreloadReceiver");
- mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+ if (mRecents != null) {
+ mRecents.cancelPreloadingRecentTasksList();
+ }
+ }
- RecentTasksLoader.getInstance(mContext).cancelPreloadingFirstTask();
+ protected void closeRecents() {
+ if (mRecents != null) {
+ mRecents.closeRecents();
+ }
}
protected class H extends Handler {
@@ -667,14 +529,10 @@
Intent intent;
switch (m.what) {
case MSG_TOGGLE_RECENTS_PANEL:
- if (DEBUG) Log.d(TAG, "toggle recents panel");
toggleRecentsActivity();
break;
case MSG_CLOSE_RECENTS_PANEL:
- if (DEBUG) Log.d(TAG, "closing recents panel");
- intent = new Intent(RecentsActivity.CLOSE_RECENTS_INTENT);
- intent.setPackage("com.android.systemui");
- mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+ closeRecents();
break;
case MSG_PRELOAD_RECENT_APPS:
preloadRecentTasksList();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ServiceMonitor.java b/packages/SystemUI/src/com/android/systemui/statusbar/ServiceMonitor.java
index f763f03..aea9ec6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ServiceMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ServiceMonitor.java
@@ -98,6 +98,11 @@
public void onChange(boolean selfChange, Uri uri) {
if (mDebug) Log.d(mTag, "onChange selfChange=" + selfChange + " uri=" + uri);
+ ComponentName cn = getComponentNameFromSetting();
+ if (cn == null && mServiceName == null || cn != null && cn.equals(mServiceName)) {
+ if (mDebug) Log.d(mTag, "skipping no-op restart");
+ return;
+ }
if (mBound) {
mHandler.sendEmptyMessage(MSG_STOP_SERVICE);
}
@@ -178,6 +183,12 @@
mHandler.sendEmptyMessage(MSG_START_SERVICE);
}
+ private ComponentName getComponentNameFromSetting() {
+ String cn = Settings.Secure.getStringForUser(mContext.getContentResolver(),
+ mSettingKey, UserHandle.USER_CURRENT);
+ return cn == null ? null : ComponentName.unflattenFromString(cn);
+ }
+
// everything below is called on the handler
private void packageIntent(Intent intent) {
@@ -210,9 +221,7 @@
}
private void startService() {
- String cn = Settings.Secure.getStringForUser(mContext.getContentResolver(),
- mSettingKey, UserHandle.USER_CURRENT);
- mServiceName = cn == null ? null : ComponentName.unflattenFromString(cn);
+ mServiceName = getComponentNameFromSetting();
if (mDebug) Log.d(mTag, "startService mServiceName=" + mServiceName);
if (mServiceName == null) {
mBound = false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SystemBars.java b/packages/SystemUI/src/com/android/systemui/statusbar/SystemBars.java
index 847bf96..05282fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SystemBars.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SystemBars.java
@@ -84,6 +84,7 @@
throw andLog("Error creating status bar component: " + clsName, t);
}
mStatusBar.mContext = mContext;
+ mStatusBar.mComponents = mComponents;
mStatusBar.start();
if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName());
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index dca8c97e..ee94cc8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -670,31 +670,6 @@
}
@Override
- protected WindowManager.LayoutParams getRecentsLayoutParams(LayoutParams layoutParams) {
- boolean opaque = false;
- WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
- layoutParams.width,
- layoutParams.height,
- WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
- WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
- | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
- (opaque ? PixelFormat.OPAQUE : PixelFormat.TRANSLUCENT));
- if (ActivityManager.isHighEndGfx()) {
- lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
- } else {
- lp.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
- lp.dimAmount = 0.75f;
- }
- lp.gravity = Gravity.BOTTOM | Gravity.START;
- lp.setTitle("RecentsPanel");
- lp.windowAnimations = com.android.internal.R.style.Animation_RecentApplications;
- lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
- | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
- return lp;
- }
-
- @Override
protected WindowManager.LayoutParams getSearchLayoutParams(LayoutParams layoutParams) {
boolean opaque = false;
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 57ec0e5..4ee2a4b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -24,7 +24,6 @@
import android.content.IntentFilter;
import android.media.AudioManager;
import android.os.Handler;
-import android.os.storage.StorageManager;
import android.util.Log;
import com.android.internal.telephony.IccCardConstants;
@@ -57,10 +56,6 @@
private final StatusBarManager mService;
private final Handler mHandler = new Handler();
- // storage
- private StorageManager mStorageManager;
-
-
// Assume it's all good unless we hear otherwise. We don't always seem
// to get broadcasts that it *is* there.
IccCardConstants.State mSimState = IccCardConstants.State.READY;
@@ -136,11 +131,6 @@
filter.addAction(TtyIntent.TTY_ENABLED_CHANGE_ACTION);
mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
- // storage
- mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
- mStorageManager.registerListener(
- new com.android.systemui.usb.StorageNotification(context));
-
// TTY status
mService.setIcon("tty", R.drawable.stat_sys_tty_mode, 0, null);
mService.setIconVisibility("tty", false);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 0e40140..fb2348e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -27,11 +27,9 @@
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wimax.WimaxManagerConstants;
-import android.os.Binder;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
-import android.os.RemoteException;
import android.provider.Settings;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
@@ -42,12 +40,10 @@
import android.widget.ImageView;
import android.widget.TextView;
-import com.android.internal.app.IBatteryStats;
import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.cdma.EriInfo;
import com.android.internal.util.AsyncChannel;
-import com.android.server.am.BatteryStatsService;
import com.android.systemui.R;
import java.io.FileDescriptor;
@@ -166,9 +162,6 @@
boolean mDataAndWifiStacked = false;
- // yuck -- stop doing this here and put it in the framework
- IBatteryStats mBatteryStats;
-
public interface SignalCluster {
void setWifiIndicators(boolean visible, int strengthIcon, int activityIcon,
String contentDescription);
@@ -253,9 +246,6 @@
// AIRPLANE_MODE_CHANGED is sent at boot; we've probably already missed it
updateAirplaneMode();
- // yuck
- mBatteryStats = BatteryStatsService.getService();
-
mLastLocale = mContext.getResources().getConfiguration().locale;
}
@@ -792,15 +782,6 @@
}
}
- // yuck - this should NOT be done by the status bar
- long ident = Binder.clearCallingIdentity();
- try {
- mBatteryStats.notePhoneDataConnectionState(mPhone.getNetworkType(), visible);
- } catch (RemoteException e) {
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
-
mDataDirectionIconId = iconId;
mDataConnected = visible;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index 18b9e26..cf909f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -97,12 +97,6 @@
}
@Override
- protected WindowManager.LayoutParams getRecentsLayoutParams(
- LayoutParams layoutParams) {
- return null;
- }
-
- @Override
protected WindowManager.LayoutParams getSearchLayoutParams(
LayoutParams layoutParams) {
return null;
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index a3eeb47..b75f8b3 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -31,18 +31,15 @@
import android.provider.Settings;
import android.util.Log;
-public class StorageNotification extends StorageEventListener {
+import com.android.systemui.SystemUI;
+
+public class StorageNotification extends SystemUI {
private static final String TAG = "StorageNotification";
private static final boolean DEBUG = false;
private static final boolean POP_UMS_ACTIVITY_ON_CONNECT = true;
/**
- * Binder context for this service
- */
- private Context mContext;
-
- /**
* The notification that is shown when a USB mass storage host
* is connected.
* <p>
@@ -66,32 +63,40 @@
private Handler mAsyncEventHandler;
- public StorageNotification(Context context) {
- mContext = context;
+ private class StorageNotificationEventListener extends StorageEventListener {
+ public void onUsbMassStorageConnectionChanged(final boolean connected) {
+ mAsyncEventHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ onUsbMassStorageConnectionChangedAsync(connected);
+ }
+ });
+ }
+ public void onStorageStateChanged(final String path,
+ final String oldState, final String newState) {
+ mAsyncEventHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ onStorageStateChangedAsync(path, oldState, newState);
+ }
+ });
+ }
+ }
- mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
+ @Override
+ public void start() {
+ mStorageManager = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);
final boolean connected = mStorageManager.isUsbMassStorageConnected();
if (DEBUG) Log.d(TAG, String.format( "Startup with UMS connection %s (media state %s)",
mUmsAvailable, Environment.getExternalStorageState()));
-
+
HandlerThread thr = new HandlerThread("SystemUI StorageNotification");
thr.start();
mAsyncEventHandler = new Handler(thr.getLooper());
- onUsbMassStorageConnectionChanged(connected);
- }
-
- /*
- * @override com.android.os.storage.StorageEventListener
- */
- @Override
- public void onUsbMassStorageConnectionChanged(final boolean connected) {
- mAsyncEventHandler.post(new Runnable() {
- @Override
- public void run() {
- onUsbMassStorageConnectionChangedAsync(connected);
- }
- });
+ StorageNotificationEventListener listener = new StorageNotificationEventListener();
+ listener.onUsbMassStorageConnectionChanged(connected);
+ mStorageManager.registerListener(listener);
}
private void onUsbMassStorageConnectionChangedAsync(boolean connected) {
@@ -115,19 +120,6 @@
updateUsbMassStorageNotification(connected);
}
- /*
- * @override com.android.os.storage.StorageEventListener
- */
- @Override
- public void onStorageStateChanged(final String path, final String oldState, final String newState) {
- mAsyncEventHandler.post(new Runnable() {
- @Override
- public void run() {
- onStorageStateChangedAsync(path, oldState, newState);
- }
- });
- }
-
private void onStorageStateChangedAsync(String path, String oldState, String newState) {
if (DEBUG) Log.i(TAG, String.format(
"Media {%s} state changed from {%s} -> {%s}", path, oldState, newState));
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index a21b089..3ed8bd8 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -49,6 +49,7 @@
import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle;
+import android.os.Debug;
import android.os.Handler;
import android.os.Parcel;
import android.os.Parcelable;
@@ -58,6 +59,7 @@
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
+import android.util.Slog;
import android.util.SparseArray;
import android.util.TypedValue;
import android.view.ActionMode;
diff --git a/services/java/com/android/server/BatteryService.java b/services/java/com/android/server/BatteryService.java
index 32fc18e..de58496 100644
--- a/services/java/com/android/server/BatteryService.java
+++ b/services/java/com/android/server/BatteryService.java
@@ -16,6 +16,7 @@
package com.android.server;
+import android.os.BatteryStats;
import com.android.internal.app.IBatteryStats;
import com.android.server.am.BatteryStatsService;
@@ -89,7 +90,6 @@
private static final int DUMP_MAX_LENGTH = 24 * 1024;
private static final String[] DUMPSYS_ARGS = new String[] { "--checkin", "--unplugged" };
- private static final String BATTERY_STATS_SERVICE_NAME = "batteryinfo";
private static final String DUMPSYS_DATA_PATH = "/data/system/";
@@ -509,7 +509,7 @@
}
private void logBatteryStatsLocked() {
- IBinder batteryInfoService = ServiceManager.getService(BATTERY_STATS_SERVICE_NAME);
+ IBinder batteryInfoService = ServiceManager.getService(BatteryStats.SERVICE_NAME);
if (batteryInfoService == null) return;
DropBoxManager db = (DropBoxManager) mContext.getSystemService(Context.DROPBOX_SERVICE);
@@ -519,7 +519,7 @@
FileOutputStream dumpStream = null;
try {
// dump the service to a file
- dumpFile = new File(DUMPSYS_DATA_PATH + BATTERY_STATS_SERVICE_NAME + ".dump");
+ dumpFile = new File(DUMPSYS_DATA_PATH + BatteryStats.SERVICE_NAME + ".dump");
dumpStream = new FileOutputStream(dumpFile);
batteryInfoService.dump(dumpStream.getFD(), DUMPSYS_ARGS);
FileUtils.sync(dumpStream);
@@ -642,15 +642,25 @@
update = false;
}
if (update) {
- mUpdatesStopped = true;
- processValuesLocked();
+ long ident = Binder.clearCallingIdentity();
+ try {
+ mUpdatesStopped = true;
+ processValuesLocked();
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
}
} catch (NumberFormatException ex) {
pw.println("Bad value: " + value);
}
} else if (args.length == 1 && "reset".equals(args[0])) {
- mUpdatesStopped = false;
- updateLocked();
+ long ident = Binder.clearCallingIdentity();
+ try {
+ mUpdatesStopped = false;
+ updateLocked();
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
} else {
pw.println("Dump current battery state, or:");
pw.println(" set ac|usb|wireless|status|level|invalid <value>");
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 6f8c323..54f6118 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -97,6 +97,7 @@
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.am.BatteryStatsService;
+import com.android.server.connectivity.DataConnectionStats;
import com.android.server.connectivity.Nat464Xlat;
import com.android.server.connectivity.Tethering;
import com.android.server.connectivity.Vpn;
@@ -346,6 +347,8 @@
// the set of network types that can only be enabled by system/sig apps
List mProtectedNetworks;
+ private DataConnectionStats mDataConnectionStats;
+
public ConnectivityService(Context context, INetworkManagementService netd,
INetworkStatsService statsService, INetworkPolicyManager policyManager) {
// Currently, omitting a NetworkFactory will create one internally
@@ -574,6 +577,9 @@
mCaptivePortalTracker = CaptivePortalTracker.makeCaptivePortalTracker(mContext, this);
loadGlobalProxy();
+
+ mDataConnectionStats = new DataConnectionStats(mContext);
+ mDataConnectionStats.startMonitoring();
}
/**
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index 0ab56df..fd6b467 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -195,6 +195,9 @@
private int mCurrentUserId = UserHandle.USER_OWNER;
+ //TODO: Remove this hack
+ private boolean mInitialized;
+
private UserState getCurrentUserStateLocked() {
return getUserStateLocked(mCurrentUserId);
}
@@ -771,6 +774,10 @@
private void switchUser(int userId) {
synchronized (mLock) {
+ if (mCurrentUserId == userId && mInitialized) {
+ return;
+ }
+
// Disconnect from services for the old user.
UserState oldUserState = getUserStateLocked(mCurrentUserId);
oldUserState.onSwitchToAnotherUser();
@@ -1283,6 +1290,8 @@
}
private void onUserStateChangedLocked(UserState userState) {
+ // TODO: Remove this hack
+ mInitialized = true;
updateLegacyCapabilities(userState);
updateServicesLocked(userState);
updateFilterKeyEventsLocked(userState);
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 6b13fc7..ad6ae432 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -33,6 +33,7 @@
import com.android.internal.os.BatteryStatsImpl;
import com.android.internal.os.ProcessStats;
import com.android.internal.os.TransferPipe;
+import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.FastXmlSerializer;
import com.android.server.AppOpsService;
import com.android.server.AttributeCache;
@@ -204,6 +205,7 @@
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_IMMERSIVE = localLOGV || false;
static final boolean DEBUG_MU = localLOGV || false;
static final boolean DEBUG_OOM_ADJ = localLOGV || false;
@@ -1367,9 +1369,9 @@
StringBuilder dropBuilder = new StringBuilder(1024);
StringBuilder logBuilder = new StringBuilder(1024);
StringWriter oomSw = new StringWriter();
- PrintWriter oomPw = new PrintWriter(oomSw);
+ PrintWriter oomPw = new FastPrintWriter(oomSw, false, 256);
StringWriter catSw = new StringWriter();
- PrintWriter catPw = new PrintWriter(catSw);
+ PrintWriter catPw = new FastPrintWriter(catSw, false, 256);
String[] emptyArgs = new String[] { };
StringBuilder tag = new StringBuilder(128);
StringBuilder stack = new StringBuilder(128);
@@ -1379,6 +1381,7 @@
dropBuilder.append(stack);
dropBuilder.append('\n');
dropBuilder.append('\n');
+ oomPw.flush();
String oomString = oomSw.toString();
dropBuilder.append(oomString);
dropBuilder.append('\n');
@@ -1414,6 +1417,7 @@
catPw.println();
dumpActivitiesLocked(null, catPw, emptyArgs, 0, false, false, null);
}
+ catPw.flush();
dropBuilder.append(catSw.toString());
addErrorToDropBox("lowmem", null, "system_server", null,
null, tag.toString(), dropBuilder.toString(), null, null);
@@ -1920,6 +1924,16 @@
st.rel_stime-otherSTime);
ps.addSpeedStepTimes(cpuSpeedTimes);
pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
+ } else if (st.uid >= Process.FIRST_APPLICATION_UID) {
+ BatteryStatsImpl.Uid.Proc ps = st.batteryStats;
+ if (ps == null) {
+ st.batteryStats = ps = bstats.getProcessStatsLocked(st.uid,
+ "(Unknown)");
+ }
+ ps.addCpuTimeLocked(st.rel_utime-otherUTime,
+ st.rel_stime-otherSTime);
+ ps.addSpeedStepTimes(cpuSpeedTimes);
+ pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10;
} else {
BatteryStatsImpl.Uid.Proc ps =
bstats.getProcessStatsLocked(st.name, st.pid);
@@ -1981,6 +1995,7 @@
final void setFocusedActivityLocked(ActivityRecord r) {
if (mFocusedActivity != r) {
+ if (DEBUG_FOCUS) Slog.d(TAG, "setFocusedActivitiyLocked: r=" + r);
mFocusedActivity = r;
mStackSupervisor.setFocusedStack(r);
if (r != null) {
@@ -1992,6 +2007,7 @@
@Override
public void setFocusedStack(int stackId) {
+ if (DEBUG_FOCUS) Slog.d(TAG, "setFocusedStack: stackId=" + stackId);
mHandler.obtainMessage(SET_FOCUSED_STACK, stackId, 0).sendToTarget();
}
@@ -6367,34 +6383,55 @@
@Override
public int createStack(int taskId, int relativeStackBoxId, int position, float weight) {
+ enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
+ "createStack()");
if (DEBUG_STACK) Slog.d(TAG, "createStack: taskId=" + taskId + " relStackBoxId=" +
relativeStackBoxId + " position=" + position + " weight=" + weight);
synchronized (this) {
- int stackId = mStackSupervisor.createStack();
- mWindowManager.createStack(stackId, relativeStackBoxId, position, weight);
- if (taskId > 0) {
- moveTaskToStack(taskId, stackId, true);
+ long ident = Binder.clearCallingIdentity();
+ try {
+ int stackId = mStackSupervisor.createStack();
+ mWindowManager.createStack(stackId, relativeStackBoxId, position, weight);
+ if (taskId > 0) {
+ moveTaskToStack(taskId, stackId, true);
+ }
+ return stackId;
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
- return stackId;
}
}
@Override
public void moveTaskToStack(int taskId, int stackId, boolean toTop) {
+ enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
+ "moveTaskToStack()");
if (stackId == HOME_STACK_ID) {
Slog.e(TAG, "moveTaskToStack: Attempt to move task " + taskId + " to home stack",
new RuntimeException("here").fillInStackTrace());
}
synchronized (this) {
- if (DEBUG_STACK) Slog.d(TAG, "moveTaskToStack: moving task=" + taskId + " to stackId="
- + stackId + " toTop=" + toTop);
- mStackSupervisor.moveTaskToStack(taskId, stackId, toTop);
+ long ident = Binder.clearCallingIdentity();
+ try {
+ if (DEBUG_STACK) Slog.d(TAG, "moveTaskToStack: moving task=" + taskId + " to stackId="
+ + stackId + " toTop=" + toTop);
+ mStackSupervisor.moveTaskToStack(taskId, stackId, toTop);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
}
}
@Override
public void resizeStackBox(int stackBoxId, float weight) {
- mWindowManager.resizeStackBox(stackBoxId, weight);
+ enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
+ "resizeStackBox()");
+ long ident = Binder.clearCallingIdentity();
+ try {
+ mWindowManager.resizeStackBox(stackBoxId, weight);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
}
private ArrayList<StackInfo> getStacks() {
@@ -6444,30 +6481,44 @@
@Override
public List<StackBoxInfo> getStackBoxes() {
- List<StackBoxInfo> stackBoxInfos = mWindowManager.getStackBoxInfos();
- synchronized (this) {
- List<StackInfo> stackInfos = getStacks();
- for (StackBoxInfo stackBoxInfo : stackBoxInfos) {
- addStackInfoToStackBoxInfo(stackBoxInfo, stackInfos);
+ enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
+ "getStackBoxes()");
+ long ident = Binder.clearCallingIdentity();
+ try {
+ List<StackBoxInfo> stackBoxInfos = mWindowManager.getStackBoxInfos();
+ synchronized (this) {
+ List<StackInfo> stackInfos = getStacks();
+ for (StackBoxInfo stackBoxInfo : stackBoxInfos) {
+ addStackInfoToStackBoxInfo(stackBoxInfo, stackInfos);
+ }
}
+ return stackBoxInfos;
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
- return stackBoxInfos;
}
@Override
public StackBoxInfo getStackBoxInfo(int stackBoxId) {
- List<StackBoxInfo> stackBoxInfos = mWindowManager.getStackBoxInfos();
- StackBoxInfo info = null;
- synchronized (this) {
- List<StackInfo> stackInfos = getStacks();
- for (StackBoxInfo stackBoxInfo : stackBoxInfos) {
- addStackInfoToStackBoxInfo(stackBoxInfo, stackInfos);
- if (stackBoxInfo.stackBoxId == stackBoxId) {
- info = stackBoxInfo;
+ enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
+ "getStackBoxInfo()");
+ long ident = Binder.clearCallingIdentity();
+ try {
+ List<StackBoxInfo> stackBoxInfos = mWindowManager.getStackBoxInfos();
+ StackBoxInfo info = null;
+ synchronized (this) {
+ List<StackInfo> stackInfos = getStacks();
+ for (StackBoxInfo stackBoxInfo : stackBoxInfos) {
+ addStackInfoToStackBoxInfo(stackBoxInfo, stackInfos);
+ if (stackBoxInfo.stackBoxId == stackBoxId) {
+ info = stackBoxInfo;
+ }
}
}
+ return info;
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
- return info;
}
@Override
@@ -7527,8 +7578,13 @@
}
synchronized(this) {
- mLockScreenShown = shown;
- comeOutOfSleepIfNeededLocked();
+ long ident = Binder.clearCallingIdentity();
+ try {
+ mLockScreenShown = shown;
+ comeOutOfSleepIfNeededLocked();
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
}
}
@@ -7586,33 +7642,36 @@
enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
"setDebugApp()");
- // Note that this is not really thread safe if there are multiple
- // callers into it at the same time, but that's not a situation we
- // care about.
- if (persistent) {
- final ContentResolver resolver = mContext.getContentResolver();
- Settings.Global.putString(
- resolver, Settings.Global.DEBUG_APP,
- packageName);
- Settings.Global.putInt(
- resolver, Settings.Global.WAIT_FOR_DEBUGGER,
- waitForDebugger ? 1 : 0);
- }
+ long ident = Binder.clearCallingIdentity();
+ try {
+ // Note that this is not really thread safe if there are multiple
+ // callers into it at the same time, but that's not a situation we
+ // care about.
+ if (persistent) {
+ final ContentResolver resolver = mContext.getContentResolver();
+ Settings.Global.putString(
+ resolver, Settings.Global.DEBUG_APP,
+ packageName);
+ Settings.Global.putInt(
+ resolver, Settings.Global.WAIT_FOR_DEBUGGER,
+ waitForDebugger ? 1 : 0);
+ }
- synchronized (this) {
- if (!persistent) {
- mOrigDebugApp = mDebugApp;
- mOrigWaitForDebugger = mWaitForDebugger;
+ synchronized (this) {
+ if (!persistent) {
+ mOrigDebugApp = mDebugApp;
+ mOrigWaitForDebugger = mWaitForDebugger;
+ }
+ mDebugApp = packageName;
+ mWaitForDebugger = waitForDebugger;
+ mDebugTransient = !persistent;
+ if (packageName != null) {
+ forceStopPackageLocked(packageName, -1, false, false, true, true,
+ UserHandle.USER_ALL, "set debug app");
+ }
}
- mDebugApp = packageName;
- mWaitForDebugger = waitForDebugger;
- mDebugTransient = !persistent;
- if (packageName != null) {
- final long origId = Binder.clearCallingIdentity();
- forceStopPackageLocked(packageName, -1, false, false, true, true,
- UserHandle.USER_ALL, "set debug app");
- Binder.restoreCallingIdentity(origId);
- }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
}
@@ -7851,12 +7910,33 @@
}
}
+ @Override
public void unregisterProcessObserver(IProcessObserver observer) {
synchronized (this) {
mProcessObservers.unregister(observer);
}
}
+ @Override
+ public void convertToOpaque(IBinder token) {
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ synchronized (this) {
+ final ActivityRecord r = ActivityRecord.isInStackLocked(token);
+ if (r == null) {
+ return;
+ }
+ if (r.convertToOpaque()) {
+ mWindowManager.setAppFullscreen(token);
+ mStackSupervisor.ensureActivitiesVisibleLocked(null, 0);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+
+ @Override
public void setImmersive(IBinder token, boolean immersive) {
synchronized(this) {
final ActivityRecord r = ActivityRecord.isInStackLocked(token);
@@ -7875,6 +7955,7 @@
}
}
+ @Override
public boolean isImmersive(IBinder token) {
synchronized (this) {
ActivityRecord r = ActivityRecord.isInStackLocked(token);
@@ -7947,7 +8028,7 @@
String reason = (pReason == null) ? "Unknown" : pReason;
// XXX Note: don't acquire main activity lock here, because the window
// manager calls in with its locks held.
-
+
boolean killed = false;
synchronized (mPidsSelfLocked) {
int[] types = new int[pids.length];
@@ -7962,7 +8043,7 @@
}
}
}
-
+
// If the worst oom_adj is somewhere in the cached proc LRU range,
// then constrain it so we will kill all cached procs.
if (worstType < ProcessList.CACHED_APP_MAX_ADJ
@@ -8129,7 +8210,7 @@
// no need to synchronize(this) just to read & return the value
return mSystemReady;
}
-
+
private static File getCalledPreBootReceiversFile() {
File dataDir = Environment.getDataDirectory();
File systemDir = new File(dataDir, "system");
@@ -10930,6 +11011,10 @@
r.processName, myTotalPss, 0);
procMems.add(pssItem);
+ synchronized (this) {
+ r.baseProcessTracker.addPss(myTotalPss);
+ }
+
nativePss += mi.nativePss;
dalvikPss += mi.dalvikPss;
otherPss += mi.otherPss;
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index 561dd0f..f730e07 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -71,7 +71,7 @@
final String processName; // process where this component wants to run
final String taskAffinity; // as per ActivityInfo.taskAffinity
final boolean stateNotNeeded; // As per ActivityInfo.flags
- final boolean fullscreen; // covers the full screen?
+ boolean fullscreen; // covers the full screen?
final boolean noDisplay; // activity is not displayed?
final boolean componentSpecified; // did caller specifiy an explicit component?
@@ -503,6 +503,21 @@
}
}
+ boolean convertToOpaque() {
+ if (fullscreen) {
+ return false;
+ }
+
+ AttributeCache.Entry ent = AttributeCache.instance().get(packageName,
+ realTheme, com.android.internal.R.styleable.Window);
+ if (ent != null && !ent.array.getBoolean(
+ com.android.internal.R.styleable.Window_windowIsFloating, false)) {
+ fullscreen = true;
+ ++task.numFullscreen;
+ }
+ return fullscreen;
+ }
+
void putInHistory() {
if (!inHistory) {
inHistory = true;
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 5e6bdb1..8e8bb55 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -69,6 +69,7 @@
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
+import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -120,6 +121,10 @@
// is being started.
static final boolean SHOW_APP_STARTING_PREVIEW = true;
+ // For debugging to make sure the caller when acquiring/releasing our
+ // wake lock is the system process.
+ static final boolean VALIDATE_WAKE_LOCK_CALLER = true;
+
enum ActivityState {
INITIALIZING,
RESUMED,
@@ -288,6 +293,10 @@
synchronized (mService) {
if (mLaunchingActivity.isHeld()) {
Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
+ if (VALIDATE_WAKE_LOCK_CALLER
+ && Binder.getCallingUid() != Process.myUid()) {
+ throw new IllegalStateException("Calling must be system uid");
+ }
mLaunchingActivity.release();
}
}
@@ -328,6 +337,9 @@
mStackSupervisor = service.mStackSupervisor;
mContext = context;
PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+ if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
+ throw new IllegalStateException("Calling must be system uid");
+ }
mLaunchingActivity =
pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
mLaunchingActivity.setReferenceCounted(false);
@@ -595,6 +607,9 @@
void stopIfSleepingLocked() {
if (mLaunchingActivity.isHeld()) {
+ if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
+ throw new IllegalStateException("Calling must be system uid");
+ }
mLaunchingActivity.release();
mService.mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
}
@@ -722,6 +737,9 @@
// If we are not going to sleep, we want to ensure the device is
// awake until the next activity is started.
if (!mService.isSleepingOrShuttingDown()) {
+ if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
+ throw new IllegalStateException("Calling must be system uid");
+ }
mLaunchingActivity.acquire();
if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
// To be safe, don't allow the wake lock to be held for too long.
@@ -1070,11 +1088,25 @@
r.visible = false;
try {
mWindowManager.setAppVisibility(r.appToken, false);
- if ((r.state == ActivityState.STOPPING
- || r.state == ActivityState.STOPPED)
- && r.app != null && r.app.thread != null) {
- if (DEBUG_VISBILITY) Slog.v(TAG, "Scheduling invisibility: " + r);
- r.app.thread.scheduleWindowVisibility(r.appToken, false);
+ switch (r.state) {
+ case STOPPING:
+ case STOPPED:
+ if (r.app != null && r.app.thread != null) {
+ if (DEBUG_VISBILITY) Slog.v(
+ TAG, "Scheduling invisibility: " + r);
+ r.app.thread.scheduleWindowVisibility(r.appToken, false);
+ }
+ break;
+
+ case INITIALIZING:
+ case RESUMED:
+ case PAUSING:
+ case PAUSED:
+ stopActivityLocked(r);
+ break;
+
+ default:
+ break;
}
} catch (Exception e) {
// Just skip on any failure; we'll make it
@@ -2092,6 +2124,9 @@
// No longer need to keep the device awake.
if (mResumedActivity == res && mLaunchingActivity.isHeld()) {
mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
+ if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
+ throw new IllegalStateException("Calling must be system uid");
+ }
mLaunchingActivity.release();
}
@@ -3298,13 +3333,16 @@
if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
mLastPausedActivity = null;
}
+ final ActivityRecord top = topRunningActivityLocked(null);
+ final boolean launchHomeTaskNext =
+ top != null && top.app == app && top.mLaunchHomeTaskNext;
// Remove this application's activities from active lists.
boolean hasVisibleActivities = removeHistoryRecordsForAppLocked(app);
if (!restarting) {
ActivityStack stack = mStackSupervisor.getFocusedStack();
- if (stack == null) {
+ if (stack == null || launchHomeTaskNext) {
mStackSupervisor.resumeHomeActivity(null);
} else if (!mStackSupervisor.resumeTopActivitiesLocked(stack, null, null)) {
// If there was nothing to resume, and we are not already
diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java
index a4fd7ad..8d98109 100644
--- a/services/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/java/com/android/server/am/ActivityStackSupervisor.java
@@ -22,6 +22,7 @@
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static com.android.server.am.ActivityManagerService.localLOGV;
import static com.android.server.am.ActivityManagerService.DEBUG_CONFIGURATION;
+import static com.android.server.am.ActivityManagerService.DEBUG_FOCUS;
import static com.android.server.am.ActivityManagerService.DEBUG_PAUSE;
import static com.android.server.am.ActivityManagerService.DEBUG_RESULTS;
import static com.android.server.am.ActivityManagerService.DEBUG_STACK;
@@ -1198,9 +1199,13 @@
// Time to create the first app stack for this user.
int stackId = mService.createStack(-1, HOME_STACK_ID,
StackBox.TASK_STACK_GOES_OVER, 1.0f);
+ if (DEBUG_FOCUS) Slog.d(TAG, "getCorrectStack: New stack r=" + r + " stackId="
+ + stackId);
mFocusedStack = getStack(stackId);
}
if (task != null) {
+ if (DEBUG_FOCUS) Slog.d(TAG, "getCorrectStack: Setting focused stack to r=" +
+ r + " task=" + task);
mFocusedStack = task.stack;
}
return mFocusedStack;
@@ -1214,13 +1219,15 @@
}
if (!r.isApplicationActivity() || (r.task != null && !r.task.isApplicationTask())) {
if (mStackState != STACK_STATE_HOME_IN_FRONT) {
- if (DEBUG_STACK) Slog.d(TAG, "setFocusedStack: mStackState old=" +
+ if (DEBUG_STACK || DEBUG_FOCUS) Slog.d(TAG, "setFocusedStack: mStackState old=" +
stackStateToString(mStackState) + " new=" +
stackStateToString(STACK_STATE_HOME_TO_FRONT) +
" Callers=" + Debug.getCallers(3));
mStackState = STACK_STATE_HOME_TO_FRONT;
}
} else {
+ if (DEBUG_FOCUS) Slog.d(TAG, "setFocusedStack: Setting focused stack to r=" +
+ r + " task=" + r.task + " Callers=" + Debug.getCallers(3));
mFocusedStack = r.task.stack;
if (mStackState != STACK_STATE_HOME_IN_BACK) {
if (DEBUG_STACK) Slog.d(TAG, "setFocusedStack: mStackState old=" +
@@ -2170,29 +2177,31 @@
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = mStacks.get(stackNdx);
final ActivityRecord r = stack.topRunningActivityLocked(null);
+ final ActivityState state = r == null ? ActivityState.DESTROYED : r.state;
if (isFrontStack(stack)) {
if (r == null) {
Slog.e(TAG, "validateTop...: null top activity, stack=" + stack);
} else {
- if (stack.mPausingActivity != null) {
+ final ActivityRecord pausing = stack.mPausingActivity;
+ if (pausing != null && pausing == r) {
Slog.e(TAG, "validateTop...: top stack has pausing activity r=" + r +
- " state=" + r.state);
+ " state=" + state);
}
- if (r.state != ActivityState.INITIALIZING &&
- r.state != ActivityState.RESUMED) {
+ if (state != ActivityState.INITIALIZING && state != ActivityState.RESUMED) {
Slog.e(TAG, "validateTop...: activity in front not resumed r=" + r +
- " state=" + r.state);
+ " state=" + state);
}
}
} else {
- if (stack.mResumedActivity != null) {
+ final ActivityRecord resumed = stack.mResumedActivity;
+ if (resumed != null && resumed == r) {
Slog.e(TAG, "validateTop...: back stack has resumed activity r=" + r +
- " state=" + r.state);
+ " state=" + state);
}
- if (r != null && (r.state == ActivityState.INITIALIZING
- || r.state == ActivityState.RESUMED)) {
+ if (r != null && (state == ActivityState.INITIALIZING
+ || state == ActivityState.RESUMED)) {
Slog.e(TAG, "validateTop...: activity in back resumed r=" + r +
- " state=" + r.state);
+ " state=" + state);
}
}
}
diff --git a/services/java/com/android/server/am/ProcessTracker.java b/services/java/com/android/server/am/ProcessTracker.java
index 8a83412..30470f1 100644
--- a/services/java/com/android/server/am/ProcessTracker.java
+++ b/services/java/com/android/server/am/ProcessTracker.java
@@ -24,6 +24,7 @@
import android.util.ArraySet;
import android.util.SparseArray;
import android.util.TimeUtils;
+import com.android.internal.util.ArrayUtils;
import com.android.server.ProcessMap;
import java.io.FileDescriptor;
@@ -47,6 +48,12 @@
public static final int STATE_CACHED = 9;
public static final int STATE_COUNT = STATE_CACHED+1;
+ public static final int PSS_SAMPLE_COUNT = 0;
+ public static final int PSS_MINIMUM = 1;
+ public static final int PSS_AVERAGE = 2;
+ public static final int PSS_MAXIMUM = 3;
+ public static final int PSS_COUNT = PSS_MAXIMUM+1;
+
public static final int ADJ_NOTHING = -1;
public static final int ADJ_MEM_FACTOR_NORMAL = 0;
public static final int ADJ_MEM_FACTOR_MODERATE = 1;
@@ -58,6 +65,23 @@
public static final int ADJ_SCREEN_ON = ADJ_SCREEN_MOD;
public static final int ADJ_COUNT = ADJ_SCREEN_ON*2;
+ // Most data is kept in a sparse data structure: an integer array which integer
+ // holds the type of the entry, and the identifier for a long array that data
+ // exists in and the offset into the array to find it. The constants below
+ // define the encoding of that data in an integer.
+
+ // Where the "type"/"state" part of the data appears in an offset integer.
+ static int OFFSET_TYPE_SHIFT = 0;
+ static int OFFSET_TYPE_MASK = 0xff;
+
+ // Where the "which array" part of the data appears in an offset integer.
+ static int OFFSET_ARRAY_SHIFT = 8;
+ static int OFFSET_ARRAY_MASK = 0xff;
+
+ // Where the "index into array" part of the data appears in an offset integer.
+ static int OFFSET_INDEX_SHIFT = 16;
+ static int OFFSET_INDEX_MASK = 0xffff;
+
static final String[] STATE_NAMES = new String[] {
"Persistent ", "Top ", "Foreground ", "Visible ", "Perceptible",
"Backup ", "Service ", "Home ", "Previous ", "Cached "
@@ -76,6 +100,19 @@
"backup", "service", "home", "prev", "cached"
};
+ static final String[] ADJ_SCREEN_TAGS = new String[] {
+ "0", "1"
+ };
+
+ static final String[] ADJ_MEM_TAGS = new String[] {
+ "n", "m", "l", "c"
+ };
+
+ static final String[] STATE_TAGS = new String[] {
+ "p", "t", "f", "v", "t",
+ "b", "s", "h", "v", "c"
+ };
+
static final String CSV_SEP = "\t";
final Context mContext;
@@ -88,10 +125,16 @@
final int mUid;
final String mName;
- final long[] mDurations = new long[STATE_COUNT*ADJ_COUNT];
+ int[] mDurationsTable;
+ int mDurationsTableSize;
+
+ //final long[] mDurations = new long[STATE_COUNT*ADJ_COUNT];
int mCurState = STATE_NOTHING;
long mStartTime;
+ int[] mPssTable;
+ int mPssTableSize;
+
boolean mMultiPackage;
long mTmpTotalTime;
@@ -126,7 +169,36 @@
ProcessState clone(String pkg, long now) {
ProcessState pnew = new ProcessState(this, pkg, mUid, mName, now);
- pnew.add(this, now);
+ if (mDurationsTable != null) {
+ mState.mFindTable = new int[mDurationsTable.length];
+ mState.mFindTableSize = 0;
+ for (int i=0; i<mDurationsTableSize; i++) {
+ int origEnt = mDurationsTable[i];
+ int type = (origEnt>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
+ int newOff = mState.addLongData(i, type, 1);
+ mState.mFindTable[i] = newOff | type;
+ mState.setLong(newOff, 0, mState.getLong(origEnt, 0));
+ }
+ pnew.mDurationsTable = mState.mFindTable;
+ pnew.mDurationsTableSize = mState.mFindTableSize;
+ }
+ /*
+ if (mPssTable != null) {
+ mState.mFindTable = new int[mPssTable.length];
+ mState.mFindTableSize = 0;
+ for (int i=0; i<mPssTableSize; i++) {
+ int origEnt = mPssTable[i];
+ int type = (origEnt>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
+ int newOff = mState.addLongData(i, type, PSS_COUNT);
+ mState.mFindTable[i] = newOff | type;
+ for (int j=0; j<PSS_COUNT; j++) {
+ mState.setLong(newOff, j, mState.getLong(origEnt, j));
+ }
+ }
+ pnew.mPssTable = mState.mFindTable;
+ pnew.mPssTableSize = mState.mFindTableSize;
+ }
+ */
return pnew;
}
@@ -167,21 +239,87 @@
if (mCurState != state) {
if (mCurState != STATE_NOTHING) {
long dur = now - mStartTime;
- mDurations[mCurState] += dur;
+ int idx = State.binarySearch(mDurationsTable, mDurationsTableSize, mCurState);
+ int off;
+ if (idx >= 0) {
+ off = mDurationsTable[idx];
+ } else {
+ mState.mFindTable = mDurationsTable;
+ mState.mFindTableSize = mDurationsTableSize;
+ off = mState.addLongData(~idx, mCurState, 1);
+ mDurationsTable = mState.mFindTable;
+ mDurationsTableSize = mState.mFindTableSize;
+ }
+ long[] longs = mState.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
+ longs[(off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK] += dur;
}
mCurState = state;
mStartTime = now;
}
}
- void add(ProcessState other, long now) {
- for (int i=0; i<(STATE_COUNT*ADJ_COUNT); i++) {
- mDurations[i] += other.mDurations[i];
- if (other.mCurState == i) {
- mDurations[i] += now - other.mStartTime;
+ public void addPss(long pss) {
+ if (mCurState != STATE_NOTHING) {
+ int idx = State.binarySearch(mPssTable, mPssTableSize, mCurState);
+ int off;
+ if (idx >= 0) {
+ off = mPssTable[idx];
+ } else {
+ mState.mFindTable = mPssTable;
+ mState.mFindTableSize = mPssTableSize;
+ off = mState.addLongData(~idx, mCurState, PSS_COUNT);
+ mPssTable = mState.mFindTable;
+ mPssTableSize = mState.mFindTableSize;
+ }
+ long[] longs = mState.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;
+ } else {
+ longs[idx+PSS_SAMPLE_COUNT] = count+1;
+ if (longs[idx+PSS_MINIMUM] > pss) {
+ longs[idx+PSS_MINIMUM] = pss;
+ }
+ longs[idx+PSS_AVERAGE] = ((longs[idx+PSS_AVERAGE]*count)+pss)/(count+1);
+ if (longs[idx+PSS_MAXIMUM] < pss) {
+ longs[idx+PSS_MAXIMUM] = pss;
+ }
}
}
}
+
+ long getDuration(int state, long now) {
+ int idx = State.binarySearch(mDurationsTable, mDurationsTableSize, state);
+ long time = idx >= 0 ? mState.getLong(mDurationsTable[idx], 0) : 0;
+ if (mCurState == state) {
+ time += now - mStartTime;
+ }
+ return time;
+ }
+
+ long getPssSampleCount(int state) {
+ int idx = State.binarySearch(mPssTable, mPssTableSize, state);
+ return idx >= 0 ? mState.getLong(mPssTable[idx], PSS_SAMPLE_COUNT) : 0;
+ }
+
+ long getPssMinimum(int state) {
+ int idx = State.binarySearch(mPssTable, mPssTableSize, state);
+ return idx >= 0 ? mState.getLong(mPssTable[idx], PSS_MINIMUM) : 0;
+ }
+
+ long getPssAverage(int state) {
+ int idx = State.binarySearch(mPssTable, mPssTableSize, state);
+ return idx >= 0 ? mState.getLong(mPssTable[idx], PSS_AVERAGE) : 0;
+ }
+
+ long getPssMaximum(int state) {
+ int idx = State.binarySearch(mPssTable, mPssTableSize, state);
+ return idx >= 0 ? mState.getLong(mPssTable[idx], PSS_MAXIMUM) : 0;
+ }
}
public static final class ServiceState {
@@ -257,6 +395,76 @@
int mMemFactor = STATE_NOTHING;
long mStartTime;
+ static final int LONGS_SIZE = 4096;
+ final ArrayList<long[]> mLongs = new ArrayList<long[]>();
+ int mNextLong;
+
+ int[] mFindTable;
+ int mFindTableSize;
+
+ int addLongData(int index, int type, int num) {
+ int tableLen = mFindTable != null ? mFindTable.length : 0;
+ if (mFindTableSize >= tableLen) {
+ int newSize = ArrayUtils.idealIntArraySize(tableLen + 1);
+ int[] newTable = new int[newSize];
+ if (tableLen > 0) {
+ System.arraycopy(mFindTable, 0, newTable, 0, tableLen);
+ }
+ mFindTable = newTable;
+ }
+ if (mFindTableSize > 0 && mFindTableSize - index != 0) {
+ System.arraycopy(mFindTable, index, mFindTable, index + 1,
+ mFindTableSize - index);
+ }
+ int off = allocLongData(num);
+ mFindTable[index] = type | off;
+ mFindTableSize++;
+ return off;
+ }
+
+ int allocLongData(int num) {
+ int whichLongs = mLongs.size()-1;
+ long[] longs = mLongs.get(whichLongs);
+ if (mNextLong + num > longs.length) {
+ longs = new long[LONGS_SIZE];
+ mLongs.add(longs);
+ whichLongs++;
+ mNextLong = 0;
+ }
+ int off = (whichLongs<<OFFSET_ARRAY_SHIFT) | (mNextLong<<OFFSET_INDEX_SHIFT);
+ mNextLong += num;
+ return off;
+ }
+
+ void setLong(int off, int index, long value) {
+ long[] longs = mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
+ longs[index + ((off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK)] = value;
+ }
+
+ long getLong(int off, int index) {
+ long[] longs = mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
+ return longs[index + ((off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK)];
+ }
+
+ static int binarySearch(int[] array, int size, int value) {
+ int lo = 0;
+ int hi = size - 1;
+
+ while (lo <= hi) {
+ int mid = (lo + hi) >>> 1;
+ int midVal = (array[mid] >> OFFSET_TYPE_SHIFT) & OFFSET_TYPE_MASK;
+
+ if (midVal < value) {
+ lo = mid + 1;
+ } else if (midVal > value) {
+ hi = mid - 1;
+ } else {
+ return mid; // value found
+ }
+ }
+ return ~lo; // value not present
+ }
+
PackageState getPackageStateLocked(String packageName, int uid) {
PackageState as = mPackages.get(packageName, uid);
if (as != null) {
@@ -305,9 +513,16 @@
return ps;
}
+ State() {
+ reset();
+ }
+
void reset() {
mPackages.getMap().clear();
mProcesses.getMap().clear();
+ mLongs.clear();
+ mLongs.add(new long[LONGS_SIZE]);
+ mNextLong = 0;
Arrays.fill(mMemFactorDurations, 0);
mMemFactor = STATE_NOTHING;
mStartTime = 0;
@@ -480,11 +695,7 @@
time += now - curStartTime;
}
pw.print(sep);
- if (time != 0) {
- pw.print(time);
- } else {
- pw.print("0");
- }
+ pw.print(time);
}
}
}
@@ -510,15 +721,21 @@
long computeProcessTimeLocked(ProcessState proc, int[] screenStates, int[] memStates,
int[] procStates, long now) {
long totalTime = 0;
+ /*
+ for (int i=0; i<proc.mDurationsTableSize; i++) {
+ int val = proc.mDurationsTable[i];
+ totalTime += proc.mState.getLong(val, 0);
+ if ((val&0xff) == proc.mCurState) {
+ totalTime += now - proc.mStartTime;
+ }
+ }
+ */
for (int is=0; is<screenStates.length; is++) {
for (int im=0; im<memStates.length; im++) {
for (int ip=0; ip<procStates.length; ip++) {
int bucket = ((screenStates[is]+ memStates[im]) * STATE_COUNT)
+ procStates[ip];
- totalTime += proc.mDurations[bucket];
- if (proc.mCurState == bucket) {
- totalTime += now - proc.mStartTime;
- }
+ totalTime += proc.getDuration(bucket, now);
}
}
}
@@ -579,10 +796,9 @@
final int iscreen = screenStates[is];
final int imem = memStates[im];
final int bucket = ((iscreen + imem) * STATE_COUNT) + procStates[ip];
- long time = proc.mDurations[bucket];
+ long time = proc.getDuration(bucket, now);
String running = "";
if (proc.mCurState == bucket) {
- time += now - proc.mStartTime;
running = " (running)";
}
if (time != 0) {
@@ -617,6 +833,52 @@
}
}
+ void dumpProcessPss(PrintWriter pw, String prefix, ProcessState proc, int[] screenStates,
+ int[] memStates, int[] procStates) {
+ boolean printedHeader = false;
+ int printedScreen = -1;
+ for (int is=0; is<screenStates.length; is++) {
+ int printedMem = -1;
+ for (int im=0; im<memStates.length; im++) {
+ for (int ip=0; ip<procStates.length; ip++) {
+ final int iscreen = screenStates[is];
+ final int imem = memStates[im];
+ final int bucket = ((iscreen + imem) * STATE_COUNT) + procStates[ip];
+ long count = proc.getPssSampleCount(bucket);
+ if (count > 0) {
+ if (!printedHeader) {
+ pw.print(prefix);
+ pw.print("PSS (");
+ pw.print(proc.mPssTableSize);
+ pw.println(" entries):");
+ printedHeader = true;
+ }
+ pw.print(prefix);
+ pw.print(" ");
+ if (screenStates.length > 1) {
+ printScreenLabel(pw, printedScreen != iscreen
+ ? iscreen : STATE_NOTHING);
+ printedScreen = iscreen;
+ }
+ if (memStates.length > 1) {
+ printMemLabel(pw, printedMem != imem ? imem : STATE_NOTHING);
+ printedMem = imem;
+ }
+ pw.print(STATE_NAMES[procStates[ip]]); pw.print(": ");
+ pw.print(count);
+ pw.print(" samples ");
+ pw.print(proc.getPssMinimum(bucket));
+ pw.print("kB ");
+ pw.print(proc.getPssAverage(bucket));
+ pw.print("kB ");
+ pw.print(proc.getPssMaximum(bucket));
+ pw.println("kB");
+ }
+ }
+ }
+ }
+ }
+
void dumpStateHeadersCsv(PrintWriter pw, String sep, int[] screenStates,
int[] memStates, int[] procStates) {
final int NS = screenStates != null ? screenStates.length : 1;
@@ -673,19 +935,12 @@
final int vaproc = sepProcStates ? 0 : procStates[ipa];
final int bucket = ((vsscreen + vascreen + vsmem + vamem)
* STATE_COUNT) + vsproc + vaproc;
- totalTime += proc.mDurations[bucket];
- if (proc.mCurState == bucket) {
- totalTime += now - proc.mStartTime;
- }
+ totalTime += proc.getDuration(bucket, now);
}
}
}
pw.print(CSV_SEP);
- if (totalTime != 0) {
- pw.print(totalTime);
- } else {
- pw.print("0");
- }
+ pw.print(totalTime);
}
}
}
@@ -700,8 +955,14 @@
pw.print(proc.mName);
pw.print(" / ");
UserHandle.formatUid(pw, proc.mUid);
+ pw.print(" (");
+ pw.print(proc.mDurationsTableSize);
+ pw.print(" entries)");
pw.println(":");
dumpProcessState(pw, innerPrefix, proc, screenStates, memStates, procStates, now);
+ if (proc.mPssTableSize > 0) {
+ dumpProcessPss(pw, innerPrefix, proc, screenStates, memStates, procStates);
+ }
}
}
@@ -753,8 +1014,7 @@
return false;
}
- void dumpAllProcessState(PrintWriter pw, String prefix, boolean isCheckin,
- ProcessState proc, long now) {
+ void dumpAllProcessState(PrintWriter pw, String prefix, ProcessState proc, long now) {
long totalTime = 0;
int printedScreen = -1;
for (int iscreen=0; iscreen<ADJ_COUNT; iscreen+=ADJ_SCREEN_MOD) {
@@ -762,50 +1022,97 @@
for (int imem=0; imem<ADJ_MEM_FACTOR_COUNT; imem++) {
for (int is=0; is<STATE_NAMES.length; is++) {
int bucket = is+(STATE_COUNT*(imem+iscreen));
- long time = proc.mDurations[bucket];
+ long time = proc.getDuration(bucket, now);
String running = "";
if (proc.mCurState == bucket) {
- time += now - proc.mStartTime;
running = " (running)";
}
- if (!isCheckin) {
- if (time != 0) {
- pw.print(prefix);
- printScreenLabel(pw, printedScreen != iscreen
- ? iscreen : STATE_NOTHING);
- printedScreen = iscreen;
- printMemLabel(pw, printedMem != imem
- ? imem : STATE_NOTHING);
- printedMem = imem;
- pw.print(STATE_NAMES[is]); pw.print(": ");
- TimeUtils.formatDuration(time, pw); pw.println(running);
- totalTime += time;
- }
- } else {
- pw.print(",");
- if (time != 0) {
- pw.print(time);
- } else {
- pw.print("0");
- }
+ if (time != 0) {
+ pw.print(prefix);
+ printScreenLabel(pw, printedScreen != iscreen
+ ? iscreen : STATE_NOTHING);
+ printedScreen = iscreen;
+ printMemLabel(pw, printedMem != imem
+ ? imem : STATE_NOTHING);
+ printedMem = imem;
+ pw.print(STATE_NAMES[is]); pw.print(": ");
+ TimeUtils.formatDuration(time, pw); pw.println(running);
+ totalTime += time;
}
}
}
}
- if (!isCheckin) {
- if (totalTime != 0) {
- pw.print(prefix);
- printScreenLabel(pw, STATE_NOTHING);
- printMemLabel(pw, STATE_NOTHING);
- pw.print("TOTAL : ");
- TimeUtils.formatDuration(totalTime, pw);
- pw.println();
- }
- } else {
+ if (totalTime != 0) {
+ pw.print(prefix);
+ printScreenLabel(pw, STATE_NOTHING);
+ printMemLabel(pw, STATE_NOTHING);
+ pw.print("TOTAL : ");
+ TimeUtils.formatDuration(totalTime, pw);
pw.println();
}
}
+ static int printArrayEntry(PrintWriter pw, String[] array, int value, int mod) {
+ int index = value/mod;
+ if (index >= 0 && index < array.length) {
+ pw.print(array[index]);
+ } else {
+ pw.print('?');
+ }
+ return value - index*mod;
+ }
+
+ void printProcStateTag(PrintWriter pw, int state) {
+ state = printArrayEntry(pw, ADJ_SCREEN_TAGS, state, ADJ_SCREEN_MOD*STATE_COUNT);
+ state = printArrayEntry(pw, ADJ_MEM_TAGS, state, STATE_COUNT);
+ printArrayEntry(pw, STATE_TAGS, state, 1);
+ }
+
+ void printProcStateTagAndValue(PrintWriter pw, int state, long value) {
+ pw.print(',');
+ printProcStateTag(pw, state);
+ pw.print(':');
+ pw.print(value);
+ }
+
+ void dumpAllProcessStateCheckin(PrintWriter pw, ProcessState proc, long now) {
+ boolean didCurState = false;
+ for (int i=0; i<proc.mDurationsTableSize; i++) {
+ int off = proc.mDurationsTable[i];
+ int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
+ long time = proc.mState.getLong(off, 0);
+ if (proc.mCurState == type) {
+ didCurState = true;
+ time += now - proc.mStartTime;
+ }
+ printProcStateTagAndValue(pw, type, time);
+ }
+ if (!didCurState) {
+ printProcStateTagAndValue(pw, proc.mCurState, now - proc.mStartTime);
+ }
+ }
+
+ void dumpAllProcessPssCheckin(PrintWriter pw, ProcessState proc, long now) {
+ for (int i=0; i<proc.mPssTableSize; i++) {
+ int off = proc.mPssTable[i];
+ int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
+ long count = proc.mState.getLong(off, PSS_SAMPLE_COUNT);
+ long min = proc.mState.getLong(off, PSS_MINIMUM);
+ long avg = proc.mState.getLong(off, PSS_AVERAGE);
+ long max = proc.mState.getLong(off, PSS_MAXIMUM);
+ pw.print(',');
+ printProcStateTag(pw, type);
+ pw.print(':');
+ pw.print(count);
+ pw.print(':');
+ pw.print(min);
+ pw.print(':');
+ pw.print(avg);
+ pw.print(':');
+ pw.print(max);
+ }
+ }
+
static int[] parseStateList(String[] states, int mult, String arg, boolean[] outSep,
String[] outError) {
ArrayList<Integer> res = new ArrayList<Integer>();
@@ -1025,6 +1332,8 @@
if (NPROCS > 0 || NSRVS > 0) {
if (!printedHeader) {
pw.println("Per-Package Process Stats:");
+ pw.print(" Num long arrays: "); pw.println(mState.mLongs.size());
+ pw.print(" Next long entry: "); pw.println(mState.mNextLong);
printedHeader = true;
}
pw.print(" * "); pw.print(pkgName); pw.print(" / ");
@@ -1032,10 +1341,15 @@
}
}
for (int iproc=0; iproc<NPROCS; iproc++) {
+ ProcessState proc = state.mProcesses.valueAt(iproc);
if (!isCheckin) {
pw.print(" Process ");
pw.print(state.mProcesses.keyAt(iproc));
+ pw.print(" (");
+ pw.print(proc.mDurationsTableSize);
+ pw.print(" entries)");
pw.println(":");
+ dumpAllProcessState(pw, " ", proc, now);
} else {
pw.print("pkgproc,");
pw.print(pkgName);
@@ -1043,9 +1357,9 @@
pw.print(uid);
pw.print(",");
pw.print(state.mProcesses.keyAt(iproc));
+ dumpAllProcessStateCheckin(pw, proc, now);
+ pw.println();
}
- dumpAllProcessState(pw, " ", isCheckin,
- state.mProcesses.valueAt(iproc), now);
}
for (int isvc=0; isvc<NSRVS; isvc++) {
if (!isCheckin) {
@@ -1125,14 +1439,25 @@
for (int iu=0; iu<uids.size(); iu++) {
int uid = uids.keyAt(iu);
ProcessState state = uids.valueAt(iu);
- pw.print("proc,");
- pw.print(procName);
- pw.print(",");
- pw.print(uid);
- dumpAllProcessState(pw, " ", isCheckin, state, now);
+ if (state.mDurationsTableSize > 0) {
+ pw.print("proc,");
+ pw.print(procName);
+ pw.print(",");
+ pw.print(uid);
+ dumpAllProcessStateCheckin(pw, state, now);
+ pw.println();
+ }
+ if (state.mPssTableSize > 0) {
+ pw.print("pss,");
+ pw.print(procName);
+ pw.print(",");
+ pw.print(uid);
+ dumpAllProcessPssCheckin(pw, state, now);
+ pw.println();
+ }
}
}
- pw.print("total,");
+ pw.print("total");
dumpSingleTimeCsv(pw, ",", mState.mMemFactorDurations, mState.mMemFactor,
mState.mStartTime, now);
pw.println();
diff --git a/services/java/com/android/server/connectivity/DataConnectionStats.java b/services/java/com/android/server/connectivity/DataConnectionStats.java
new file mode 100644
index 0000000..227ab23
--- /dev/null
+++ b/services/java/com/android/server/connectivity/DataConnectionStats.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.os.RemoteException;
+import android.telephony.PhoneStateListener;
+import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+
+import com.android.internal.app.IBatteryStats;
+import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.server.am.BatteryStatsService;
+
+public class DataConnectionStats extends BroadcastReceiver {
+ private static final String TAG = "DataConnectionStats";
+ private static final boolean DEBUG = false;
+
+ private final Context mContext;
+ private final IBatteryStats mBatteryStats;
+
+ private IccCardConstants.State mSimState = IccCardConstants.State.READY;
+ private SignalStrength mSignalStrength;
+ private ServiceState mServiceState;
+ private int mDataState = TelephonyManager.DATA_DISCONNECTED;
+
+ public DataConnectionStats(Context context) {
+ mContext = context;
+ mBatteryStats = BatteryStatsService.getService();
+ }
+
+ public void startMonitoring() {
+ TelephonyManager phone =
+ (TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ phone.listen(mPhoneStateListener,
+ PhoneStateListener.LISTEN_SERVICE_STATE
+ | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
+ | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
+ | PhoneStateListener.LISTEN_DATA_ACTIVITY);
+
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+ filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+ filter.addAction(ConnectivityManager.INET_CONDITION_ACTION);
+ mContext.registerReceiver(this, filter);
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
+ updateSimState(intent);
+ notePhoneDataConnectionState();
+ } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION) ||
+ action.equals(ConnectivityManager.INET_CONDITION_ACTION)) {
+ notePhoneDataConnectionState();
+ }
+ }
+
+ private void notePhoneDataConnectionState() {
+ if (mServiceState == null) {
+ return;
+ }
+ boolean simReadyOrUnknown = mSimState == IccCardConstants.State.READY
+ || mSimState == IccCardConstants.State.UNKNOWN;
+ boolean visible = (simReadyOrUnknown || isCdma()) // we only check the sim state for GSM
+ && hasService()
+ && mDataState == TelephonyManager.DATA_CONNECTED;
+ int networkType = mServiceState.getDataNetworkType();
+ if (DEBUG) Log.d(TAG, String.format("Noting data connection for network type %s: %svisible",
+ networkType, visible ? "" : "not "));
+ try {
+ mBatteryStats.notePhoneDataConnectionState(networkType, visible);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error noting data connection state", e);
+ }
+ }
+
+ private final void updateSimState(Intent intent) {
+ String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
+ if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
+ mSimState = IccCardConstants.State.ABSENT;
+ } else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
+ mSimState = IccCardConstants.State.READY;
+ } else if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(stateExtra)) {
+ final String lockedReason =
+ intent.getStringExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON);
+ if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN.equals(lockedReason)) {
+ mSimState = IccCardConstants.State.PIN_REQUIRED;
+ } else if (IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK.equals(lockedReason)) {
+ mSimState = IccCardConstants.State.PUK_REQUIRED;
+ } else {
+ mSimState = IccCardConstants.State.NETWORK_LOCKED;
+ }
+ } else {
+ mSimState = IccCardConstants.State.UNKNOWN;
+ }
+ }
+
+ private boolean isCdma() {
+ return mSignalStrength != null && !mSignalStrength.isGsm();
+ }
+
+ private boolean hasService() {
+ return mServiceState != null
+ && mServiceState.getState() != ServiceState.STATE_OUT_OF_SERVICE
+ && mServiceState.getState() != ServiceState.STATE_POWER_OFF;
+ }
+
+ private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
+ @Override
+ public void onSignalStrengthsChanged(SignalStrength signalStrength) {
+ mSignalStrength = signalStrength;
+ }
+
+ @Override
+ public void onServiceStateChanged(ServiceState state) {
+ mServiceState = state;
+ notePhoneDataConnectionState();
+ }
+
+ @Override
+ public void onDataConnectionStateChanged(int state, int networkType) {
+ mDataState = state;
+ notePhoneDataConnectionState();
+ }
+
+ @Override
+ public void onDataActivity(int direction) {
+ notePhoneDataConnectionState();
+ }
+ };
+}
diff --git a/services/java/com/android/server/content/SyncManager.java b/services/java/com/android/server/content/SyncManager.java
index 80c7d88..9e2e841 100644
--- a/services/java/com/android/server/content/SyncManager.java
+++ b/services/java/com/android/server/content/SyncManager.java
@@ -75,6 +75,7 @@
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.accounts.AccountManagerService;
+import com.android.server.content.SyncStorageEngine.AuthorityInfo;
import com.android.server.content.SyncStorageEngine.OnSyncRequestListener;
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
@@ -112,7 +113,7 @@
private static final long MAX_TIME_PER_SYNC;
static {
- final boolean isLargeRAM = ActivityManager.isLargeRAM();
+ final boolean isLargeRAM = !ActivityManager.isLowRamDeviceStatic();
int defaultMaxInitSyncs = isLargeRAM ? 5 : 2;
int defaultMaxRegularSyncs = isLargeRAM ? 2 : 1;
MAX_SIMULTANEOUS_INITIALIZATION_SYNCS =
@@ -1248,10 +1249,11 @@
continue;
}
int row = table.getNumRows();
- SyncStorageEngine.AuthorityInfo settings =
- mSyncStorageEngine.getOrCreateAuthority(
+ Pair<AuthorityInfo, SyncStatusInfo> syncAuthoritySyncStatus =
+ mSyncStorageEngine.getCopyOfAuthorityWithSyncStatus(
account.account, account.userId, syncAdapterType.type.authority);
- SyncStatusInfo status = mSyncStorageEngine.getOrCreateSyncStatus(settings);
+ SyncStorageEngine.AuthorityInfo settings = syncAuthoritySyncStatus.first;
+ SyncStatusInfo status = syncAuthoritySyncStatus.second;
String authority = settings.authority;
if (authority.length() > 50) {
@@ -1269,10 +1271,10 @@
for (int i = 0; i < settings.periodicSyncs.size(); i++) {
- final Pair<Bundle, Long> pair = settings.periodicSyncs.get(0);
+ final Pair<Bundle, Long> pair = settings.periodicSyncs.get(i);
final String period = String.valueOf(pair.second);
final String extras = pair.first.size() > 0 ? pair.first.toString() : "";
- final String next = formatTime(status.getPeriodicSyncTime(0)
+ final String next = formatTime(status.getPeriodicSyncTime(i)
+ pair.second * 1000);
table.set(row + i * 2, 12, period + extras);
table.set(row + i * 2 + 1, 12, next);
@@ -1758,7 +1760,8 @@
final Pair<Account, String> wakeLockKey = Pair.create(account, authority);
PowerManager.WakeLock wakeLock = mWakeLocks.get(wakeLockKey);
if (wakeLock == null) {
- final String name = SYNC_WAKE_LOCK_PREFIX + "_" + authority + "_" + account;
+ final String name = SYNC_WAKE_LOCK_PREFIX + "/" + authority + "/" + account.type
+ + "/" + account.name;
wakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, name);
wakeLock.setReferenceCounted(false);
mWakeLocks.put(wakeLockKey, wakeLock);
@@ -1942,30 +1945,36 @@
final long nowAbsolute = System.currentTimeMillis();
final long shiftedNowAbsolute = (0 < nowAbsolute - mSyncRandomOffsetMillis)
- ? (nowAbsolute - mSyncRandomOffsetMillis) : 0;
+ ? (nowAbsolute - mSyncRandomOffsetMillis) : 0;
- ArrayList<SyncStorageEngine.AuthorityInfo> infos = mSyncStorageEngine.getAuthorities();
- for (SyncStorageEngine.AuthorityInfo info : infos) {
- // skip the sync if the account of this operation no longer exists
- if (!containsAccountAndUser(accounts, info.account, info.userId)) {
+ ArrayList<Pair<AuthorityInfo, SyncStatusInfo>> infos = mSyncStorageEngine
+ .getCopyOfAllAuthoritiesWithSyncStatus();
+ for (Pair<AuthorityInfo, SyncStatusInfo> info : infos) {
+ final AuthorityInfo authorityInfo = info.first;
+ final SyncStatusInfo status = info.second;
+ // skip the sync if the account of this operation no longer
+ // exists
+ if (!containsAccountAndUser(
+ accounts, authorityInfo.account, authorityInfo.userId)) {
continue;
}
- if (!mSyncStorageEngine.getMasterSyncAutomatically(info.userId)
- || !mSyncStorageEngine.getSyncAutomatically(info.account, info.userId,
- info.authority)) {
+ if (!mSyncStorageEngine.getMasterSyncAutomatically(authorityInfo.userId)
+ || !mSyncStorageEngine.getSyncAutomatically(
+ authorityInfo.account, authorityInfo.userId,
+ authorityInfo.authority)) {
continue;
}
- if (getIsSyncable(info.account, info.userId, info.authority)
+ if (getIsSyncable(
+ authorityInfo.account, authorityInfo.userId, authorityInfo.authority)
== 0) {
continue;
}
- SyncStatusInfo status = mSyncStorageEngine.getOrCreateSyncStatus(info);
- for (int i = 0, N = info.periodicSyncs.size(); i < N; i++) {
- final Bundle extras = info.periodicSyncs.get(i).first;
- final Long periodInMillis = info.periodicSyncs.get(i).second * 1000;
+ for (int i = 0, N = authorityInfo.periodicSyncs.size(); i < N; i++) {
+ final Bundle extras = authorityInfo.periodicSyncs.get(i).first;
+ final Long periodInMillis = authorityInfo.periodicSyncs.get(i).second * 1000;
// Skip if the period is invalid
if (periodInMillis <= 0) {
continue;
@@ -1974,51 +1983,56 @@
final long lastPollTimeAbsolute = status.getPeriodicSyncTime(i);
long remainingMillis
- = periodInMillis - (shiftedNowAbsolute % periodInMillis);
+ = periodInMillis - (shiftedNowAbsolute % periodInMillis);
/*
- * Sync scheduling strategy:
- * Set the next periodic sync based on a random offset (in seconds).
- *
- * Also sync right now if any of the following cases hold
- * and mark it as having been scheduled
- *
- * Case 1: This sync is ready to run now.
- * Case 2: If the lastPollTimeAbsolute is in the future,
- * sync now and reinitialize. This can happen for
- * example if the user changed the time, synced and
- * changed back.
- * Case 3: If we failed to sync at the last scheduled time
+ * Sync scheduling strategy: Set the next periodic sync
+ * based on a random offset (in seconds). Also sync right
+ * now if any of the following cases hold and mark it as
+ * having been scheduled
+ * Case 1: This sync is ready to run
+ * now.
+ * Case 2: If the lastPollTimeAbsolute is in the
+ * future, sync now and reinitialize. This can happen for
+ * example if the user changed the time, synced and changed
+ * back.
+ * Case 3: If we failed to sync at the last scheduled
+ * time
*/
- if (remainingMillis == periodInMillis // Case 1
+ if (remainingMillis == periodInMillis // Case 1
|| lastPollTimeAbsolute > nowAbsolute // Case 2
|| (nowAbsolute - lastPollTimeAbsolute
>= periodInMillis)) { // Case 3
// Sync now
final Pair<Long, Long> backoff = mSyncStorageEngine.getBackoff(
- info.account, info.userId, info.authority);
+ authorityInfo.account, authorityInfo.userId,
+ authorityInfo.authority);
final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo;
syncAdapterInfo = mSyncAdapters.getServiceInfo(
- SyncAdapterType.newKey(info.authority, info.account.type),
- info.userId);
+ SyncAdapterType.newKey(
+ authorityInfo.authority, authorityInfo.account.type),
+ authorityInfo.userId);
if (syncAdapterInfo == null) {
continue;
}
scheduleSyncOperation(
- new SyncOperation(info.account, info.userId,
+ new SyncOperation(authorityInfo.account, authorityInfo.userId,
SyncOperation.REASON_PERIODIC,
SyncStorageEngine.SOURCE_PERIODIC,
- info.authority, extras, 0 /* delay */,
- backoff != null ? backoff.first : 0,
+ authorityInfo.authority, extras, 0 /* delay */,
+ backoff != null ? backoff.first : 0,
mSyncStorageEngine.getDelayUntilTime(
- info.account, info.userId, info.authority),
+ authorityInfo.account, authorityInfo.userId,
+ authorityInfo.authority),
syncAdapterInfo.type.allowParallelSyncs()));
- status.setPeriodicSyncTime(i, nowAbsolute);
+ mSyncStorageEngine.setPeriodicSyncTime(authorityInfo.ident,
+ authorityInfo.periodicSyncs.get(i), nowAbsolute);
}
// Compute when this periodic sync should next run
final long nextPollTimeAbsolute = nowAbsolute + remainingMillis;
- // remember this time if it is earlier than earliestFuturePollTime
+ // remember this time if it is earlier than
+ // earliestFuturePollTime
if (nextPollTimeAbsolute < earliestFuturePollTime) {
earliestFuturePollTime = nextPollTimeAbsolute;
}
@@ -2032,8 +2046,8 @@
// convert absolute time to elapsed time
return SystemClock.elapsedRealtime()
+ ((earliestFuturePollTime < nowAbsolute)
- ? 0
- : (earliestFuturePollTime - nowAbsolute));
+ ? 0
+ : (earliestFuturePollTime - nowAbsolute));
}
private long maybeStartNextSyncLocked() {
diff --git a/services/java/com/android/server/content/SyncStorageEngine.java b/services/java/com/android/server/content/SyncStorageEngine.java
index 5b8d26f..863def3 100644
--- a/services/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/java/com/android/server/content/SyncStorageEngine.java
@@ -44,6 +44,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
+import com.android.server.content.SyncStorageEngine.AuthorityInfo;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -813,14 +814,6 @@
}
}
- public AuthorityInfo getOrCreateAuthority(Account account, int userId, String authority) {
- synchronized (mAuthorities) {
- return getOrCreateAuthorityLocked(account, userId, authority,
- -1 /* assign a new identifier if creating a new authority */,
- true /* write to storage if this results in a change */);
- }
- }
-
public void removeAuthority(Account account, int userId, String authority) {
synchronized (mAuthorities) {
removeAuthorityLocked(account, userId, authority, true /* doWrite */);
@@ -1238,17 +1231,27 @@
}
/**
- * Return an array of the current authorities. Note
- * that the objects inside the array are the real, live objects,
- * so be careful what you do with them.
+ * Return a copy of the specified authority with the corresponding sync status
*/
- public ArrayList<AuthorityInfo> getAuthorities() {
+ public Pair<AuthorityInfo, SyncStatusInfo> getCopyOfAuthorityWithSyncStatus(
+ Account account, int userId, String authority) {
synchronized (mAuthorities) {
- final int N = mAuthorities.size();
- ArrayList<AuthorityInfo> infos = new ArrayList<AuthorityInfo>(N);
- for (int i=0; i<N; i++) {
- // Make deep copy because AuthorityInfo syncs are liable to change.
- infos.add(new AuthorityInfo(mAuthorities.valueAt(i)));
+ AuthorityInfo authorityInfo = getOrCreateAuthorityLocked(account, userId, authority,
+ -1 /* assign a new identifier if creating a new authority */,
+ true /* write to storage if this results in a change */);
+ return createCopyPairOfAuthorityWithSyncStatusLocked(authorityInfo);
+ }
+ }
+
+ /**
+ * Return a copy of all authorities with their corresponding sync status
+ */
+ public ArrayList<Pair<AuthorityInfo, SyncStatusInfo>> getCopyOfAllAuthoritiesWithSyncStatus() {
+ synchronized (mAuthorities) {
+ ArrayList<Pair<AuthorityInfo, SyncStatusInfo>> infos =
+ new ArrayList<Pair<AuthorityInfo, SyncStatusInfo>>(mAuthorities.size());
+ for (int i = 0; i < mAuthorities.size(); i++) {
+ infos.add(createCopyPairOfAuthorityWithSyncStatusLocked(mAuthorities.valueAt(i)));
}
return infos;
}
@@ -1337,6 +1340,12 @@
}
}
+ private Pair<AuthorityInfo, SyncStatusInfo> createCopyPairOfAuthorityWithSyncStatusLocked(
+ AuthorityInfo authorityInfo) {
+ SyncStatusInfo syncStatusInfo = getOrCreateSyncStatusLocked(authorityInfo.ident);
+ return Pair.create(new AuthorityInfo(authorityInfo), new SyncStatusInfo(syncStatusInfo));
+ }
+
private int getCurrentDayLocked() {
mCal.setTimeInMillis(System.currentTimeMillis());
final int dayOfYear = mCal.get(Calendar.DAY_OF_YEAR);
@@ -1427,9 +1436,22 @@
}
}
- public SyncStatusInfo getOrCreateSyncStatus(AuthorityInfo authority) {
+ /**
+ * Updates (in a synchronized way) the periodic sync time of the specified
+ * authority id and target periodic sync
+ */
+ public void setPeriodicSyncTime(
+ int authorityId, Pair<Bundle, Long> targetPeriodicSync, long when) {
synchronized (mAuthorities) {
- return getOrCreateSyncStatusLocked(authority.ident);
+ final AuthorityInfo authority = mAuthorities.get(authorityId);
+ for (int i = 0; i < authority.periodicSyncs.size(); i++) {
+ Pair<Bundle, Long> periodicSync = authority.periodicSyncs.get(i);
+ if (periodicSync.first == targetPeriodicSync.first
+ && periodicSync.second == targetPeriodicSync.second) {
+ mSyncStatus.get(authorityId).setPeriodicSyncTime(i, when);
+ break;
+ }
+ }
}
}
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
old mode 100644
new mode 100755
index 9ea4262..8fde010
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -35,6 +35,7 @@
import com.android.internal.app.ResolverActivity;
import com.android.internal.content.NativeLibraryHelper;
import com.android.internal.content.PackageHelper;
+import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
import com.android.server.DeviceStorageMonitorService;
@@ -1932,8 +1933,6 @@
getDataPathForPackage(packageName, 0).getPath();
pkg.applicationInfo.nativeLibraryDir = ps.nativeLibraryPathString;
}
- // pkg.mSetEnabled = ps.getEnabled(userId);
- // pkg.mSetStopped = ps.getStopped(userId);
return generatePackageInfo(pkg, flags, userId);
}
return null;
@@ -3363,7 +3362,7 @@
try {
File fname = getSettingsProblemFile();
FileOutputStream out = new FileOutputStream(fname, true);
- PrintWriter pw = new PrintWriter(out);
+ PrintWriter pw = new FastPrintWriter(out);
SimpleDateFormat formatter = new SimpleDateFormat();
String dateString = formatter.format(new Date(System.currentTimeMillis()));
pw.println(dateString + ": " + msg);
@@ -3553,10 +3552,13 @@
}
// The apk is forward locked (not public) if its code and resources
- // are kept in different files.
+ // are kept in different files. (except for app in either system or
+ // vendor path).
// TODO grab this value from PackageSettings
- if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
- parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
+ if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
+ if (ps != null && !ps.codePath.equals(ps.resourcePath)) {
+ parseFlags |= PackageParser.PARSE_FORWARD_LOCK;
+ }
}
String codePath = null;
@@ -6148,6 +6150,120 @@
mHandler.sendMessage(msg);
}
+ private void sendPackageAddedForUser(String packageName, PackageSetting pkgSetting, int userId) {
+ Bundle extras = new Bundle(1);
+ extras.putInt(Intent.EXTRA_UID, UserHandle.getUid(userId, pkgSetting.appId));
+
+ sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
+ packageName, extras, null, null, new int[] {userId});
+ try {
+ IActivityManager am = ActivityManagerNative.getDefault();
+ final boolean isSystem =
+ isSystemApp(pkgSetting) || isUpdatedSystemApp(pkgSetting);
+ if (isSystem && am.isUserRunning(userId, false)) {
+ // The just-installed/enabled app is bundled on the system, so presumed
+ // to be able to run automatically without needing an explicit launch.
+ // Send it a BOOT_COMPLETED if it would ordinarily have gotten one.
+ Intent bcIntent = new Intent(Intent.ACTION_BOOT_COMPLETED)
+ .addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
+ .setPackage(packageName);
+ am.broadcastIntent(null, bcIntent, null, null, 0, null, null, null,
+ android.app.AppOpsManager.OP_NONE, false, false, userId);
+ }
+ } catch (RemoteException e) {
+ // shouldn't happen
+ Slog.w(TAG, "Unable to bootstrap installed package", e);
+ }
+ }
+
+ @Override
+ public boolean setApplicationBlockedSettingAsUser(String packageName, boolean blocked,
+ int userId) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
+ PackageSetting pkgSetting;
+ final int uid = Binder.getCallingUid();
+ if (UserHandle.getUserId(uid) != userId) {
+ mContext.enforceCallingPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ "setApplicationBlocked for user " + userId);
+ }
+
+ if (blocked && isPackageDeviceAdmin(packageName, userId)) {
+ Slog.w(TAG, "Not blocking package " + packageName + ": has active device admin");
+ return false;
+ }
+
+ long callingId = Binder.clearCallingIdentity();
+ try {
+ boolean sendAdded = false;
+ boolean sendRemoved = false;
+ // writer
+ synchronized (mPackages) {
+ pkgSetting = mSettings.mPackages.get(packageName);
+ if (pkgSetting == null) {
+ return false;
+ }
+ if (pkgSetting.getBlocked(userId) != blocked) {
+ pkgSetting.setBlocked(blocked, userId);
+ mSettings.writePackageRestrictionsLPr(userId);
+ if (blocked) {
+ sendRemoved = true;
+ } else {
+ sendAdded = true;
+ }
+ }
+ }
+ if (sendAdded) {
+ sendPackageAddedForUser(packageName, pkgSetting, userId);
+ return true;
+ }
+ if (sendRemoved) {
+ sendPackageBlockedForUser(packageName, pkgSetting, userId);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(callingId);
+ }
+ return false;
+ }
+
+ private void sendPackageBlockedForUser(String packageName, PackageSetting pkgSetting,
+ int userId) {
+ final PackageRemovedInfo info = new PackageRemovedInfo();
+ info.removedPackage = packageName;
+ info.removedUsers = new int[] {userId};
+ info.uid = UserHandle.getUid(userId, pkgSetting.appId);
+ info.sendBroadcast(false, false, false);
+ }
+
+ /**
+ * Returns true if application is not found or there was an error. Otherwise it returns
+ * the blocked state of the package for the given user.
+ */
+ @Override
+ public boolean getApplicationBlockedSettingAsUser(String packageName, int userId) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
+ PackageSetting pkgSetting;
+ final int uid = Binder.getCallingUid();
+ if (UserHandle.getUserId(uid) != userId) {
+ mContext.enforceCallingPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ "getApplicationBlocked for user " + userId);
+ }
+ long callingId = Binder.clearCallingIdentity();
+ try {
+ // writer
+ synchronized (mPackages) {
+ pkgSetting = mSettings.mPackages.get(packageName);
+ if (pkgSetting == null) {
+ return true;
+ }
+ return pkgSetting.getBlocked(userId);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(callingId);
+ }
+ }
+
/**
* @hide
*/
@@ -6179,33 +6295,14 @@
}
if (!pkgSetting.getInstalled(userId)) {
pkgSetting.setInstalled(true, userId);
+ pkgSetting.setBlocked(false, userId);
mSettings.writePackageRestrictionsLPr(userId);
- extras.putInt(Intent.EXTRA_UID, UserHandle.getUid(userId, pkgSetting.appId));
sendAdded = true;
}
}
if (sendAdded) {
- sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
- packageName, extras, null, null, new int[] {userId});
- try {
- IActivityManager am = ActivityManagerNative.getDefault();
- final boolean isSystem =
- isSystemApp(pkgSetting) || isUpdatedSystemApp(pkgSetting);
- if (isSystem && am.isUserRunning(userId, false)) {
- // The just-installed/enabled app is bundled on the system, so presumed
- // to be able to run automatically without needing an explicit launch.
- // Send it a BOOT_COMPLETED if it would ordinarily have gotten one.
- Intent bcIntent = new Intent(Intent.ACTION_BOOT_COMPLETED)
- .addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES)
- .setPackage(packageName);
- am.broadcastIntent(null, bcIntent, null, null, 0, null, null, null,
- android.app.AppOpsManager.OP_NONE, false, false, userId);
- }
- } catch (RemoteException e) {
- // shouldn't happen
- Slog.w(TAG, "Unable to bootstrap installed package", e);
- }
+ sendPackageAddedForUser(packageName, pkgSetting, userId);
}
} finally {
Binder.restoreCallingIdentity(callingId);
@@ -8272,6 +8369,9 @@
boolean updatedSettings = false;
parseFlags |= PackageManager.INSTALL_REPLACE_EXISTING |
PackageParser.PARSE_IS_SYSTEM;
+ if ((deletedPackage.applicationInfo.flags&ApplicationInfo.FLAG_PRIVILEGED) != 0) {
+ parseFlags |= PackageParser.PARSE_IS_PRIVILEGED;
+ }
String packageName = deletedPackage.packageName;
res.returnCode = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
if (packageName == null) {
@@ -8696,6 +8796,19 @@
});
}
+ private boolean isPackageDeviceAdmin(String packageName, int userId) {
+ IDevicePolicyManager dpm = IDevicePolicyManager.Stub.asInterface(
+ ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
+ try {
+ if (dpm != null && (dpm.packageHasActiveAdmins(packageName, userId)
+ || dpm.isDeviceOwner(packageName))) {
+ return true;
+ }
+ } catch (RemoteException e) {
+ }
+ return false;
+ }
+
/**
* This method is an internal method that could be get invoked either
* to delete an installed package or to clean up a failed installation.
@@ -8714,15 +8827,9 @@
final PackageRemovedInfo info = new PackageRemovedInfo();
final boolean res;
- IDevicePolicyManager dpm = IDevicePolicyManager.Stub.asInterface(
- ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
- try {
- if (dpm != null && (dpm.packageHasActiveAdmins(packageName, userId)
- || dpm.isDeviceOwner(packageName))) {
- Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");
- return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER;
- }
- } catch (RemoteException e) {
+ if (isPackageDeviceAdmin(packageName, userId)) {
+ Slog.w(TAG, "Not removing package " + packageName + ": has active device admin");
+ return PackageManager.DELETE_FAILED_DEVICE_POLICY_MANAGER;
}
boolean removedForAllUsers = false;
@@ -9038,6 +9145,7 @@
false, //installed
true, //stopped
true, //notLaunched
+ false, //blocked
null, null, null);
if (!isSystemApp(ps)) {
if (ps.isAnyInstalled(sUserManager.getUserIds())) {
diff --git a/services/java/com/android/server/pm/PackageSettingBase.java b/services/java/com/android/server/pm/PackageSettingBase.java
index b3fd60c..7747c8f 100644
--- a/services/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/java/com/android/server/pm/PackageSettingBase.java
@@ -260,14 +260,24 @@
modifyUserState(userId).notLaunched = stop;
}
+ boolean getBlocked(int userId) {
+ return readUserState(userId).blocked;
+ }
+
+ void setBlocked(boolean blocked, int userId) {
+ modifyUserState(userId).blocked = blocked;
+ }
+
void setUserState(int userId, int enabled, boolean installed, boolean stopped,
- boolean notLaunched, String lastDisableAppCaller, HashSet<String> enabledComponents,
+ boolean notLaunched, boolean blocked,
+ String lastDisableAppCaller, HashSet<String> enabledComponents,
HashSet<String> disabledComponents) {
PackageUserState state = modifyUserState(userId);
state.enabled = enabled;
state.installed = installed;
state.stopped = stopped;
state.notLaunched = notLaunched;
+ state.blocked = blocked;
state.lastDisableAppCaller = lastDisableAppCaller;
state.enabledComponents = enabledComponents;
state.disabledComponents = disabledComponents;
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index 0cae5d65..2d7d8a0 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -109,6 +109,7 @@
private static final String ATTR_ENABLED = "enabled";
private static final String ATTR_ENABLED_CALLER = "enabledCaller";
private static final String ATTR_STOPPED = "stopped";
+ private static final String ATTR_BLOCKED = "blocked";
private static final String ATTR_INSTALLED = "inst";
private final File mSettingsFilename;
@@ -462,6 +463,7 @@
installed,
true, // stopped,
true, // notLaunched
+ false, // blocked
null, null, null);
writePackageRestrictionsLPr(user.id);
}
@@ -860,6 +862,7 @@
true, // installed
false, // stopped
false, // notLaunched
+ false, // blocked
null, null, null);
}
return;
@@ -913,6 +916,9 @@
final String stoppedStr = parser.getAttributeValue(null, ATTR_STOPPED);
final boolean stopped = stoppedStr == null
? false : Boolean.parseBoolean(stoppedStr);
+ final String blockedStr = parser.getAttributeValue(null, ATTR_BLOCKED);
+ final boolean blocked = blockedStr == null
+ ? false : Boolean.parseBoolean(blockedStr);
final String notLaunchedStr = parser.getAttributeValue(null, ATTR_NOT_LAUNCHED);
final boolean notLaunched = stoppedStr == null
? false : Boolean.parseBoolean(notLaunchedStr);
@@ -936,7 +942,7 @@
}
}
- ps.setUserState(userId, enabled, installed, stopped, notLaunched,
+ ps.setUserState(userId, enabled, installed, stopped, notLaunched, blocked,
enabledCaller, enabledComponents, disabledComponents);
} else if (tagName.equals("preferred-activities")) {
readPreferredActivitiesLPw(parser, userId);
@@ -1044,6 +1050,7 @@
PackageUserState ustate = pkg.readUserState(userId);
if (ustate.stopped || ustate.notLaunched || !ustate.installed
|| ustate.enabled != COMPONENT_ENABLED_STATE_DEFAULT
+ || ustate.blocked
|| (ustate.enabledComponents != null
&& ustate.enabledComponents.size() > 0)
|| (ustate.disabledComponents != null
@@ -1061,6 +1068,9 @@
if (ustate.notLaunched) {
serializer.attribute(null, ATTR_NOT_LAUNCHED, "true");
}
+ if (ustate.blocked) {
+ serializer.attribute(null, ATTR_BLOCKED, "true");
+ }
if (ustate.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
serializer.attribute(null, ATTR_ENABLED,
Integer.toString(ustate.enabled));
@@ -2847,6 +2857,8 @@
pw.print(prefix); pw.print(" User "); pw.print(user.id); pw.print(": ");
pw.print(" installed=");
pw.print(ps.getInstalled(user.id));
+ pw.print(" blocked=");
+ pw.print(ps.getBlocked(user.id));
pw.print(" stopped=");
pw.print(ps.getStopped(user.id));
pw.print(" notLaunched=");
diff --git a/services/java/com/android/server/pm/UserManagerService.java b/services/java/com/android/server/pm/UserManagerService.java
index 1323c93..d86f2c7 100644
--- a/services/java/com/android/server/pm/UserManagerService.java
+++ b/services/java/com/android/server/pm/UserManagerService.java
@@ -39,12 +39,15 @@
import android.os.IUserManager;
import android.os.Process;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.AtomicFile;
+import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
+import android.util.SparseLongArray;
import android.util.TimeUtils;
import android.util.Xml;
@@ -63,6 +66,9 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
@@ -78,6 +84,10 @@
private static final String ATTR_ID = "id";
private static final String ATTR_CREATION_TIME = "created";
private static final String ATTR_LAST_LOGGED_IN_TIME = "lastLoggedIn";
+ private static final String ATTR_SALT = "salt";
+ private static final String ATTR_PIN_HASH = "pinHash";
+ private static final String ATTR_FAILED_ATTEMPTS = "failedAttempts";
+ private static final String ATTR_LAST_RETRY_MS = "lastAttemptMs";
private static final String ATTR_SERIAL_NO = "serialNumber";
private static final String ATTR_NEXT_SERIAL_NO = "nextSerialNumber";
private static final String ATTR_PARTIAL = "partial";
@@ -107,6 +117,13 @@
private static final long EPOCH_PLUS_30_YEARS = 30L * 365 * 24 * 60 * 60 * 1000L; // ms
+ // Number of attempts before jumping to the next BACKOFF_TIMES slot
+ private static final int BACKOFF_INC_INTERVAL = 5;
+
+ // Amount of time to force the user to wait before entering the PIN again, after failing
+ // BACKOFF_INC_INTERVAL times.
+ private static final int[] BACKOFF_TIMES = { 0, 30*1000, 60*1000, 5*60*1000, 30*60*1000 };
+
private final Context mContext;
private final PackageManagerService mPm;
private final Object mInstallLock;
@@ -121,6 +138,16 @@
private final SparseArray<UserInfo> mUsers = new SparseArray<UserInfo>();
private final SparseArray<Bundle> mUserRestrictions = new SparseArray<Bundle>();
+ class RestrictionsPinState {
+ long salt;
+ String pinHash;
+ int failedAttempts;
+ long lastAttemptTime;
+ }
+
+ private final SparseArray<RestrictionsPinState> mRestrictionsPinStates =
+ new SparseArray<RestrictionsPinState>();
+
/**
* Set of user IDs being actively removed. Removed IDs linger in this set
* for several seconds to work around a VFS caching issue.
@@ -604,6 +631,21 @@
serializer.attribute(null, ATTR_CREATION_TIME, Long.toString(userInfo.creationTime));
serializer.attribute(null, ATTR_LAST_LOGGED_IN_TIME,
Long.toString(userInfo.lastLoggedInTime));
+ RestrictionsPinState pinState = mRestrictionsPinStates.get(userInfo.id);
+ if (pinState != null) {
+ if (pinState.salt != 0) {
+ serializer.attribute(null, ATTR_SALT, Long.toString(pinState.salt));
+ }
+ if (pinState.pinHash != null) {
+ serializer.attribute(null, ATTR_PIN_HASH, pinState.pinHash);
+ }
+ if (pinState.failedAttempts != 0) {
+ serializer.attribute(null, ATTR_FAILED_ATTEMPTS,
+ Integer.toString(pinState.failedAttempts));
+ serializer.attribute(null, ATTR_LAST_RETRY_MS,
+ Long.toString(pinState.lastAttemptTime));
+ }
+ }
if (userInfo.iconPath != null) {
serializer.attribute(null, ATTR_ICON_PATH, userInfo.iconPath);
}
@@ -690,6 +732,10 @@
String iconPath = null;
long creationTime = 0L;
long lastLoggedInTime = 0L;
+ long salt = 0L;
+ String pinHash = null;
+ int failedAttempts = 0;
+ long lastAttemptTime = 0L;
boolean partial = false;
Bundle restrictions = new Bundle();
@@ -722,6 +768,10 @@
iconPath = parser.getAttributeValue(null, ATTR_ICON_PATH);
creationTime = readLongAttribute(parser, ATTR_CREATION_TIME, 0);
lastLoggedInTime = readLongAttribute(parser, ATTR_LAST_LOGGED_IN_TIME, 0);
+ salt = readLongAttribute(parser, ATTR_SALT, 0L);
+ pinHash = parser.getAttributeValue(null, ATTR_PIN_HASH);
+ failedAttempts = readIntAttribute(parser, ATTR_FAILED_ATTEMPTS, 0);
+ lastAttemptTime = readLongAttribute(parser, ATTR_LAST_RETRY_MS, 0L);
String valueString = parser.getAttributeValue(null, ATTR_PARTIAL);
if ("true".equals(valueString)) {
partial = true;
@@ -761,6 +811,17 @@
userInfo.lastLoggedInTime = lastLoggedInTime;
userInfo.partial = partial;
mUserRestrictions.append(id, restrictions);
+ if (salt != 0L) {
+ RestrictionsPinState pinState = mRestrictionsPinStates.get(id);
+ if (pinState == null) {
+ pinState = new RestrictionsPinState();
+ mRestrictionsPinStates.put(id, pinState);
+ }
+ pinState.salt = salt;
+ pinState.pinHash = pinHash;
+ pinState.failedAttempts = failedAttempts;
+ pinState.lastAttemptTime = lastAttemptTime;
+ }
return userInfo;
} catch (IOException ioe) {
@@ -949,6 +1010,7 @@
}
}, MINUTE_IN_MILLIS);
+ mRestrictionsPinStates.remove(userHandle);
// Remove user file
AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + ".xml"));
userFile.delete();
@@ -999,6 +1061,123 @@
}
}
+ @Override
+ public boolean changeRestrictionsPin(String newPin) {
+ checkManageUsersPermission("Only system can modify the restrictions pin");
+ int userId = UserHandle.getCallingUserId();
+ synchronized (mPackagesLock) {
+ RestrictionsPinState pinState = mRestrictionsPinStates.get(userId);
+ if (pinState == null) {
+ pinState = new RestrictionsPinState();
+ }
+ if (newPin == null) {
+ pinState.salt = 0;
+ pinState.pinHash = null;
+ } else {
+ try {
+ pinState.salt = SecureRandom.getInstance("SHA1PRNG").nextLong();
+ } catch (NoSuchAlgorithmException e) {
+ pinState.salt = (long) (Math.random() * Long.MAX_VALUE);
+ }
+ pinState.pinHash = passwordToHash(newPin, pinState.salt);
+ pinState.failedAttempts = 0;
+ }
+ mRestrictionsPinStates.put(userId, pinState);
+ writeUserLocked(mUsers.get(userId));
+ }
+ return true;
+ }
+
+ @Override
+ public int checkRestrictionsPin(String pin) {
+ checkManageUsersPermission("Only system can verify the restrictions pin");
+ int userId = UserHandle.getCallingUserId();
+ synchronized (mPackagesLock) {
+ RestrictionsPinState pinState = mRestrictionsPinStates.get(userId);
+ // If there's no pin set, return error code
+ if (pinState == null || pinState.salt == 0 || pinState.pinHash == null) {
+ return UserManager.PIN_VERIFICATION_FAILED_NOT_SET;
+ } else if (pin == null) {
+ // If just checking if user can be prompted, return remaining time
+ int waitTime = getRemainingTimeForPinAttempt(pinState);
+ Slog.d(LOG_TAG, "Remaining waittime peek=" + waitTime);
+ return waitTime;
+ } else {
+ int waitTime = getRemainingTimeForPinAttempt(pinState);
+ Slog.d(LOG_TAG, "Remaining waittime=" + waitTime);
+ if (waitTime > 0) {
+ return waitTime;
+ }
+ if (passwordToHash(pin, pinState.salt).equals(pinState.pinHash)) {
+ pinState.failedAttempts = 0;
+ writeUserLocked(mUsers.get(userId));
+ return UserManager.PIN_VERIFICATION_SUCCESS;
+ } else {
+ pinState.failedAttempts++;
+ pinState.lastAttemptTime = System.currentTimeMillis();
+ writeUserLocked(mUsers.get(userId));
+ return waitTime;
+ }
+ }
+ }
+ }
+
+ private int getRemainingTimeForPinAttempt(RestrictionsPinState pinState) {
+ int backoffIndex = Math.min(pinState.failedAttempts / BACKOFF_INC_INTERVAL,
+ BACKOFF_TIMES.length - 1);
+ int backoffTime = (pinState.failedAttempts % BACKOFF_INC_INTERVAL) == 0 ?
+ BACKOFF_TIMES[backoffIndex] : 0;
+ return (int) Math.max(backoffTime + pinState.lastAttemptTime - System.currentTimeMillis(),
+ 0);
+ }
+
+ @Override
+ public boolean hasRestrictionsPin() {
+ int userId = UserHandle.getCallingUserId();
+ synchronized (mPackagesLock) {
+ RestrictionsPinState pinState = mRestrictionsPinStates.get(userId);
+ if (pinState == null || pinState.salt == 0 || pinState.pinHash == null) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /*
+ * Generate a hash for the given password. To avoid brute force attacks, we use a salted hash.
+ * Not the most secure, but it is at least a second level of protection. First level is that
+ * the file is in a location only readable by the system process.
+ * @param password the password.
+ * @param salt the randomly generated salt
+ * @return the hash of the pattern in a String.
+ */
+ private String passwordToHash(String password, long salt) {
+ if (password == null) {
+ return null;
+ }
+ String algo = null;
+ String hashed = salt + password;
+ try {
+ byte[] saltedPassword = (password + salt).getBytes();
+ byte[] sha1 = MessageDigest.getInstance(algo = "SHA-1").digest(saltedPassword);
+ byte[] md5 = MessageDigest.getInstance(algo = "MD5").digest(saltedPassword);
+ hashed = toHex(sha1) + toHex(md5);
+ } catch (NoSuchAlgorithmException e) {
+ Log.w(LOG_TAG, "Failed to encode string because of missing algorithm: " + algo);
+ }
+ return hashed;
+ }
+
+ private static String toHex(byte[] ary) {
+ final String hex = "0123456789ABCDEF";
+ String ret = "";
+ for (int i = 0; i < ary.length; i++) {
+ ret += hex.charAt((ary[i] >> 4) & 0xf);
+ ret += hex.charAt(ary[i] & 0xf);
+ }
+ return ret;
+ }
+
private int getUidForPackage(String packageName) {
long ident = Binder.clearCallingIdentity();
try {
diff --git a/services/java/com/android/server/wifi/WifiService.java b/services/java/com/android/server/wifi/WifiService.java
index 66ef978..a70978e 100644
--- a/services/java/com/android/server/wifi/WifiService.java
+++ b/services/java/com/android/server/wifi/WifiService.java
@@ -114,10 +114,6 @@
/* Tracks the persisted states for wi-fi & airplane mode */
final WifiSettingsStore mSettingsStore;
- /* The work source (UID) that triggered the current WIFI scan, synchronized
- * on this */
- private WorkSource mScanWorkSource;
-
/**
* Asynchronous channel to WifiStateMachine
*/
@@ -255,17 +251,6 @@
},
new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));
- mContext.registerReceiver(
- new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals(
- WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
- noteScanEnd();
- }
- }
- }, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
-
// Adding optimizations of only receiving broadcasts when wifi is enabled
// can result in race conditions when apps toggle wifi in the background
// without active user involvement. Always receive broadcasts.
@@ -274,44 +259,6 @@
private WifiController mWifiController;
- /** Tell battery stats about a new WIFI scan */
- private void noteScanStart() {
- WorkSource scanWorkSource = null;
- synchronized (WifiService.this) {
- if (mScanWorkSource != null) {
- // Scan already in progress, don't add this one to battery stats
- return;
- }
- scanWorkSource = new WorkSource(Binder.getCallingUid());
- mScanWorkSource = scanWorkSource;
- }
-
- long id = Binder.clearCallingIdentity();
- try {
- mBatteryStats.noteWifiScanStartedFromSource(scanWorkSource);
- } catch (RemoteException e) {
- Log.w(TAG, e);
- } finally {
- Binder.restoreCallingIdentity(id);
- }
- }
-
- /** Tell battery stats that the current WIFI scan has completed */
- private void noteScanEnd() {
- WorkSource scanWorkSource = null;
- synchronized (WifiService.this) {
- scanWorkSource = mScanWorkSource;
- mScanWorkSource = null;
- }
- if (scanWorkSource != null) {
- try {
- mBatteryStats.noteWifiScanStoppedFromSource(scanWorkSource);
- } catch (RemoteException e) {
- Log.w(TAG, e);
- }
- }
- }
-
/**
* Check if Wi-Fi needs to be enabled and start
* if needed
@@ -352,8 +299,7 @@
*/
public void startScan() {
enforceChangePermission();
- mWifiStateMachine.startScan();
- noteScanStart();
+ mWifiStateMachine.startScan(Binder.getCallingUid());
}
private void enforceAccessPermission() {
diff --git a/services/java/com/android/server/wm/TaskStack.java b/services/java/com/android/server/wm/TaskStack.java
index 827958d..b43a7a1 100644
--- a/services/java/com/android/server/wm/TaskStack.java
+++ b/services/java/com/android/server/wm/TaskStack.java
@@ -16,7 +16,12 @@
package com.android.server.wm;
+import static com.android.server.wm.WindowManagerService.DEBUG_TASK_MOVEMENT;
+import static com.android.server.wm.WindowManagerService.TAG;
+
import android.graphics.Rect;
+import android.os.Debug;
+import android.util.Slog;
import android.util.TypedValue;
import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
@@ -88,6 +93,7 @@
* @param toTop Whether to add it to the top or bottom.
*/
boolean addTask(Task task, boolean toTop) {
+ if (DEBUG_TASK_MOVEMENT) Slog.d(TAG, "addTask: task=" + task + " toTop=" + toTop);
mStackBox.makeDirty();
mTasks.add(toTop ? mTasks.size() : 0, task);
task.mStack = this;
@@ -95,11 +101,14 @@
}
boolean moveTaskToTop(Task task) {
+ if (DEBUG_TASK_MOVEMENT) Slog.d(TAG, "moveTaskToTop: task=" + task + " Callers="
+ + Debug.getCallers(6));
mTasks.remove(task);
return addTask(task, true);
}
boolean moveTaskToBottom(Task task) {
+ if (DEBUG_TASK_MOVEMENT) Slog.d(TAG, "moveTaskToBottom: task=" + task);
mTasks.remove(task);
return addTask(task, false);
}
@@ -110,6 +119,7 @@
* @param task The Task to delete.
*/
void removeTask(Task task) {
+ if (DEBUG_TASK_MOVEMENT) Slog.d(TAG, "removeTask: task=" + task);
mStackBox.makeDirty();
mTasks.remove(task);
}
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index fd06535..ee2ef37 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -28,6 +28,7 @@
import com.android.internal.app.IBatteryStats;
import com.android.internal.policy.PolicyManager;
import com.android.internal.policy.impl.PhoneWindowManager;
+import com.android.internal.util.FastPrintWriter;
import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputMethodClient;
import com.android.internal.view.IInputMethodManager;
@@ -3776,7 +3777,6 @@
}
changed = mFocusedApp != newFocus;
mFocusedApp = newFocus;
- moveTaskToTop(newFocus.groupId);
if (DEBUG_FOCUS) Slog.v(TAG, "Set focused app to: " + mFocusedApp
+ " moveFocusNow=" + moveFocusNow);
if (changed) {
@@ -4117,6 +4117,13 @@
}
}
+ public void setAppFullscreen(IBinder token) {
+ AppWindowToken atoken = findAppWindowToken(token);
+ if (atoken != null) {
+ atoken.appFullscreen = true;
+ }
+ }
+
boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp,
boolean visible, int transit, boolean performLayout) {
boolean delayed = false;
@@ -5318,8 +5325,9 @@
if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!");
if (false) {
StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
+ PrintWriter pw = new FastPrintWriter(sw, false, 1024);
this.dump(null, pw, null);
+ pw.flush();
Slog.i(TAG, sw.toString());
}
try {
@@ -6609,8 +6617,9 @@
displayInfo.logicalDensityDpi = displayContent.mBaseDisplayDensity;
displayInfo.appWidth = appWidth;
displayInfo.appHeight = appHeight;
- displayInfo.getLogicalMetrics(mRealDisplayMetrics, null);
- displayInfo.getAppMetrics(mDisplayMetrics, null);
+ displayInfo.getLogicalMetrics(mRealDisplayMetrics,
+ CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
+ displayInfo.getAppMetrics(mDisplayMetrics);
mDisplayManagerService.setDisplayInfoOverrideFromWindowManager(
displayContent.getDisplayId(), displayInfo);
}
@@ -7897,7 +7906,7 @@
WindowState ws = mRebuildTmp[i];
if (ws.mRebuilding) {
StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
+ PrintWriter pw = new FastPrintWriter(sw, false, 1024);
ws.dump(pw, "", true);
pw.flush();
Slog.w(TAG, "This window was lost: " + ws);
@@ -10472,7 +10481,7 @@
*/
public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState) {
StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
+ PrintWriter pw = new FastPrintWriter(sw, false, 1024);
pw.println(" ANR time: " + DateFormat.getInstance().format(new Date()));
if (appWindowToken != null) {
pw.println(" Application at fault: " + appWindowToken.stringName);
diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java
index 29d6e4d..44077ae 100644
--- a/test-runner/src/android/test/mock/MockContext.java
+++ b/test-runner/src/android/test/mock/MockContext.java
@@ -39,7 +39,7 @@
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
-import android.view.CompatibilityInfoHolder;
+import android.view.DisplayAdjustments;
import android.view.Display;
import java.io.File;
@@ -574,7 +574,7 @@
/** @hide */
@Override
- public CompatibilityInfoHolder getCompatibilityInfo(int displayId) {
+ public DisplayAdjustments getDisplayAdjustments(int displayId) {
throw new UnsupportedOperationException();
}
}
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 20a26ab..4683534 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -45,6 +45,8 @@
import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.os.Binder;
+import android.os.UserHandle;
import java.util.List;
@@ -585,6 +587,23 @@
* @hide
*/
@Override
+ public boolean setApplicationBlockedSettingAsUser(String packageName, boolean blocked,
+ UserHandle user) {
+ return false;
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public boolean getApplicationBlockedSettingAsUser(String packageName, UserHandle user) {
+ return false;
+ }
+
+ /**
+ * @hide
+ */
+ @Override
public int installExistingPackage(String packageName)
throws NameNotFoundException {
throw new UnsupportedOperationException();
diff --git a/tools/aapt/Android.mk b/tools/aapt/Android.mk
index 61180a0..3b49819 100644
--- a/tools/aapt/Android.mk
+++ b/tools/aapt/Android.mk
@@ -86,15 +86,17 @@
LOCAL_CFLAGS += -DSTATIC_ANDROIDFW_FOR_TOOLS
LOCAL_CFLAGS += -Wno-non-virtual-dtor
+LOCAL_SHARED_LIBRARIES := \
+ libpng \
+ libz
+
LOCAL_STATIC_LIBRARIES := \
libstlport_static \
libandroidfw \
libutils \
libcutils \
libexpat_static \
- libpng \
- liblog \
- libz
+ liblog
include $(BUILD_EXECUTABLE)
endif
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 21bef1c..98a32a5 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -67,8 +67,8 @@
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.BridgeInflater;
-import android.view.CompatibilityInfoHolder;
import android.view.Display;
+import android.view.DisplayAdjustments;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
@@ -1394,7 +1394,7 @@
}
@Override
- public CompatibilityInfoHolder getCompatibilityInfo(int displayId) {
+ public DisplayAdjustments getDisplayAdjustments(int displayId) {
// pass
return null;
}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index ec76a8b..a3c172a 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -70,6 +70,18 @@
public static final int ERROR_AUTHENTICATING = 1;
/**
+ * Broadcast intent action indicating whether Wi-Fi scanning is allowed currently
+ * @hide
+ */
+ public static final String WIFI_SCAN_AVAILABLE = "wifi_scan_available";
+
+ /**
+ * Extra int indicating scan availability, WIFI_STATE_ENABLED and WIFI_STATE_DISABLED
+ * @hide
+ */
+ public static final String EXTRA_SCAN_AVAILABLE = "scan_enabled";
+
+ /**
* Broadcast intent action indicating that Wi-Fi has been enabled, disabled,
* enabling, disabling, or unknown. One extra provides this state as an int.
* Another extra provides the previous state, if available.
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 1040ab19..1f51b2a 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -142,6 +142,8 @@
*/
private int mOperationalMode = CONNECT_MODE;
private boolean mScanResultIsPending = false;
+ private WorkSource mScanWorkSource = null;
+ private static final int UNKNOWN_SCAN_SOURCE = -1;
/* Tracks if state machine has received any screen state change broadcast yet.
* We can miss one of these at boot.
*/
@@ -603,7 +605,7 @@
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- startScan();
+ startScan(UNKNOWN_SCAN_SOURCE);
}
},
new IntentFilter(ACTION_START_SCAN));
@@ -696,6 +698,11 @@
//start the state machine
start();
+
+ final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_DISABLED);
+ mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}
/*********************************************************
@@ -718,8 +725,31 @@
/**
* TODO: doc
*/
- public void startScan() {
- sendMessage(CMD_START_SCAN);
+ public void startScan(int callingUid) {
+ sendMessage(CMD_START_SCAN, callingUid);
+ }
+
+ private void noteScanStart(int callingUid) {
+ if (mScanWorkSource == null && callingUid != UNKNOWN_SCAN_SOURCE) {
+ mScanWorkSource = new WorkSource(callingUid);
+ try {
+ mBatteryStats.noteWifiScanStartedFromSource(mScanWorkSource);
+ } catch (RemoteException e) {
+ log(e.toString());
+ }
+ }
+ }
+
+ private void noteScanEnd() {
+ if (mScanWorkSource != null) {
+ try {
+ mBatteryStats.noteWifiScanStoppedFromSource(mScanWorkSource);
+ } catch (RemoteException e) {
+ log(e.toString());
+ } finally {
+ mScanWorkSource = null;
+ }
+ }
}
private void startScanNative(int type) {
@@ -1577,6 +1607,7 @@
}
private void sendScanResultsAvailableBroadcast() {
+ noteScanEnd();
Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
@@ -1921,6 +1952,7 @@
}
break;
/* Discard */
+ case CMD_START_SCAN:
case CMD_START_SUPPLICANT:
case CMD_STOP_SUPPLICANT:
case CMD_STOP_SUPPLICANT_FAILED:
@@ -1935,7 +1967,6 @@
case CMD_STOP_AP:
case CMD_TETHER_STATE_CHANGE:
case CMD_TETHER_NOTIFICATION_TIMED_OUT:
- case CMD_START_SCAN:
case CMD_DISCONNECT:
case CMD_RECONNECT:
case CMD_REASSOCIATE:
@@ -2440,11 +2471,18 @@
mWifiNative.setPowerSave(true);
if (mP2pSupported) mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_ENABLE_P2P);
+
+ final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_ENABLED);
+ mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}
+
@Override
public boolean processMessage(Message message) {
switch(message.what) {
case CMD_START_SCAN:
+ noteScanStart(message.arg1);
startScanNative(WifiNative.SCAN_WITH_CONNECTION_SETUP);
break;
case CMD_SET_COUNTRY_CODE:
@@ -2565,6 +2603,12 @@
mIsRunning = false;
updateBatteryWorkSource(null);
mScanResults = new ArrayList<ScanResult>();
+
+ final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_DISABLED);
+ mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+ noteScanEnd(); // wrap up any pending request.
}
}
@@ -2715,6 +2759,7 @@
// Handle scan. All the connection related commands are
// handled only in ConnectModeState
case CMD_START_SCAN:
+ noteScanStart(message.arg1);
startScanNative(WifiNative.SCAN_WITHOUT_CONNECTION_SETUP);
break;
default:
@@ -2981,6 +3026,7 @@
break;
case CMD_START_SCAN:
/* Do not attempt to connect when we are already connected */
+ noteScanStart(message.arg1);
startScanNative(WifiNative.SCAN_WITHOUT_CONNECTION_SETUP);
break;
/* Ignore connection to same network */
@@ -3298,7 +3344,7 @@
if (mP2pConnected.get()) break;
if (message.arg1 == mPeriodicScanToken &&
mWifiConfigStore.getConfiguredNetworks().size() == 0) {
- sendMessage(CMD_START_SCAN);
+ sendMessage(CMD_START_SCAN, UNKNOWN_SCAN_SOURCE);
sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN,
++mPeriodicScanToken, 0), mSupplicantScanIntervalMs);
}