summaryrefslogtreecommitdiffstats
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/app/ActivityManagerNative.java8
-rw-r--r--core/java/android/app/AppOpsManager.java306
-rw-r--r--core/java/android/app/ApplicationThreadNative.java8
-rw-r--r--core/java/android/app/ContextImpl.java22
-rw-r--r--core/java/android/app/DownloadManager.java20
-rw-r--r--core/java/android/content/ContentProvider.java2
-rw-r--r--core/java/android/content/ContentProviderClient.java13
-rw-r--r--core/java/android/content/ContentResolver.java29
-rw-r--r--core/java/android/content/res/Resources.java25
-rw-r--r--core/java/android/hardware/camera2/CameraAccessException.java40
-rw-r--r--core/java/android/hardware/camera2/CameraCharacteristics.java (renamed from core/java/android/hardware/camera2/CameraProperties.java)8
-rw-r--r--core/java/android/hardware/camera2/CameraDevice.java379
-rw-r--r--core/java/android/hardware/camera2/CameraManager.java86
-rw-r--r--core/java/android/hardware/camera2/CameraMetadata.java28
-rw-r--r--core/java/android/hardware/camera2/CaptureFailure.java144
-rw-r--r--core/java/android/hardware/camera2/CaptureRequest.java47
-rw-r--r--core/java/android/hardware/camera2/CaptureResult.java74
-rw-r--r--core/java/android/hardware/camera2/Face.java2
-rw-r--r--core/java/android/hardware/camera2/impl/CameraDevice.java43
-rw-r--r--core/java/android/hardware/camera2/impl/CameraMetadataNative.java2
-rw-r--r--core/java/android/hardware/camera2/package.html2
-rw-r--r--core/java/android/hardware/camera2/utils/CameraBinderDecorator.java4
-rw-r--r--core/java/android/hardware/location/GeofenceHardwareImpl.java14
-rw-r--r--core/java/android/net/MobileDataStateTracker.java9
-rw-r--r--core/java/android/os/Binder.java1
-rw-r--r--core/java/android/os/Bundle.java34
-rw-r--r--core/java/android/os/Environment.java64
-rw-r--r--core/java/android/os/Parcel.java32
-rw-r--r--core/java/android/os/ParcelFileDescriptor.java33
-rw-r--r--core/java/android/os/WorkSource.java17
-rw-r--r--core/java/android/os/storage/IMountService.java40
-rw-r--r--core/java/android/preference/PreferenceActivity.java5
-rw-r--r--core/java/android/print/PrintAttributes.java232
-rw-r--r--core/java/android/provider/Downloads.java2
-rw-r--r--core/java/android/text/Layout.java2
-rw-r--r--core/java/android/text/SpannableStringBuilder.java41
-rw-r--r--core/java/android/text/SpannableStringInternal.java41
-rw-r--r--core/java/android/transition/TextChange.java7
-rw-r--r--core/java/android/webkit/WebView.java31
-rw-r--r--core/java/android/webkit/WebViewClassic.java5
-rw-r--r--core/java/android/webkit/WebViewFactoryProvider.java6
-rw-r--r--core/java/android/widget/AdapterView.java4
42 files changed, 1529 insertions, 383 deletions
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index a727b07..7d4d57c 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -152,7 +152,7 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
int startFlags = data.readInt();
String profileFile = data.readString();
ParcelFileDescriptor profileFd = data.readInt() != 0
- ? data.readFileDescriptor() : null;
+ ? ParcelFileDescriptor.CREATOR.createFromParcel(data) : null;
Bundle options = data.readInt() != 0
? Bundle.CREATOR.createFromParcel(data) : null;
int userId = data.readInt();
@@ -178,7 +178,7 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
int startFlags = data.readInt();
String profileFile = data.readString();
ParcelFileDescriptor profileFd = data.readInt() != 0
- ? data.readFileDescriptor() : null;
+ ? ParcelFileDescriptor.CREATOR.createFromParcel(data) : null;
Bundle options = data.readInt() != 0
? Bundle.CREATOR.createFromParcel(data) : null;
int userId = data.readInt();
@@ -1354,7 +1354,7 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
int profileType = data.readInt();
String path = data.readString();
ParcelFileDescriptor fd = data.readInt() != 0
- ? data.readFileDescriptor() : null;
+ ? ParcelFileDescriptor.CREATOR.createFromParcel(data) : null;
boolean res = profileControl(process, userId, start, path, fd, profileType);
reply.writeNoException();
reply.writeInt(res ? 1 : 0);
@@ -1608,7 +1608,7 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
boolean managed = data.readInt() != 0;
String path = data.readString();
ParcelFileDescriptor fd = data.readInt() != 0
- ? data.readFileDescriptor() : null;
+ ? ParcelFileDescriptor.CREATOR.createFromParcel(data) : null;
boolean res = dumpHeap(process, userId, managed, path, fd);
reply.writeNoException();
reply.writeInt(res ? 1 : 0);
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index bf2a1e4..055044b 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -23,6 +23,7 @@ import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IAppOpsCallback;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import android.content.Context;
@@ -32,50 +33,76 @@ import android.os.Process;
import android.os.RemoteException;
/**
- * API for interacting with "application operation" tracking. Allows you to:
+ * API for interacting with "application operation" tracking.
*
- * <ul>
- * <li> Note when operations are happening, and find out if they are allowed for the current
- * caller.</li>
- * <li> Disallow specific apps from doing specific operations.</li>
- * <li> Collect all of the current information about operations that have been executed or are not
- * being allowed.</li>
- * <li> Monitor for changes in whether an operation is allowed.</li>
- * </ul>
- *
- * <p>Each operation is identified by a single integer; these integers are a fixed set of
- * operations, enumerated by the OP_* constants.
- *
- * <p></p>When checking operations, the result is a "mode" integer indicating the current setting
- * for the operation under that caller: MODE_ALLOWED, MODE_IGNORED (don't execute the operation but
- * fake its behavior enough so that the caller doesn't crash), MODE_ERRORED (through a
- * SecurityException back to the caller; the normal operation calls will do this for you).
+ * <p>This API is not generally intended for third party application developers; most
+ * features are only available to system applicatins. Obtain an instance of it through
+ * {@link Context#getSystemService(String) Context.getSystemService} with
+ * {@link Context#APP_OPS_SERVICE Context.APP_OPS_SERVICE}.</p>
*/
public class AppOpsManager {
+ /**
+ * <p>App ops allows callers to:</p>
+ *
+ * <ul>
+ * <li> Note when operations are happening, and find out if they are allowed for the current
+ * caller.</li>
+ * <li> Disallow specific apps from doing specific operations.</li>
+ * <li> Collect all of the current information about operations that have been executed or
+ * are not being allowed.</li>
+ * <li> Monitor for changes in whether an operation is allowed.</li>
+ * </ul>
+ *
+ * <p>Each operation is identified by a single integer; these integers are a fixed set of
+ * operations, enumerated by the OP_* constants.
+ *
+ * <p></p>When checking operations, the result is a "mode" integer indicating the current
+ * setting for the operation under that caller: MODE_ALLOWED, MODE_IGNORED (don't execute
+ * the operation but fake its behavior enough so that the caller doesn't crash),
+ * MODE_ERRORED (throw a SecurityException back to the caller; the normal operation calls
+ * will do this for you).
+ */
+
final Context mContext;
final IAppOpsService mService;
- final ArrayMap<Callback, IAppOpsCallback> mModeWatchers
- = new ArrayMap<Callback, IAppOpsCallback>();
+ final ArrayMap<OnOpChangedListener, IAppOpsCallback> mModeWatchers
+ = new ArrayMap<OnOpChangedListener, IAppOpsCallback>();
static IBinder sToken;
+ /**
+ * Result from {@link #checkOp}, {@link #noteOp}, {@link #startOp}: the given caller is
+ * allowed to perform the given operation.
+ */
public static final int MODE_ALLOWED = 0;
+
+ /**
+ * Result from {@link #checkOp}, {@link #noteOp}, {@link #startOp}: the given caller is
+ * not allowed to perform the given operation, and this attempt should
+ * <em>silently fail</em> (it should not cause the app to crash).
+ */
public static final int MODE_IGNORED = 1;
+
+ /**
+ * Result from {@link #checkOpNoThrow}, {@link #noteOpNoThrow}, {@link #startOpNoThrow}: the
+ * given caller is not allowed to perform the given operation, and this attempt should
+ * cause it to have a fatal error, typically a {@link SecurityException}.
+ */
public static final int MODE_ERRORED = 2;
// when adding one of these:
// - increment _NUM_OP
- // - add rows to sOpToSwitch, sOpNames, sOpPerms, sOpDefaultMode
+ // - add rows to sOpToSwitch, sOpToString, sOpNames, sOpPerms, sOpDefaultMode
// - add descriptive strings to Settings/res/values/arrays.xml
// - add the op to the appropriate template in AppOpsState.OpsTemplate (settings app)
- /** No operation specified. */
+ /** @hide No operation specified. */
public static final int OP_NONE = -1;
- /** Access to coarse location information. */
+ /** @hide Access to coarse location information. */
public static final int OP_COARSE_LOCATION = 0;
- /** Access to fine location information. */
+ /** @hide Access to fine location information. */
public static final int OP_FINE_LOCATION = 1;
- /** Causing GPS to run. */
+ /** @hide Causing GPS to run. */
public static final int OP_GPS = 2;
/** @hide */
public static final int OP_VIBRATE = 3;
@@ -153,13 +180,26 @@ public class AppOpsManager {
public static final int OP_AUDIO_BLUETOOTH_VOLUME = 39;
/** @hide */
public static final int OP_WAKE_LOCK = 40;
- /** Continually monitoring location data. */
+ /** @hide Continually monitoring location data. */
public static final int OP_MONITOR_LOCATION = 41;
- /** Continually monitoring location data with a relatively high power request. */
+ /** @hide Continually monitoring location data with a relatively high power request. */
public static final int OP_MONITOR_HIGH_POWER_LOCATION = 42;
/** @hide */
public static final int _NUM_OP = 43;
+ /** Access to coarse location information. */
+ public static final String OPSTR_COARSE_LOCATION =
+ "android:coarse_location";
+ /** Access to fine location information. */
+ public static final String OPSTR_FINE_LOCATION =
+ "android:fine_location";
+ /** Continually monitoring location data. */
+ public static final String OPSTR_MONITOR_LOCATION
+ = "android:monitor_location";
+ /** Continually monitoring location data with a relatively high power request. */
+ public static final String OPSTR_MONITOR_HIGH_POWER_LOCATION
+ = "android:monitor_location_high_power";
+
/**
* This maps each operation to the operation that serves as the
* switch to determine whether it is allowed. Generally this is
@@ -215,6 +255,56 @@ public class AppOpsManager {
};
/**
+ * This maps each operation to the public string constant for it.
+ * If it doesn't have a public string constant, it maps to null.
+ */
+ private static String[] sOpToString = new String[] {
+ OPSTR_COARSE_LOCATION,
+ OPSTR_FINE_LOCATION,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ null,
+ OPSTR_MONITOR_LOCATION,
+ OPSTR_MONITOR_HIGH_POWER_LOCATION,
+ };
+
+ /**
* This provides a simple name for each operation to be used
* in debug output.
*/
@@ -363,6 +453,36 @@ public class AppOpsManager {
AppOpsManager.MODE_ALLOWED,
};
+ private static HashMap<String, Integer> sOpStrToOp = new HashMap<String, Integer>();
+
+ static {
+ if (sOpToSwitch.length != _NUM_OP) {
+ throw new IllegalStateException("sOpStringLength " + sOpToSwitch.length
+ + " should be " + _NUM_OP);
+ }
+ if (sOpToString.length != _NUM_OP) {
+ throw new IllegalStateException("sOpStringLength " + sOpToString.length
+ + " should be " + _NUM_OP);
+ }
+ if (sOpNames.length != _NUM_OP) {
+ throw new IllegalStateException("sOpStringLength " + sOpNames.length
+ + " should be " + _NUM_OP);
+ }
+ if (sOpPerms.length != _NUM_OP) {
+ throw new IllegalStateException("sOpStringLength " + sOpPerms.length
+ + " should be " + _NUM_OP);
+ }
+ if (sOpDefaultMode.length != _NUM_OP) {
+ throw new IllegalStateException("sOpStringLength " + sOpDefaultMode.length
+ + " should be " + _NUM_OP);
+ }
+ for (int i=0; i<_NUM_OP; i++) {
+ if (sOpToString[i] != null) {
+ sOpStrToOp.put(sOpToString[i], i);
+ }
+ }
+ }
+
/**
* Retrieve the op switch that controls the given operation.
* @hide
@@ -373,6 +493,7 @@ public class AppOpsManager {
/**
* Retrieve a non-localized name for the operation, for debugging output.
+ * @hide
*/
public static String opToName(int op) {
if (op == OP_NONE) return "NONE";
@@ -537,8 +658,18 @@ public class AppOpsManager {
/**
* Callback for notification of changes to operation state.
*/
- public interface Callback {
- public void opChanged(int op, String packageName);
+ public interface OnOpChangedListener {
+ public void onOpChanged(String op, String packageName);
+ }
+
+ /**
+ * Callback for notification of changes to operation state.
+ * This allows you to see the raw op codes instead of strings.
+ * @hide
+ */
+ public static class OnOpChangedInternalListener implements OnOpChangedListener {
+ public void onOpChanged(String op, String packageName) { }
+ public void onOpChanged(int op, String packageName) { }
}
AppOpsManager(Context context, IAppOpsService service) {
@@ -598,13 +729,18 @@ public class AppOpsManager {
* @param packageName The name of the application to monitor.
* @param callback Where to report changes.
*/
- public void startWatchingMode(int op, String packageName, final Callback callback) {
+ public void startWatchingMode(int op, String packageName, final OnOpChangedListener callback) {
synchronized (mModeWatchers) {
IAppOpsCallback cb = mModeWatchers.get(callback);
if (cb == null) {
cb = new IAppOpsCallback.Stub() {
public void opChanged(int op, String packageName) {
- callback.opChanged(op, packageName);
+ if (callback instanceof OnOpChangedInternalListener) {
+ ((OnOpChangedInternalListener)callback).onOpChanged(op, packageName);
+ }
+ if (sOpToString[op] != null) {
+ callback.onOpChanged(sOpToString[op], packageName);
+ }
}
};
mModeWatchers.put(callback, cb);
@@ -620,7 +756,7 @@ public class AppOpsManager {
* Stop monitoring that was previously started with {@link #startWatchingMode}. All
* monitoring associated with this callback will be removed.
*/
- public void stopWatchingMode(Callback callback) {
+ public void stopWatchingMode(OnOpChangedListener callback) {
synchronized (mModeWatchers) {
IAppOpsCallback cb = mModeWatchers.get(callback);
if (cb != null) {
@@ -636,6 +772,106 @@ public class AppOpsManager {
return packageName + " from uid " + uid + " not allowed to perform " + sOpNames[op];
}
+ private int strOpToOp(String op) {
+ Integer val = sOpStrToOp.get(op);
+ if (val == null) {
+ throw new IllegalArgumentException("Unknown operation string: " + op);
+ }
+ return val;
+ }
+
+ /**
+ * Do a quick check for whether an application might be able to perform an operation.
+ * This is <em>not</em> a security check; you must use {@link #noteOp(String, int, String)}
+ * or {@link #startOp(String, int, String)} for your actual security checks, which also
+ * ensure that the given uid and package name are consistent. This function can just be
+ * used for a quick check to see if an operation has been disabled for the application,
+ * as an early reject of some work. This does not modify the time stamp or other data
+ * about the operation.
+ * @param op The operation to check. One of the OPSTR_* constants.
+ * @param uid The user id of the application attempting to perform the operation.
+ * @param packageName The name of the application attempting to perform the operation.
+ * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
+ * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
+ * causing the app to crash).
+ * @throws SecurityException If the app has been configured to crash on this op.
+ */
+ public int checkOp(String op, int uid, String packageName) {
+ return checkOp(strOpToOp(op), uid, packageName);
+ }
+
+ /**
+ * Like {@link #checkOp but instead of throwing a {@link SecurityException} it
+ * returns {@link #MODE_ERRORED}.
+ */
+ public int checkOpNoThrow(String op, int uid, String packageName) {
+ return checkOpNoThrow(strOpToOp(op), uid, packageName);
+ }
+
+ /**
+ * Make note of an application performing an operation. Note that you must pass
+ * in both the uid and name of the application to be checked; this function will verify
+ * that these two match, and if not, return {@link #MODE_IGNORED}. If this call
+ * succeeds, the last execution time of the operation for this app will be updated to
+ * the current time.
+ * @param op The operation to note. One of the OPSTR_* constants.
+ * @param uid The user id of the application attempting to perform the operation.
+ * @param packageName The name of the application attempting to perform the operation.
+ * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
+ * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
+ * causing the app to crash).
+ * @throws SecurityException If the app has been configured to crash on this op.
+ */
+ public int noteOp(String op, int uid, String packageName) {
+ return noteOp(strOpToOp(op), uid, packageName);
+ }
+
+ /**
+ * Like {@link #noteOp} but instead of throwing a {@link SecurityException} it
+ * returns {@link #MODE_ERRORED}.
+ */
+ public int noteOpNoThrow(String op, int uid, String packageName) {
+ return noteOpNoThrow(strOpToOp(op), uid, packageName);
+ }
+
+ /**
+ * Report that an application has started executing a long-running operation. Note that you
+ * must pass in both the uid and name of the application to be checked; this function will
+ * verify that these two match, and if not, return {@link #MODE_IGNORED}. If this call
+ * succeeds, the last execution time of the operation for this app will be updated to
+ * the current time and the operation will be marked as "running". In this case you must
+ * later call {@link #finishOp(String, int, String)} to report when the application is no
+ * longer performing the operation.
+ * @param op The operation to start. One of the OPSTR_* constants.
+ * @param uid The user id of the application attempting to perform the operation.
+ * @param packageName The name of the application attempting to perform the operation.
+ * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
+ * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
+ * causing the app to crash).
+ * @throws SecurityException If the app has been configured to crash on this op.
+ */
+ public int startOp(String op, int uid, String packageName) {
+ return startOp(strOpToOp(op), uid, packageName);
+ }
+
+ /**
+ * Like {@link #startOp} but instead of throwing a {@link SecurityException} it
+ * returns {@link #MODE_ERRORED}.
+ */
+ public int startOpNoThrow(String op, int uid, String packageName) {
+ return startOpNoThrow(strOpToOp(op), uid, packageName);
+ }
+
+ /**
+ * Report that an application is no longer performing an operation that had previously
+ * been started with {@link #startOp(String, int, String)}. There is no validation of input
+ * or result; the parameters supplied here must be the exact same ones previously passed
+ * in when starting the operation.
+ */
+ public void finishOp(String op, int uid, String packageName) {
+ finishOp(strOpToOp(op), uid, packageName);
+ }
+
/**
* Do a quick check for whether an application might be able to perform an operation.
* This is <em>not</em> a security check; you must use {@link #noteOp(int, int, String)}
@@ -651,6 +887,7 @@ public class AppOpsManager {
* {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
* causing the app to crash).
* @throws SecurityException If the app has been configured to crash on this op.
+ * @hide
*/
public int checkOp(int op, int uid, String packageName) {
try {
@@ -667,6 +904,7 @@ public class AppOpsManager {
/**
* Like {@link #checkOp} but instead of throwing a {@link SecurityException} it
* returns {@link #MODE_ERRORED}.
+ * @hide
*/
public int checkOpNoThrow(int op, int uid, String packageName) {
try {
@@ -706,6 +944,7 @@ public class AppOpsManager {
* {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
* causing the app to crash).
* @throws SecurityException If the app has been configured to crash on this op.
+ * @hide
*/
public int noteOp(int op, int uid, String packageName) {
try {
@@ -722,6 +961,7 @@ public class AppOpsManager {
/**
* Like {@link #noteOp} but instead of throwing a {@link SecurityException} it
* returns {@link #MODE_ERRORED}.
+ * @hide
*/
public int noteOpNoThrow(int op, int uid, String packageName) {
try {
@@ -766,6 +1006,7 @@ public class AppOpsManager {
* {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without
* causing the app to crash).
* @throws SecurityException If the app has been configured to crash on this op.
+ * @hide
*/
public int startOp(int op, int uid, String packageName) {
try {
@@ -782,6 +1023,7 @@ public class AppOpsManager {
/**
* Like {@link #startOp} but instead of throwing a {@link SecurityException} it
* returns {@link #MODE_ERRORED}.
+ * @hide
*/
public int startOpNoThrow(int op, int uid, String packageName) {
try {
@@ -801,6 +1043,7 @@ public class AppOpsManager {
* been started with {@link #startOp(int, int, String)}. There is no validation of input
* or result; the parameters supplied here must be the exact same ones previously passed
* in when starting the operation.
+ * @hide
*/
public void finishOp(int op, int uid, String packageName) {
try {
@@ -809,6 +1052,7 @@ public class AppOpsManager {
}
}
+ /** @hide */
public void finishOp(int op) {
finishOp(op, Process.myUid(), mContext.getOpPackageName());
}
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 876bf78..e40a04b 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -143,7 +143,7 @@ public abstract class ApplicationThreadNative extends Binder
boolean isForward = data.readInt() != 0;
String profileName = data.readString();
ParcelFileDescriptor profileFd = data.readInt() != 0
- ? data.readFileDescriptor() : null;
+ ? ParcelFileDescriptor.CREATOR.createFromParcel(data) : null;
boolean autoStopProfiler = data.readInt() != 0;
scheduleLaunchActivity(intent, b, ident, info, curConfig, compatInfo, procState, state,
ri, pi, notResumed, isForward, profileName, profileFd, autoStopProfiler);
@@ -267,7 +267,7 @@ public abstract class ApplicationThreadNative extends Binder
? new ComponentName(data) : null;
String profileName = data.readString();
ParcelFileDescriptor profileFd = data.readInt() != 0
- ? data.readFileDescriptor() : null;
+ ? ParcelFileDescriptor.CREATOR.createFromParcel(data) : null;
boolean autoStopProfiler = data.readInt() != 0;
Bundle testArgs = data.readBundle();
IBinder binder = data.readStrongBinder();
@@ -418,7 +418,7 @@ public abstract class ApplicationThreadNative extends Binder
int profileType = data.readInt();
String path = data.readString();
ParcelFileDescriptor fd = data.readInt() != 0
- ? data.readFileDescriptor() : null;
+ ? ParcelFileDescriptor.CREATOR.createFromParcel(data) : null;
profilerControl(start, path, fd, profileType);
return true;
}
@@ -473,7 +473,7 @@ public abstract class ApplicationThreadNative extends Binder
boolean managed = data.readInt() != 0;
String path = data.readString();
ParcelFileDescriptor fd = data.readInt() != 0
- ? data.readFileDescriptor() : null;
+ ? ParcelFileDescriptor.CREATOR.createFromParcel(data) : null;
dumpHeap(managed, path, fd);
return true;
}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 8e9f3bb..0ba2ac5 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -92,6 +92,7 @@ import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.SystemVibrator;
import android.os.UserManager;
+import android.os.storage.IMountService;
import android.os.storage.StorageManager;
import android.print.IPrintManager;
import android.print.PrintManager;
@@ -864,7 +865,9 @@ class ContextImpl extends Context {
if (mExternalObbDirs == null) {
mExternalObbDirs = Environment.buildExternalStorageAppObbDirs(getPackageName());
}
- return mExternalObbDirs;
+
+ // Create dirs if needed
+ return ensureDirsExistOrFilter(mExternalObbDirs);
}
}
@@ -2127,14 +2130,25 @@ class ContextImpl extends Context {
* Ensure that given directories exist, trying to create them if missing. If
* unable to create, they are filtered by replacing with {@code null}.
*/
- private static File[] ensureDirsExistOrFilter(File[] dirs) {
+ private File[] ensureDirsExistOrFilter(File[] dirs) {
File[] result = new File[dirs.length];
for (int i = 0; i < dirs.length; i++) {
File dir = dirs[i];
if (!dir.exists()) {
if (!dir.mkdirs()) {
- Log.w(TAG, "Failed to ensure directory: " + dir);
- dir = null;
+ // Failing to mkdir() may be okay, since we might not have
+ // enough permissions; ask vold to create on our behalf.
+ final IMountService mount = IMountService.Stub.asInterface(
+ ServiceManager.getService("mount"));
+ int res = -1;
+ try {
+ res = mount.mkdirs(getPackageName(), dir.getAbsolutePath());
+ } catch (RemoteException e) {
+ }
+ if (res != 0) {
+ Log.w(TAG, "Failed to ensure directory: " + dir);
+ dir = null;
+ }
}
}
result[i] = dir;
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index 165c3db..800ead9 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -150,6 +150,11 @@ public class DownloadManager {
public static final String COLUMN_MEDIAPROVIDER_URI = Downloads.Impl.COLUMN_MEDIAPROVIDER_URI;
/**
+ * @hide
+ */
+ public final static String COLUMN_ALLOW_WRITE = Downloads.Impl.COLUMN_ALLOW_WRITE;
+
+ /**
* Value of {@link #COLUMN_STATUS} when the download is waiting to start.
*/
public final static int STATUS_PENDING = 1 << 0;
@@ -315,6 +320,7 @@ public class DownloadManager {
Downloads.Impl.COLUMN_TOTAL_BYTES + " AS " + COLUMN_TOTAL_SIZE_BYTES,
Downloads.Impl.COLUMN_LAST_MODIFICATION + " AS " + COLUMN_LAST_MODIFIED_TIMESTAMP,
Downloads.Impl.COLUMN_CURRENT_BYTES + " AS " + COLUMN_BYTES_DOWNLOADED_SO_FAR,
+ Downloads.Impl.COLUMN_ALLOW_WRITE,
/* add the following 'computed' columns to the cursor.
* they are not 'returned' by the database, but their inclusion
* eliminates need to have lot of methods in CursorTranslator
@@ -1185,6 +1191,14 @@ public class DownloadManager {
public long addCompletedDownload(String title, String description,
boolean isMediaScannerScannable, String mimeType, String path, long length,
boolean showNotification) {
+ return addCompletedDownload(title, description, isMediaScannerScannable, mimeType, path,
+ length, showNotification, false);
+ }
+
+ /** {@hide} */
+ public long addCompletedDownload(String title, String description,
+ boolean isMediaScannerScannable, String mimeType, String path, long length,
+ boolean showNotification, boolean allowWrite) {
// make sure the input args are non-null/non-zero
validateArgumentIsNonEmpty("title", title);
validateArgumentIsNonEmpty("description", description);
@@ -1210,12 +1224,14 @@ public class DownloadManager {
Request.SCANNABLE_VALUE_NO);
values.put(Downloads.Impl.COLUMN_VISIBILITY, (showNotification) ?
Request.VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION : Request.VISIBILITY_HIDDEN);
+ values.put(Downloads.Impl.COLUMN_ALLOW_WRITE, allowWrite ? 1 : 0);
Uri downloadUri = mResolver.insert(Downloads.Impl.CONTENT_URI, values);
if (downloadUri == null) {
return -1;
}
return Long.parseLong(downloadUri.getLastPathSegment());
}
+
private static final String NON_DOWNLOADMANAGER_DOWNLOAD =
"non-dwnldmngr-download-dont-retry2download";
@@ -1227,8 +1243,10 @@ public class DownloadManager {
/**
* Get the DownloadProvider URI for the download with the given ID.
+ *
+ * @hide
*/
- Uri getDownloadUri(long id) {
+ public Uri getDownloadUri(long id) {
return ContentUris.withAppendedId(mBaseUri, id);
}
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 9a258dc..461dc1d 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -1310,7 +1310,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
throw new FileNotFoundException("Column _data not found.");
}
- int modeBits = ContentResolver.modeToMode(uri, mode);
+ int modeBits = ParcelFileDescriptor.parseMode(mode);
return ParcelFileDescriptor.open(new File(path), modeBits);
}
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index 39b453d..0650798 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -26,6 +26,8 @@ import android.os.RemoteException;
import android.os.ParcelFileDescriptor;
import android.content.res.AssetFileDescriptor;
+import dalvik.system.CloseGuard;
+
import java.io.FileNotFoundException;
import java.util.ArrayList;
@@ -49,6 +51,8 @@ public class ContentProviderClient {
private final boolean mStable;
private boolean mReleased;
+ private final CloseGuard mGuard = CloseGuard.get();
+
/**
* @hide
*/
@@ -58,6 +62,7 @@ public class ContentProviderClient {
mContentResolver = contentResolver;
mPackageName = contentResolver.mPackageName;
mStable = stable;
+ mGuard.open("release");
}
/** See {@link ContentProvider#query ContentProvider.query} */
@@ -324,6 +329,7 @@ public class ContentProviderClient {
throw new IllegalStateException("Already released");
}
mReleased = true;
+ mGuard.close();
if (mStable) {
return mContentResolver.releaseProvider(mContentProvider);
} else {
@@ -332,6 +338,13 @@ public class ContentProviderClient {
}
}
+ @Override
+ protected void finalize() throws Throwable {
+ if (mGuard != null) {
+ mGuard.warnIfOpen();
+ }
+ }
+
/**
* Get a reference to the {@link ContentProvider} that is associated with this
* client. If the {@link ContentProvider} is running in a different process then
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 5618cab..2750d68 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -886,7 +886,7 @@ public abstract class ContentResolver {
}
} else if (SCHEME_FILE.equals(scheme)) {
ParcelFileDescriptor pfd = ParcelFileDescriptor.open(
- new File(uri.getPath()), modeToMode(uri, mode));
+ new File(uri.getPath()), ParcelFileDescriptor.parseMode(mode));
return new AssetFileDescriptor(pfd, 0, -1);
} else {
if ("r".equals(mode)) {
@@ -1158,33 +1158,6 @@ public abstract class ContentResolver {
return res;
}
- /** @hide */
- static public int modeToMode(Uri uri, String mode) throws FileNotFoundException {
- int modeBits;
- if ("r".equals(mode)) {
- modeBits = ParcelFileDescriptor.MODE_READ_ONLY;
- } else if ("w".equals(mode) || "wt".equals(mode)) {
- modeBits = ParcelFileDescriptor.MODE_WRITE_ONLY
- | ParcelFileDescriptor.MODE_CREATE
- | ParcelFileDescriptor.MODE_TRUNCATE;
- } else if ("wa".equals(mode)) {
- modeBits = ParcelFileDescriptor.MODE_WRITE_ONLY
- | ParcelFileDescriptor.MODE_CREATE
- | ParcelFileDescriptor.MODE_APPEND;
- } else if ("rw".equals(mode)) {
- modeBits = ParcelFileDescriptor.MODE_READ_WRITE
- | ParcelFileDescriptor.MODE_CREATE;
- } else if ("rwt".equals(mode)) {
- modeBits = ParcelFileDescriptor.MODE_READ_WRITE
- | ParcelFileDescriptor.MODE_CREATE
- | ParcelFileDescriptor.MODE_TRUNCATE;
- } else {
- throw new FileNotFoundException("Bad mode for " + uri + ": "
- + mode);
- }
- return modeBits;
- }
-
/**
* Inserts a row into a table at the given URL.
*
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 6483cd9..cd5b5d2 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -195,7 +195,9 @@ public class Resources {
CompatibilityInfo compatInfo, IBinder token) {
mAssets = assets;
mMetrics.setToDefaults();
- mCompatibilityInfo = compatInfo;
+ if (compatInfo != null) {
+ mCompatibilityInfo = compatInfo;
+ }
mToken = new WeakReference<IBinder>(token);
updateConfiguration(config, metrics);
assets.ensureStringBlocks();
@@ -1536,9 +1538,8 @@ public class Resources {
// it would be cleaner and more maintainble to just be
// consistently dealing with a compatible display everywhere in
// the framework.
- if (mCompatibilityInfo != null) {
- mCompatibilityInfo.applyToDisplayMetrics(mMetrics);
- }
+ mCompatibilityInfo.applyToDisplayMetrics(mMetrics);
+
int configChanges = 0xfffffff;
if (config != null) {
mTmpConfig.setTo(config);
@@ -1546,9 +1547,9 @@ public class Resources {
if (density == Configuration.DENSITY_DPI_UNDEFINED) {
density = mMetrics.noncompatDensityDpi;
}
- if (mCompatibilityInfo != null) {
- mCompatibilityInfo.applyToConfiguration(density, mTmpConfig);
- }
+
+ mCompatibilityInfo.applyToConfiguration(density, mTmpConfig);
+
if (mTmpConfig.locale == null) {
mTmpConfig.locale = Locale.getDefault();
mTmpConfig.setLayoutDirection(mTmpConfig.locale);
@@ -1697,8 +1698,7 @@ public class Resources {
* @hide
*/
public CompatibilityInfo getCompatibilityInfo() {
- return mCompatibilityInfo != null ? mCompatibilityInfo
- : CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
+ return mCompatibilityInfo;
}
/**
@@ -1706,8 +1706,10 @@ public class Resources {
* @hide
*/
public void setCompatibilityInfo(CompatibilityInfo ci) {
- mCompatibilityInfo = ci;
- updateConfiguration(mConfiguration, mMetrics);
+ if (ci != null) {
+ mCompatibilityInfo = ci;
+ updateConfiguration(mConfiguration, mMetrics);
+ }
}
/**
@@ -2407,6 +2409,5 @@ public class Resources {
mMetrics.setToDefaults();
updateConfiguration(null, null);
mAssets.ensureStringBlocks();
- mCompatibilityInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
}
}
diff --git a/core/java/android/hardware/camera2/CameraAccessException.java b/core/java/android/hardware/camera2/CameraAccessException.java
index e08d1e6..1af575f 100644
--- a/core/java/android/hardware/camera2/CameraAccessException.java
+++ b/core/java/android/hardware/camera2/CameraAccessException.java
@@ -29,22 +29,24 @@ import android.util.AndroidException;
public class CameraAccessException extends AndroidException {
/**
* The camera device is in use already
+ * @hide
*/
- public static final int CAMERA_IN_USE = 1;
+ public static final int CAMERA_IN_USE = 4;
/**
* The system-wide limit for number of open cameras has been reached,
* and more camera devices cannot be opened until previous instances are
* closed.
+ * @hide
*/
- public static final int MAX_CAMERAS_IN_USE = 2;
+ public static final int MAX_CAMERAS_IN_USE = 5;
/**
* The camera is disabled due to a device policy, and cannot be opened.
*
* @see android.app.admin.DevicePolicyManager#setCameraDisabled(android.content.ComponentName, boolean)
*/
- public static final int CAMERA_DISABLED = 3;
+ public static final int CAMERA_DISABLED = 1;
/**
* The camera device is removable and has been disconnected from the Android
@@ -52,7 +54,23 @@ public class CameraAccessException extends AndroidException {
* is no longer valid, or the camera service has shut down the connection due to a
* higher-priority access request for the camera device.
*/
- public static final int CAMERA_DISCONNECTED = 4;
+ public static final int CAMERA_DISCONNECTED = 2;
+
+ /**
+ * The camera device is currently in the error state.
+ *
+ * <p>The camera has failed to open or has failed at a later time
+ * as a result of some non-user interaction. Refer to
+ * {@link CameraDevice.StateListener#onError} for the exact
+ * nature of the error.</p>
+ *
+ * <p>No further calls to the camera will succeed. Clean up
+ * the camera with {@link CameraDevice#close} and try
+ * handling the error in order to successfully re-open the camera.
+ * </p>
+ *
+ */
+ public static final int CAMERA_ERROR = 3;
/**
* A deprecated HAL version is in use.
@@ -68,10 +86,9 @@ public class CameraAccessException extends AndroidException {
/**
* The reason for the failure to access the camera.
*
- * @see #CAMERA_IN_USE
- * @see #MAX_CAMERAS_IN_USE
* @see #CAMERA_DISABLED
* @see #CAMERA_DISCONNECTED
+ * @see #CAMERA_ERROR
*/
public final int getReason() {
return mReason;
@@ -105,12 +122,15 @@ public class CameraAccessException extends AndroidException {
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_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.";
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.";
+ case CAMERA_ERROR:
+ return "The camera device is currently in the error state; " +
+ "no further calls to it will succeed.";
}
return null;
}
diff --git a/core/java/android/hardware/camera2/CameraProperties.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index a2faf09..85fa7d6 100644
--- a/core/java/android/hardware/camera2/CameraProperties.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -32,7 +32,7 @@ import java.util.List;
* @see CameraDevice
* @see CameraManager
*/
-public final class CameraProperties extends CameraMetadata {
+public final class CameraCharacteristics extends CameraMetadata {
private final CameraMetadataNative mProperties;
private List<Key<?>> mAvailableRequestKeys;
@@ -42,7 +42,7 @@ public final class CameraProperties extends CameraMetadata {
* Takes ownership of the passed-in properties object
* @hide
*/
- public CameraProperties(CameraMetadataNative properties) {
+ public CameraCharacteristics(CameraMetadataNative properties) {
mProperties = properties;
}
@@ -60,7 +60,7 @@ public final class CameraProperties extends CameraMetadata {
*
* <p>Each key is only listed once in the list. The order of the keys is undefined.</p>
*
- * <p>Note that there is no {@code getAvailableCameraPropertiesKeys()} -- use
+ * <p>Note that there is no {@code getAvailableCameraCharacteristicsKeys()} -- use
* {@link #getKeys()} instead.</p>
*
* @return List of keys supported by this CameraDevice for CaptureRequests.
@@ -81,7 +81,7 @@ public final class CameraProperties extends CameraMetadata {
*
* <p>Each key is only listed once in the list. The order of the keys is undefined.</p>
*
- * <p>Note that there is no {@code getAvailableCameraPropertiesKeys()} -- use
+ * <p>Note that there is no {@code getAvailableCameraCharacteristicsKeys()} -- use
* {@link #getKeys()} instead.</p>
*
* @return List of keys supported by this CameraDevice for CaptureResults.
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 0c13b0f..ec89041 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -118,31 +118,32 @@ public interface CameraDevice extends AutoCloseable {
* this camera device.</p>
*
* <p>This ID can be used to query the camera device's {@link
- * CameraProperties fixed properties} with {@link
- * CameraManager#getCameraProperties}.</p>
+ * CameraCharacteristics fixed properties} with {@link
+ * CameraManager#getCameraCharacteristics}.</p>
*
* <p>This method can be called even if the device has been closed or has encountered
* a serious error.</p>
*
* @return the ID for this camera device
*
- * @see CameraManager#getCameraProperties
+ * @see CameraManager#getCameraCharacteristics
* @see CameraManager#getDeviceIdList
*/
public String getId();
/**
* Get the static properties for this camera. These are identical to the
- * properties returned by {@link CameraManager#getCameraProperties}.
+ * properties returned by {@link CameraManager#getCameraCharacteristics}.
*
* @return the static properties of the camera
*
- * @throws CameraAccessException if the camera device is no longer connected
+ * @throws CameraAccessException if the camera device is no longer connected or has
+ * encountered a fatal error
+ * @throws IllegalStateException if the camera device has been closed
*
- * @see CameraManager#getCameraProperties
+ * @see CameraManager#getCameraCharacteristics
*/
- public CameraProperties getProperties() throws CameraAccessException;
-
+ public CameraCharacteristics getProperties() throws CameraAccessException;
/**
* <p>Set up a new output set of Surfaces for the camera device.</p>
*
@@ -163,7 +164,7 @@ public interface CameraDevice extends AutoCloseable {
* the size of the Surface with
* {@link android.view.SurfaceHolder#setFixedSize} to be one of the
* supported
- * {@link CameraProperties#SCALER_AVAILABLE_PROCESSED_SIZES processed sizes}
+ * {@link CameraCharacteristics#SCALER_AVAILABLE_PROCESSED_SIZES processed sizes}
* before calling {@link android.view.SurfaceHolder#getSurface}.</li>
*
* <li>For accessing through an OpenGL texture via a
@@ -171,14 +172,14 @@ public interface CameraDevice extends AutoCloseable {
* the SurfaceTexture with
* {@link android.graphics.SurfaceTexture#setDefaultBufferSize} to be one
* of the supported
- * {@link CameraProperties#SCALER_AVAILABLE_PROCESSED_SIZES processed sizes}
+ * {@link CameraCharacteristics#SCALER_AVAILABLE_PROCESSED_SIZES processed sizes}
* before creating a Surface from the SurfaceTexture with
* {@link Surface#Surface}.</li>
*
* <li>For recording with {@link android.media.MediaCodec}: Call
* {@link android.media.MediaCodec#createInputSurface} after configuring
* the media codec to use one of the
- * {@link CameraProperties#SCALER_AVAILABLE_PROCESSED_SIZES processed sizes}
+ * {@link CameraCharacteristics#SCALER_AVAILABLE_PROCESSED_SIZES processed sizes}
* </li>
*
* <li>For recording with {@link android.media.MediaRecorder}: TODO</li>
@@ -187,16 +188,16 @@ public interface CameraDevice extends AutoCloseable {
* Create a RenderScript
* {@link android.renderscript.Allocation Allocation} with a supported YUV
* type, the IO_INPUT flag, and one of the supported
- * {@link CameraProperties#SCALER_AVAILABLE_PROCESSED_SIZES processed sizes}. Then
+ * {@link CameraCharacteristics#SCALER_AVAILABLE_PROCESSED_SIZES processed sizes}. Then
* obtain the Surface with
* {@link android.renderscript.Allocation#getSurface}.</li>
*
* <li>For access to uncompressed or JPEG data in the application: Create a
* {@link android.media.ImageReader} object with the desired
- * {@link CameraProperties#SCALER_AVAILABLE_FORMATS image format}, and a
+ * {@link CameraCharacteristics#SCALER_AVAILABLE_FORMATS image format}, and a
* size from the matching
- * {@link CameraProperties#SCALER_AVAILABLE_PROCESSED_SIZES processed},
- * {@link CameraProperties#SCALER_AVAILABLE_JPEG_SIZES jpeg}. Then obtain
+ * {@link CameraCharacteristics#SCALER_AVAILABLE_PROCESSED_SIZES processed},
+ * {@link CameraCharacteristics#SCALER_AVAILABLE_JPEG_SIZES jpeg}. Then obtain
* a Surface from it.</li>
*
* </ul>
@@ -218,23 +219,31 @@ public interface CameraDevice extends AutoCloseable {
*
* <p>To reach an idle state without cancelling any submitted captures, first
* stop any repeating request/burst with {@link #stopRepeating}, and then
- * wait for the {@link CameraDeviceListener#onCameraIdle} callback to be
+ * wait for the {@link StateListener#onIdle} callback to be
* called. To idle as fast as possible, use {@link #flush} and wait for the
* idle callback.</p>
*
* <p>Using larger resolution outputs, or more outputs, can result in slower
* output rate from the device.</p>
*
+ * <p>Configuring the outputs with an empty or null list will transition
+ * the camera into an {@link StateListener#onUnconfigured unconfigured state}.
+ * </p>
+ *
+ * <p>Calling configureOutputs with the same arguments as the last call to
+ * configureOutputs has no effect.</p>
+ *
* @param outputs The new set of Surfaces that should be made available as
* targets for captured image data.
*
* @throws IllegalArgumentException if the set of output Surfaces do not
* meet the requirements
- * @throws CameraAccessException if the camera device is no longer connected
- * @throws IllegalStateException if the camera device is not idle, or has
- * encountered a fatal error
+ * @throws CameraAccessException if the camera device is no longer connected or has
+ * encountered a fatal error
+ * @throws IllegalStateException if the camera device is not idle, or
+ * if the camera device has been closed
*
- * @see CameraDeviceListener#onCameraIdle
+ * @see StateListener#onIdle
* @see #stopRepeating
* @see #flush
*/
@@ -255,9 +264,9 @@ public interface CameraDevice extends AutoCloseable {
*
* @throws IllegalArgumentException if the templateType is not in the list
* of supported templates.
- * @throws CameraAccessException if the camera device is no longer connected
- * @throws IllegalStateException if the camera device has been closed or the
- * device has encountered a fatal error.
+ * @throws CameraAccessException if the camera device is no longer connected or has
+ * encountered a fatal error
+ * @throws IllegalStateException if the camera device has been closed
*
* @see #TEMPLATE_PREVIEW
* @see #TEMPLATE_RECORD
@@ -295,9 +304,13 @@ public interface CameraDevice extends AutoCloseable {
* {@code null} to use the current thread's {@link android.os.Looper
* looper}.
*
- * @throws CameraAccessException if the camera device is no longer connected
- * @throws IllegalStateException if the camera device has been closed or the
- * device has encountered a fatal error.
+ * @return int A unique capture sequence ID used by
+ * {@link CaptureListener#onCaptureSequenceCompleted}.
+ *
+ * @throws CameraAccessException if the camera device is no longer connected or has
+ * encountered a fatal error
+ * @throws IllegalStateException if the camera is currently busy or unconfigured,
+ * or the camera device has been closed.
* @throws IllegalArgumentException If the request targets Surfaces not
* currently configured as outputs. Or if the handler is null, the listener
* is not null, and the calling thread has no looper.
@@ -306,7 +319,7 @@ public interface CameraDevice extends AutoCloseable {
* @see #setRepeatingRequest
* @see #setRepeatingBurst
*/
- public void capture(CaptureRequest request, CaptureListener listener, Handler handler)
+ public int capture(CaptureRequest request, CaptureListener listener, Handler handler)
throws CameraAccessException;
/**
@@ -335,9 +348,13 @@ public interface CameraDevice extends AutoCloseable {
* {@code null} to use the current thread's {@link android.os.Looper
* looper}.
*
- * @throws CameraAccessException if the camera device is no longer connected
- * @throws IllegalStateException if the camera device has been closed or the
- * device has encountered a fatal error.
+ * @return int A unique capture sequence ID used by
+ * {@link CaptureListener#onCaptureSequenceCompleted}.
+ *
+ * @throws CameraAccessException if the camera device is no longer connected or has
+ * encountered a fatal error
+ * @throws IllegalStateException if the camera is currently busy or unconfigured,
+ * or the camera device has been closed.
* @throws IllegalArgumentException If the requests target Surfaces not
* currently configured as outputs. Or if the handler is null, the listener
* is not null, and the calling thread has no looper.
@@ -346,7 +363,7 @@ public interface CameraDevice extends AutoCloseable {
* @see #setRepeatingRequest
* @see #setRepeatingBurst
*/
- public void captureBurst(List<CaptureRequest> requests, CaptureListener listener,
+ public int captureBurst(List<CaptureRequest> requests, CaptureListener listener,
Handler handler) throws CameraAccessException;
/**
@@ -387,10 +404,13 @@ public interface CameraDevice extends AutoCloseable {
* {@code null} to use the current thread's {@link android.os.Looper
* looper}.
*
- * @throws CameraAccessException if the camera device is no longer
- * connected
- * @throws IllegalStateException if the camera device has been closed or the
- * device has encountered a fatal error.
+ * @return int A unique capture sequence ID used by
+ * {@link CaptureListener#onCaptureSequenceCompleted}.
+ *
+ * @throws CameraAccessException if the camera device is no longer connected or has
+ * encountered a fatal error
+ * @throws IllegalStateException if the camera is currently busy or unconfigured,
+ * or the camera device has been closed.
* @throws IllegalArgumentException If the requests reference Surfaces not
* currently configured as outputs. Or if the handler is null, the listener
* is not null, and the calling thread has no looper.
@@ -401,7 +421,7 @@ public interface CameraDevice extends AutoCloseable {
* @see #stopRepeating
* @see #flush
*/
- public void setRepeatingRequest(CaptureRequest request, CaptureListener listener,
+ public int setRepeatingRequest(CaptureRequest request, CaptureListener listener,
Handler handler) throws CameraAccessException;
/**
@@ -442,9 +462,13 @@ public interface CameraDevice extends AutoCloseable {
* {@code null} to use the current thread's {@link android.os.Looper
* looper}.
*
- * @throws CameraAccessException if the camera device is no longer connected
- * @throws IllegalStateException if the camera device has been closed or the
- * device has encountered a fatal error.
+ * @return int A unique capture sequence ID used by
+ * {@link CaptureListener#onCaptureSequenceCompleted}.
+ *
+ * @throws CameraAccessException if the camera device is no longer connected or has
+ * encountered a fatal error
+ * @throws IllegalStateException if the camera is currently busy or unconfigured,
+ * or the camera device has been closed.
* @throws IllegalArgumentException If the requests reference Surfaces not
* currently configured as outputs. Or if the handler is null, the listener
* is not null, and the calling thread has no looper.
@@ -455,7 +479,7 @@ public interface CameraDevice extends AutoCloseable {
* @see #stopRepeating
* @see #flush
*/
- public void setRepeatingBurst(List<CaptureRequest> requests, CaptureListener listener,
+ public int setRepeatingBurst(List<CaptureRequest> requests, CaptureListener listener,
Handler handler) throws CameraAccessException;
/**
@@ -467,21 +491,17 @@ public interface CameraDevice extends AutoCloseable {
* <p>Any currently in-flight captures will still complete, as will any
* burst that is mid-capture. To ensure that the device has finished
* processing all of its capture requests and is in idle state, wait for the
- * {@link CameraDeviceListener#onCameraIdle} callback after calling this
+ * {@link StateListener#onIdle} callback after calling this
* method..</p>
*
- * @throws CameraAccessException if the camera device is no longer connected
- * @throws IllegalStateException if the camera device has been closed or the
- * device has encountered a fatal error.
+ * @throws CameraAccessException if the camera device is no longer connected or has
+ * encountered a fatal error
+ * @throws IllegalStateException if the camera is currently busy or unconfigured,
+ * or the camera device has been closed.
*
* @see #setRepeatingRequest
* @see #setRepeatingBurst
- * @see CameraDeviceListener#onCameraIdle
- *
- * @throws CameraAccessException if the camera device is no longer connected
- * @throws IllegalStateException if the camera device has been closed, the
- * device has encountered a fatal error, or if there is an active repeating
- * request or burst.
+ * @see StateListener#onIdle
*/
public void stopRepeating() throws CameraAccessException;
@@ -519,7 +539,7 @@ public interface CameraDevice extends AutoCloseable {
* {@link CaptureListener}.</p>
*
* <p>If the camera device is idle when the listener is set, then the
- * {@link CameraDeviceListener#onCameraIdle} method will be immediately called,
+ * {@link StateListener#onIdle} method will be immediately called,
* even if the device has never been active before.
* </p>
*
@@ -530,8 +550,10 @@ public interface CameraDevice extends AutoCloseable {
*
* @throws IllegalArgumentException if handler is null, the listener is
* not null, and the calling thread has no looper
+ *
+ * @hide
*/
- public void setDeviceListener(CameraDeviceListener listener, Handler handler);
+ public void setDeviceListener(StateListener listener, Handler handler);
/**
* Flush all captures currently pending and in-progress as fast as
@@ -558,7 +580,11 @@ public interface CameraDevice extends AutoCloseable {
* configurations, or for cancelling long in-progress requests (such as a
* multi-second capture).</p>
*
- * @throws CameraAccessException if the camera device is no longer connected
+ * @throws CameraAccessException if the camera device is no longer connected or has
+ * encountered a fatal error
+ * @throws IllegalStateException if the camera is not idle/active,
+ * or the camera device has been closed.
+ *
* @see #setRepeatingRequest
* @see #setRepeatingBurst
* @see #configureOutputs
@@ -569,10 +595,9 @@ public interface CameraDevice extends AutoCloseable {
* 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
*/
@Override
- public void close() throws Exception;
+ public void close();
// TODO: We should decide on the behavior of in-flight requests should be on close.
/**
@@ -587,7 +612,6 @@ public interface CameraDevice extends AutoCloseable {
* @see #captureBurst
* @see #setRepeatingRequest
* @see #setRepeatingBurst
- *
*/
public static abstract class CaptureListener {
@@ -658,8 +682,13 @@ public interface CameraDevice extends AutoCloseable {
*
* <p>The default implementation of this method does nothing.</p>
*
- * @param camera The CameraDevice sending the callback.
- * @param request The request that was given to the CameraDevice
+ * @param camera
+ * The CameraDevice sending the callback.
+ * @param request
+ * The request that was given to the CameraDevice
+ * @param failure
+ * The output failure from the capture, including the failure reason
+ * and the frame number.
*
* @see #capture
* @see #captureBurst
@@ -667,7 +696,30 @@ public interface CameraDevice extends AutoCloseable {
* @see #setRepeatingBurst
*/
public void onCaptureFailed(CameraDevice camera,
- CaptureRequest request) {
+ CaptureRequest request, CaptureFailure failure) {
+ // default empty implementation
+ }
+
+ /**
+ * This method is called independently of the others in CaptureListener,
+ * when a capture sequence finishes and all {@link CaptureResult}
+ * or {@link CaptureFailure} for it have been returned via this listener.
+ *
+ * @param camera
+ * The CameraDevice sending the callback.
+ * @param sequenceId
+ * A sequence ID returned by the {@link #capture} family of functions.
+ * @param frameNumber
+ * The last frame number (returned by {@link CaptureResult#getFrameNumber}
+ * or {@link CaptureFailure#getFrameNumber}) in the capture sequence.
+ *
+ * @see CaptureResult#getFrameNumber()
+ * @see CaptureFailure#getFrameNumber()
+ * @see CaptureResult#getSequenceId()
+ * @see CaptureFailure#getSequenceId()
+ */
+ public void onCaptureSequenceCompleted(CameraDevice camera,
+ int sequenceId, int frameNumber) {
// default empty implementation
}
}
@@ -687,37 +739,190 @@ public interface CameraDevice extends AutoCloseable {
*
* @see #setDeviceListener
*/
- public static abstract class CameraDeviceListener {
+ public static abstract class StateListener {
+ /**
+ * An error code that can be reported by {@link #onError}
+ * indicating that the camera device is in use already.
+ *
+ * <p>
+ * This error can be produced when opening the camera fails.
+ * </p>
+ *
+ * @see #onError
+ */
+ public static final int ERROR_CAMERA_IN_USE = 1;
/**
- * An error code that can be reported by {@link #onCameraError}
+ * An error code that can be reported by {@link #onError}
+ * indicating that the camera device could not be opened
+ * because there are too many other open camera devices.
+ *
+ * <p>
+ * The system-wide limit for number of open cameras has been reached,
+ * and more camera devices cannot be opened until previous instances are
+ * closed.
+ * </p>
+ *
+ * <p>
+ * This error can be produced when opening the camera fails.
+ * </p>
+ *
+ * @see #onError
+ */
+ public static final int ERROR_MAX_CAMERAS_IN_USE = 2;
+
+ /**
+ * An error code that can be reported by {@link #onError}
+ * indicating that the camera device could not be opened due to a device
+ * policy.
+ *
+ * @see android.app.admin.DevicePolicyManager#setCameraDisabled(android.content.ComponentName, boolean)
+ * @see #onError
+ */
+ public static final int ERROR_CAMERA_DISABLED = 3;
+
+ /**
+ * An error code that can be reported by {@link #onError}
* indicating that the camera device has encountered a fatal error.
*
* <p>The camera device needs to be re-opened to be used again.</p>
*
- * @see #onCameraDeviceError
+ * @see #onError
*/
- public static final int ERROR_CAMERA_DEVICE = 1;
+ public static final int ERROR_CAMERA_DEVICE = 4;
/**
- * An error code that can be reported by {@link #onCameraError}
+ * An error code that can be reported by {@link #onError}
* indicating that the camera service has encountered a fatal error.
*
* <p>The Android device may need to be shut down and restarted to restore
* camera function, or there may be a persistent hardware problem.</p>
*
- * @see #onCameraDeviceError
+ * <p>An attempt at recovery <i>may</i> be possible by closing the
+ * CameraDevice and the CameraManager, and trying to acquire all resources
+ * again from scratch.</p>
+ *
+ * @see #onError
*/
- public static final int ERROR_CAMERA_SERVICE = 2;
+ public static final int ERROR_CAMERA_SERVICE = 5;
+
+ /**
+ * The method called when a camera device has finished opening.
+ *
+ * <p>An opened camera will immediately afterwards transition into
+ * {@link #onUnconfigured}.</p>
+ *
+ * @param camera the camera device that has become opened
+ */
+ public abstract void onOpened(CameraDevice camera); // Must implement
+
+ /**
+ * The method called when a camera device has no outputs configured.
+ *
+ * <p>An unconfigured camera device needs to be configured with
+ * {@link CameraDevice#configureOutputs} before being able to
+ * submit any capture request.</p>
+ *
+ * <p>This state may be entered by a newly opened camera or by
+ * calling {@link CameraDevice#configureOutputs} with a null/empty
+ * list of Surfaces when idle.</p>
+ *
+ * <p>Any attempts to submit a capture request while in this state
+ * will result in an {@link IllegalStateException} being thrown.</p>
+ *
+ * <p>The default implementation of this method does nothing.</p>
+ *
+ * @param camera the camera device has that become unconfigured
+ */
+ public void onUnconfigured(CameraDevice camera) {
+ // Default empty implementation
+ }
+
+ /**
+ * The method called when a camera device begins processing
+ * {@link CaptureRequest capture requests}.
+ *
+ * <p>A camera may not be re-configured while in this state. The camera
+ * will transition to the idle state once all pending captures have
+ * completed. If a repeating request is set, the camera will remain active
+ * until it is cleared and the remaining requests finish processing. To
+ * transition to the idle state as quickly as possible, call {@link #flush()},
+ * which will idle the camera device as quickly as possible, likely canceling
+ * most in-progress captures.</p>
+ *
+ * <p>All calls except for {@link CameraDevice#configureOutputs} are
+ * legal while in this state.
+ * </p>
+ *
+ * <p>The default implementation of this method does nothing.</p>
+ *
+ * @param camera the camera device that has become active
+ *
+ * @see CameraDevice#capture
+ * @see CameraDevice#captureBurst
+ * @see CameraDevice#setRepeatingBurst
+ * @see CameraDevice#setRepeatingRequest
+ */
+ public void onActive(CameraDevice camera) {
+ // Default empty implementation
+ }
+
+ /**
+ * The method called when a camera device is busy.
+ *
+ * <p>A camera becomes busy while it's outputs are being configured
+ * (after a call to {@link CameraDevice#configureOutputs} or while it's
+ * being flushed (after a call to {@link CameraDevice#flush}.</p>
+ *
+ * <p>Once the on-going operations are complete, the camera will automatically
+ * transition into {@link #onIdle} if there is at least one configured output,
+ * or {@link #onUnconfigured} otherwise.</p>
+ *
+ * <p>Any attempts to manipulate the camera while its is busy
+ * will result in an {@link IllegalStateException} being thrown.</p>
+ *
+ * <p>Only the following methods are valid to call while in this state:
+ * <ul>
+ * <li>{@link CameraDevice#getId}</li>
+ * <li>{@link CameraDevice#createCaptureRequest}</li>
+ * <li>{@link CameraDevice#close}</li>
+ * </ul>
+ * </p>
+ *
+ * <p>The default implementation of this method does nothing.</p>
+ *
+ * @param camera the camera device that has become busy
+ *
+ * @see CameraDevice#configureOutputs
+ * @see CameraDevice#flush
+ */
+ public void onBusy(CameraDevice camera) {
+ // Default empty implementation
+ }
+
+ /**
+ * The method called when a camera device has been closed with
+ * {@link CameraDevice#close}.
+ *
+ * <p>Any attempt to call methods on this CameraDevice in the
+ * future will throw a {@link IllegalStateException}.</p>
+ *
+ * <p>The default implementation of this method does nothing.</p>
+ *
+ * @param camera the camera device that has become closed
+ */
+ public void onClosed(CameraDevice camera) {
+ // Default empty implementation
+ }
/**
* The method called when a camera device has finished processing all
* submitted capture requests and has reached an idle state.
*
- * <p>An idle camera device can have its outputs changed by calling
- * {@link CameraDevice#configureOutputs}.</p>
+ * <p>An idle camera device can have its outputs changed by calling {@link
+ * CameraDevice#configureOutputs}, which will transition it into the busy state.</p>
*
- * <p>To idle and reconfigure outputs without cancelling any submitted
+ * <p>To idle and reconfigure outputs without canceling any submitted
* capture requests, the application needs to clear its repeating
* request/burst, if set, with {@link CameraDevice#stopRepeating}, and
* then wait for this callback to be called before calling {@link
@@ -725,7 +930,7 @@ public interface CameraDevice extends AutoCloseable {
*
* <p>To idle and reconfigure a camera device as fast as possible, the
* {@link CameraDevice#flush} method can be used, which will discard all
- * pending and in-progess capture requests. Once the {@link
+ * pending and in-progress capture requests. Once the {@link
* CameraDevice#flush} method is called, the application must wait for
* this callback to fire before calling {@link
* CameraDevice#configureOutputs}.</p>
@@ -738,7 +943,7 @@ public interface CameraDevice extends AutoCloseable {
* @see CameraDevice#stopRepeating
* @see CameraDevice#flush
*/
- public void onCameraIdle(CameraDevice camera) {
+ public void onIdle(CameraDevice camera) {
// Default empty implementation
}
@@ -746,6 +951,9 @@ public interface CameraDevice extends AutoCloseable {
* The method called when a camera device is no longer available for
* use.
*
+ * <p>This callback may be called instead of {@link #onOpened}
+ * if opening the camera fails.</p>
+ *
* <p>Any attempt to call methods on this CameraDevice will throw a
* {@link CameraAccessException}. The disconnection could be due to a
* change in security policy or permissions; the physical disconnection
@@ -759,25 +967,32 @@ public interface CameraDevice extends AutoCloseable {
* <p>The default implementation logs a notice to the system log
* about the disconnection.</p>
*
+ * <p>You should clean up the camera with {@link CameraDevice#close} after
+ * this happens, as it is not recoverable until opening the camera again
+ * after it becomes {@link CameraManager.AvailabilityListener#onCameraAvailable available}.
+ * </p>
+ *
* @param camera the device that has been disconnected
*/
- public void onCameraDisconnected(CameraDevice camera) {
- Log.i("CameraListener",
- String.format("Camera device %s disconnected", camera.getId()));
- }
+ public abstract void onDisconnected(CameraDevice camera); // Must implement
/**
* The method called when a camera device has encountered a serious error.
*
+ * <p>This callback may be called instead of {@link #onOpened}
+ * if opening the camera fails.</p>
+ *
* <p>This indicates a failure of the camera device or camera service in
* some way. Any attempt to call methods on this CameraDevice in the
- * future will throw a {@link java.lang.IllegalStateException}.</p>
+ * future will throw a {@link CameraAccessException} with the
+ * {@link CameraAccessException#CAMERA_ERROR CAMERA_ERROR} reason.
+ * </p>
*
* <p>There may still be capture completion or camera stream listeners
* that will be called after this error is received.</p>
*
- * <p>The default implementation logs an error to the system log about
- * the camera failure.</p>
+ * <p>You should clean up the camera with {@link CameraDevice#close} after
+ * this happens. Further attempts at recovery are error-code specific.</p>
*
* @param camera The device reporting the error
* @param error The error code, one of the
@@ -785,11 +1000,9 @@ public interface CameraDevice extends AutoCloseable {
*
* @see #ERROR_CAMERA_DEVICE
* @see #ERROR_CAMERA_SERVICE
+ * @see #ERROR_CAMERA_DISABLED
+ * @see #ERROR_CAMERA_IN_USE
*/
- public void onCameraError(CameraDevice camera, int error) {
- Log.e("CameraListener",
- String.format("Camera device %s has encountered an error: %d",
- camera.getId(), error));
- }
+ public abstract void onError(CameraDevice camera, int error); // Must implement
}
}
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 4ad9259..af0512e 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -58,7 +58,7 @@ public final class CameraManager {
private final ICameraService mCameraService;
private ArrayList<String> mDeviceIdList;
- private ArrayMap<AvailabilityListener, Handler> mListenerMap =
+ private final ArrayMap<AvailabilityListener, Handler> mListenerMap =
new ArrayMap<AvailabilityListener, Handler>();
private final Context mContext;
@@ -166,7 +166,7 @@ public final class CameraManager {
* @see #getCameraIdList
* @see android.app.admin.DevicePolicyManager#setCameraDisabled
*/
- public CameraProperties getCameraProperties(String cameraId)
+ public CameraCharacteristics getCameraCharacteristics(String cameraId)
throws CameraAccessException {
synchronized (mLock) {
@@ -179,7 +179,7 @@ public final class CameraManager {
// TODO: implement and call a service function to get the capabilities on C++ side
// TODO: get properties from service
- return new CameraProperties(new CameraMetadataNative());
+ return new CameraCharacteristics(new CameraMetadataNative());
}
/**
@@ -201,8 +201,7 @@ public final class CameraManager {
* @see #getCameraIdList
* @see android.app.admin.DevicePolicyManager#setCameraDisabled
*/
- public CameraDevice openCamera(String cameraId) throws CameraAccessException {
-
+ private CameraDevice openCamera(String cameraId) throws CameraAccessException {
try {
synchronized (mLock) {
@@ -237,6 +236,79 @@ public final class CameraManager {
}
/**
+ * Open a connection to a camera with the given ID.
+ *
+ * <p>Use {@link #getCameraIdList} to get the list of available camera
+ * devices. Note that even if an id is listed, open may fail if the device
+ * is disconnected between the calls to {@link #getCameraIdList} and
+ * {@link #openCamera}.</p>
+ *
+ * <p>If the camera successfully opens after this function call returns,
+ * {@link CameraDevice.StateListener#onOpened} will be invoked with the
+ * newly opened {@link CameraDevice} in the unconfigured state.</p>
+ *
+ * <p>If the camera becomes disconnected during initialization
+ * after this function call returns,
+ * {@link CameraDevice.StateListener#onDisconnected} with a
+ * {@link CameraDevice} in the disconnected state (and
+ * {@link CameraDevice.StateListener#onOpened} will be skipped).</p>
+ *
+ * <p>If the camera fails to initialize after this function call returns,
+ * {@link CameraDevice.StateListener#onError} will be invoked with a
+ * {@link CameraDevice} in the error state (and
+ * {@link CameraDevice.StateListener#onOpened} will be skipped).</p>
+ *
+ * @param cameraId
+ * The unique identifier of the camera device to open
+ * @param listener
+ * The listener which is invoked once the camera is opened
+ * @param handler
+ * The handler on which the listener should be invoked, or
+ * {@code null} to use the current thread's {@link android.os.Looper looper}.
+ *
+ * @throws CameraAccessException if the camera is disabled by device policy,
+ * or the camera has become or was disconnected.
+ *
+ * @throws IllegalArgumentException if cameraId or the listener was null,
+ * or the cameraId does not match any currently or previously available
+ * camera device.
+ *
+ * @throws SecurityException if the application does not have permission to
+ * access the camera
+ *
+ * @see #getCameraIdList
+ * @see android.app.admin.DevicePolicyManager#setCameraDisabled
+ */
+ public void openCamera(String cameraId, final CameraDevice.StateListener listener,
+ Handler handler)
+ throws CameraAccessException {
+
+ if (cameraId == null) {
+ throw new IllegalArgumentException("cameraId was null");
+ } else if (listener == null) {
+ throw new IllegalArgumentException("listener was null");
+ } else if (handler == null) {
+ if (Looper.myLooper() != null) {
+ handler = new Handler();
+ } else {
+ throw new IllegalArgumentException(
+ "Looper doesn't exist in the calling thread");
+ }
+ }
+
+ final CameraDevice camera = openCamera(cameraId);
+ camera.setDeviceListener(listener, handler);
+
+ // TODO: make truly async in the camera service
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ listener.onOpened(camera);
+ }
+ });
+ }
+
+ /**
* Interface for listening to camera devices becoming available or
* unavailable.
*
@@ -265,7 +337,7 @@ public final class CameraManager {
*
* <p>If an application had an active CameraDevice instance for the
* now-disconnected camera, that application will receive a
- * {@link CameraDevice.CameraDeviceListener#onCameraDisconnected disconnection error}.</p>
+ * {@link CameraDevice.StateListener#onDisconnected disconnection error}.</p>
*
* <p>The default implementation of this method does nothing.</p>
*
@@ -403,6 +475,7 @@ public final class CameraManager {
if (isAvailable(status)) {
handler.post(
new Runnable() {
+ @Override
public void run() {
listener.onCameraAvailable(id);
}
@@ -410,6 +483,7 @@ public final class CameraManager {
} else {
handler.post(
new Runnable() {
+ @Override
public void run() {
listener.onCameraUnavailable(id);
}
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 7f4ba4f..b447494 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -40,11 +40,19 @@ import java.util.List;
*
* @see CameraDevice
* @see CameraManager
- * @see CameraProperties
+ * @see CameraCharacteristics
**/
public abstract class CameraMetadata {
/**
+ * Set a camera metadata field to a value. The field definitions can be
+ * found in {@link CameraCharacteristics}, {@link CaptureResult}, and
+ * {@link CaptureRequest}.
+ *
+ * @param key The metadata field to write.
+ * @param value The value to set the field to, which must be of a matching
+ * type to the key.
+ *
* @hide
*/
protected CameraMetadata() {
@@ -54,7 +62,7 @@ public abstract class CameraMetadata {
* Get a camera metadata field value.
*
* <p>The field definitions can be
- * found in {@link CameraProperties}, {@link CaptureResult}, and
+ * found in {@link CameraCharacteristics}, {@link CaptureResult}, and
* {@link CaptureRequest}.</p>
*
* <p>Querying the value for the same key more than once will return a value
@@ -195,43 +203,43 @@ public abstract class CameraMetadata {
*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~*/
//
- // Enumeration values for CameraProperties#LENS_FACING
+ // Enumeration values for CameraCharacteristics#LENS_FACING
//
/**
- * @see CameraProperties#LENS_FACING
+ * @see CameraCharacteristics#LENS_FACING
*/
public static final int LENS_FACING_FRONT = 0;
/**
- * @see CameraProperties#LENS_FACING
+ * @see CameraCharacteristics#LENS_FACING
*/
public static final int LENS_FACING_BACK = 1;
//
- // Enumeration values for CameraProperties#LED_AVAILABLE_LEDS
+ // Enumeration values for CameraCharacteristics#LED_AVAILABLE_LEDS
//
/**
* <p>
* android.led.transmit control is used
* </p>
- * @see CameraProperties#LED_AVAILABLE_LEDS
+ * @see CameraCharacteristics#LED_AVAILABLE_LEDS
* @hide
*/
public static final int LED_AVAILABLE_LEDS_TRANSMIT = 0;
//
- // Enumeration values for CameraProperties#INFO_SUPPORTED_HARDWARE_LEVEL
+ // Enumeration values for CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
//
/**
- * @see CameraProperties#INFO_SUPPORTED_HARDWARE_LEVEL
+ * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
*/
public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED = 0;
/**
- * @see CameraProperties#INFO_SUPPORTED_HARDWARE_LEVEL
+ * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
*/
public static final int INFO_SUPPORTED_HARDWARE_LEVEL_FULL = 1;
diff --git a/core/java/android/hardware/camera2/CaptureFailure.java b/core/java/android/hardware/camera2/CaptureFailure.java
new file mode 100644
index 0000000..3b408cf
--- /dev/null
+++ b/core/java/android/hardware/camera2/CaptureFailure.java
@@ -0,0 +1,144 @@
+/*
+ * 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.camera2;
+
+import android.hardware.camera2.CameraDevice.CaptureListener;
+
+/**
+ * A report of failed capture for a single image capture from the image sensor.
+ *
+ * <p>CaptureFailures are produced by a {@link CameraDevice} if processing a
+ * {@link CaptureRequest} fails, either partially or fully. Use {@link #getReason}
+ * to determine the specific nature of the failed capture.</p>
+ *
+ * <p>Receiving a CaptureFailure means that the metadata associated with that frame number
+ * has been dropped -- no {@link CaptureResult} with the same frame number will be
+ * produced.</p>
+ */
+public class CaptureFailure {
+ /**
+ * The {@link CaptureResult} has been dropped this frame only due to an error
+ * in the framework.
+ *
+ * @see #getReason()
+ */
+ public static final int REASON_ERROR = 0;
+
+ /**
+ * The capture has failed due to a {@link CameraDevice#flush} call from the application.
+ *
+ * @see #getReason()
+ */
+ public static final int REASON_FLUSHED = 1;
+
+ private final CaptureRequest mRequest;
+ private final int mReason;
+ private final boolean mDropped;
+ private final int mSequenceId;
+ private final int mFrameNumber;
+
+ /**
+ * @hide
+ */
+ public CaptureFailure(CaptureRequest request, int reason, boolean dropped, int sequenceId,
+ int frameNumber) {
+ mRequest = request;
+ mReason = reason;
+ mDropped = dropped;
+ mSequenceId = sequenceId;
+ mFrameNumber = frameNumber;
+ }
+
+ /**
+ * Get the request associated with this failed capture.
+ *
+ * <p>Whenever a request is unsuccessfully captured, with
+ * {@link CameraDevice.CaptureListener#onCaptureFailed},
+ * the {@code failed capture}'s {@code getRequest()} will return that {@code request}.
+ * </p>
+ *
+ * <p>In particular,
+ * <code><pre>cameraDevice.capture(someRequest, new CaptureListener() {
+ * {@literal @}Override
+ * void onCaptureFailed(CaptureRequest myRequest, CaptureFailure myFailure) {
+ * assert(myFailure.getRequest.equals(myRequest) == true);
+ * }
+ * };
+ * </code></pre>
+ * </p>
+ *
+ * @return The request associated with this failed capture. Never {@code null}.
+ */
+ public CaptureRequest getRequest() {
+ return mRequest;
+ }
+
+ /**
+ * Get the frame number associated with this failed capture.
+ *
+ * <p>Whenever a request has been processed, regardless of failed capture or success,
+ * it gets a unique frame number assigned to its future result/failed capture.</p>
+ *
+ * <p>This value monotonically increments, starting with 0,
+ * for every new result or failure; and the scope is the lifetime of the
+ * {@link CameraDevice}.</p>
+ *
+ * @return int frame number
+ */
+ public int getFrameNumber() {
+ return mFrameNumber;
+ }
+
+ /**
+ * Determine why the request was dropped, whether due to an error or to a user
+ * action.
+ *
+ * @return int One of {@code REASON_*} integer constants.
+ *
+ * @see #REASON_ERROR
+ * @see #REASON_FLUSHED
+ */
+ public int getReason() {
+ return mReason;
+ }
+
+ /**
+ * Determine if the image was captured from the camera.
+ *
+ * <p>If the image was not captured, no image buffers will be available.
+ * If the image was captured, then image buffers may be available.</p>
+ *
+ * @return boolean True if the image was captured, false otherwise.
+ */
+ public boolean wasImageCaptured() {
+ return !mDropped;
+ }
+
+ /**
+ * The sequence ID for this failed capture that was returned by the
+ * {@link CameraDevice#capture} family of functions.
+ *
+ * <p>The sequence ID is a unique monotonically increasing value starting from 0,
+ * incremented every time a new group of requests is submitted to the CameraDevice.</p>
+ *
+ * @return int The ID for the sequence of requests that this capture failure is the result of
+ *
+ * @see CameraDevice.CaptureListener#onCaptureSequenceCompleted
+ */
+ public int getSequenceId() {
+ return mSequenceId;
+ }
+}
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 3ec5ca0..f30bcc5 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -17,11 +17,13 @@
package android.hardware.camera2;
import android.hardware.camera2.impl.CameraMetadataNative;
+import android.hardware.camera2.CameraDevice.CaptureListener;
import android.os.Parcel;
import android.os.Parcelable;
import android.view.Surface;
import java.util.HashSet;
+import java.util.Objects;
/**
@@ -62,30 +64,37 @@ public final class CaptureRequest extends CameraMetadata implements Parcelable {
private Object mUserTag;
/**
- * Construct empty request
- * @hide
+ * Construct empty request.
+ *
+ * Used by Binder to unparcel this object only.
*/
- public CaptureRequest() {
+ private CaptureRequest() {
mSettings = new CameraMetadataNative();
mSurfaceSet = new HashSet<Surface>();
}
/**
- * Clone from source capture request
+ * Clone from source capture request.
+ *
+ * Used by the Builder to create an immutable copy.
*/
+ @SuppressWarnings("unchecked")
private CaptureRequest(CaptureRequest source) {
mSettings = new CameraMetadataNative(source.mSettings);
mSurfaceSet = (HashSet<Surface>) source.mSurfaceSet.clone();
}
/**
- * Take ownership of passed-in settings
+ * Take ownership of passed-in settings.
+ *
+ * Used by the Builder to create a mutable CaptureRequest.
*/
private CaptureRequest(CameraMetadataNative settings) {
mSettings = settings;
mSurfaceSet = new HashSet<Surface>();
}
+ @SuppressWarnings("unchecked")
@Override
public <T> T get(Key<T> key) {
return mSettings.get(key);
@@ -108,6 +117,34 @@ public final class CaptureRequest extends CameraMetadata implements Parcelable {
return mUserTag;
}
+ /**
+ * Determine whether this CaptureRequest is equal to another CaptureRequest.
+ *
+ * <p>A request is considered equal to another is if it's set of key/values is equal, it's
+ * list of output surfaces is equal, and the user tag is equal.</p>
+ *
+ * @param other Another instance of CaptureRequest.
+ *
+ * @return True if the requests are the same, false otherwise.
+ */
+ @Override
+ public boolean equals(Object other) {
+ return other instanceof CaptureRequest
+ && equals((CaptureRequest)other);
+ }
+
+ private boolean equals(CaptureRequest other) {
+ return other != null
+ && Objects.equals(mUserTag, other.mUserTag)
+ && mSurfaceSet.equals(other.mSurfaceSet)
+ && mSettings.equals(other.mSettings);
+ }
+
+ @Override
+ public int hashCode() {
+ return mSettings.hashCode();
+ }
+
public static final Parcelable.Creator<CaptureRequest> CREATOR =
new Parcelable.Creator<CaptureRequest>() {
@Override
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 377e78a..b82104d 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -37,13 +37,25 @@ import android.hardware.camera2.impl.CameraMetadataNative;
public final class CaptureResult extends CameraMetadata {
private final CameraMetadataNative mResults;
+ private final CaptureRequest mRequest;
+ private final int mSequenceId;
/**
* Takes ownership of the passed-in properties object
* @hide
*/
- public CaptureResult(CameraMetadataNative results) {
+ public CaptureResult(CameraMetadataNative results, CaptureRequest parent, int sequenceId) {
+ if (results == null) {
+ throw new IllegalArgumentException("results was null");
+ }
+
+ if (parent == null) {
+ throw new IllegalArgumentException("parent was null");
+ }
+
mResults = results;
+ mRequest = parent;
+ mSequenceId = sequenceId;
}
@Override
@@ -51,6 +63,61 @@ public final class CaptureResult extends CameraMetadata {
return mResults.get(key);
}
+ /**
+ * Get the request associated with this result.
+ *
+ * <p>Whenever a request is successfully captured, with
+ * {@link CameraDevice.CaptureListener#onCaptureCompleted},
+ * the {@code result}'s {@code getRequest()} will return that {@code request}.
+ * </p>
+ *
+ * <p>In particular,
+ * <code><pre>cameraDevice.capture(someRequest, new CaptureListener() {
+ * {@literal @}Override
+ * void onCaptureCompleted(CaptureRequest myRequest, CaptureResult myResult) {
+ * assert(myResult.getRequest.equals(myRequest) == true);
+ * }
+ * };
+ * </code></pre>
+ * </p>
+ *
+ * @return The request associated with this result. Never {@code null}.
+ */
+ public CaptureRequest getRequest() {
+ return mRequest;
+ }
+
+ /**
+ * Get the frame number associated with this result.
+ *
+ * <p>Whenever a request has been processed, regardless of failure or success,
+ * it gets a unique frame number assigned to its future result/failure.</p>
+ *
+ * <p>This value monotonically increments, starting with 0,
+ * for every new result or failure; and the scope is the lifetime of the
+ * {@link CameraDevice}.</p>
+ *
+ * @return int frame number
+ */
+ public int getFrameNumber() {
+ return get(REQUEST_FRAME_COUNT);
+ }
+
+ /**
+ * The sequence ID for this failure that was returned by the
+ * {@link CameraDevice#capture} family of functions.
+ *
+ * <p>The sequence ID is a unique monotonically increasing value starting from 0,
+ * incremented every time a new group of requests is submitted to the CameraDevice.</p>
+ *
+ * @return int The ID for the sequence of requests that this capture result is a part of
+ *
+ * @see CameraDevice.CaptureListener#onCaptureSequenceCompleted
+ */
+ public int getSequenceId() {
+ return mSequenceId;
+ }
+
/*@O~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
* The key entries below this point are generated from metadata
* definitions in /system/media/camera/docs. Do not modify by hand or
@@ -523,8 +590,9 @@ public final class CaptureResult extends CameraMetadata {
/**
* <p>
- * Number of frames captured since
- * open()
+ * A frame counter set by the framework. This value monotonically
+ * increases with every new result (that is, each new result has a unique
+ * frameCount value).
* </p>
* <p>
* Reset on release()
diff --git a/core/java/android/hardware/camera2/Face.java b/core/java/android/hardware/camera2/Face.java
index 6bfc535..ef068ca 100644
--- a/core/java/android/hardware/camera2/Face.java
+++ b/core/java/android/hardware/camera2/Face.java
@@ -128,7 +128,7 @@ public final class Face {
* Bounds of the face.
*
* <p>A rectangle relative to the sensor's
- * {@link CameraProperties#SENSOR_INFO_ACTIVE_ARRAY_SIZE}, with (0,0)
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE}, with (0,0)
* representing the top-left corner of the active array rectangle.</p>
*
* <p>There is no constraints on the the Rectangle value other than it
diff --git a/core/java/android/hardware/camera2/impl/CameraDevice.java b/core/java/android/hardware/camera2/impl/CameraDevice.java
index 995555a..f126472 100644
--- a/core/java/android/hardware/camera2/impl/CameraDevice.java
+++ b/core/java/android/hardware/camera2/impl/CameraDevice.java
@@ -20,7 +20,7 @@ import static android.hardware.camera2.CameraAccessException.CAMERA_IN_USE;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraMetadata;
-import android.hardware.camera2.CameraProperties;
+import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.ICameraDeviceCallbacks;
@@ -55,7 +55,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
private final Object mLock = new Object();
private final CameraDeviceCallbacks mCallbacks = new CameraDeviceCallbacks();
- private CameraDeviceListener mDeviceListener;
+ private StateListener mDeviceListener;
private Handler mDeviceHandler;
private final SparseArray<CaptureListenerHolder> mCaptureListenerMap =
@@ -88,7 +88,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
}
@Override
- public CameraProperties getProperties() throws CameraAccessException {
+ public CameraCharacteristics getProperties() throws CameraAccessException {
CameraMetadataNative info = new CameraMetadataNative();
@@ -101,7 +101,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
return null;
}
- CameraProperties properties = new CameraProperties(info);
+ CameraCharacteristics properties = new CameraCharacteristics(info);
return properties;
}
@@ -179,24 +179,24 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
}
@Override
- public void capture(CaptureRequest request, CaptureListener listener, Handler handler)
+ public int capture(CaptureRequest request, CaptureListener listener, Handler handler)
throws CameraAccessException {
- submitCaptureRequest(request, listener, handler, /*streaming*/false);
+ return submitCaptureRequest(request, listener, handler, /*streaming*/false);
}
@Override
- public void captureBurst(List<CaptureRequest> requests, CaptureListener listener,
+ public int captureBurst(List<CaptureRequest> requests, CaptureListener listener,
Handler handler) throws CameraAccessException {
if (requests.isEmpty()) {
Log.w(TAG, "Capture burst request list is empty, do nothing!");
- return;
+ return -1;
}
// TODO
throw new UnsupportedOperationException("Burst capture implemented yet");
}
- private void submitCaptureRequest(CaptureRequest request, CaptureListener listener,
+ private int submitCaptureRequest(CaptureRequest request, CaptureListener listener,
Handler handler, boolean repeating) throws CameraAccessException {
// Need a valid handler, or current thread needs to have a looper, if
@@ -220,7 +220,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
throw e.asChecked();
} catch (RemoteException e) {
// impossible
- return;
+ return -1;
}
if (listener != null) {
mCaptureListenerMap.put(requestId, new CaptureListenerHolder(listener, request,
@@ -231,21 +231,22 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
mRepeatingRequestIdStack.add(requestId);
}
+ return requestId;
}
}
@Override
- public void setRepeatingRequest(CaptureRequest request, CaptureListener listener,
+ public int setRepeatingRequest(CaptureRequest request, CaptureListener listener,
Handler handler) throws CameraAccessException {
- submitCaptureRequest(request, listener, handler, /*streaming*/true);
+ return submitCaptureRequest(request, listener, handler, /*streaming*/true);
}
@Override
- public void setRepeatingBurst(List<CaptureRequest> requests, CaptureListener listener,
+ public int setRepeatingBurst(List<CaptureRequest> requests, CaptureListener listener,
Handler handler) throws CameraAccessException {
if (requests.isEmpty()) {
Log.w(TAG, "Set Repeating burst request list is empty, do nothing!");
- return;
+ return -1;
}
// TODO
throw new UnsupportedOperationException("Burst capture implemented yet");
@@ -292,7 +293,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
}
@Override
- public void setDeviceListener(CameraDeviceListener listener, Handler handler) {
+ public void setDeviceListener(StateListener listener, Handler handler) {
synchronized (mLock) {
mDeviceListener = listener;
mDeviceHandler = handler;
@@ -314,7 +315,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
}
@Override
- public void close() throws Exception {
+ public void close() {
// TODO: every method should throw IllegalStateException after close has been called
@@ -325,7 +326,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
mRemoteDevice.disconnect();
}
} catch (CameraRuntimeException e) {
- throw e.asChecked();
+ Log.e(TAG, "Exception while closing: ", e.asChecked());
} catch (RemoteException e) {
// impossible
}
@@ -339,8 +340,6 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
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();
@@ -431,14 +430,16 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
return;
}
- final CaptureResult resultAsCapture = new CaptureResult(result);
+ final CaptureRequest request = holder.getRequest();
+ final CaptureResult resultAsCapture = new CaptureResult(result, request, requestId);
holder.getHandler().post(
new Runnable() {
+ @Override
public void run() {
holder.getListener().onCaptureCompleted(
CameraDevice.this,
- holder.getRequest(),
+ request,
resultAsCapture);
}
});
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index c13438a..6d7b03e 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -101,7 +101,7 @@ public class CameraMetadataNative extends CameraMetadata implements Parcelable {
/**
* Set a camera metadata field to a value. The field definitions can be
- * found in {@link CameraProperties}, {@link CaptureResult}, and
+ * found in {@link CameraCharacteristics}, {@link CaptureResult}, and
* {@link CaptureRequest}.
*
* @param key The metadata field to write.
diff --git a/core/java/android/hardware/camera2/package.html b/core/java/android/hardware/camera2/package.html
index e9d9cea..9f6c2a9 100644
--- a/core/java/android/hardware/camera2/package.html
+++ b/core/java/android/hardware/camera2/package.html
@@ -34,7 +34,7 @@ framerate on most Android devices.</p>
CameraDevices} provide a set of static property information that
describes the hardware device and the available settings and output
parameters for the device. This information is provided through the
-{@link android.hardware.camera2.CameraProperties} object.</p>
+{@link android.hardware.camera2.CameraCharacteristics} object.</p>
<p>To capture or stream images from a camera device, the application
must first configure a set of output Surfaces for use with the camera
diff --git a/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java b/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java
index d0b3ec4..e535e00 100644
--- a/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java
+++ b/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java
@@ -51,7 +51,7 @@ public class CameraBinderDecorator {
public static final int EBUSY = -16;
public static final int ENODEV = -19;
public static final int EOPNOTSUPP = -95;
- public static final int EDQUOT = -122;
+ public static final int EUSERS = -87;
private static class CameraBinderDecoratorListener implements Decorator.DecoratorListener {
@@ -85,7 +85,7 @@ public class CameraBinderDecorator {
case EBUSY:
UncheckedThrow.throwAnyException(new CameraRuntimeException(
CAMERA_IN_USE));
- case EDQUOT:
+ case EUSERS:
UncheckedThrow.throwAnyException(new CameraRuntimeException(
MAX_CAMERAS_IN_USE));
case ENODEV:
diff --git a/core/java/android/hardware/location/GeofenceHardwareImpl.java b/core/java/android/hardware/location/GeofenceHardwareImpl.java
index eac6620..6b61690 100644
--- a/core/java/android/hardware/location/GeofenceHardwareImpl.java
+++ b/core/java/android/hardware/location/GeofenceHardwareImpl.java
@@ -18,17 +18,14 @@ package android.hardware.location;
import android.content.Context;
import android.content.pm.PackageManager;
-import android.location.FusedBatchOptions;
import android.location.IFusedGeofenceHardware;
import android.location.IGpsGeofenceHardware;
import android.location.Location;
-import android.location.LocationManager;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
-import android.os.SystemClock;
import android.util.Log;
import android.util.SparseArray;
@@ -601,12 +598,13 @@ public final class GeofenceHardwareImpl {
GeofenceTransition geofenceTransition = (GeofenceTransition)(msg.obj);
synchronized (mGeofences) {
callback = mGeofences.get(geofenceTransition.mGeofenceId);
- }
- if (DEBUG) Log.d(TAG, "GeofenceTransistionCallback: GPS : GeofenceId: " +
- geofenceTransition.mGeofenceId +
- " Transition: " + geofenceTransition.mTransition +
- " Location: " + geofenceTransition.mLocation + ":" + mGeofences);
+ // need to keep access to mGeofences synchronized at all times
+ if (DEBUG) Log.d(TAG, "GeofenceTransistionCallback: GPS : GeofenceId: " +
+ geofenceTransition.mGeofenceId +
+ " Transition: " + geofenceTransition.mTransition +
+ " Location: " + geofenceTransition.mLocation + ":" + mGeofences);
+ }
if (callback != null) {
try {
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index b914940..c106514 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -211,8 +211,6 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker {
private class MobileDataStateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
- // Assume this isn't a provisioning network.
- mNetworkInfo.setIsConnectedToProvisioningNetwork(false);
if (intent.getAction().equals(TelephonyIntents.
ACTION_DATA_CONNECTION_CONNECTED_TO_PROVISIONING_APN)) {
String apnName = intent.getStringExtra(PhoneConstants.DATA_APN_KEY);
@@ -244,6 +242,11 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker {
if (!TextUtils.equals(apnType, mApnType)) {
return;
}
+ // Assume this isn't a provisioning network.
+ mNetworkInfo.setIsConnectedToProvisioningNetwork(false);
+ if (DBG) {
+ log("Broadcast received: " + intent.getAction() + " apnType=" + apnType);
+ }
int oldSubtype = mNetworkInfo.getSubtype();
int newSubType = TelephonyManager.getDefault().getNetworkType();
@@ -351,6 +354,8 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker {
}
return;
}
+ // Assume this isn't a provisioning network.
+ mNetworkInfo.setIsConnectedToProvisioningNetwork(false);
String reason = intent.getStringExtra(PhoneConstants.FAILURE_REASON_KEY);
String apnName = intent.getStringExtra(PhoneConstants.DATA_APN_KEY);
if (DBG) {
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index 26fc769..f4a8391 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -299,7 +299,6 @@ public class Binder implements IBinder {
try {
dump(fd, pw, args);
} catch (SecurityException e) {
- pw.println();
pw.println("Security exception: " + e.getMessage());
throw e;
} catch (Throwable e) {
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index 32b1b60..f47ac4e 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -33,6 +33,8 @@ public final class Bundle implements Parcelable, Cloneable {
private static final String LOG_TAG = "Bundle";
public static final Bundle EMPTY;
+ static final int BUNDLE_MAGIC = 0x4C444E42; // 'B' 'N' 'D' 'L'
+
static {
EMPTY = new Bundle();
EMPTY.mMap = ArrayMap.EMPTY;
@@ -1643,11 +1645,11 @@ public final class Bundle implements Parcelable, Cloneable {
if (mParcelledData != null) {
int length = mParcelledData.dataSize();
parcel.writeInt(length);
- parcel.writeInt(0x4C444E42); // 'B' 'N' 'D' 'L'
+ parcel.writeInt(BUNDLE_MAGIC);
parcel.appendFrom(mParcelledData, 0, length);
} else {
parcel.writeInt(-1); // dummy, will hold length
- parcel.writeInt(0x4C444E42); // 'B' 'N' 'D' 'L'
+ parcel.writeInt(BUNDLE_MAGIC);
int oldPos = parcel.dataPosition();
parcel.writeArrayMapInternal(mMap);
@@ -1679,11 +1681,10 @@ public final class Bundle implements Parcelable, Cloneable {
void readFromParcelInner(Parcel parcel, int length) {
int magic = parcel.readInt();
- if (magic != 0x4C444E42) {
+ if (magic != BUNDLE_MAGIC) {
//noinspection ThrowableInstanceNeverThrown
- String st = Log.getStackTraceString(new RuntimeException());
- Log.e("Bundle", "readBundle: bad magic number");
- Log.e("Bundle", "readBundle: trace = " + st);
+ throw new IllegalStateException("Bad magic number for Bundle: 0x"
+ + Integer.toHexString(magic));
}
// Advance within this Parcel
@@ -1694,10 +1695,23 @@ public final class Bundle implements Parcelable, Cloneable {
p.setDataPosition(0);
p.appendFrom(parcel, offset, length);
p.setDataPosition(0);
-
- mParcelledData = p;
- mHasFds = p.hasFileDescriptors();
- mFdsKnown = true;
+
+ if (mMap != null) {
+ // It is not allowed to have a Bundle with both a map and a parcel, so if we
+ // already have a map then we need to immediately unparcel into it. This also
+ // lets us know we need to go through the slow path of unparceling, since the
+ // map may already contains some data so the two need to be merged.
+ if (mFdsKnown) {
+ mHasFds |= p.hasFileDescriptors();
+ }
+ int N = p.readInt();
+ p.readArrayMapSafelyInternal(mMap, N, mClassLoader);
+ p.recycle();
+ } else {
+ mParcelledData = p;
+ mHasFds = p.hasFileDescriptors();
+ mFdsKnown = true;
+ }
}
@Override
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 5b36bca..fc53580 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -109,29 +109,36 @@ public class Environment {
// TODO: generalize further to create package-specific environment
// TODO: add support for secondary external storage
- private final File[] mExternalDirs;
- private final File mMediaDir;
+ /** External storage dirs, as visible to vold */
+ private final File[] mExternalDirsForVold;
+ /** External storage dirs, as visible to apps */
+ private final File[] mExternalDirsForApp;
+ /** Primary emulated storage dir for direct access */
+ private final File mEmulatedDirForDirect;
public UserEnvironment(int userId) {
// See storage config details at http://source.android.com/tech/storage/
String rawExternalStorage = System.getenv(ENV_EXTERNAL_STORAGE);
- String rawEmulatedStorageTarget = System.getenv(ENV_EMULATED_STORAGE_TARGET);
+ String rawEmulatedSource = System.getenv(ENV_EMULATED_STORAGE_SOURCE);
+ String rawEmulatedTarget = System.getenv(ENV_EMULATED_STORAGE_TARGET);
String rawMediaStorage = System.getenv(ENV_MEDIA_STORAGE);
if (TextUtils.isEmpty(rawMediaStorage)) {
rawMediaStorage = "/data/media";
}
- if (!TextUtils.isEmpty(rawEmulatedStorageTarget)) {
+ if (!TextUtils.isEmpty(rawEmulatedTarget)) {
// Device has emulated storage; external storage paths should have
// userId burned into them.
final String rawUserId = Integer.toString(userId);
- final File emulatedBase = new File(rawEmulatedStorageTarget);
+ final File emulatedSourceBase = new File(rawEmulatedSource);
+ final File emulatedTargetBase = new File(rawEmulatedTarget);
final File mediaBase = new File(rawMediaStorage);
// /storage/emulated/0
- mExternalDirs = new File[] { buildPath(emulatedBase, rawUserId) };
+ mExternalDirsForVold = new File[] { buildPath(emulatedSourceBase, rawUserId) };
+ mExternalDirsForApp = new File[] { buildPath(emulatedTargetBase, rawUserId) };
// /data/media/0
- mMediaDir = buildPath(mediaBase, rawUserId);
+ mEmulatedDirForDirect = buildPath(mediaBase, rawUserId);
} else {
// Device has physical external storage; use plain paths.
@@ -141,15 +148,16 @@ public class Environment {
}
// /storage/sdcard0
- mExternalDirs = new File[] { new File(rawExternalStorage) };
+ mExternalDirsForVold = new File[] { new File(rawExternalStorage) };
+ mExternalDirsForApp = new File[] { new File(rawExternalStorage) };
// /data/media
- mMediaDir = new File(rawMediaStorage);
+ mEmulatedDirForDirect = new File(rawMediaStorage);
}
}
@Deprecated
public File getExternalStorageDirectory() {
- return mExternalDirs[0];
+ return mExternalDirsForApp[0];
}
@Deprecated
@@ -157,44 +165,56 @@ public class Environment {
return buildExternalStoragePublicDirs(type)[0];
}
- public File[] getExternalDirs() {
- return mExternalDirs;
+ public File[] getExternalDirsForVold() {
+ return mExternalDirsForVold;
+ }
+
+ public File[] getExternalDirsForApp() {
+ return mExternalDirsForApp;
}
public File getMediaDir() {
- return mMediaDir;
+ return mEmulatedDirForDirect;
}
public File[] buildExternalStoragePublicDirs(String type) {
- return buildPaths(mExternalDirs, type);
+ return buildPaths(mExternalDirsForApp, type);
}
public File[] buildExternalStorageAndroidDataDirs() {
- return buildPaths(mExternalDirs, DIR_ANDROID, DIR_DATA);
+ return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_DATA);
}
public File[] buildExternalStorageAndroidObbDirs() {
- return buildPaths(mExternalDirs, DIR_ANDROID, DIR_OBB);
+ return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_OBB);
}
public File[] buildExternalStorageAppDataDirs(String packageName) {
- return buildPaths(mExternalDirs, DIR_ANDROID, DIR_DATA, packageName);
+ return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_DATA, packageName);
+ }
+
+ public File[] buildExternalStorageAppDataDirsForVold(String packageName) {
+ return buildPaths(mExternalDirsForVold, DIR_ANDROID, DIR_DATA, packageName);
}
public File[] buildExternalStorageAppMediaDirs(String packageName) {
- return buildPaths(mExternalDirs, DIR_ANDROID, DIR_MEDIA, packageName);
+ return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_MEDIA, packageName);
}
public File[] buildExternalStorageAppObbDirs(String packageName) {
- return buildPaths(mExternalDirs, DIR_ANDROID, DIR_OBB, packageName);
+ return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_OBB, packageName);
+ }
+
+ public File[] buildExternalStorageAppObbDirsForVold(String packageName) {
+ return buildPaths(mExternalDirsForVold, DIR_ANDROID, DIR_OBB, packageName);
}
public File[] buildExternalStorageAppFilesDirs(String packageName) {
- return buildPaths(mExternalDirs, DIR_ANDROID, DIR_DATA, packageName, DIR_FILES);
+ return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_DATA, packageName, DIR_FILES);
}
public File[] buildExternalStorageAppCacheDirs(String packageName) {
- return buildPaths(mExternalDirs, DIR_ANDROID, DIR_DATA, packageName, DIR_CACHE);
+ return buildPaths(mExternalDirsForApp, DIR_ANDROID, DIR_DATA, packageName, DIR_CACHE);
}
}
@@ -344,7 +364,7 @@ public class Environment {
*/
public static File getExternalStorageDirectory() {
throwIfUserRequired();
- return sCurrentUser.getExternalDirs()[0];
+ return sCurrentUser.getExternalDirsForApp()[0];
}
/** {@hide} */
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index fec2a3e..5f3a81c 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -178,6 +178,7 @@ import java.util.Set;
*/
public final class Parcel {
private static final boolean DEBUG_RECYCLE = false;
+ private static final boolean DEBUG_ARRAY_MAP = false;
private static final String TAG = "Parcel";
@SuppressWarnings({"UnusedDeclaration"})
@@ -605,7 +606,14 @@ public final class Parcel {
}
final int N = val.size();
writeInt(N);
+ if (DEBUG_ARRAY_MAP) {
+ RuntimeException here = new RuntimeException("here");
+ here.fillInStackTrace();
+ Log.d(TAG, "Writing " + N + " ArrayMap entries", here);
+ }
for (int i=0; i<N; i++) {
+ if (DEBUG_ARRAY_MAP) Log.d(TAG, " Write #" + i + ": key=0x"
+ + (val.keyAt(i) != null ? val.keyAt(i).hashCode() : 0) + " " + val.keyAt(i));
writeValue(val.keyAt(i));
writeValue(val.valueAt(i));
}
@@ -2289,14 +2297,38 @@ public final class Parcel {
/* package */ void readArrayMapInternal(ArrayMap outVal, int N,
ClassLoader loader) {
+ if (DEBUG_ARRAY_MAP) {
+ RuntimeException here = new RuntimeException("here");
+ here.fillInStackTrace();
+ Log.d(TAG, "Reading " + N + " ArrayMap entries", here);
+ }
while (N > 0) {
Object key = readValue(loader);
+ if (DEBUG_ARRAY_MAP) Log.d(TAG, " Read #" + (N-1) + ": key=0x"
+ + (key != null ? key.hashCode() : 0) + " " + key);
Object value = readValue(loader);
outVal.append(key, value);
N--;
}
}
+ /* package */ void readArrayMapSafelyInternal(ArrayMap outVal, int N,
+ ClassLoader loader) {
+ if (DEBUG_ARRAY_MAP) {
+ RuntimeException here = new RuntimeException("here");
+ here.fillInStackTrace();
+ Log.d(TAG, "Reading safely " + N + " ArrayMap entries", here);
+ }
+ while (N > 0) {
+ Object key = readValue(loader);
+ if (DEBUG_ARRAY_MAP) Log.d(TAG, " Read safe #" + (N-1) + ": key=0x"
+ + (key != null ? key.hashCode() : 0) + " " + key);
+ Object value = readValue(loader);
+ outVal.put(key, value);
+ N--;
+ }
+ }
+
private void readListInternal(List outVal, int N,
ClassLoader loader) {
while (N > 0) {
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index e436241..55c083b 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -462,6 +462,39 @@ public class ParcelFileDescriptor implements Parcelable, Closeable {
}
/**
+ * Converts a string representing a file mode, such as "rw", into a bitmask suitable for use
+ * with {@link #open}.
+ * <p>
+ * @param mode The string representation of the file mode.
+ * @return A bitmask representing the given file mode.
+ * @throws IllegalArgumentException if the given string does not match a known file mode.
+ */
+ public static int parseMode(String mode) {
+ final int modeBits;
+ if ("r".equals(mode)) {
+ modeBits = ParcelFileDescriptor.MODE_READ_ONLY;
+ } else if ("w".equals(mode) || "wt".equals(mode)) {
+ modeBits = ParcelFileDescriptor.MODE_WRITE_ONLY
+ | ParcelFileDescriptor.MODE_CREATE
+ | ParcelFileDescriptor.MODE_TRUNCATE;
+ } else if ("wa".equals(mode)) {
+ modeBits = ParcelFileDescriptor.MODE_WRITE_ONLY
+ | ParcelFileDescriptor.MODE_CREATE
+ | ParcelFileDescriptor.MODE_APPEND;
+ } else if ("rw".equals(mode)) {
+ modeBits = ParcelFileDescriptor.MODE_READ_WRITE
+ | ParcelFileDescriptor.MODE_CREATE;
+ } else if ("rwt".equals(mode)) {
+ modeBits = ParcelFileDescriptor.MODE_READ_WRITE
+ | ParcelFileDescriptor.MODE_CREATE
+ | ParcelFileDescriptor.MODE_TRUNCATE;
+ } else {
+ throw new IllegalArgumentException("Bad mode '" + mode + "'");
+ }
+ return modeBits;
+ }
+
+ /**
* Retrieve the actual FileDescriptor associated with this object.
*
* @return Returns the FileDescriptor associated with this object.
diff --git a/core/java/android/os/WorkSource.java b/core/java/android/os/WorkSource.java
index 30d535b..f8da87a 100644
--- a/core/java/android/os/WorkSource.java
+++ b/core/java/android/os/WorkSource.java
@@ -103,7 +103,21 @@ public class WorkSource implements Parcelable {
* @hide
*/
public void clearNames() {
- mNames = null;
+ if (mNames != null) {
+ mNames = null;
+ // Clear out any duplicate uids now that we don't have names to disambiguate them.
+ int destIndex = 1;
+ int newNum = mNum;
+ for (int sourceIndex = 1; sourceIndex < mNum; sourceIndex++) {
+ if (mUids[sourceIndex] == mUids[sourceIndex - 1]) {
+ newNum--;
+ } else {
+ mUids[destIndex] = mUids[sourceIndex];
+ destIndex++;
+ }
+ }
+ mNum = newNum;
+ }
}
/**
@@ -209,7 +223,6 @@ public class WorkSource implements Parcelable {
}
mUids[0] = uid;
mNames[0] = name;
- mNames = null;
}
/** @hide */
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java
index fc18617..51ba2f6 100644
--- a/core/java/android/os/storage/IMountService.java
+++ b/core/java/android/os/storage/IMountService.java
@@ -20,9 +20,7 @@ import android.os.Binder;
import android.os.IBinder;
import android.os.IInterface;
import android.os.Parcel;
-import android.os.Parcelable;
import android.os.RemoteException;
-import android.os.storage.StorageVolume;
/**
* WARNING! Update IMountService.h and IMountService.cpp if you change this
@@ -737,7 +735,25 @@ public interface IMountService extends IInterface {
_data.recycle();
}
return _result;
+ }
+ @Override
+ public int mkdirs(String callingPkg, String path) throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ int _result;
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeString(callingPkg);
+ _data.writeString(path);
+ mRemote.transact(Stub.TRANSACTION_mkdirs, _data, _reply, 0);
+ _reply.readException();
+ _result = _reply.readInt();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ return _result;
}
}
@@ -811,6 +827,8 @@ public interface IMountService extends IInterface {
static final int TRANSACTION_fixPermissionsSecureContainer = IBinder.FIRST_CALL_TRANSACTION + 33;
+ static final int TRANSACTION_mkdirs = IBinder.FIRST_CALL_TRANSACTION + 34;
+
/**
* Cast an IBinder object into an IMountService interface, generating a
* proxy if needed.
@@ -1154,6 +1172,15 @@ public interface IMountService extends IInterface {
reply.writeInt(resultCode);
return true;
}
+ case TRANSACTION_mkdirs: {
+ data.enforceInterface(DESCRIPTOR);
+ String callingPkg = data.readString();
+ String path = data.readString();
+ int result = mkdirs(callingPkg, path);
+ reply.writeNoException();
+ reply.writeInt(result);
+ return true;
+ }
}
return super.onTransact(code, data, reply, flags);
}
@@ -1376,4 +1403,13 @@ public interface IMountService extends IInterface {
*/
public int fixPermissionsSecureContainer(String id, int gid, String filename)
throws RemoteException;
+
+ /**
+ * Ensure that all directories along given path exist, creating parent
+ * directories as needed. Validates that given path is absolute and that it
+ * contains no relative "." or ".." paths or symlinks. Also ensures that
+ * path belongs to a volume managed by vold, and that path is either
+ * external storage data or OBB directory belonging to calling app.
+ */
+ public int mkdirs(String callingPkg, String path) throws RemoteException;
}
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index a99705b..2ab5a91 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -887,8 +887,9 @@ public abstract class PreferenceActivity extends ListActivity implements
/**
* Subclasses should override this method and verify that the given fragment is a valid type
- * to be attached to this activity. The default implementation returns <code>true</code> prior
- * to Key Lime Pie, <code>false</code> otherwise.
+ * to be attached to this activity. The default implementation returns <code>true</code> for
+ * apps built for <code>android:targetSdkVersion</code> older than
+ * {@link android.os.Build.VERSION_CODES#KITKAT}. For later versions, it will throw an exception.
* @param fragmentName the class name of the Fragment about to be attached to this activity.
* @return true if the fragment class name is valid for this Activity and false otherwise.
*/
diff --git a/core/java/android/print/PrintAttributes.java b/core/java/android/print/PrintAttributes.java
index 94bbb08..959380d 100644
--- a/core/java/android/print/PrintAttributes.java
+++ b/core/java/android/print/PrintAttributes.java
@@ -30,10 +30,9 @@ import com.android.internal.R;
* This class represents the attributes of a print job.
*/
public final class PrintAttributes implements Parcelable {
-
- /** Color mode: Monochrome color scheme, e.g. one color is used. */
+ /** Color mode: Monochrome color scheme, for example one color is used. */
public static final int COLOR_MODE_MONOCHROME = 1 << 0;
- /** Color mode: Color color scheme, e.g. many colors are used. */
+ /** Color mode: Color color scheme, for example many colors are used. */
public static final int COLOR_MODE_COLOR = 1 << 1;
private static final int VALID_COLOR_MODES =
@@ -260,321 +259,344 @@ public final class PrintAttributes implements Parcelable {
}
/**
- * This class specifies a supported media size.
+ * This class specifies a supported media size. Media size is the
+ * dimension of the media on which the content is printed. For
+ * example, the {@link #NA_LETTER} media size designates a page
+ * with size 8.5" x 11".
*/
public static final class MediaSize {
private static final String LOG_TAG = "MediaSize";
- // TODO: Verify media sizes and add more standard ones.
+ /**
+ * Unknown media size in portrait mode.
+ * <p>
+ * <strong>Note: </strong>This is for specifying orientation without media
+ * size. You should not use the dimensions reported by this class.
+ * </p>
+ */
+ public static final MediaSize UNKNOWN_PORTRAIT =
+ new MediaSize("UNKNOWN_PORTRAIT", "android",
+ R.string.mediasize_unknown_portrait, Integer.MAX_VALUE, 1);
+
+ /**
+ * Unknown media size in landscape mode.
+ * <p>
+ * <strong>Note: </strong>This is for specifying orientation without media
+ * size. You should not use the dimensions reported by this class.
+ * </p>
+ */
+ public static final MediaSize UNKNOWN_LANDSCAPE =
+ new MediaSize("UNKNOWN_LANDSCAPE", "android",
+ R.string.mediasize_unknown_landscape, 1, Integer.MAX_VALUE);
// ISO sizes
/** ISO A0 media size: 841mm x 1189mm (33.11" x 46.81") */
public static final MediaSize ISO_A0 =
- new MediaSize("ISO_A0", "android", R.string.mediaSize_iso_a0, 33110, 46810);
+ new MediaSize("ISO_A0", "android", R.string.mediasize_iso_a0, 33110, 46810);
/** ISO A1 media size: 594mm x 841mm (23.39" x 33.11") */
public static final MediaSize ISO_A1 =
- new MediaSize("ISO_A1", "android", R.string.mediaSize_iso_a1, 23390, 33110);
+ new MediaSize("ISO_A1", "android", R.string.mediasize_iso_a1, 23390, 33110);
/** ISO A2 media size: 420mm x 594mm (16.54" x 23.39") */
public static final MediaSize ISO_A2 =
- new MediaSize("ISO_A2", "android", R.string.mediaSize_iso_a2, 16540, 23390);
+ new MediaSize("ISO_A2", "android", R.string.mediasize_iso_a2, 16540, 23390);
/** ISO A3 media size: 297mm x 420mm (11.69" x 16.54") */
public static final MediaSize ISO_A3 =
- new MediaSize("ISO_A3", "android", R.string.mediaSize_iso_a3, 11690, 16540);
+ new MediaSize("ISO_A3", "android", R.string.mediasize_iso_a3, 11690, 16540);
/** ISO A4 media size: 210mm x 297mm (8.27" x 11.69") */
public static final MediaSize ISO_A4 =
- new MediaSize("ISO_A4", "android", R.string.mediaSize_iso_a4, 8270, 11690);
+ new MediaSize("ISO_A4", "android", R.string.mediasize_iso_a4, 8270, 11690);
/** ISO A5 media size: 148mm x 210mm (5.83" x 8.27") */
public static final MediaSize ISO_A5 =
- new MediaSize("ISO_A5", "android", R.string.mediaSize_iso_a5, 5830, 8270);
+ new MediaSize("ISO_A5", "android", R.string.mediasize_iso_a5, 5830, 8270);
/** ISO A6 media size: 105mm x 148mm (4.13" x 5.83") */
public static final MediaSize ISO_A6 =
- new MediaSize("ISO_A6", "android", R.string.mediaSize_iso_a6, 4130, 5830);
+ new MediaSize("ISO_A6", "android", R.string.mediasize_iso_a6, 4130, 5830);
/** ISO A7 media size: 74mm x 105mm (2.91" x 4.13") */
public static final MediaSize ISO_A7 =
- new MediaSize("ISO_A7", "android", R.string.mediaSize_iso_a7, 2910, 4130);
+ new MediaSize("ISO_A7", "android", R.string.mediasize_iso_a7, 2910, 4130);
/** ISO A8 media size: 52mm x 74mm (2.05" x 2.91") */
public static final MediaSize ISO_A8 =
- new MediaSize("ISO_A8", "android", R.string.mediaSize_iso_a8, 2050, 2910);
+ new MediaSize("ISO_A8", "android", R.string.mediasize_iso_a8, 2050, 2910);
/** ISO A9 media size: 37mm x 52mm (1.46" x 2.05") */
public static final MediaSize ISO_A9 =
- new MediaSize("ISO_A9", "android", R.string.mediaSize_iso_a9, 1460, 2050);
+ new MediaSize("ISO_A9", "android", R.string.mediasize_iso_a9, 1460, 2050);
/** ISO A10 media size: 26mm x 37mm (1.02" x 1.46") */
public static final MediaSize ISO_A10 =
- new MediaSize("ISO_A10", "android", R.string.mediaSize_iso_a10, 1020, 1460);
+ new MediaSize("ISO_A10", "android", R.string.mediasize_iso_a10, 1020, 1460);
/** ISO B0 media size: 1000mm x 1414mm (39.37" x 55.67") */
public static final MediaSize ISO_B0 =
- new MediaSize("ISO_B0", "android", R.string.mediaSize_iso_b0, 39370, 55670);
+ new MediaSize("ISO_B0", "android", R.string.mediasize_iso_b0, 39370, 55670);
/** ISO B1 media size: 707mm x 1000mm (27.83" x 39.37") */
public static final MediaSize ISO_B1 =
- new MediaSize("ISO_B1", "android", R.string.mediaSize_iso_b1, 27830, 39370);
+ new MediaSize("ISO_B1", "android", R.string.mediasize_iso_b1, 27830, 39370);
/** ISO B2 media size: 500mm x 707mm (19.69" x 27.83") */
public static final MediaSize ISO_B2 =
- new MediaSize("ISO_B2", "android", R.string.mediaSize_iso_b2, 19690, 27830);
+ new MediaSize("ISO_B2", "android", R.string.mediasize_iso_b2, 19690, 27830);
/** ISO B3 media size: 353mm x 500mm (13.90" x 19.69") */
public static final MediaSize ISO_B3 =
- new MediaSize("ISO_B3", "android", R.string.mediaSize_iso_b3, 13900, 19690);
+ new MediaSize("ISO_B3", "android", R.string.mediasize_iso_b3, 13900, 19690);
/** ISO B4 media size: 250mm x 353mm (9.84" x 13.90") */
public static final MediaSize ISO_B4 =
- new MediaSize("ISO_B4", "android", R.string.mediaSize_iso_b4, 9840, 13900);
+ new MediaSize("ISO_B4", "android", R.string.mediasize_iso_b4, 9840, 13900);
/** ISO B5 media size: 176mm x 250mm (6.93" x 9.84") */
public static final MediaSize ISO_B5 =
- new MediaSize("ISO_B5", "android", R.string.mediaSize_iso_b5, 6930, 9840);
+ new MediaSize("ISO_B5", "android", R.string.mediasize_iso_b5, 6930, 9840);
/** ISO B6 media size: 125mm x 176mm (4.92" x 6.93") */
public static final MediaSize ISO_B6 =
- new MediaSize("ISO_B6", "android", R.string.mediaSize_iso_b6, 4920, 6930);
+ new MediaSize("ISO_B6", "android", R.string.mediasize_iso_b6, 4920, 6930);
/** ISO B7 media size: 88mm x 125mm (3.46" x 4.92") */
public static final MediaSize ISO_B7 =
- new MediaSize("ISO_B7", "android", R.string.mediaSize_iso_b7, 3460, 4920);
+ new MediaSize("ISO_B7", "android", R.string.mediasize_iso_b7, 3460, 4920);
/** ISO B8 media size: 62mm x 88mm (2.44" x 3.46") */
public static final MediaSize ISO_B8 =
- new MediaSize("ISO_B8", "android", R.string.mediaSize_iso_b8, 2440, 3460);
+ new MediaSize("ISO_B8", "android", R.string.mediasize_iso_b8, 2440, 3460);
/** ISO B9 media size: 44mm x 62mm (1.73" x 2.44") */
public static final MediaSize ISO_B9 =
- new MediaSize("ISO_B9", "android", R.string.mediaSize_iso_b9, 1730, 2440);
+ new MediaSize("ISO_B9", "android", R.string.mediasize_iso_b9, 1730, 2440);
/** ISO B10 media size: 31mm x 44mm (1.22" x 1.73") */
public static final MediaSize ISO_B10 =
- new MediaSize("ISO_B10", "android", R.string.mediaSize_iso_b10, 1220, 1730);
+ new MediaSize("ISO_B10", "android", R.string.mediasize_iso_b10, 1220, 1730);
/** ISO C0 media size: 917mm x 1297mm (36.10" x 51.06") */
public static final MediaSize ISO_C0 =
- new MediaSize("ISO_C0", "android", R.string.mediaSize_iso_c0, 36100, 51060);
+ new MediaSize("ISO_C0", "android", R.string.mediasize_iso_c0, 36100, 51060);
/** ISO C1 media size: 648mm x 917mm (25.51" x 36.10") */
public static final MediaSize ISO_C1 =
- new MediaSize("ISO_C1", "android", R.string.mediaSize_iso_c1, 25510, 36100);
+ new MediaSize("ISO_C1", "android", R.string.mediasize_iso_c1, 25510, 36100);
/** ISO C2 media size: 458mm x 648mm (18.03" x 25.51") */
public static final MediaSize ISO_C2 =
- new MediaSize("ISO_C2", "android", R.string.mediaSize_iso_c2, 18030, 25510);
+ new MediaSize("ISO_C2", "android", R.string.mediasize_iso_c2, 18030, 25510);
/** ISO C3 media size: 324mm x 458mm (12.76" x 18.03") */
public static final MediaSize ISO_C3 =
- new MediaSize("ISO_C3", "android", R.string.mediaSize_iso_c3, 12760, 18030);
+ new MediaSize("ISO_C3", "android", R.string.mediasize_iso_c3, 12760, 18030);
/** ISO C4 media size: 229mm x 324mm (9.02" x 12.76") */
public static final MediaSize ISO_C4 =
- new MediaSize("ISO_C4", "android", R.string.mediaSize_iso_c4, 9020, 12760);
+ new MediaSize("ISO_C4", "android", R.string.mediasize_iso_c4, 9020, 12760);
/** ISO C5 media size: 162mm x 229mm (6.38" x 9.02") */
public static final MediaSize ISO_C5 =
- new MediaSize("ISO_C5", "android", R.string.mediaSize_iso_c5, 6380, 9020);
+ new MediaSize("ISO_C5", "android", R.string.mediasize_iso_c5, 6380, 9020);
/** ISO C6 media size: 114mm x 162mm (4.49" x 6.38") */
public static final MediaSize ISO_C6 =
- new MediaSize("ISO_C6", "android", R.string.mediaSize_iso_c6, 4490, 6380);
+ new MediaSize("ISO_C6", "android", R.string.mediasize_iso_c6, 4490, 6380);
/** ISO C7 media size: 81mm x 114mm (3.19" x 4.49") */
public static final MediaSize ISO_C7 =
- new MediaSize("ISO_C7", "android", R.string.mediaSize_iso_c7, 3190, 4490);
+ new MediaSize("ISO_C7", "android", R.string.mediasize_iso_c7, 3190, 4490);
/** ISO C8 media size: 57mm x 81mm (2.24" x 3.19") */
public static final MediaSize ISO_C8 =
- new MediaSize("ISO_C8", "android", R.string.mediaSize_iso_c8, 2240, 3190);
+ new MediaSize("ISO_C8", "android", R.string.mediasize_iso_c8, 2240, 3190);
/** ISO C9 media size: 40mm x 57mm (1.57" x 2.24") */
public static final MediaSize ISO_C9 =
- new MediaSize("ISO_C9", "android", R.string.mediaSize_iso_c9, 1570, 2240);
+ new MediaSize("ISO_C9", "android", R.string.mediasize_iso_c9, 1570, 2240);
/** ISO C10 media size: 28mm x 40mm (1.10" x 1.57") */
public static final MediaSize ISO_C10 =
- new MediaSize("ISO_C10", "android", R.string.mediaSize_iso_c10, 1100, 1570);
+ new MediaSize("ISO_C10", "android", R.string.mediasize_iso_c10, 1100, 1570);
// North America
/** North America Letter media size: 8.5" x 11" (279mm x 216mm) */
public static final MediaSize NA_LETTER =
- new MediaSize("NA_LETTER", "android", R.string.mediaSize_na_letter, 8500, 11000);
+ new MediaSize("NA_LETTER", "android", R.string.mediasize_na_letter, 8500, 11000);
/** North America Government-Letter media size: 8.0" x 10.5" (203mm x 267mm) */
public static final MediaSize NA_GOVT_LETTER =
new MediaSize("NA_GOVT_LETTER", "android",
- R.string.mediaSize_na_gvrnmt_letter, 8000, 10500);
+ R.string.mediasize_na_gvrnmt_letter, 8000, 10500);
/** North America Legal media size: 8.5" x 14" (216mm x 356mm) */
public static final MediaSize NA_LEGAL =
- new MediaSize("NA_LEGAL", "android", R.string.mediaSize_na_legal, 8500, 14000);
+ new MediaSize("NA_LEGAL", "android", R.string.mediasize_na_legal, 8500, 14000);
/** North America Junior Legal media size: 8.0" x 5.0" (203mm × 127mm) */
public static final MediaSize NA_JUNIOR_LEGAL =
new MediaSize("NA_JUNIOR_LEGAL", "android",
- R.string.mediaSize_na_junior_legal, 8000, 5000);
+ R.string.mediasize_na_junior_legal, 8000, 5000);
/** North America Ledger media size: 17" x 11" (432mm × 279mm) */
public static final MediaSize NA_LEDGER =
- new MediaSize("NA_LEDGER", "android", R.string.mediaSize_na_ledger, 17000, 11000);
+ new MediaSize("NA_LEDGER", "android", R.string.mediasize_na_ledger, 17000, 11000);
/** North America Tabloid media size: 11" x 17" (279mm × 432mm) */
public static final MediaSize NA_TABLOID =
new MediaSize("NA_TABLOID", "android",
- R.string.mediaSize_na_tabloid, 11000, 17000);
+ R.string.mediasize_na_tabloid, 11000, 17000);
/** North America Index Card 3x5 media size: 3" x 5" (76mm x 127mm) */
public static final MediaSize NA_INDEX_3X5 =
new MediaSize("NA_INDEX_3X5", "android",
- R.string.mediaSize_na_index_3x5, 3000, 5000);
+ R.string.mediasize_na_index_3x5, 3000, 5000);
/** North America Index Card 4x6 media size: 4" x 6" (102mm x 152mm) */
public static final MediaSize NA_INDEX_4X6 =
new MediaSize("NA_INDEX_4X6", "android",
- R.string.mediaSize_na_index_4x6, 4000, 6000);
+ R.string.mediasize_na_index_4x6, 4000, 6000);
/** North America Index Card 5x8 media size: 5" x 8" (127mm x 203mm) */
public static final MediaSize NA_INDEX_5X8 =
new MediaSize("NA_INDEX_5X8", "android",
- R.string.mediaSize_na_index_5x8, 5000, 8000);
+ R.string.mediasize_na_index_5x8, 5000, 8000);
/** North America Monarch media size: 7.25" x 10.5" (184mm x 267mm) */
public static final MediaSize NA_MONARCH =
new MediaSize("NA_MONARCH", "android",
- R.string.mediaSize_na_monarch, 7250, 10500);
+ R.string.mediasize_na_monarch, 7250, 10500);
/** North America Quarto media size: 8" x 10" (203mm x 254mm) */
public static final MediaSize NA_QUARTO =
new MediaSize("NA_QUARTO", "android",
- R.string.mediaSize_na_quarto, 8000, 10000);
+ R.string.mediasize_na_quarto, 8000, 10000);
/** North America Foolscap media size: 8" x 13" (203mm x 330mm) */
public static final MediaSize NA_FOOLSCAP =
new MediaSize("NA_FOOLSCAP", "android",
- R.string.mediaSize_na_foolscap, 8000, 13000);
+ R.string.mediasize_na_foolscap, 8000, 13000);
// Chinese
/** Chinese ROC 8K media size: 270mm x 390mm (10.629" x 15.3543") */
public static final MediaSize ROC_8K =
new MediaSize("ROC_8K", "android",
- R.string.mediaSize_chinese_roc_8k, 10629, 15354);
+ R.string.mediasize_chinese_roc_8k, 10629, 15354);
/** Chinese ROC 16K media size: 195mm x 270mm (7.677" x 10.629") */
public static final MediaSize ROC_16K =
new MediaSize("ROC_16K", "android",
- R.string.mediaSize_chinese_roc_16k, 7677, 10629);
+ R.string.mediasize_chinese_roc_16k, 7677, 10629);
/** Chinese PRC 1 media size: 102mm x 165mm (4.015" x 6.496") */
public static final MediaSize PRC_1 =
new MediaSize("PRC_1", "android",
- R.string.mediaSize_chinese_prc_1, 4015, 6496);
+ R.string.mediasize_chinese_prc_1, 4015, 6496);
/** Chinese PRC 2 media size: 102mm x 176mm (4.015" x 6.929") */
public static final MediaSize PRC_2 =
new MediaSize("PRC_2", "android",
- R.string.mediaSize_chinese_prc_2, 4015, 6929);
+ R.string.mediasize_chinese_prc_2, 4015, 6929);
/** Chinese PRC 3 media size: 125mm x 176mm (4.921" x 6.929") */
public static final MediaSize PRC_3 =
new MediaSize("PRC_3", "android",
- R.string.mediaSize_chinese_prc_3, 4921, 6929);
+ R.string.mediasize_chinese_prc_3, 4921, 6929);
/** Chinese PRC 4 media size: 110mm x 208mm (4.330" x 8.189") */
public static final MediaSize PRC_4 =
new MediaSize("PRC_4", "android",
- R.string.mediaSize_chinese_prc_4, 4330, 8189);
+ R.string.mediasize_chinese_prc_4, 4330, 8189);
/** Chinese PRC 5 media size: 110mm x 220mm (4.330" x 8.661") */
public static final MediaSize PRC_5 =
new MediaSize("PRC_5", "android",
- R.string.mediaSize_chinese_prc_5, 4330, 8661);
+ R.string.mediasize_chinese_prc_5, 4330, 8661);
/** Chinese PRC 6 media size: 120mm x 320mm (4.724" x 12.599") */
public static final MediaSize PRC_6 =
new MediaSize("PRC_6", "android",
- R.string.mediaSize_chinese_prc_6, 4724, 12599);
+ R.string.mediasize_chinese_prc_6, 4724, 12599);
/** Chinese PRC 7 media size: 160mm x 230mm (6.299" x 9.055") */
public static final MediaSize PRC_7 =
new MediaSize("PRC_7", "android",
- R.string.mediaSize_chinese_prc_7, 6299, 9055);
+ R.string.mediasize_chinese_prc_7, 6299, 9055);
/** Chinese PRC 8 media size: 120mm x 309mm (4.724" x 12.165") */
public static final MediaSize PRC_8 =
new MediaSize("PRC_8", "android",
- R.string.mediaSize_chinese_prc_8, 4724, 12165);
+ R.string.mediasize_chinese_prc_8, 4724, 12165);
/** Chinese PRC 9 media size: 229mm x 324mm (9.016" x 12.756") */
public static final MediaSize PRC_9 =
new MediaSize("PRC_9", "android",
- R.string.mediaSize_chinese_prc_9, 9016, 12756);
+ R.string.mediasize_chinese_prc_9, 9016, 12756);
/** Chinese PRC 10 media size: 324mm x 458mm (12.756" x 18.032") */
public static final MediaSize PRC_10 =
new MediaSize("PRC_10", "android",
- R.string.mediaSize_chinese_prc_10, 12756, 18032);
+ R.string.mediasize_chinese_prc_10, 12756, 18032);
/** Chinese PRC 16k media size: 146mm x 215mm (5.749" x 8.465") */
public static final MediaSize PRC_16k =
new MediaSize("PRC_16k", "android",
- R.string.mediaSize_chinese_prc_16k, 5749, 8465);
+ R.string.mediasize_chinese_prc_16k, 5749, 8465);
/** Chinese Pa Kai media size: 267mm x 389mm (10.512" x 15.315") */
public static final MediaSize OM_PA_KAI =
new MediaSize("OM_PA_KAI", "android",
- R.string.mediaSize_chinese_om_pa_kai, 10512, 15315);
+ R.string.mediasize_chinese_om_pa_kai, 10512, 15315);
/** Chinese Dai Pa Kai media size: 275mm x 395mm (10.827" x 15.551") */
public static final MediaSize OM_DAI_PA_KAI =
new MediaSize("OM_DAI_PA_KAI", "android",
- R.string.mediaSize_chinese_om_dai_pa_kai, 10827, 15551);
+ R.string.mediasize_chinese_om_dai_pa_kai, 10827, 15551);
/** Chinese Jurro Ku Kai media size: 198mm x 275mm (7.796" x 10.827") */
public static final MediaSize OM_JUURO_KU_KAI =
new MediaSize("OM_JUURO_KU_KAI", "android",
- R.string.mediaSize_chinese_om_jurro_ku_kai, 7796, 10827);
+ R.string.mediasize_chinese_om_jurro_ku_kai, 7796, 10827);
// Japanese
/** Japanese JIS B10 media size: 32mm x 45mm (1.259" x 1.772") */
public static final MediaSize JIS_B10 =
new MediaSize("JIS_B10", "android",
- R.string.mediaSize_japanese_jis_b10, 1259, 1772);
+ R.string.mediasize_japanese_jis_b10, 1259, 1772);
/** Japanese JIS B9 media size: 45mm x 64mm (1.772" x 2.52") */
public static final MediaSize JIS_B9 =
new MediaSize("JIS_B9", "android",
- R.string.mediaSize_japanese_jis_b9, 1772, 2520);
+ R.string.mediasize_japanese_jis_b9, 1772, 2520);
/** Japanese JIS B8 media size: 64mm x 91mm (2.52" x 3.583") */
public static final MediaSize JIS_B8 =
new MediaSize("JIS_B8", "android",
- R.string.mediaSize_japanese_jis_b8, 2520, 3583);
+ R.string.mediasize_japanese_jis_b8, 2520, 3583);
/** Japanese JIS B7 media size: 91mm x 128mm (3.583" x 5.049") */
public static final MediaSize JIS_B7 =
new MediaSize("JIS_B7", "android",
- R.string.mediaSize_japanese_jis_b7, 3583, 5049);
+ R.string.mediasize_japanese_jis_b7, 3583, 5049);
/** Japanese JIS B6 media size: 128mm x 182mm (5.049" x 7.165") */
public static final MediaSize JIS_B6 =
new MediaSize("JIS_B6", "android",
- R.string.mediaSize_japanese_jis_b6, 5049, 7165);
+ R.string.mediasize_japanese_jis_b6, 5049, 7165);
/** Japanese JIS B5 media size: 182mm x 257mm (7.165" x 10.118") */
public static final MediaSize JIS_B5 =
new MediaSize("JIS_B5", "android",
- R.string.mediaSize_japanese_jis_b5, 7165, 10118);
+ R.string.mediasize_japanese_jis_b5, 7165, 10118);
/** Japanese JIS B4 media size: 257mm x 364mm (10.118" x 14.331") */
public static final MediaSize JIS_B4 =
new MediaSize("JIS_B4", "android",
- R.string.mediaSize_japanese_jis_b4, 10118, 14331);
+ R.string.mediasize_japanese_jis_b4, 10118, 14331);
/** Japanese JIS B3 media size: 364mm x 515mm (14.331" x 20.276") */
public static final MediaSize JIS_B3 =
new MediaSize("JIS_B3", "android",
- R.string.mediaSize_japanese_jis_b3, 14331, 20276);
+ R.string.mediasize_japanese_jis_b3, 14331, 20276);
/** Japanese JIS B2 media size: 515mm x 728mm (20.276" x 28.661") */
public static final MediaSize JIS_B2 =
new MediaSize("JIS_B2", "android",
- R.string.mediaSize_japanese_jis_b2, 20276, 28661);
+ R.string.mediasize_japanese_jis_b2, 20276, 28661);
/** Japanese JIS B1 media size: 728mm x 1030mm (28.661" x 40.551") */
public static final MediaSize JIS_B1 =
new MediaSize("JIS_B1", "android",
- R.string.mediaSize_japanese_jis_b1, 28661, 40551);
+ R.string.mediasize_japanese_jis_b1, 28661, 40551);
/** Japanese JIS B0 media size: 1030mm x 1456mm (40.551" x 57.323") */
public static final MediaSize JIS_B0 =
new MediaSize("JIS_B0", "android",
- R.string.mediaSize_japanese_jis_b0, 40551, 57323);
+ R.string.mediasize_japanese_jis_b0, 40551, 57323);
/** Japanese JIS Exec media size: 216mm x 330mm (8.504" x 12.992") */
public static final MediaSize JIS_EXEC =
new MediaSize("JIS_EXEC", "android",
- R.string.mediaSize_japanese_jis_exec, 8504, 12992);
+ R.string.mediasize_japanese_jis_exec, 8504, 12992);
/** Japanese Chou4 media size: 90mm x 205mm (3.543" x 8.071") */
public static final MediaSize JPN_CHOU4 =
new MediaSize("JPN_CHOU4", "android",
- R.string.mediaSize_japanese_chou4, 3543, 8071);
+ R.string.mediasize_japanese_chou4, 3543, 8071);
/** Japanese Chou3 media size: 120mm x 235mm (4.724" x 9.252") */
public static final MediaSize JPN_CHOU3 =
new MediaSize("JPN_CHOU3", "android",
- R.string.mediaSize_japanese_chou3, 4724, 9252);
+ R.string.mediasize_japanese_chou3, 4724, 9252);
/** Japanese Chou2 media size: 111.1mm x 146mm (4.374" x 5.748") */
public static final MediaSize JPN_CHOU2 =
new MediaSize("JPN_CHOU2", "android",
- R.string.mediaSize_japanese_chou2, 4374, 5748);
+ R.string.mediasize_japanese_chou2, 4374, 5748);
/** Japanese Hagaki media size: 100mm x 148mm (3.937" x 5.827") */
public static final MediaSize JPN_HAGAKI =
new MediaSize("JPN_HAGAKI", "android",
- R.string.mediaSize_japanese_hagaki, 3937, 5827);
+ R.string.mediasize_japanese_hagaki, 3937, 5827);
/** Japanese Oufuku media size: 148mm x 200mm (5.827" x 7.874") */
public static final MediaSize JPN_OUFUKU =
new MediaSize("JPN_OUFUKU", "android",
- R.string.mediaSize_japanese_oufuku, 5827, 7874);
+ R.string.mediasize_japanese_oufuku, 5827, 7874);
/** Japanese Kahu media size: 240mm x 322.1mm (9.449" x 12.681") */
public static final MediaSize JPN_KAHU =
new MediaSize("JPN_KAHU", "android",
- R.string.mediaSize_japanese_kahu, 9449, 12681);
+ R.string.mediasize_japanese_kahu, 9449, 12681);
/** Japanese Kaku2 media size: 240mm x 332mm (9.449" x 13.071") */
public static final MediaSize JPN_KAKU2 =
new MediaSize("JPN_KAKU2", "android",
- R.string.mediaSize_japanese_kaku2, 9449, 13071);
+ R.string.mediasize_japanese_kaku2, 9449, 13071);
/** Japanese You4 media size: 105mm x 235mm (4.134" x 9.252") */
public static final MediaSize JPN_YOU4 =
new MediaSize("JPN_YOU4", "android",
- R.string.mediaSize_japanese_you4, 4134, 9252);
+ R.string.mediasize_japanese_you4, 4134, 9252);
private final String mId;
/**@hide */
@@ -634,7 +656,8 @@ public final class PrintAttributes implements Parcelable {
/**
* Creates a new instance.
*
- * @param id The unique media size id.
+ * @param id The unique media size id. It is unique amongst other media sizes
+ * supported by the printer.
* @param label The <strong>internationalized</strong> human readable label.
* @param widthMils The width in mils (thousands of an inch).
* @param heightMils The height in mils (thousands of an inch).
@@ -679,7 +702,12 @@ public final class PrintAttributes implements Parcelable {
}
/**
- * Gets the unique media size id.
+ * Gets the unique media size id. It is unique amongst other media sizes
+ * supported by the printer.
+ * <p>
+ * This id is defined by the client that generated the media size
+ * instance and should not be interpreted by other parties.
+ * </p>
*
* @return The unique media size id.
*/
@@ -829,7 +857,11 @@ public final class PrintAttributes implements Parcelable {
}
/**
- * This class specifies a supported resolution in dpi (dots per inch).
+ * This class specifies a supported resolution in DPI (dots per inch).
+ * Resolution defines how many points with different color can be placed
+ * on one inch in horizontal or vertical direction of the target media.
+ * For example, a printer with 600DIP can produce higher quality images
+ * the one with 300DPI resolution.
*/
public static final class Resolution {
private final String mId;
@@ -840,10 +872,11 @@ public final class PrintAttributes implements Parcelable {
/**
* Creates a new instance.
*
- * @param id The unique resolution id.
+ * @param id The unique resolution id. It is unique amongst other resolutions
+ * supported by the printer.
* @param label The <strong>internationalized</strong> human readable label.
- * @param horizontalDpi The horizontal resolution in dpi.
- * @param verticalDpi The vertical resolution in dpi.
+ * @param horizontalDpi The horizontal resolution in DPI (dots per inch).
+ * @param verticalDpi The vertical resolution in DPI (dots per inch).
*
* @throws IllegalArgumentException If the id is empty.
* @throws IllegalArgumentException If the label is empty.
@@ -872,7 +905,12 @@ public final class PrintAttributes implements Parcelable {
}
/**
- * Gets the unique resolution id.
+ * Gets the unique resolution id. It is unique amongst other resolutions
+ * supported by the printer.
+ * <p>
+ * This id is defined by the client that generated the resolution
+ * instance and should not be interpreted by other parties.
+ * </p>
*
* @return The unique resolution id.
*/
@@ -890,7 +928,7 @@ public final class PrintAttributes implements Parcelable {
}
/**
- * Gets the vertical resolution in dpi.
+ * Gets the horizontal resolution in DPI (dots per inch).
*
* @return The horizontal resolution.
*/
@@ -899,7 +937,7 @@ public final class PrintAttributes implements Parcelable {
}
/**
- * Gets the vertical resolution in dpi.
+ * Gets the vertical resolution in DPI (dots per inch).
*
* @return The vertical resolution.
*/
@@ -966,7 +1004,9 @@ public final class PrintAttributes implements Parcelable {
}
/**
- * This class specifies content margins.
+ * This class specifies content margins. Margins define the white space
+ * around the content where the left margin defines the amount of white
+ * space on the left of the content and so on.
*/
public static final class Margins {
public static final Margins NO_MARGINS = new Margins(0, 0, 0, 0);
diff --git a/core/java/android/provider/Downloads.java b/core/java/android/provider/Downloads.java
index 9999760..b2d9b93 100644
--- a/core/java/android/provider/Downloads.java
+++ b/core/java/android/provider/Downloads.java
@@ -410,6 +410,8 @@ public final class Downloads {
/** The column that is used to count retries */
public static final String COLUMN_FAILED_CONNECTIONS = "numfailed";
+ public static final String COLUMN_ALLOW_WRITE = "allow_write";
+
/**
* default value for {@link #COLUMN_LAST_UPDATESRC}.
* This value is used when this column's value is not relevant.
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index a6e8c70..9dfd383 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -1115,7 +1115,7 @@ public abstract class Layout {
float dist = Math.abs(getPrimaryHorizontal(max) - horiz);
- if (dist < bestdist) {
+ if (dist <= bestdist) {
bestdist = dist;
best = max;
}
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index 8929930..6efde05 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -1288,6 +1288,47 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
return mFilters;
}
+ // Same as SpannableStringInternal
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof Spanned &&
+ toString().equals(o.toString())) {
+ // Check span data
+ Object[] otherSpans = ((Spanned) o).getSpans(0,
+ ((Spanned) o).length(), Object.class);
+ if (mSpanCount == otherSpans.length) {
+ for (int i = 0; i < mSpanCount; ++i) {
+ Object thisSpan = mSpans[i];
+ Object otherSpan = otherSpans[i];
+ if (!thisSpan.equals(otherSpan) ||
+ getSpanStart(thisSpan) != getSpanStart(otherSpan) ||
+ getSpanEnd(thisSpan) != getSpanEnd(otherSpan) ||
+ getSpanFlags(thisSpan) != getSpanFlags(otherSpan)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ }
+ return false;
+ }
+
+ // Same as SpannableStringInternal
+ @Override
+ public int hashCode() {
+ int hash = toString().hashCode();
+ hash = hash * 31 + mSpanCount;
+ for (int i = 0; i < mSpanCount; ++i) {
+ Object span = mSpans[i];
+ hash = hash * 31 + span.hashCode();
+ hash = hash * 31 + getSpanStart(span);
+ hash = hash * 31 + getSpanEnd(span);
+ hash = hash * 31 + getSpanFlags(span);
+ }
+ return hash;
+ }
+
private static final InputFilter[] NO_FILTERS = new InputFilter[0];
private InputFilter[] mFilters = NO_FILTERS;
diff --git a/core/java/android/text/SpannableStringInternal.java b/core/java/android/text/SpannableStringInternal.java
index 0825bf3..9b24a2e 100644
--- a/core/java/android/text/SpannableStringInternal.java
+++ b/core/java/android/text/SpannableStringInternal.java
@@ -358,6 +358,47 @@ import java.lang.reflect.Array;
}
}
+ // Same as SpannableStringBuilder
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof Spanned &&
+ toString().equals(o.toString())) {
+ // Check span data
+ Object[] otherSpans = ((Spanned) o).getSpans(0,
+ ((Spanned) o).length(), Object.class);
+ if (mSpanCount == otherSpans.length) {
+ for (int i = 0; i < mSpanCount; ++i) {
+ Object thisSpan = mSpans[i];
+ Object otherSpan = otherSpans[i];
+ if (!thisSpan.equals(otherSpan) ||
+ getSpanStart(thisSpan) != getSpanStart(otherSpan) ||
+ getSpanEnd(thisSpan) != getSpanEnd(otherSpan) ||
+ getSpanFlags(thisSpan) != getSpanFlags(otherSpan)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ }
+ return false;
+ }
+
+ // Same as SpannableStringBuilder
+ @Override
+ public int hashCode() {
+ int hash = toString().hashCode();
+ hash = hash * 31 + mSpanCount;
+ for (int i = 0; i < mSpanCount; ++i) {
+ Object span = mSpans[i];
+ hash = hash * 31 + span.hashCode();
+ hash = hash * 31 + getSpanStart(span);
+ hash = hash * 31 + getSpanEnd(span);
+ hash = hash * 31 + getSpanFlags(span);
+ }
+ return hash;
+ }
+
private String mText;
private Object[] mSpans;
private int[] mSpanData;
diff --git a/core/java/android/transition/TextChange.java b/core/java/android/transition/TextChange.java
index 0b1e4e1..fa2f548 100644
--- a/core/java/android/transition/TextChange.java
+++ b/core/java/android/transition/TextChange.java
@@ -21,6 +21,7 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.graphics.Color;
+import android.util.Log;
import android.view.ViewGroup;
import android.widget.TextView;
@@ -36,6 +37,9 @@ import java.util.Map;
* @hide
*/
public class TextChange extends Transition {
+
+ private static final String LOG_TAG = "TextChange";
+
private static final String PROPNAME_TEXT = "android:textchange:text";
private static final String PROPNAME_TEXT_COLOR = "android:textchange:textColor";
@@ -224,6 +228,9 @@ public class TextChange extends Transition {
}
};
addListener(transitionListener);
+ if (DBG) {
+ Log.d(LOG_TAG, "createAnimator returning " + anim);
+ }
return anim;
}
return null;
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 20fb1a7..90cc72e 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -58,9 +58,6 @@ import java.util.Map;
* It uses the WebKit rendering engine to display
* web pages and includes methods to navigate forward and backward
* through a history, zoom in and out, perform text searches and more.</p>
- * <p>To enable the built-in zoom, set
- * {@link #getSettings() WebSettings}.{@link WebSettings#setBuiltInZoomControls(boolean)}
- * (introduced in API level {@link android.os.Build.VERSION_CODES#CUPCAKE}).
* <p>Note that, in order for your Activity to access the Internet and load web pages
* in a WebView, you must add the {@code INTERNET} permissions to your
* Android Manifest file:</p>
@@ -161,9 +158,18 @@ import java.util.Map;
* }
* });
*
- * webview.loadUrl("http://slashdot.org/");
+ * webview.loadUrl("http://developer.android.com/");
* </pre>
*
+ * <h3>Zoom</h3>
+ *
+ * <p>To enable the built-in zoom, set
+ * {@link #getSettings() WebSettings}.{@link WebSettings#setBuiltInZoomControls(boolean)}
+ * (introduced in API level {@link android.os.Build.VERSION_CODES#CUPCAKE}).</p>
+ * <p>NOTE: Using zoom if either the height or width is set to
+ * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} may lead to undefined behavior
+ * and should be avoided.</p>
+ *
* <h3>Cookie and window management</h3>
*
* <p>For obvious security reasons, your application has its own
@@ -222,6 +228,7 @@ import java.util.Map;
* <p>The {@code hdpi.css} stylesheet is only used for devices with a screen pixel ration of 1.5,
* which is the high density pixel ratio.</p>
* </li>
+ * </ul>
*
* <h3>HTML5 Video support</h3>
*
@@ -1673,6 +1680,22 @@ public class WebView extends AbsoluteLayout
}
/**
+ * Enables debugging of web contents (HTML / CSS / JavaScript)
+ * loaded into any WebViews of this application. This flag can be enabled
+ * in order to facilitate debugging of web layouts and JavaScript
+ * code running inside WebViews. Please refer to WebView documentation
+ * for the debugging guide.
+ *
+ * The default is false.
+ *
+ * @param enabled whether to enable web contents debugging
+ */
+ public static void setWebContentsDebuggingEnabled(boolean enabled) {
+ checkThread();
+ getFactory().getStatics().setWebContentsDebuggingEnabled(enabled);
+ }
+
+ /**
* Gets the list of currently loaded plugins.
*
* @return the list of currently loaded plugins
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index e82ce30..3c377d3 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -1361,6 +1361,11 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
return WebSettingsClassic.getDefaultUserAgentForLocale(context,
Locale.getDefault());
}
+
+ @Override
+ public void setWebContentsDebuggingEnabled(boolean enable) {
+ // no-op for WebViewClassic.
+ }
}
private void onHandleUiEvent(MotionEvent event, int eventType, int flags) {
diff --git a/core/java/android/webkit/WebViewFactoryProvider.java b/core/java/android/webkit/WebViewFactoryProvider.java
index 934ef83..9d9d882 100644
--- a/core/java/android/webkit/WebViewFactoryProvider.java
+++ b/core/java/android/webkit/WebViewFactoryProvider.java
@@ -48,6 +48,12 @@ public interface WebViewFactoryProvider {
* {@link android.webkit.WebSettings#getDefaultUserAgent(Context) }
*/
String getDefaultUserAgent(Context context);
+
+ /**
+ * Implements the API method:
+ * {@link android.webkit.WebView#setWebContentsDebuggingEnabled(boolean) }
+ */
+ void setWebContentsDebuggingEnabled(boolean enable);
}
Statics getStatics();
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index 31ab0af..a5fad60 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -280,7 +280,9 @@ public abstract class AdapterView<T extends Adapter> extends ViewGroup {
}
/**
- * Call the OnItemClickListener, if it is defined.
+ * Call the OnItemClickListener, if it is defined. Performs all normal
+ * actions associated with clicking: reporting accessibility event, playing
+ * a sound, etc.
*
* @param view The view within the AdapterView that was clicked.
* @param position The position of the view in the adapter.