summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt22
-rwxr-xr-xcore/java/android/animation/ValueAnimator.java2
-rw-r--r--core/java/android/os/FileUtils.java10
-rw-r--r--core/java/android/os/Parcel.java220
-rw-r--r--core/java/android/view/Choreographer.java282
-rw-r--r--core/java/android/view/View.java57
-rw-r--r--core/java/android/view/ViewRootImpl.java8
-rw-r--r--core/java/android/widget/Spinner.java172
-rw-r--r--core/java/android/widget/Switch.java152
-rw-r--r--core/java/com/android/internal/os/ZygoteInit.java2
-rw-r--r--core/jni/Android.mk1
-rw-r--r--core/jni/AndroidRuntime.cpp2
-rw-r--r--core/jni/android/graphics/Bitmap.cpp1
-rw-r--r--core/jni/android/graphics/Region.cpp1
-rw-r--r--core/jni/android_database_CursorWindow.cpp1
-rw-r--r--core/jni/android_os_Parcel.cpp676
-rw-r--r--core/jni/android_os_Parcel.h27
-rw-r--r--core/jni/android_util_Binder.cpp676
-rw-r--r--core/jni/android_util_Binder.h14
-rw-r--r--core/jni/android_view_InputChannel.cpp1
-rw-r--r--core/jni/android_view_MotionEvent.cpp1
-rw-r--r--core/jni/android_view_Surface.cpp2
-rw-r--r--core/res/res/values-es-rUS/strings.xml6
-rw-r--r--core/res/res/values-ms/strings.xml2
-rw-r--r--core/res/res/values-nb/strings.xml2
-rw-r--r--core/res/res/values-pl/strings.xml4
-rw-r--r--core/res/res/values-sw/strings.xml4
-rw-r--r--core/res/res/values-zh-rCN/strings.xml2
-rw-r--r--include/media/AudioSystem.h2
-rw-r--r--include/media/IAudioPolicyService.h2
-rw-r--r--media/jni/android_media_MediaPlayer.cpp1
-rw-r--r--media/libmedia/AudioSystem.cpp4
-rw-r--r--media/libmedia/IAudioPolicyService.cpp4
-rw-r--r--media/libstagefright/AwesomePlayer.cpp2
-rw-r--r--media/libstagefright/WVMExtractor.cpp6
-rw-r--r--media/libstagefright/include/WVMExtractor.h3
-rw-r--r--packages/SystemUI/res/values-in/strings.xml2
-rw-r--r--services/audioflinger/AudioPolicyService.cpp6
-rw-r--r--services/audioflinger/AudioPolicyService.h2
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java2
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java2
41 files changed, 1555 insertions, 833 deletions
diff --git a/api/current.txt b/api/current.txt
index 0603a63a79e9..a6bdf5a40c71 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -27495,9 +27495,19 @@ package android.widget {
ctor public Spinner(android.content.Context, android.util.AttributeSet);
ctor public Spinner(android.content.Context, android.util.AttributeSet, int);
ctor public Spinner(android.content.Context, android.util.AttributeSet, int, int);
+ method public int getDropDownHorizontalOffset();
+ method public int getDropDownVerticalOffset();
+ method public int getDropDownWidth();
+ method public int getGravity();
+ method public android.graphics.drawable.Drawable getPopupBackground();
method public java.lang.CharSequence getPrompt();
method public void onClick(android.content.DialogInterface, int);
+ method public void setDropDownHorizontalOffset(int);
+ method public void setDropDownVerticalOffset(int);
+ method public void setDropDownWidth(int);
method public void setGravity(int);
+ method public void setPopupBackgroundDrawable(android.graphics.drawable.Drawable);
+ method public void setPopupBackgroundResource(int);
method public void setPrompt(java.lang.CharSequence);
method public void setPromptId(int);
field public static final int MODE_DIALOG = 0; // 0x0
@@ -27518,14 +27528,26 @@ package android.widget {
ctor public Switch(android.content.Context);
ctor public Switch(android.content.Context, android.util.AttributeSet);
ctor public Switch(android.content.Context, android.util.AttributeSet, int);
+ method public int getSwitchMinWidth();
+ method public int getSwitchPadding();
method public java.lang.CharSequence getTextOff();
method public java.lang.CharSequence getTextOn();
+ method public android.graphics.drawable.Drawable getThumbDrawable();
+ method public int getThumbTextPadding();
+ method public android.graphics.drawable.Drawable getTrackDrawable();
method public void onMeasure(int, int);
+ method public void setSwitchMinWidth(int);
+ method public void setSwitchPadding(int);
method public void setSwitchTextAppearance(android.content.Context, int);
method public void setSwitchTypeface(android.graphics.Typeface, int);
method public void setSwitchTypeface(android.graphics.Typeface);
method public void setTextOff(java.lang.CharSequence);
method public void setTextOn(java.lang.CharSequence);
+ method public void setThumbDrawable(android.graphics.drawable.Drawable);
+ method public void setThumbResource(int);
+ method public void setThumbTextPadding(int);
+ method public void setTrackDrawable(android.graphics.drawable.Drawable);
+ method public void setTrackResource(int);
}
public class TabHost extends android.widget.FrameLayout implements android.view.ViewTreeObserver.OnTouchModeChangeListener {
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 6fbeee36e03a..954ae66c7f91 100755
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -645,7 +645,7 @@ public class ValueAnimator extends Animator {
// onAnimate to process the next frame of the animations.
if (!mAnimationScheduled
&& (!mAnimations.isEmpty() || !mDelayedAnims.isEmpty())) {
- mChoreographer.postAnimationCallback(this);
+ mChoreographer.postAnimationCallback(this, null);
mAnimationScheduled = true;
}
}
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 215e836bf735..6c1445df74a0 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -28,6 +28,8 @@ import java.util.regex.Pattern;
import java.util.zip.CRC32;
import java.util.zip.CheckedInputStream;
+import libcore.io.Os;
+import libcore.io.StructStat;
/**
* Tools for managing files. Not for public consumption.
@@ -52,8 +54,10 @@ public class FileUtils {
/**
* File status information. This class maps directly to the POSIX stat structure.
+ * @deprecated use {@link StructStat} instead.
* @hide
*/
+ @Deprecated
public static final class FileStatus {
public int dev;
public int ino;
@@ -77,7 +81,9 @@ public class FileUtils {
* exists.
* @return true if the file exists and false if it does not exist. If you do not have
* permission to stat the file, then this method will return false.
+ * @deprecated use {@link Os#stat(String)} instead.
*/
+ @Deprecated
public static boolean getFileStatus(String path, FileStatus status) {
StrictMode.noteDiskRead();
return getFileStatusNative(path, status);
@@ -90,6 +96,10 @@ public class FileUtils {
public static native int setPermissions(String file, int mode, int uid, int gid);
+ /**
+ * @deprecated use {@link Os#stat(String)} instead.
+ */
+ @Deprecated
public static native int getPermissions(String file, int[] outPermissions);
public static native int setUMask(int mask);
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 15e3af42c4e3..1507387d78fa 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -180,9 +180,14 @@ public final class Parcel {
private static final String TAG = "Parcel";
@SuppressWarnings({"UnusedDeclaration"})
- private int mObject; // used by native code
- @SuppressWarnings({"UnusedDeclaration"})
- private int mOwnObject; // used by native code
+ private int mNativePtr; // used by native code
+
+ /**
+ * Flag indicating if {@link #mNativePtr} was allocated by this object,
+ * indicating that we're responsible for its lifecycle.
+ */
+ private boolean mOwnsNativeParcelObject;
+
private RuntimeException mStack;
private static final int POOL_SIZE = 6;
@@ -224,6 +229,48 @@ public final class Parcel {
private static final int EX_ILLEGAL_STATE = -5;
private static final int EX_HAS_REPLY_HEADER = -128; // special; see below
+ private static native int nativeDataSize(int nativePtr);
+ private static native int nativeDataAvail(int nativePtr);
+ private static native int nativeDataPosition(int nativePtr);
+ private static native int nativeDataCapacity(int nativePtr);
+ private static native void nativeSetDataSize(int nativePtr, int size);
+ private static native void nativeSetDataPosition(int nativePtr, int pos);
+ private static native void nativeSetDataCapacity(int nativePtr, int size);
+
+ private static native boolean nativePushAllowFds(int nativePtr, boolean allowFds);
+ private static native void nativeRestoreAllowFds(int nativePtr, boolean lastValue);
+
+ private static native void nativeWriteByteArray(int nativePtr, byte[] b, int offset, int len);
+ private static native void nativeWriteInt(int nativePtr, int val);
+ private static native void nativeWriteLong(int nativePtr, long val);
+ private static native void nativeWriteFloat(int nativePtr, float val);
+ private static native void nativeWriteDouble(int nativePtr, double val);
+ private static native void nativeWriteString(int nativePtr, String val);
+ private static native void nativeWriteStrongBinder(int nativePtr, IBinder val);
+ private static native void nativeWriteFileDescriptor(int nativePtr, FileDescriptor val);
+
+ private static native byte[] nativeCreateByteArray(int nativePtr);
+ private static native int nativeReadInt(int nativePtr);
+ private static native long nativeReadLong(int nativePtr);
+ private static native float nativeReadFloat(int nativePtr);
+ private static native double nativeReadDouble(int nativePtr);
+ private static native String nativeReadString(int nativePtr);
+ private static native IBinder nativeReadStrongBinder(int nativePtr);
+ private static native FileDescriptor nativeReadFileDescriptor(int nativePtr);
+
+ private static native int nativeCreate();
+ private static native void nativeFreeBuffer(int nativePtr);
+ private static native void nativeDestroy(int nativePtr);
+
+ private static native byte[] nativeMarshall(int nativePtr);
+ private static native void nativeUnmarshall(
+ int nativePtr, byte[] data, int offest, int length);
+ private static native void nativeAppendFrom(
+ int thisNativePtr, int otherNativePtr, int offset, int length);
+ private static native boolean nativeHasFileDescriptors(int nativePtr);
+ private static native void nativeWriteInterfaceToken(int nativePtr, String interfaceName);
+ private static native void nativeEnforceInterface(int nativePtr, String interfaceName);
+
public final static Parcelable.Creator<String> STRING_CREATOR
= new Parcelable.Creator<String>() {
public String createFromParcel(Parcel source) {
@@ -262,7 +309,15 @@ public final class Parcel {
public final void recycle() {
if (DEBUG_RECYCLE) mStack = null;
freeBuffer();
- final Parcel[] pool = mOwnObject != 0 ? sOwnedPool : sHolderPool;
+
+ final Parcel[] pool;
+ if (mOwnsNativeParcelObject) {
+ pool = sOwnedPool;
+ } else {
+ mNativePtr = 0;
+ pool = sHolderPool;
+ }
+
synchronized (pool) {
for (int i=0; i<POOL_SIZE; i++) {
if (pool[i] == null) {
@@ -276,19 +331,25 @@ public final class Parcel {
/**
* Returns the total amount of data contained in the parcel.
*/
- public final native int dataSize();
+ public final int dataSize() {
+ return nativeDataSize(mNativePtr);
+ }
/**
* Returns the amount of data remaining to be read from the
* parcel. That is, {@link #dataSize}-{@link #dataPosition}.
*/
- public final native int dataAvail();
+ public final int dataAvail() {
+ return nativeDataAvail(mNativePtr);
+ }
/**
* Returns the current position in the parcel data. Never
* more than {@link #dataSize}.
*/
- public final native int dataPosition();
+ public final int dataPosition() {
+ return nativeDataPosition(mNativePtr);
+ }
/**
* Returns the total amount of space in the parcel. This is always
@@ -296,7 +357,9 @@ public final class Parcel {
* amount of room left until the parcel needs to re-allocate its
* data buffer.
*/
- public final native int dataCapacity();
+ public final int dataCapacity() {
+ return nativeDataCapacity(mNativePtr);
+ }
/**
* Change the amount of data in the parcel. Can be either smaller or
@@ -305,14 +368,18 @@ public final class Parcel {
*
* @param size The new number of bytes in the Parcel.
*/
- public final native void setDataSize(int size);
+ public final void setDataSize(int size) {
+ nativeSetDataSize(mNativePtr, size);
+ }
/**
* Move the current read/write position in the parcel.
* @param pos New offset in the parcel; must be between 0 and
* {@link #dataSize}.
*/
- public final native void setDataPosition(int pos);
+ public final void setDataPosition(int pos) {
+ nativeSetDataPosition(mNativePtr, pos);
+ }
/**
* Change the capacity (current available space) of the parcel.
@@ -321,13 +388,19 @@ public final class Parcel {
* less than {@link #dataSize} -- that is, you can not drop existing data
* with this method.
*/
- public final native void setDataCapacity(int size);
+ public final void setDataCapacity(int size) {
+ nativeSetDataCapacity(mNativePtr, size);
+ }
/** @hide */
- public final native boolean pushAllowFds(boolean allowFds);
+ public final boolean pushAllowFds(boolean allowFds) {
+ return nativePushAllowFds(mNativePtr, allowFds);
+ }
/** @hide */
- public final native void restoreAllowFds(boolean lastValue);
+ public final void restoreAllowFds(boolean lastValue) {
+ nativeRestoreAllowFds(mNativePtr, lastValue);
+ }
/**
* Returns the raw bytes of the parcel.
@@ -340,27 +413,40 @@ public final class Parcel {
* such does not attempt to maintain compatibility with data created
* in different versions of the platform.
*/
- public final native byte[] marshall();
+ public final byte[] marshall() {
+ return nativeMarshall(mNativePtr);
+ }
/**
* Set the bytes in data to be the raw bytes of this Parcel.
*/
- public final native void unmarshall(byte[] data, int offest, int length);
+ public final void unmarshall(byte[] data, int offest, int length) {
+ nativeUnmarshall(mNativePtr, data, offest, length);
+ }
- public final native void appendFrom(Parcel parcel, int offset, int length);
+ public final void appendFrom(Parcel parcel, int offset, int length) {
+ nativeAppendFrom(mNativePtr, parcel.mNativePtr, offset, length);
+ }
/**
* Report whether the parcel contains any marshalled file descriptors.
*/
- public final native boolean hasFileDescriptors();
+ public final boolean hasFileDescriptors() {
+ return nativeHasFileDescriptors(mNativePtr);
+ }
/**
* Store or read an IBinder interface token in the parcel at the current
* {@link #dataPosition}. This is used to validate that the marshalled
* transaction is intended for the target interface.
*/
- public final native void writeInterfaceToken(String interfaceName);
- public final native void enforceInterface(String interfaceName);
+ public final void writeInterfaceToken(String interfaceName) {
+ nativeWriteInterfaceToken(mNativePtr, interfaceName);
+ }
+
+ public final void enforceInterface(String interfaceName) {
+ nativeEnforceInterface(mNativePtr, interfaceName);
+ }
/**
* Write a byte array into the parcel at the current {@link #dataPosition},
@@ -384,40 +470,48 @@ public final class Parcel {
return;
}
Arrays.checkOffsetAndCount(b.length, offset, len);
- writeNative(b, offset, len);
+ nativeWriteByteArray(mNativePtr, b, offset, len);
}
- private native void writeNative(byte[] b, int offset, int len);
-
/**
* Write an integer value into the parcel at the current dataPosition(),
* growing dataCapacity() if needed.
*/
- public final native void writeInt(int val);
+ public final void writeInt(int val) {
+ nativeWriteInt(mNativePtr, val);
+ }
/**
* Write a long integer value into the parcel at the current dataPosition(),
* growing dataCapacity() if needed.
*/
- public final native void writeLong(long val);
+ public final void writeLong(long val) {
+ nativeWriteLong(mNativePtr, val);
+ }
/**
* Write a floating point value into the parcel at the current
* dataPosition(), growing dataCapacity() if needed.
*/
- public final native void writeFloat(float val);
+ public final void writeFloat(float val) {
+ nativeWriteFloat(mNativePtr, val);
+ }
/**
* Write a double precision floating point value into the parcel at the
* current dataPosition(), growing dataCapacity() if needed.
*/
- public final native void writeDouble(double val);
+ public final void writeDouble(double val) {
+ nativeWriteDouble(mNativePtr, val);
+ }
/**
* Write a string value into the parcel at the current dataPosition(),
* growing dataCapacity() if needed.
*/
- public final native void writeString(String val);
+ public final void writeString(String val) {
+ nativeWriteString(mNativePtr, val);
+ }
/**
* Write a CharSequence value into the parcel at the current dataPosition(),
@@ -432,7 +526,9 @@ public final class Parcel {
* Write an object into the parcel at the current dataPosition(),
* growing dataCapacity() if needed.
*/
- public final native void writeStrongBinder(IBinder val);
+ public final void writeStrongBinder(IBinder val) {
+ nativeWriteStrongBinder(mNativePtr, val);
+ }
/**
* Write an object into the parcel at the current dataPosition(),
@@ -452,7 +548,9 @@ public final class Parcel {
* accepts contextual flags and will close the original file descriptor
* if {@link Parcelable#PARCELABLE_WRITE_RETURN_VALUE} is set.</p>
*/
- public final native void writeFileDescriptor(FileDescriptor val);
+ public final void writeFileDescriptor(FileDescriptor val) {
+ nativeWriteFileDescriptor(mNativePtr, val);
+ }
/**
* Write an byte value into the parcel at the current dataPosition(),
@@ -1341,29 +1439,39 @@ public final class Parcel {
/**
* Read an integer value from the parcel at the current dataPosition().
*/
- public final native int readInt();
+ public final int readInt() {
+ return nativeReadInt(mNativePtr);
+ }
/**
* Read a long integer value from the parcel at the current dataPosition().
*/
- public final native long readLong();
+ public final long readLong() {
+ return nativeReadLong(mNativePtr);
+ }
/**
* Read a floating point value from the parcel at the current
* dataPosition().
*/
- public final native float readFloat();
+ public final float readFloat() {
+ return nativeReadFloat(mNativePtr);
+ }
/**
* Read a double precision floating point value from the parcel at the
* current dataPosition().
*/
- public final native double readDouble();
+ public final double readDouble() {
+ return nativeReadDouble(mNativePtr);
+ }
/**
* Read a string value from the parcel at the current dataPosition().
*/
- public final native String readString();
+ public final String readString() {
+ return nativeReadString(mNativePtr);
+ }
/**
* Read a CharSequence value from the parcel at the current dataPosition().
@@ -1376,17 +1484,18 @@ public final class Parcel {
/**
* Read an object from the parcel at the current dataPosition().
*/
- public final native IBinder readStrongBinder();
+ public final IBinder readStrongBinder() {
+ return nativeReadStrongBinder(mNativePtr);
+ }
/**
* Read a FileDescriptor from the parcel at the current dataPosition().
*/
public final ParcelFileDescriptor readFileDescriptor() {
- FileDescriptor fd = internalReadFileDescriptor();
+ FileDescriptor fd = nativeReadFileDescriptor(mNativePtr);
return fd != null ? new ParcelFileDescriptor(fd) : null;
}
- private native FileDescriptor internalReadFileDescriptor();
/*package*/ static native FileDescriptor openFileDescriptor(String file,
int mode) throws FileNotFoundException;
/*package*/ static native FileDescriptor dupFileDescriptor(FileDescriptor orig)
@@ -1471,7 +1580,9 @@ public final class Parcel {
/**
* Read and return a byte[] object from the parcel.
*/
- public final native byte[] createByteArray();
+ public final byte[] createByteArray() {
+ return nativeCreateByteArray(mNativePtr);
+ }
/**
* Read a byte[] object from the parcel and copy it into the
@@ -2065,12 +2176,37 @@ public final class Parcel {
return new Parcel(obj);
}
- private Parcel(int obj) {
+ private Parcel(int nativePtr) {
if (DEBUG_RECYCLE) {
mStack = new RuntimeException();
}
//Log.i(TAG, "Initializing obj=0x" + Integer.toHexString(obj), mStack);
- init(obj);
+ init(nativePtr);
+ }
+
+ private void init(int nativePtr) {
+ if (nativePtr != 0) {
+ mNativePtr = nativePtr;
+ mOwnsNativeParcelObject = false;
+ } else {
+ mNativePtr = nativeCreate();
+ mOwnsNativeParcelObject = true;
+ }
+ }
+
+ private void freeBuffer() {
+ if (mOwnsNativeParcelObject) {
+ nativeFreeBuffer(mNativePtr);
+ }
+ }
+
+ private void destroy() {
+ if (mNativePtr != 0) {
+ if (mOwnsNativeParcelObject) {
+ nativeDestroy(mNativePtr);
+ }
+ mNativePtr = 0;
+ }
}
@Override
@@ -2083,10 +2219,6 @@ public final class Parcel {
destroy();
}
- private native void freeBuffer();
- private native void init(int obj);
- private native void destroy();
-
/* package */ void readMapInternal(Map outVal, int N,
ClassLoader loader) {
while (N > 0) {
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index f4d7af96192b..10edc0678d05 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -81,8 +81,8 @@ public final class Choreographer {
private static final int MSG_DO_ANIMATION = 0;
private static final int MSG_DO_DRAW = 1;
private static final int MSG_DO_SCHEDULE_VSYNC = 2;
- private static final int MSG_POST_DELAYED_ANIMATION = 3;
- private static final int MSG_POST_DELAYED_DRAW = 4;
+ private static final int MSG_DO_SCHEDULE_ANIMATION = 3;
+ private static final int MSG_DO_SCHEDULE_DRAW = 4;
private final Object mLock = new Object();
@@ -152,134 +152,158 @@ public final class Choreographer {
}
/**
+ * Subtracts typical frame delay time from a delay interval in milliseconds.
+ *
+ * This method can be used to compensate for animation delay times that have baked
+ * in assumptions about the frame delay. For example, it's quite common for code to
+ * assume a 60Hz frame time and bake in a 16ms delay. When we call
+ * {@link #postAnimationCallbackDelayed} we want to know how long to wait before
+ * posting the animation callback but let the animation timer take care of the remaining
+ * frame delay time.
+ *
+ * This method is somewhat conservative about how much of the frame delay it
+ * subtracts. It uses the same value returned by {@link #getFrameDelay} which by
+ * default is 10ms even though many parts of the system assume 16ms. Consequently,
+ * we might still wait 6ms before posting an animation callback that we want to run
+ * on the next frame, but this is much better than waiting a whole 16ms and likely
+ * missing the deadline.
+ *
+ * @param delayMillis The original delay time including an assumed frame delay.
+ * @return The adjusted delay time with the assumed frame delay subtracted out.
+ */
+ public static long subtractFrameDelay(long delayMillis) {
+ final long frameDelay = sFrameDelay;
+ return delayMillis <= frameDelay ? 0 : delayMillis - frameDelay;
+ }
+
+ /**
* Posts a callback to run on the next animation cycle.
* The callback only runs once and then is automatically removed.
*
- * @param runnable The callback to run during the next animation cycle.
+ * @param action The callback action to run during the next animation cycle.
+ * @param token The callback token, or null if none.
*
* @see #removeAnimationCallback
*/
- public void postAnimationCallback(Runnable runnable) {
- if (runnable == null) {
- throw new IllegalArgumentException("runnable must not be null");
- }
- postAnimationCallbackUnchecked(runnable);
- }
-
- private void postAnimationCallbackUnchecked(Runnable runnable) {
- synchronized (mLock) {
- mAnimationCallbacks = addCallbackLocked(mAnimationCallbacks, runnable);
- scheduleAnimationLocked();
- }
+ public void postAnimationCallback(Runnable action, Object token) {
+ postAnimationCallbackDelayed(action, token, 0);
}
/**
* Posts a callback to run on the next animation cycle following the specified delay.
* The callback only runs once and then is automatically removed.
*
- * @param runnable The callback to run during the next animation cycle following
+ * @param action The callback action to run during the next animation cycle after
* the specified delay.
+ * @param token The callback token, or null if none.
* @param delayMillis The delay time in milliseconds.
*
* @see #removeAnimationCallback
*/
- public void postAnimationCallbackDelayed(Runnable runnable, long delayMillis) {
- if (runnable == null) {
- throw new IllegalArgumentException("runnable must not be null");
+ public void postAnimationCallbackDelayed(Runnable action, Object token, long delayMillis) {
+ if (action == null) {
+ throw new IllegalArgumentException("action must not be null");
}
- if (delayMillis <= 0) {
- postAnimationCallbackUnchecked(runnable);
- } else {
- Message msg = mHandler.obtainMessage(MSG_POST_DELAYED_ANIMATION, runnable);
- mHandler.sendMessageDelayed(msg, delayMillis);
+
+ synchronized (mLock) {
+ final long now = SystemClock.uptimeMillis();
+ final long dueTime = now + delayMillis;
+ mAnimationCallbacks = addCallbackLocked(mAnimationCallbacks, dueTime, action, token);
+
+ if (dueTime <= now) {
+ scheduleAnimationLocked(now);
+ } else {
+ Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_ANIMATION, action);
+ mHandler.sendMessageAtTime(msg, dueTime);
+ }
}
}
/**
- * Removes animation callbacks for the specified runnable.
- * Does nothing if the specified animation callback has not been posted or has already
- * been removed.
+ * Removes animation callbacks that have the specified action and token.
*
- * @param runnable The animation callback to remove.
+ * @param action The action property of the callbacks to remove, or null to remove
+ * callbacks with any action.
+ * @param token The token property of the callbacks to remove, or null to remove
+ * callbacks with any token.
*
* @see #postAnimationCallback
* @see #postAnimationCallbackDelayed
*/
- public void removeAnimationCallbacks(Runnable runnable) {
- if (runnable == null) {
- throw new IllegalArgumentException("runnable must not be null");
- }
+ public void removeAnimationCallbacks(Runnable action, Object token) {
synchronized (mLock) {
- mAnimationCallbacks = removeCallbacksLocked(mAnimationCallbacks, runnable);
+ mAnimationCallbacks = removeCallbacksLocked(mAnimationCallbacks, action, token);
+ if (action != null && token == null) {
+ mHandler.removeMessages(MSG_DO_SCHEDULE_ANIMATION, action);
+ }
}
- mHandler.removeMessages(MSG_POST_DELAYED_ANIMATION, runnable);
}
/**
* Posts a callback to run on the next draw cycle.
* The callback only runs once and then is automatically removed.
*
- * @param runnable The callback to run during the next draw cycle.
+ * @param action The callback action to run during the next draw cycle.
+ * @param token The callback token, or null if none.
*
* @see #removeDrawCallback
*/
- public void postDrawCallback(Runnable runnable) {
- if (runnable == null) {
- throw new IllegalArgumentException("runnable must not be null");
- }
- postDrawCallbackUnchecked(runnable);
- }
-
- private void postDrawCallbackUnchecked(Runnable runnable) {
- synchronized (mLock) {
- mDrawCallbacks = addCallbackLocked(mDrawCallbacks, runnable);
- scheduleDrawLocked();
- }
+ public void postDrawCallback(Runnable action, Object token) {
+ postDrawCallbackDelayed(action, token, 0);
}
/**
* Posts a callback to run on the next draw cycle following the specified delay.
* The callback only runs once and then is automatically removed.
*
- * @param runnable The callback to run during the next draw cycle following
+ * @param action The callback action to run during the next animation cycle after
* the specified delay.
+ * @param token The callback token, or null if none.
* @param delayMillis The delay time in milliseconds.
*
* @see #removeDrawCallback
*/
- public void postDrawCallbackDelayed(Runnable runnable, long delayMillis) {
- if (runnable == null) {
- throw new IllegalArgumentException("runnable must not be null");
+ public void postDrawCallbackDelayed(Runnable action, Object token, long delayMillis) {
+ if (action == null) {
+ throw new IllegalArgumentException("action must not be null");
}
- if (delayMillis <= 0) {
- postDrawCallbackUnchecked(runnable);
- } else {
- Message msg = mHandler.obtainMessage(MSG_POST_DELAYED_DRAW, runnable);
- mHandler.sendMessageDelayed(msg, delayMillis);
+
+ synchronized (mLock) {
+ final long now = SystemClock.uptimeMillis();
+ final long dueTime = now + delayMillis;
+ mDrawCallbacks = addCallbackLocked(mDrawCallbacks, dueTime, action, token);
+ scheduleDrawLocked(now);
+
+ if (dueTime <= now) {
+ scheduleDrawLocked(now);
+ } else {
+ Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_DRAW, action);
+ mHandler.sendMessageAtTime(msg, dueTime);
+ }
}
}
/**
- * Removes draw callbacks for the specified runnable.
- * Does nothing if the specified draw callback has not been posted or has already
- * been removed.
+ * Removes draw callbacks that have the specified action and token.
*
- * @param runnable The draw callback to remove.
+ * @param action The action property of the callbacks to remove, or null to remove
+ * callbacks with any action.
+ * @param token The token property of the callbacks to remove, or null to remove
+ * callbacks with any token.
*
* @see #postDrawCallback
* @see #postDrawCallbackDelayed
*/
- public void removeDrawCallbacks(Runnable runnable) {
- if (runnable == null) {
- throw new IllegalArgumentException("runnable must not be null");
- }
+ public void removeDrawCallbacks(Runnable action, Object token) {
synchronized (mLock) {
- mDrawCallbacks = removeCallbacksLocked(mDrawCallbacks, runnable);
+ mDrawCallbacks = removeCallbacksLocked(mDrawCallbacks, action, token);
+ if (action != null && token == null) {
+ mHandler.removeMessages(MSG_DO_SCHEDULE_DRAW, action);
+ }
}
- mHandler.removeMessages(MSG_POST_DELAYED_DRAW, runnable);
}
- private void scheduleAnimationLocked() {
+ private void scheduleAnimationLocked(long now) {
if (!mAnimationScheduled) {
mAnimationScheduled = true;
if (USE_VSYNC) {
@@ -291,14 +315,13 @@ public final class Choreographer {
// otherwise post a message to schedule the vsync from the UI thread
// as soon as possible.
if (isRunningOnLooperThreadLocked()) {
- doScheduleVsyncLocked();
+ scheduleVsyncLocked();
} else {
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC);
msg.setAsynchronous(true);
mHandler.sendMessageAtFrontOfQueue(msg);
}
} else {
- final long now = SystemClock.uptimeMillis();
final long nextAnimationTime = Math.max(mLastAnimationTime + sFrameDelay, now);
if (DEBUG) {
Log.d(TAG, "Scheduling animation in " + (nextAnimationTime - now) + " ms.");
@@ -310,18 +333,18 @@ public final class Choreographer {
}
}
- private void scheduleDrawLocked() {
+ private void scheduleDrawLocked(long now) {
if (!mDrawScheduled) {
mDrawScheduled = true;
if (USE_ANIMATION_TIMER_FOR_DRAW) {
- scheduleAnimationLocked();
+ scheduleAnimationLocked(now);
} else {
if (DEBUG) {
Log.d(TAG, "Scheduling draw immediately.");
}
Message msg = mHandler.obtainMessage(MSG_DO_DRAW);
msg.setAsynchronous(true);
- mHandler.sendMessage(msg);
+ mHandler.sendMessageAtTime(msg, now);
}
}
}
@@ -336,7 +359,7 @@ public final class Choreographer {
void doAnimationInner() {
final long start;
- final Callback callbacks;
+ Callback callbacks;
synchronized (mLock) {
if (!mAnimationScheduled) {
return; // no work to do
@@ -351,7 +374,23 @@ public final class Choreographer {
mLastAnimationTime = start;
callbacks = mAnimationCallbacks;
- mAnimationCallbacks = null;
+ if (callbacks != null) {
+ if (callbacks.dueTime > start) {
+ callbacks = null;
+ } else {
+ Callback predecessor = callbacks;
+ Callback successor = predecessor.next;
+ while (successor != null) {
+ if (successor.dueTime > start) {
+ predecessor.next = null;
+ break;
+ }
+ predecessor = successor;
+ successor = successor.next;
+ }
+ mAnimationCallbacks = successor;
+ }
+ }
}
if (callbacks != null) {
@@ -368,7 +407,7 @@ public final class Choreographer {
void doDraw() {
final long start;
- final Callback callbacks;
+ Callback callbacks;
synchronized (mLock) {
if (!mDrawScheduled) {
return; // no work to do
@@ -383,7 +422,23 @@ public final class Choreographer {
mLastDrawTime = start;
callbacks = mDrawCallbacks;
- mDrawCallbacks = null;
+ if (callbacks != null) {
+ if (callbacks.dueTime > start) {
+ callbacks = null;
+ } else {
+ Callback predecessor = callbacks;
+ Callback successor = predecessor.next;
+ while (successor != null) {
+ if (successor.dueTime > start) {
+ predecessor.next = null;
+ break;
+ }
+ predecessor = successor;
+ successor = successor.next;
+ }
+ mDrawCallbacks = successor;
+ }
+ }
}
if (callbacks != null) {
@@ -400,38 +455,66 @@ public final class Choreographer {
void doScheduleVsync() {
synchronized (mLock) {
- doScheduleVsyncLocked();
+ if (mAnimationScheduled) {
+ scheduleVsyncLocked();
+ }
}
}
- private void doScheduleVsyncLocked() {
- if (mAnimationScheduled) {
- mDisplayEventReceiver.scheduleVsync();
+ void doScheduleAnimation() {
+ synchronized (mLock) {
+ final long now = SystemClock.uptimeMillis();
+ if (mAnimationCallbacks != null && mAnimationCallbacks.dueTime <= now) {
+ scheduleAnimationLocked(now);
+ }
}
}
+ void doScheduleDraw() {
+ synchronized (mLock) {
+ final long now = SystemClock.uptimeMillis();
+ if (mDrawCallbacks != null && mDrawCallbacks.dueTime <= now) {
+ scheduleDrawLocked(now);
+ }
+ }
+ }
+
+ private void scheduleVsyncLocked() {
+ mDisplayEventReceiver.scheduleVsync();
+ }
+
private boolean isRunningOnLooperThreadLocked() {
return Looper.myLooper() == mLooper;
}
- private Callback addCallbackLocked(Callback head, Runnable runnable) {
- Callback callback = obtainCallbackLocked(runnable);
+ private Callback addCallbackLocked(Callback head,
+ long dueTime, Runnable action, Object token) {
+ Callback callback = obtainCallbackLocked(dueTime, action, token);
if (head == null) {
return callback;
}
- Callback tail = head;
- while (tail.next != null) {
- tail = tail.next;
+ Callback entry = head;
+ if (dueTime < entry.dueTime) {
+ callback.next = entry;
+ return callback;
+ }
+ while (entry.next != null) {
+ if (dueTime < entry.next.dueTime) {
+ callback.next = entry.next;
+ break;
+ }
+ entry = entry.next;
}
- tail.next = callback;
+ entry.next = callback;
return head;
}
- private Callback removeCallbacksLocked(Callback head, Runnable runnable) {
+ private Callback removeCallbacksLocked(Callback head, Runnable action, Object token) {
Callback predecessor = null;
for (Callback callback = head; callback != null;) {
final Callback next = callback.next;
- if (callback.runnable == runnable) {
+ if ((action == null || callback.action == action)
+ && (token == null || callback.token == token)) {
if (predecessor != null) {
predecessor.next = next;
} else {
@@ -448,7 +531,7 @@ public final class Choreographer {
private void runCallbacks(Callback head) {
while (head != null) {
- head.runnable.run();
+ head.action.run();
head = head.next;
}
}
@@ -461,7 +544,7 @@ public final class Choreographer {
}
}
- private Callback obtainCallbackLocked(Runnable runnable) {
+ private Callback obtainCallbackLocked(long dueTime, Runnable action, Object token) {
Callback callback = mCallbackPool;
if (callback == null) {
callback = new Callback();
@@ -469,12 +552,15 @@ public final class Choreographer {
mCallbackPool = callback.next;
callback.next = null;
}
- callback.runnable = runnable;
+ callback.dueTime = dueTime;
+ callback.action = action;
+ callback.token = token;
return callback;
}
private void recycleCallbackLocked(Callback callback) {
- callback.runnable = null;
+ callback.action = null;
+ callback.token = null;
callback.next = mCallbackPool;
mCallbackPool = callback;
}
@@ -496,11 +582,11 @@ public final class Choreographer {
case MSG_DO_SCHEDULE_VSYNC:
doScheduleVsync();
break;
- case MSG_POST_DELAYED_ANIMATION:
- postAnimationCallbackUnchecked((Runnable)msg.obj);
+ case MSG_DO_SCHEDULE_ANIMATION:
+ doScheduleAnimation();
break;
- case MSG_POST_DELAYED_DRAW:
- postDrawCallbackUnchecked((Runnable)msg.obj);
+ case MSG_DO_SCHEDULE_DRAW:
+ doScheduleDraw();
break;
}
}
@@ -519,6 +605,8 @@ public final class Choreographer {
private static final class Callback {
public Callback next;
- public Runnable runnable;
+ public long dueTime;
+ public Runnable action;
+ public Object token;
}
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index b38ca5b88061..a651362d82b6 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -8793,6 +8793,52 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
}
/**
+ * <p>Causes the Runnable to execute on the next animation time step.
+ * The runnable will be run on the user interface thread.</p>
+ *
+ * <p>This method can be invoked from outside of the UI thread
+ * only when this View is attached to a window.</p>
+ *
+ * @param action The Runnable that will be executed.
+ *
+ * @hide
+ */
+ public void postOnAnimation(Runnable action) {
+ final AttachInfo attachInfo = mAttachInfo;
+ if (attachInfo != null) {
+ attachInfo.mViewRootImpl.mChoreographer.postAnimationCallback(action, null);
+ } else {
+ // Assume that post will succeed later
+ ViewRootImpl.getRunQueue().post(action);
+ }
+ }
+
+ /**
+ * <p>Causes the Runnable to execute on the next animation time step,
+ * after the specified amount of time elapses.
+ * The runnable will be run on the user interface thread.</p>
+ *
+ * <p>This method can be invoked from outside of the UI thread
+ * only when this View is attached to a window.</p>
+ *
+ * @param action The Runnable that will be executed.
+ * @param delayMillis The delay (in milliseconds) until the Runnable
+ * will be executed.
+ *
+ * @hide
+ */
+ public void postOnAnimationDelayed(Runnable action, long delayMillis) {
+ final AttachInfo attachInfo = mAttachInfo;
+ if (attachInfo != null) {
+ attachInfo.mViewRootImpl.mChoreographer.postAnimationCallbackDelayed(
+ action, null, delayMillis);
+ } else {
+ // Assume that post will succeed later
+ ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
+ }
+ }
+
+ /**
* <p>Removes the specified Runnable from the message queue.</p>
*
* <p>This method can be invoked from outside of the UI thread
@@ -8809,6 +8855,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
attachInfo.mHandler.removeCallbacks(action);
+ attachInfo.mViewRootImpl.mChoreographer.removeAnimationCallbacks(action, null);
} else {
// Assume that post will succeed later
ViewRootImpl.getRunQueue().removeCallbacks(action);
@@ -11880,10 +11927,12 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
*/
public void scheduleDrawable(Drawable who, Runnable what, long when) {
if (verifyDrawable(who) && what != null) {
+ final long delay = when - SystemClock.uptimeMillis();
if (mAttachInfo != null) {
- mAttachInfo.mHandler.postAtTime(what, who, when);
+ mAttachInfo.mViewRootImpl.mChoreographer.postAnimationCallbackDelayed(
+ what, who, Choreographer.subtractFrameDelay(delay));
} else {
- ViewRootImpl.getRunQueue().postDelayed(what, when - SystemClock.uptimeMillis());
+ ViewRootImpl.getRunQueue().postDelayed(what, delay);
}
}
}
@@ -11897,7 +11946,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
public void unscheduleDrawable(Drawable who, Runnable what) {
if (verifyDrawable(who) && what != null) {
if (mAttachInfo != null) {
- mAttachInfo.mHandler.removeCallbacks(what, who);
+ mAttachInfo.mViewRootImpl.mChoreographer.removeAnimationCallbacks(what, who);
} else {
ViewRootImpl.getRunQueue().removeCallbacks(what);
}
@@ -11915,7 +11964,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
*/
public void unscheduleDrawable(Drawable who) {
if (mAttachInfo != null) {
- mAttachInfo.mHandler.removeCallbacksAndMessages(who);
+ mAttachInfo.mViewRootImpl.mChoreographer.removeAnimationCallbacks(null, who);
}
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 9cde153006c9..72365c795ec8 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -884,7 +884,7 @@ public final class ViewRootImpl implements ViewParent,
void scheduleFrame() {
if (!mFrameScheduled) {
mFrameScheduled = true;
- mChoreographer.postDrawCallback(mFrameRunnable);
+ mChoreographer.postDrawCallback(mFrameRunnable, null);
}
}
@@ -893,7 +893,7 @@ public final class ViewRootImpl implements ViewParent,
if (mFrameScheduled) {
mFrameScheduled = false;
- mChoreographer.removeDrawCallbacks(mFrameRunnable);
+ mChoreographer.removeDrawCallbacks(mFrameRunnable, null);
}
}
@@ -4051,7 +4051,7 @@ public final class ViewRootImpl implements ViewParent,
}
if (mPosted && mViews.isEmpty() && mViewRects.isEmpty()) {
- mChoreographer.removeAnimationCallbacks(this);
+ mChoreographer.removeAnimationCallbacks(this, null);
mPosted = false;
}
}
@@ -4092,7 +4092,7 @@ public final class ViewRootImpl implements ViewParent,
private void postIfNeededLocked() {
if (!mPosted) {
- mChoreographer.postAnimationCallback(this);
+ mChoreographer.postAnimationCallback(this, null);
mPosted = true;
}
}
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index 6540613e9609..aef8a34bd356 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -26,6 +26,7 @@ import android.database.DataSetObserver;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
@@ -202,6 +203,130 @@ public class Spinner extends AbsSpinner implements OnClickListener {
}
}
+ /**
+ * Set the background drawable for the spinner's popup window of choices.
+ * Only valid in {@link #MODE_DROPDOWN}; this method is a no-op in other modes.
+ *
+ * @param background Background drawable
+ *
+ * @attr ref android.R.styleable#Spinner_popupBackground
+ */
+ public void setPopupBackgroundDrawable(Drawable background) {
+ if (!(mPopup instanceof DropdownPopup)) {
+ Log.e(TAG, "setPopupBackgroundDrawable: incompatible spinner mode; ignoring...");
+ return;
+ }
+ ((DropdownPopup) mPopup).setBackgroundDrawable(background);
+ }
+
+ /**
+ * Set the background drawable for the spinner's popup window of choices.
+ * Only valid in {@link #MODE_DROPDOWN}; this method is a no-op in other modes.
+ *
+ * @param resId Resource ID of a background drawable
+ *
+ * @attr ref android.R.styleable#Spinner_popupBackground
+ */
+ public void setPopupBackgroundResource(int resId) {
+ setPopupBackgroundDrawable(getContext().getResources().getDrawable(resId));
+ }
+
+ /**
+ * Get the background drawable for the spinner's popup window of choices.
+ * Only valid in {@link #MODE_DROPDOWN}; other modes will return null.
+ *
+ * @return background Background drawable
+ *
+ * @attr ref android.R.styleable#Spinner_popupBackground
+ */
+ public Drawable getPopupBackground() {
+ return mPopup.getBackground();
+ }
+
+ /**
+ * Set a vertical offset in pixels for the spinner's popup window of choices.
+ * Only valid in {@link #MODE_DROPDOWN}; this method is a no-op in other modes.
+ *
+ * @param pixels Vertical offset in pixels
+ *
+ * @attr ref android.R.styleable#Spinner_dropDownVerticalOffset
+ */
+ public void setDropDownVerticalOffset(int pixels) {
+ mPopup.setVerticalOffset(pixels);
+ }
+
+ /**
+ * Get the configured vertical offset in pixels for the spinner's popup window of choices.
+ * Only valid in {@link #MODE_DROPDOWN}; other modes will return 0.
+ *
+ * @return Vertical offset in pixels
+ *
+ * @attr ref android.R.styleable#Spinner_dropDownVerticalOffset
+ */
+ public int getDropDownVerticalOffset() {
+ return mPopup.getVerticalOffset();
+ }
+
+ /**
+ * Set a horizontal offset in pixels for the spinner's popup window of choices.
+ * Only valid in {@link #MODE_DROPDOWN}; this method is a no-op in other modes.
+ *
+ * @param pixels Horizontal offset in pixels
+ *
+ * @attr ref android.R.styleable#Spinner_dropDownHorizontalOffset
+ */
+ public void setDropDownHorizontalOffset(int pixels) {
+ mPopup.setHorizontalOffset(pixels);
+ }
+
+ /**
+ * Get the configured horizontal offset in pixels for the spinner's popup window of choices.
+ * Only valid in {@link #MODE_DROPDOWN}; other modes will return 0.
+ *
+ * @return Horizontal offset in pixels
+ *
+ * @attr ref android.R.styleable#Spinner_dropDownHorizontalOffset
+ */
+ public int getDropDownHorizontalOffset() {
+ return mPopup.getHorizontalOffset();
+ }
+
+ /**
+ * Set the width of the spinner's popup window of choices in pixels. This value
+ * may also be set to {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT}
+ * to match the width of the Spinner itself, or
+ * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} to wrap to the measured size
+ * of contained dropdown list items.
+ *
+ * <p>Only valid in {@link #MODE_DROPDOWN}; this method is a no-op in other modes.</p>
+ *
+ * @param pixels Width in pixels, WRAP_CONTENT, or MATCH_PARENT
+ *
+ * @attr ref android.R.styleable#Spinner_dropDownWidth
+ */
+ public void setDropDownWidth(int pixels) {
+ if (!(mPopup instanceof DropdownPopup)) {
+ Log.e(TAG, "Cannot set dropdown width for MODE_DIALOG, ignoring");
+ return;
+ }
+ mDropDownWidth = pixels;
+ }
+
+ /**
+ * Get the configured width of the spinner's popup window of choices in pixels.
+ * The returned value may also be {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT}
+ * meaning the popup window will match the width of the Spinner itself, or
+ * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT} to wrap to the measured size
+ * of contained dropdown list items.
+ *
+ * @return Width in pixels, WRAP_CONTENT, or MATCH_PARENT
+ *
+ * @attr ref android.R.styleable#Spinner_dropDownWidth
+ */
+ public int getDropDownWidth() {
+ return mDropDownWidth;
+ }
+
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
@@ -231,6 +356,16 @@ public class Spinner extends AbsSpinner implements OnClickListener {
}
}
+ /**
+ * Describes how the selected item view is positioned. The default is determined by the
+ * current theme.
+ *
+ * @return A {@link android.view.Gravity Gravity} value
+ */
+ public int getGravity() {
+ return mGravity;
+ }
+
@Override
public void setAdapter(SpinnerAdapter adapter) {
super.setAdapter(adapter);
@@ -675,6 +810,13 @@ public class Spinner extends AbsSpinner implements OnClickListener {
*/
public void setPromptText(CharSequence hintText);
public CharSequence getHintText();
+
+ public void setBackgroundDrawable(Drawable bg);
+ public void setVerticalOffset(int px);
+ public void setHorizontalOffset(int px);
+ public Drawable getBackground();
+ public int getVerticalOffset();
+ public int getHorizontalOffset();
}
private class DialogPopup implements SpinnerPopup, DialogInterface.OnClickListener {
@@ -719,6 +861,36 @@ public class Spinner extends AbsSpinner implements OnClickListener {
}
dismiss();
}
+
+ @Override
+ public void setBackgroundDrawable(Drawable bg) {
+ Log.e(TAG, "Cannot set popup background for MODE_DIALOG, ignoring");
+ }
+
+ @Override
+ public void setVerticalOffset(int px) {
+ Log.e(TAG, "Cannot set vertical offset for MODE_DIALOG, ignoring");
+ }
+
+ @Override
+ public void setHorizontalOffset(int px) {
+ Log.e(TAG, "Cannot set horizontal offset for MODE_DIALOG, ignoring");
+ }
+
+ @Override
+ public Drawable getBackground() {
+ return null;
+ }
+
+ @Override
+ public int getVerticalOffset() {
+ return 0;
+ }
+
+ @Override
+ public int getHorizontalOffset() {
+ return 0;
+ }
}
private class DropdownPopup extends ListPopupWindow implements SpinnerPopup {
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index 334b9c450ef2..92ad88da6414 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -169,6 +169,8 @@ public class Switch extends CompoundButton {
/**
* Sets the switch text color, size, style, hint color, and highlight color
* from the specified TextAppearance resource.
+ *
+ * @attr ref android.R.styleable#Switch_switchTextAppearance
*/
public void setSwitchTextAppearance(Context context, int resid) {
TypedArray appearance =
@@ -274,7 +276,151 @@ public class Switch extends CompoundButton {
}
/**
+ * Set the amount of horizontal padding between the switch and the associated text.
+ *
+ * @param pixels Amount of padding in pixels
+ *
+ * @attr ref android.R.styleable#Switch_switchPadding
+ */
+ public void setSwitchPadding(int pixels) {
+ mSwitchPadding = pixels;
+ requestLayout();
+ }
+
+ /**
+ * Get the amount of horizontal padding between the switch and the associated text.
+ *
+ * @return Amount of padding in pixels
+ *
+ * @attr ref android.R.styleable#Switch_switchPadding
+ */
+ public int getSwitchPadding() {
+ return mSwitchPadding;
+ }
+
+ /**
+ * Set the minimum width of the switch in pixels. The switch's width will be the maximum
+ * of this value and its measured width as determined by the switch drawables and text used.
+ *
+ * @param pixels Minimum width of the switch in pixels
+ *
+ * @attr ref android.R.styleable#Switch_switchMinWidth
+ */
+ public void setSwitchMinWidth(int pixels) {
+ mSwitchMinWidth = pixels;
+ requestLayout();
+ }
+
+ /**
+ * Get the minimum width of the switch in pixels. The switch's width will be the maximum
+ * of this value and its measured width as determined by the switch drawables and text used.
+ *
+ * @return Minimum width of the switch in pixels
+ *
+ * @attr ref android.R.styleable#Switch_switchMinWidth
+ */
+ public int getSwitchMinWidth() {
+ return mSwitchMinWidth;
+ }
+
+ /**
+ * Set the horizontal padding around the text drawn on the switch itself.
+ *
+ * @param pixels Horizontal padding for switch thumb text in pixels
+ *
+ * @attr ref android.R.styleable#Switch_thumbTextPadding
+ */
+ public void setThumbTextPadding(int pixels) {
+ mThumbTextPadding = pixels;
+ requestLayout();
+ }
+
+ /**
+ * Get the horizontal padding around the text drawn on the switch itself.
+ *
+ * @return Horizontal padding for switch thumb text in pixels
+ *
+ * @attr ref android.R.styleable#Switch_thumbTextPadding
+ */
+ public int getThumbTextPadding() {
+ return mThumbTextPadding;
+ }
+
+ /**
+ * Set the drawable used for the track that the switch slides within.
+ *
+ * @param track Track drawable
+ *
+ * @attr ref android.R.styleable#Switch_track
+ */
+ public void setTrackDrawable(Drawable track) {
+ mTrackDrawable = track;
+ requestLayout();
+ }
+
+ /**
+ * Set the drawable used for the track that the switch slides within.
+ *
+ * @param resId Resource ID of a track drawable
+ *
+ * @attr ref android.R.styleable#Switch_track
+ */
+ public void setTrackResource(int resId) {
+ setTrackDrawable(getContext().getResources().getDrawable(resId));
+ }
+
+ /**
+ * Get the drawable used for the track that the switch slides within.
+ *
+ * @return Track drawable
+ *
+ * @attr ref android.R.styleable#Switch_track
+ */
+ public Drawable getTrackDrawable() {
+ return mTrackDrawable;
+ }
+
+ /**
+ * Set the drawable used for the switch "thumb" - the piece that the user
+ * can physically touch and drag along the track.
+ *
+ * @param thumb Thumb drawable
+ *
+ * @attr ref android.R.styleable#Switch_thumb
+ */
+ public void setThumbDrawable(Drawable thumb) {
+ mThumbDrawable = thumb;
+ requestLayout();
+ }
+
+ /**
+ * Set the drawable used for the switch "thumb" - the piece that the user
+ * can physically touch and drag along the track.
+ *
+ * @param resId Resource ID of a thumb drawable
+ *
+ * @attr ref android.R.styleable#Switch_thumb
+ */
+ public void setThumbResource(int resId) {
+ setThumbDrawable(getContext().getResources().getDrawable(resId));
+ }
+
+ /**
+ * Get the drawable used for the switch "thumb" - the piece that the user
+ * can physically touch and drag along the track.
+ *
+ * @return Thumb drawable
+ *
+ * @attr ref android.R.styleable#Switch_thumb
+ */
+ public Drawable getThumbDrawable() {
+ return mThumbDrawable;
+ }
+
+ /**
* Returns the text displayed when the button is in the checked state.
+ *
+ * @attr ref android.R.styleable#Switch_textOn
*/
public CharSequence getTextOn() {
return mTextOn;
@@ -282,6 +428,8 @@ public class Switch extends CompoundButton {
/**
* Sets the text displayed when the button is in the checked state.
+ *
+ * @attr ref android.R.styleable#Switch_textOn
*/
public void setTextOn(CharSequence textOn) {
mTextOn = textOn;
@@ -290,6 +438,8 @@ public class Switch extends CompoundButton {
/**
* Returns the text displayed when the button is not in the checked state.
+ *
+ * @attr ref android.R.styleable#Switch_textOff
*/
public CharSequence getTextOff() {
return mTextOff;
@@ -297,6 +447,8 @@ public class Switch extends CompoundButton {
/**
* Sets the text displayed when the button is not in the checked state.
+ *
+ * @attr ref android.R.styleable#Switch_textOff
*/
public void setTextOff(CharSequence textOff) {
mTextOff = textOff;
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 6a99a2bb3473..998c037fc23a 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -348,6 +348,7 @@ public class ZygoteInit {
TypedArray ar = mResources.obtainTypedArray(
com.android.internal.R.array.preloaded_drawables);
int N = preloadDrawables(runtime, ar);
+ ar.recycle();
Log.i(TAG, "...preloaded " + N + " resources in "
+ (SystemClock.uptimeMillis()-startTime) + "ms.");
@@ -355,6 +356,7 @@ public class ZygoteInit {
ar = mResources.obtainTypedArray(
com.android.internal.R.array.preloaded_color_state_lists);
N = preloadColorStateLists(runtime, ar);
+ ar.recycle();
Log.i(TAG, "...preloaded " + N + " resources in "
+ (SystemClock.uptimeMillis()-startTime) + "ms.");
}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index c389cf7179cb..642988be8840 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -64,6 +64,7 @@ LOCAL_SRC_FILES:= \
android_os_MemoryFile.cpp \
android_os_MessageQueue.cpp \
android_os_ParcelFileDescriptor.cpp \
+ android_os_Parcel.cpp \
android_os_Power.cpp \
android_os_StatFs.cpp \
android_os_SystemClock.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 3067e75d71f1..de9fd33d053b 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -130,6 +130,7 @@ extern int register_android_nio_utils(JNIEnv* env);
extern int register_android_text_format_Time(JNIEnv* env);
extern int register_android_os_Debug(JNIEnv* env);
extern int register_android_os_MessageQueue(JNIEnv* env);
+extern int register_android_os_Parcel(JNIEnv* env);
extern int register_android_os_ParcelFileDescriptor(JNIEnv *env);
extern int register_android_os_Power(JNIEnv *env);
extern int register_android_os_StatFs(JNIEnv *env);
@@ -1094,6 +1095,7 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_os_Process),
REG_JNI(register_android_os_SystemProperties),
REG_JNI(register_android_os_Binder),
+ REG_JNI(register_android_os_Parcel),
REG_JNI(register_android_view_Display),
REG_JNI(register_android_view_DisplayEventReceiver),
REG_JNI(register_android_nio_utils),
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index d1d3b787c335..5e73a5fc1ea6 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -7,6 +7,7 @@
#include "SkUnPreMultiply.h"
#include <binder/Parcel.h>
+#include "android_os_Parcel.h"
#include "android_util_Binder.h"
#include "android_nio_utils.h"
#include "CreateJavaOutputStreamAdaptor.h"
diff --git a/core/jni/android/graphics/Region.cpp b/core/jni/android/graphics/Region.cpp
index 5c6ebdf0b9c4..866d223c40b8 100644
--- a/core/jni/android/graphics/Region.cpp
+++ b/core/jni/android/graphics/Region.cpp
@@ -19,6 +19,7 @@
#include "GraphicsJNI.h"
#include <binder/Parcel.h>
+#include "android_os_Parcel.h"
#include "android_util_Binder.h"
#include <jni.h>
diff --git a/core/jni/android_database_CursorWindow.cpp b/core/jni/android_database_CursorWindow.cpp
index 579d6ad858ab..ea02f537c0e7 100644
--- a/core/jni/android_database_CursorWindow.cpp
+++ b/core/jni/android_database_CursorWindow.cpp
@@ -31,6 +31,7 @@
#include <unistd.h>
#include <androidfw/CursorWindow.h>
+#include "android_os_Parcel.h"
#include "android_util_Binder.h"
#include "android_database_SQLiteCommon.h"
diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp
new file mode 100644
index 000000000000..3dfaac39dec4
--- /dev/null
+++ b/core/jni/android_os_Parcel.cpp
@@ -0,0 +1,676 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Parcel"
+//#define LOG_NDEBUG 0
+
+#include "android_os_Parcel.h"
+#include "android_util_Binder.h"
+
+#include "JNIHelp.h"
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <utils/Atomic.h>
+#include <binder/IInterface.h>
+#include <binder/IPCThreadState.h>
+#include <utils/Log.h>
+#include <utils/SystemClock.h>
+#include <utils/List.h>
+#include <utils/KeyedVector.h>
+#include <cutils/logger.h>
+#include <binder/Parcel.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
+#include <utils/threads.h>
+#include <utils/String8.h>
+
+#include <ScopedUtfChars.h>
+#include <ScopedLocalRef.h>
+
+#include <android_runtime/AndroidRuntime.h>
+
+//#undef ALOGV
+//#define ALOGV(...) fprintf(stderr, __VA_ARGS__)
+
+#define DEBUG_DEATH 0
+#if DEBUG_DEATH
+#define LOGDEATH ALOGD
+#else
+#define LOGDEATH ALOGV
+#endif
+
+namespace android {
+
+static struct parcel_offsets_t
+{
+ jfieldID mNativePtr;
+} gParcelOffsets;
+
+Parcel* parcelForJavaObject(JNIEnv* env, jobject obj)
+{
+ if (obj) {
+ Parcel* p = (Parcel*)env->GetIntField(obj, gParcelOffsets.mNativePtr);
+ if (p != NULL) {
+ return p;
+ }
+ jniThrowException(env, "java/lang/IllegalStateException", "Parcel has been finalized!");
+ }
+ return NULL;
+}
+
+static jint android_os_Parcel_dataSize(JNIEnv* env, jclass clazz, jint nativePtr)
+{
+ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+ return parcel ? parcel->dataSize() : 0;
+}
+
+static jint android_os_Parcel_dataAvail(JNIEnv* env, jclass clazz, jint nativePtr)
+{
+ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+ return parcel ? parcel->dataAvail() : 0;
+}
+
+static jint android_os_Parcel_dataPosition(JNIEnv* env, jclass clazz, jint nativePtr)
+{
+ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+ return parcel ? parcel->dataPosition() : 0;
+}
+
+static jint android_os_Parcel_dataCapacity(JNIEnv* env, jclass clazz, jint nativePtr)
+{
+ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+ return parcel ? parcel->dataCapacity() : 0;
+}
+
+static void android_os_Parcel_setDataSize(JNIEnv* env, jclass clazz, jint nativePtr, jint size)
+{
+ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+ if (parcel != NULL) {
+ const status_t err = parcel->setDataSize(size);
+ if (err != NO_ERROR) {
+ signalExceptionForError(env, clazz, err);
+ }
+ }
+}
+
+static void android_os_Parcel_setDataPosition(JNIEnv* env, jclass clazz, jint nativePtr, jint pos)
+{
+ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+ if (parcel != NULL) {
+ parcel->setDataPosition(pos);
+ }
+}
+
+static void android_os_Parcel_setDataCapacity(JNIEnv* env, jclass clazz, jint nativePtr, jint size)
+{
+ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+ if (parcel != NULL) {
+ const status_t err = parcel->setDataCapacity(size);
+ if (err != NO_ERROR) {
+ signalExceptionForError(env, clazz, err);
+ }
+ }
+}
+
+static jboolean android_os_Parcel_pushAllowFds(JNIEnv* env, jclass clazz, jint nativePtr, jboolean allowFds)
+{
+ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+ jboolean ret = JNI_TRUE;
+ if (parcel != NULL) {
+ ret = (jboolean)parcel->pushAllowFds(allowFds);
+ }
+ return ret;
+}
+
+static void android_os_Parcel_restoreAllowFds(JNIEnv* env, jclass clazz, jint nativePtr, jboolean lastValue)
+{
+ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+ if (parcel != NULL) {
+ parcel->restoreAllowFds((bool)lastValue);
+ }
+}
+
+static void android_os_Parcel_writeNative(JNIEnv* env, jclass clazz, jint nativePtr, jobject data,
+ jint offset, jint length)
+{
+ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+ if (parcel == NULL) {
+ return;
+ }
+
+ const status_t err = parcel->writeInt32(length);
+ if (err != NO_ERROR) {
+ signalExceptionForError(env, clazz, err);
+ return;
+ }
+
+ void* dest = parcel->writeInplace(length);
+ if (dest == NULL) {
+ signalExceptionForError(env, clazz, NO_MEMORY);
+ return;
+ }
+
+ jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)data, 0);
+ if (ar) {
+ memcpy(dest, ar + offset, length);
+ env->ReleasePrimitiveArrayCritical((jarray)data, ar, 0);
+ }
+}
+
+static void android_os_Parcel_writeInt(JNIEnv* env, jclass clazz, jint nativePtr, jint val) {
+ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+ const status_t err = parcel->writeInt32(val);
+ if (err != NO_ERROR) {
+ signalExceptionForError(env, clazz, err);
+ }
+}
+
+static void android_os_Parcel_writeLong(JNIEnv* env, jclass clazz, jint nativePtr, jlong val)
+{
+ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+ if (parcel != NULL) {
+ const status_t err = parcel->writeInt64(val);
+ if (err != NO_ERROR) {
+ signalExceptionForError(env, clazz, err);
+ }
+ }
+}
+
+static void android_os_Parcel_writeFloat(JNIEnv* env, jclass clazz, jint nativePtr, jfloat val)
+{
+ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+ if (parcel != NULL) {
+ const status_t err = parcel->writeFloat(val);
+ if (err != NO_ERROR) {
+ signalExceptionForError(env, clazz, err);
+ }
+ }
+}
+
+static void android_os_Parcel_writeDouble(JNIEnv* env, jclass clazz, jint nativePtr, jdouble val)
+{
+ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+ if (parcel != NULL) {
+ const status_t err = parcel->writeDouble(val);
+ if (err != NO_ERROR) {
+ signalExceptionForError(env, clazz, err);
+ }
+ }
+}
+
+static void android_os_Parcel_writeString(JNIEnv* env, jclass clazz, jint nativePtr, jstring val)
+{
+ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+ if (parcel != NULL) {
+ status_t err = NO_MEMORY;
+ if (val) {
+ const jchar* str = env->GetStringCritical(val, 0);
+ if (str) {
+ err = parcel->writeString16(str, env->GetStringLength(val));
+ env->ReleaseStringCritical(val, str);
+ }
+ } else {
+ err = parcel->writeString16(NULL, 0);
+ }
+ if (err != NO_ERROR) {
+ signalExceptionForError(env, clazz, err);
+ }
+ }
+}
+
+static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jint nativePtr, jobject object)
+{
+ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+ if (parcel != NULL) {
+ const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
+ if (err != NO_ERROR) {
+ signalExceptionForError(env, clazz, err);
+ }
+ }
+}
+
+static void android_os_Parcel_writeFileDescriptor(JNIEnv* env, jclass clazz, jint nativePtr, jobject object)
+{
+ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+ if (parcel != NULL) {
+ const status_t err =
+ parcel->writeDupFileDescriptor(jniGetFDFromFileDescriptor(env, object));
+ if (err != NO_ERROR) {
+ signalExceptionForError(env, clazz, err);
+ }
+ }
+}
+
+static jbyteArray android_os_Parcel_createByteArray(JNIEnv* env, jclass clazz, jint nativePtr)
+{
+ jbyteArray ret = NULL;
+
+ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+ if (parcel != NULL) {
+ int32_t len = parcel->readInt32();
+
+ // sanity check the stored length against the true data size
+ if (len >= 0 && len <= (int32_t)parcel->dataAvail()) {
+ ret = env->NewByteArray(len);
+
+ if (ret != NULL) {
+ jbyte* a2 = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
+ if (a2) {
+ const void* data = parcel->readInplace(len);
+ memcpy(a2, data, len);
+ env->ReleasePrimitiveArrayCritical(ret, a2, 0);
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+static jint android_os_Parcel_readInt(JNIEnv* env, jclass clazz, jint nativePtr)
+{
+ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+ if (parcel != NULL) {
+ return parcel->readInt32();
+ }
+ return 0;
+}
+
+static jlong android_os_Parcel_readLong(JNIEnv* env, jclass clazz, jint nativePtr)
+{
+ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+ if (parcel != NULL) {
+ return parcel->readInt64();
+ }
+ return 0;
+}
+
+static jfloat android_os_Parcel_readFloat(JNIEnv* env, jclass clazz, jint nativePtr)
+{
+ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+ if (parcel != NULL) {
+ return parcel->readFloat();
+ }
+ return 0;
+}
+
+static jdouble android_os_Parcel_readDouble(JNIEnv* env, jclass clazz, jint nativePtr)
+{
+ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+ if (parcel != NULL) {
+ return parcel->readDouble();
+ }
+ return 0;
+}
+
+static jstring android_os_Parcel_readString(JNIEnv* env, jclass clazz, jint nativePtr)
+{
+ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+ if (parcel != NULL) {
+ size_t len;
+ const char16_t* str = parcel->readString16Inplace(&len);
+ if (str) {
+ return env->NewString(str, len);
+ }
+ return NULL;
+ }
+ return NULL;
+}
+
+static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jint nativePtr)
+{
+ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+ if (parcel != NULL) {
+ return javaObjectForIBinder(env, parcel->readStrongBinder());
+ }
+ return NULL;
+}
+
+static jobject android_os_Parcel_readFileDescriptor(JNIEnv* env, jclass clazz, jint nativePtr)
+{
+ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+ if (parcel != NULL) {
+ int fd = parcel->readFileDescriptor();
+ if (fd < 0) return NULL;
+ fd = dup(fd);
+ if (fd < 0) return NULL;
+ return jniCreateFileDescriptor(env, fd);
+ }
+ return NULL;
+}
+
+static jobject android_os_Parcel_openFileDescriptor(JNIEnv* env, jclass clazz,
+ jstring name, jint mode)
+{
+ if (name == NULL) {
+ jniThrowNullPointerException(env, NULL);
+ return NULL;
+ }
+ const jchar* str = env->GetStringCritical(name, 0);
+ if (str == NULL) {
+ // Whatever, whatever.
+ jniThrowException(env, "java/lang/IllegalStateException", NULL);
+ return NULL;
+ }
+ String8 name8(str, env->GetStringLength(name));
+ env->ReleaseStringCritical(name, str);
+ int flags=0;
+ switch (mode&0x30000000) {
+ case 0:
+ case 0x10000000:
+ flags = O_RDONLY;
+ break;
+ case 0x20000000:
+ flags = O_WRONLY;
+ break;
+ case 0x30000000:
+ flags = O_RDWR;
+ break;
+ }
+
+ if (mode&0x08000000) flags |= O_CREAT;
+ if (mode&0x04000000) flags |= O_TRUNC;
+ if (mode&0x02000000) flags |= O_APPEND;
+
+ int realMode = S_IRWXU|S_IRWXG;
+ if (mode&0x00000001) realMode |= S_IROTH;
+ if (mode&0x00000002) realMode |= S_IWOTH;
+
+ int fd = open(name8.string(), flags, realMode);
+ if (fd < 0) {
+ jniThrowException(env, "java/io/FileNotFoundException", strerror(errno));
+ return NULL;
+ }
+ jobject object = jniCreateFileDescriptor(env, fd);
+ if (object == NULL) {
+ close(fd);
+ }
+ return object;
+}
+
+static jobject android_os_Parcel_dupFileDescriptor(JNIEnv* env, jclass clazz, jobject orig)
+{
+ if (orig == NULL) {
+ jniThrowNullPointerException(env, NULL);
+ return NULL;
+ }
+ int origfd = jniGetFDFromFileDescriptor(env, orig);
+ if (origfd < 0) {
+ jniThrowException(env, "java/lang/IllegalArgumentException", "bad FileDescriptor");
+ return NULL;
+ }
+
+ int fd = dup(origfd);
+ if (fd < 0) {
+ jniThrowIOException(env, errno);
+ return NULL;
+ }
+ jobject object = jniCreateFileDescriptor(env, fd);
+ if (object == NULL) {
+ close(fd);
+ }
+ return object;
+}
+
+static void android_os_Parcel_closeFileDescriptor(JNIEnv* env, jclass clazz, jobject object)
+{
+ if (object == NULL) {
+ jniThrowNullPointerException(env, NULL);
+ return;
+ }
+ int fd = jniGetFDFromFileDescriptor(env, object);
+ if (fd >= 0) {
+ jniSetFileDescriptorOfFD(env, object, -1);
+ //ALOGI("Closing ParcelFileDescriptor %d\n", fd);
+ close(fd);
+ }
+}
+
+static void android_os_Parcel_clearFileDescriptor(JNIEnv* env, jclass clazz, jobject object)
+{
+ if (object == NULL) {
+ jniThrowNullPointerException(env, NULL);
+ return;
+ }
+ int fd = jniGetFDFromFileDescriptor(env, object);
+ if (fd >= 0) {
+ jniSetFileDescriptorOfFD(env, object, -1);
+ }
+}
+
+static jint android_os_Parcel_create(JNIEnv* env, jclass clazz)
+{
+ Parcel* parcel = new Parcel();
+ return reinterpret_cast<jint>(parcel);
+}
+
+static void android_os_Parcel_freeBuffer(JNIEnv* env, jclass clazz, jint nativePtr)
+{
+ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+ if (parcel != NULL) {
+ parcel->freeData();
+ }
+}
+
+static void android_os_Parcel_destroy(JNIEnv* env, jclass clazz, jint nativePtr)
+{
+ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+ delete parcel;
+}
+
+static jbyteArray android_os_Parcel_marshall(JNIEnv* env, jclass clazz, jint nativePtr)
+{
+ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+ if (parcel == NULL) {
+ return NULL;
+ }
+
+ // do not marshall if there are binder objects in the parcel
+ if (parcel->objectsCount())
+ {
+ jniThrowException(env, "java/lang/RuntimeException", "Tried to marshall a Parcel that contained Binder objects.");
+ return NULL;
+ }
+
+ jbyteArray ret = env->NewByteArray(parcel->dataSize());
+
+ if (ret != NULL)
+ {
+ jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
+ if (array != NULL)
+ {
+ memcpy(array, parcel->data(), parcel->dataSize());
+ env->ReleasePrimitiveArrayCritical(ret, array, 0);
+ }
+ }
+
+ return ret;
+}
+
+static void android_os_Parcel_unmarshall(JNIEnv* env, jclass clazz, jint nativePtr,
+ jbyteArray data, jint offset, jint length)
+{
+ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+ if (parcel == NULL || length < 0) {
+ return;
+ }
+
+ jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(data, 0);
+ if (array)
+ {
+ parcel->setDataSize(length);
+ parcel->setDataPosition(0);
+
+ void* raw = parcel->writeInplace(length);
+ memcpy(raw, (array + offset), length);
+
+ env->ReleasePrimitiveArrayCritical(data, array, 0);
+ }
+}
+
+static void android_os_Parcel_appendFrom(JNIEnv* env, jclass clazz, jint thisNativePtr,
+ jint otherNativePtr, jint offset, jint length)
+{
+ Parcel* thisParcel = reinterpret_cast<Parcel*>(thisNativePtr);
+ if (thisParcel == NULL) {
+ return;
+ }
+ Parcel* otherParcel = reinterpret_cast<Parcel*>(otherNativePtr);
+ if (otherParcel == NULL) {
+ return;
+ }
+
+ status_t err = thisParcel->appendFrom(otherParcel, offset, length);
+ if (err != NO_ERROR) {
+ signalExceptionForError(env, clazz, err);
+ }
+}
+
+static jboolean android_os_Parcel_hasFileDescriptors(JNIEnv* env, jclass clazz, jint nativePtr)
+{
+ jboolean ret = JNI_FALSE;
+ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+ if (parcel != NULL) {
+ if (parcel->hasFileDescriptors()) {
+ ret = JNI_TRUE;
+ }
+ }
+ return ret;
+}
+
+static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jclass clazz, jint nativePtr,
+ jstring name)
+{
+ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+ if (parcel != NULL) {
+ // In the current implementation, the token is just the serialized interface name that
+ // the caller expects to be invoking
+ const jchar* str = env->GetStringCritical(name, 0);
+ if (str != NULL) {
+ parcel->writeInterfaceToken(String16(str, env->GetStringLength(name)));
+ env->ReleaseStringCritical(name, str);
+ }
+ }
+}
+
+static void android_os_Parcel_enforceInterface(JNIEnv* env, jclass clazz, jint nativePtr, jstring name)
+{
+ jboolean ret = JNI_FALSE;
+
+ Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
+ if (parcel != NULL) {
+ const jchar* str = env->GetStringCritical(name, 0);
+ if (str) {
+ IPCThreadState* threadState = IPCThreadState::self();
+ const int32_t oldPolicy = threadState->getStrictModePolicy();
+ const bool isValid = parcel->enforceInterface(
+ String16(str, env->GetStringLength(name)),
+ threadState);
+ env->ReleaseStringCritical(name, str);
+ if (isValid) {
+ const int32_t newPolicy = threadState->getStrictModePolicy();
+ if (oldPolicy != newPolicy) {
+ // Need to keep the Java-level thread-local strict
+ // mode policy in sync for the libcore
+ // enforcements, which involves an upcall back
+ // into Java. (We can't modify the
+ // Parcel.enforceInterface signature, as it's
+ // pseudo-public, and used via AIDL
+ // auto-generation...)
+ set_dalvik_blockguard_policy(env, newPolicy);
+ }
+ return; // everything was correct -> return silently
+ }
+ }
+ }
+
+ // all error conditions wind up here
+ jniThrowException(env, "java/lang/SecurityException",
+ "Binder invocation to an incorrect interface");
+}
+
+// ----------------------------------------------------------------------------
+
+static const JNINativeMethod gParcelMethods[] = {
+ {"nativeDataSize", "(I)I", (void*)android_os_Parcel_dataSize},
+ {"nativeDataAvail", "(I)I", (void*)android_os_Parcel_dataAvail},
+ {"nativeDataPosition", "(I)I", (void*)android_os_Parcel_dataPosition},
+ {"nativeDataCapacity", "(I)I", (void*)android_os_Parcel_dataCapacity},
+ {"nativeSetDataSize", "(II)V", (void*)android_os_Parcel_setDataSize},
+ {"nativeSetDataPosition", "(II)V", (void*)android_os_Parcel_setDataPosition},
+ {"nativeSetDataCapacity", "(II)V", (void*)android_os_Parcel_setDataCapacity},
+
+ {"nativePushAllowFds", "(IZ)Z", (void*)android_os_Parcel_pushAllowFds},
+ {"nativeRestoreAllowFds", "(IZ)V", (void*)android_os_Parcel_restoreAllowFds},
+
+ {"nativeWriteByteArray", "(I[BII)V", (void*)android_os_Parcel_writeNative},
+ {"nativeWriteInt", "(II)V", (void*)android_os_Parcel_writeInt},
+ {"nativeWriteLong", "(IJ)V", (void*)android_os_Parcel_writeLong},
+ {"nativeWriteFloat", "(IF)V", (void*)android_os_Parcel_writeFloat},
+ {"nativeWriteDouble", "(ID)V", (void*)android_os_Parcel_writeDouble},
+ {"nativeWriteString", "(ILjava/lang/String;)V", (void*)android_os_Parcel_writeString},
+ {"nativeWriteStrongBinder", "(ILandroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder},
+ {"nativeWriteFileDescriptor", "(ILjava/io/FileDescriptor;)V", (void*)android_os_Parcel_writeFileDescriptor},
+
+ {"nativeCreateByteArray", "(I)[B", (void*)android_os_Parcel_createByteArray},
+ {"nativeReadInt", "(I)I", (void*)android_os_Parcel_readInt},
+ {"nativeReadLong", "(I)J", (void*)android_os_Parcel_readLong},
+ {"nativeReadFloat", "(I)F", (void*)android_os_Parcel_readFloat},
+ {"nativeReadDouble", "(I)D", (void*)android_os_Parcel_readDouble},
+ {"nativeReadString", "(I)Ljava/lang/String;", (void*)android_os_Parcel_readString},
+ {"nativeReadStrongBinder", "(I)Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder},
+ {"nativeReadFileDescriptor", "(I)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_readFileDescriptor},
+
+ {"openFileDescriptor", "(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_openFileDescriptor},
+ {"dupFileDescriptor", "(Ljava/io/FileDescriptor;)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_dupFileDescriptor},
+ {"closeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_closeFileDescriptor},
+ {"clearFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_clearFileDescriptor},
+
+ {"nativeCreate", "()I", (void*)android_os_Parcel_create},
+ {"nativeFreeBuffer", "(I)V", (void*)android_os_Parcel_freeBuffer},
+ {"nativeDestroy", "(I)V", (void*)android_os_Parcel_destroy},
+
+ {"nativeMarshall", "(I)[B", (void*)android_os_Parcel_marshall},
+ {"nativeUnmarshall", "(I[BII)V", (void*)android_os_Parcel_unmarshall},
+ {"nativeAppendFrom", "(IIII)V", (void*)android_os_Parcel_appendFrom},
+ {"nativeHasFileDescriptors", "(I)Z", (void*)android_os_Parcel_hasFileDescriptors},
+ {"nativeWriteInterfaceToken", "(ILjava/lang/String;)V", (void*)android_os_Parcel_writeInterfaceToken},
+ {"nativeEnforceInterface", "(ILjava/lang/String;)V", (void*)android_os_Parcel_enforceInterface},
+};
+
+const char* const kParcelPathName = "android/os/Parcel";
+
+int register_android_os_Parcel(JNIEnv* env)
+{
+ jclass clazz;
+
+ clazz = env->FindClass(kParcelPathName);
+ LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Parcel");
+
+ gParcelOffsets.mNativePtr
+ = env->GetFieldID(clazz, "mNativePtr", "I");
+
+ return AndroidRuntime::registerNativeMethods(
+ env, kParcelPathName,
+ gParcelMethods, NELEM(gParcelMethods));
+}
+
+};
diff --git a/core/jni/android_os_Parcel.h b/core/jni/android_os_Parcel.h
new file mode 100644
index 000000000000..65f3819ef867
--- /dev/null
+++ b/core/jni/android_os_Parcel.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#include <binder/IBinder.h>
+
+#include "jni.h"
+
+namespace android {
+
+// Conversion from Java Parcel Object to C++ Parcel instance.
+// Note: does not type checking; must guarantee jobject is a Java Parcel
+extern Parcel* parcelForJavaObject(JNIEnv* env, jobject obj);
+
+}
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index e00970a2dbde..0f99fb2af86d 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -17,7 +17,9 @@
#define LOG_TAG "JavaBinder"
//#define LOG_NDEBUG 0
+#include "android_os_Parcel.h"
#include "android_util_Binder.h"
+
#include "JNIHelp.h"
#include <fcntl.h>
@@ -127,12 +129,6 @@ static struct class_offsets_t
// ----------------------------------------------------------------------------
-static struct parcel_offsets_t
-{
- jfieldID mObject;
- jfieldID mOwnObject;
-} gParcelOffsets;
-
static struct log_offsets_t
{
// Class state.
@@ -232,15 +228,6 @@ bail:
env->DeleteLocalRef(msgstr);
}
-static void set_dalvik_blockguard_policy(JNIEnv* env, jint strict_policy)
-{
- // Call back into android.os.StrictMode#onBinderStrictModePolicyChange
- // to sync our state back to it. See the comments in StrictMode.java.
- env->CallStaticVoidMethod(gStrictModeCallbackOffsets.mClass,
- gStrictModeCallbackOffsets.mCallback,
- strict_policy);
-}
-
class JavaBBinderHolder;
class JavaBBinder : public BBinder
@@ -634,26 +621,23 @@ sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
return NULL;
}
-Parcel* parcelForJavaObject(JNIEnv* env, jobject obj)
-{
- if (obj) {
- Parcel* p = (Parcel*)env->GetIntField(obj, gParcelOffsets.mObject);
- if (p != NULL) {
- return p;
- }
- jniThrowException(env, "java/lang/IllegalStateException", "Parcel has been finalized!");
- }
- return NULL;
-}
-
jobject newParcelFileDescriptor(JNIEnv* env, jobject fileDesc)
{
return env->NewObject(
gParcelFileDescriptorOffsets.mClass, gParcelFileDescriptorOffsets.mConstructor, fileDesc);
}
-static void signalExceptionForError(JNIEnv* env, jobject obj, status_t err,
- bool canThrowRemoteException = false)
+void set_dalvik_blockguard_policy(JNIEnv* env, jint strict_policy)
+{
+ // Call back into android.os.StrictMode#onBinderStrictModePolicyChange
+ // to sync our state back to it. See the comments in StrictMode.java.
+ env->CallStaticVoidMethod(gStrictModeCallbackOffsets.mClass,
+ gStrictModeCallbackOffsets.mCallback,
+ strict_policy);
+}
+
+void signalExceptionForError(JNIEnv* env, jobject obj, status_t err,
+ bool canThrowRemoteException)
{
switch (err) {
case UNKNOWN_ERROR:
@@ -1273,612 +1257,15 @@ static int int_register_android_os_BinderProxy(JNIEnv* env)
// ****************************************************************************
// ****************************************************************************
-static jint android_os_Parcel_dataSize(JNIEnv* env, jobject clazz)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- return parcel ? parcel->dataSize() : 0;
-}
-
-static jint android_os_Parcel_dataAvail(JNIEnv* env, jobject clazz)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- return parcel ? parcel->dataAvail() : 0;
-}
-
-static jint android_os_Parcel_dataPosition(JNIEnv* env, jobject clazz)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- return parcel ? parcel->dataPosition() : 0;
-}
-
-static jint android_os_Parcel_dataCapacity(JNIEnv* env, jobject clazz)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- return parcel ? parcel->dataCapacity() : 0;
-}
-
-static void android_os_Parcel_setDataSize(JNIEnv* env, jobject clazz, jint size)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- const status_t err = parcel->setDataSize(size);
- if (err != NO_ERROR) {
- signalExceptionForError(env, clazz, err);
- }
- }
-}
-
-static void android_os_Parcel_setDataPosition(JNIEnv* env, jobject clazz, jint pos)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- parcel->setDataPosition(pos);
- }
-}
-
-static void android_os_Parcel_setDataCapacity(JNIEnv* env, jobject clazz, jint size)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- const status_t err = parcel->setDataCapacity(size);
- if (err != NO_ERROR) {
- signalExceptionForError(env, clazz, err);
- }
- }
-}
-
-static jboolean android_os_Parcel_pushAllowFds(JNIEnv* env, jobject clazz, jboolean allowFds)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- jboolean ret = JNI_TRUE;
- if (parcel != NULL) {
- ret = (jboolean)parcel->pushAllowFds(allowFds);
- }
- return ret;
-}
-
-static void android_os_Parcel_restoreAllowFds(JNIEnv* env, jobject clazz, jboolean lastValue)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- parcel->restoreAllowFds((bool)lastValue);
- }
-}
-
-static void android_os_Parcel_writeNative(JNIEnv* env, jobject clazz,
- jobject data, jint offset,
- jint length)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel == NULL) {
- return;
- }
-
- const status_t err = parcel->writeInt32(length);
- if (err != NO_ERROR) {
- signalExceptionForError(env, clazz, err);
- return;
- }
-
- void* dest = parcel->writeInplace(length);
- if (dest == NULL) {
- signalExceptionForError(env, clazz, NO_MEMORY);
- return;
- }
-
- jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)data, 0);
- if (ar) {
- memcpy(dest, ar + offset, length);
- env->ReleasePrimitiveArrayCritical((jarray)data, ar, 0);
- }
-}
-
-
-static void android_os_Parcel_writeInt(JNIEnv* env, jobject clazz, jint val)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- const status_t err = parcel->writeInt32(val);
- if (err != NO_ERROR) {
- signalExceptionForError(env, clazz, err);
- }
- }
-}
-
-static void android_os_Parcel_writeLong(JNIEnv* env, jobject clazz, jlong val)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- const status_t err = parcel->writeInt64(val);
- if (err != NO_ERROR) {
- signalExceptionForError(env, clazz, err);
- }
- }
-}
-
-static void android_os_Parcel_writeFloat(JNIEnv* env, jobject clazz, jfloat val)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- const status_t err = parcel->writeFloat(val);
- if (err != NO_ERROR) {
- signalExceptionForError(env, clazz, err);
- }
- }
-}
-
-static void android_os_Parcel_writeDouble(JNIEnv* env, jobject clazz, jdouble val)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- const status_t err = parcel->writeDouble(val);
- if (err != NO_ERROR) {
- signalExceptionForError(env, clazz, err);
- }
- }
-}
-
-static void android_os_Parcel_writeString(JNIEnv* env, jobject clazz, jstring val)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- status_t err = NO_MEMORY;
- if (val) {
- const jchar* str = env->GetStringCritical(val, 0);
- if (str) {
- err = parcel->writeString16(str, env->GetStringLength(val));
- env->ReleaseStringCritical(val, str);
- }
- } else {
- err = parcel->writeString16(NULL, 0);
- }
- if (err != NO_ERROR) {
- signalExceptionForError(env, clazz, err);
- }
- }
-}
-
-static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jobject clazz, jobject object)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
- if (err != NO_ERROR) {
- signalExceptionForError(env, clazz, err);
- }
- }
-}
-
-static void android_os_Parcel_writeFileDescriptor(JNIEnv* env, jobject clazz, jobject object)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- const status_t err =
- parcel->writeDupFileDescriptor(jniGetFDFromFileDescriptor(env, object));
- if (err != NO_ERROR) {
- signalExceptionForError(env, clazz, err);
- }
- }
-}
-
-static jbyteArray android_os_Parcel_createByteArray(JNIEnv* env, jobject clazz)
-{
- jbyteArray ret = NULL;
-
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- int32_t len = parcel->readInt32();
-
- // sanity check the stored length against the true data size
- if (len >= 0 && len <= (int32_t)parcel->dataAvail()) {
- ret = env->NewByteArray(len);
-
- if (ret != NULL) {
- jbyte* a2 = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
- if (a2) {
- const void* data = parcel->readInplace(len);
- memcpy(a2, data, len);
- env->ReleasePrimitiveArrayCritical(ret, a2, 0);
- }
- }
- }
- }
-
- return ret;
-}
-
-static jint android_os_Parcel_readInt(JNIEnv* env, jobject clazz)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- return parcel->readInt32();
- }
- return 0;
-}
-
-static jlong android_os_Parcel_readLong(JNIEnv* env, jobject clazz)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- return parcel->readInt64();
- }
- return 0;
-}
-
-static jfloat android_os_Parcel_readFloat(JNIEnv* env, jobject clazz)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- return parcel->readFloat();
- }
- return 0;
-}
-
-static jdouble android_os_Parcel_readDouble(JNIEnv* env, jobject clazz)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- return parcel->readDouble();
- }
- return 0;
-}
-
-static jstring android_os_Parcel_readString(JNIEnv* env, jobject clazz)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- size_t len;
- const char16_t* str = parcel->readString16Inplace(&len);
- if (str) {
- return env->NewString(str, len);
- }
- return NULL;
- }
- return NULL;
-}
-
-static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jobject clazz)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- return javaObjectForIBinder(env, parcel->readStrongBinder());
- }
- return NULL;
-}
-
-static jobject android_os_Parcel_readFileDescriptor(JNIEnv* env, jobject clazz)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- int fd = parcel->readFileDescriptor();
- if (fd < 0) return NULL;
- fd = dup(fd);
- if (fd < 0) return NULL;
- return jniCreateFileDescriptor(env, fd);
- }
- return NULL;
-}
-
-static jobject android_os_Parcel_openFileDescriptor(JNIEnv* env, jobject clazz,
- jstring name, jint mode)
-{
- if (name == NULL) {
- jniThrowNullPointerException(env, NULL);
- return NULL;
- }
- const jchar* str = env->GetStringCritical(name, 0);
- if (str == NULL) {
- // Whatever, whatever.
- jniThrowException(env, "java/lang/IllegalStateException", NULL);
- return NULL;
- }
- String8 name8(str, env->GetStringLength(name));
- env->ReleaseStringCritical(name, str);
- int flags=0;
- switch (mode&0x30000000) {
- case 0:
- case 0x10000000:
- flags = O_RDONLY;
- break;
- case 0x20000000:
- flags = O_WRONLY;
- break;
- case 0x30000000:
- flags = O_RDWR;
- break;
- }
-
- if (mode&0x08000000) flags |= O_CREAT;
- if (mode&0x04000000) flags |= O_TRUNC;
- if (mode&0x02000000) flags |= O_APPEND;
-
- int realMode = S_IRWXU|S_IRWXG;
- if (mode&0x00000001) realMode |= S_IROTH;
- if (mode&0x00000002) realMode |= S_IWOTH;
-
- int fd = open(name8.string(), flags, realMode);
- if (fd < 0) {
- jniThrowException(env, "java/io/FileNotFoundException", strerror(errno));
- return NULL;
- }
- jobject object = jniCreateFileDescriptor(env, fd);
- if (object == NULL) {
- close(fd);
- }
- return object;
-}
-
-static jobject android_os_Parcel_dupFileDescriptor(JNIEnv* env, jobject clazz, jobject orig)
-{
- if (orig == NULL) {
- jniThrowNullPointerException(env, NULL);
- return NULL;
- }
- int origfd = jniGetFDFromFileDescriptor(env, orig);
- if (origfd < 0) {
- jniThrowException(env, "java/lang/IllegalArgumentException", "bad FileDescriptor");
- return NULL;
- }
-
- int fd = dup(origfd);
- if (fd < 0) {
- jniThrowIOException(env, errno);
- return NULL;
- }
- jobject object = jniCreateFileDescriptor(env, fd);
- if (object == NULL) {
- close(fd);
- }
- return object;
-}
-
-static void android_os_Parcel_closeFileDescriptor(JNIEnv* env, jobject clazz, jobject object)
-{
- if (object == NULL) {
- jniThrowNullPointerException(env, NULL);
- return;
- }
- int fd = jniGetFDFromFileDescriptor(env, object);
- if (fd >= 0) {
- jniSetFileDescriptorOfFD(env, object, -1);
- //ALOGI("Closing ParcelFileDescriptor %d\n", fd);
- close(fd);
- }
-}
-
-static void android_os_Parcel_clearFileDescriptor(JNIEnv* env, jobject clazz, jobject object)
-{
- if (object == NULL) {
- jniThrowNullPointerException(env, NULL);
- return;
- }
- int fd = jniGetFDFromFileDescriptor(env, object);
- if (fd >= 0) {
- jniSetFileDescriptorOfFD(env, object, -1);
- }
-}
-
-static void android_os_Parcel_freeBuffer(JNIEnv* env, jobject clazz)
-{
- int32_t own = env->GetIntField(clazz, gParcelOffsets.mOwnObject);
- if (own) {
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- //ALOGI("Parcel.freeBuffer() called for C++ Parcel %p\n", parcel);
- parcel->freeData();
- }
- }
-}
-
-static void android_os_Parcel_init(JNIEnv* env, jobject clazz, jint parcelInt)
-{
- Parcel* parcel = (Parcel*)parcelInt;
- int own = 0;
- if (!parcel) {
- //ALOGI("Initializing obj %p: creating new Parcel\n", clazz);
- own = 1;
- parcel = new Parcel;
- } else {
- //ALOGI("Initializing obj %p: given existing Parcel %p\n", clazz, parcel);
- }
- if (parcel == NULL) {
- jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
- return;
- }
- //ALOGI("Initializing obj %p from C++ Parcel %p, own=%d\n", clazz, parcel, own);
- env->SetIntField(clazz, gParcelOffsets.mOwnObject, own);
- env->SetIntField(clazz, gParcelOffsets.mObject, (int)parcel);
-}
-
-static void android_os_Parcel_destroy(JNIEnv* env, jobject clazz)
-{
- int32_t own = env->GetIntField(clazz, gParcelOffsets.mOwnObject);
- if (own) {
- Parcel* parcel = parcelForJavaObject(env, clazz);
- env->SetIntField(clazz, gParcelOffsets.mObject, 0);
- //ALOGI("Destroying obj %p: deleting C++ Parcel %p\n", clazz, parcel);
- delete parcel;
- } else {
- env->SetIntField(clazz, gParcelOffsets.mObject, 0);
- //ALOGI("Destroying obj %p: leaving C++ Parcel %p\n", clazz);
- }
-}
-
-static jbyteArray android_os_Parcel_marshall(JNIEnv* env, jobject clazz)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel == NULL) {
- return NULL;
- }
-
- // do not marshall if there are binder objects in the parcel
- if (parcel->objectsCount())
- {
- jniThrowException(env, "java/lang/RuntimeException", "Tried to marshall a Parcel that contained Binder objects.");
- return NULL;
- }
-
- jbyteArray ret = env->NewByteArray(parcel->dataSize());
-
- if (ret != NULL)
- {
- jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(ret, 0);
- if (array != NULL)
- {
- memcpy(array, parcel->data(), parcel->dataSize());
- env->ReleasePrimitiveArrayCritical(ret, array, 0);
- }
- }
-
- return ret;
-}
-
-static void android_os_Parcel_unmarshall(JNIEnv* env, jobject clazz, jbyteArray data, jint offset, jint length)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel == NULL || length < 0) {
- return;
- }
-
- jbyte* array = (jbyte*)env->GetPrimitiveArrayCritical(data, 0);
- if (array)
- {
- parcel->setDataSize(length);
- parcel->setDataPosition(0);
-
- void* raw = parcel->writeInplace(length);
- memcpy(raw, (array + offset), length);
-
- env->ReleasePrimitiveArrayCritical(data, array, 0);
- }
-}
-
-static void android_os_Parcel_appendFrom(JNIEnv* env, jobject clazz, jobject parcel, jint offset, jint length)
-{
- Parcel* thisParcel = parcelForJavaObject(env, clazz);
- if (thisParcel == NULL) {
- return;
- }
- Parcel* otherParcel = parcelForJavaObject(env, parcel);
- if (otherParcel == NULL) {
- return;
- }
-
- status_t err = thisParcel->appendFrom(otherParcel, offset, length);
- if (err != NO_ERROR) {
- signalExceptionForError(env, clazz, err);
- }
-}
-
-static jboolean android_os_Parcel_hasFileDescriptors(JNIEnv* env, jobject clazz)
-{
- jboolean ret = JNI_FALSE;
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- if (parcel->hasFileDescriptors()) {
- ret = JNI_TRUE;
- }
- }
- return ret;
-}
-
-static void android_os_Parcel_writeInterfaceToken(JNIEnv* env, jobject clazz, jstring name)
-{
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- // In the current implementation, the token is just the serialized interface name that
- // the caller expects to be invoking
- const jchar* str = env->GetStringCritical(name, 0);
- if (str != NULL) {
- parcel->writeInterfaceToken(String16(str, env->GetStringLength(name)));
- env->ReleaseStringCritical(name, str);
- }
- }
-}
-
-static void android_os_Parcel_enforceInterface(JNIEnv* env, jobject clazz, jstring name)
+int register_android_os_Binder(JNIEnv* env)
{
- jboolean ret = JNI_FALSE;
-
- Parcel* parcel = parcelForJavaObject(env, clazz);
- if (parcel != NULL) {
- const jchar* str = env->GetStringCritical(name, 0);
- if (str) {
- IPCThreadState* threadState = IPCThreadState::self();
- const int32_t oldPolicy = threadState->getStrictModePolicy();
- const bool isValid = parcel->enforceInterface(
- String16(str, env->GetStringLength(name)),
- threadState);
- env->ReleaseStringCritical(name, str);
- if (isValid) {
- const int32_t newPolicy = threadState->getStrictModePolicy();
- if (oldPolicy != newPolicy) {
- // Need to keep the Java-level thread-local strict
- // mode policy in sync for the libcore
- // enforcements, which involves an upcall back
- // into Java. (We can't modify the
- // Parcel.enforceInterface signature, as it's
- // pseudo-public, and used via AIDL
- // auto-generation...)
- set_dalvik_blockguard_policy(env, newPolicy);
- }
- return; // everything was correct -> return silently
- }
- }
- }
-
- // all error conditions wind up here
- jniThrowException(env, "java/lang/SecurityException",
- "Binder invocation to an incorrect interface");
-}
-
-// ----------------------------------------------------------------------------
-
-static const JNINativeMethod gParcelMethods[] = {
- {"dataSize", "()I", (void*)android_os_Parcel_dataSize},
- {"dataAvail", "()I", (void*)android_os_Parcel_dataAvail},
- {"dataPosition", "()I", (void*)android_os_Parcel_dataPosition},
- {"dataCapacity", "()I", (void*)android_os_Parcel_dataCapacity},
- {"setDataSize", "(I)V", (void*)android_os_Parcel_setDataSize},
- {"setDataPosition", "(I)V", (void*)android_os_Parcel_setDataPosition},
- {"setDataCapacity", "(I)V", (void*)android_os_Parcel_setDataCapacity},
- {"pushAllowFds", "(Z)Z", (void*)android_os_Parcel_pushAllowFds},
- {"restoreAllowFds", "(Z)V", (void*)android_os_Parcel_restoreAllowFds},
- {"writeNative", "([BII)V", (void*)android_os_Parcel_writeNative},
- {"writeInt", "(I)V", (void*)android_os_Parcel_writeInt},
- {"writeLong", "(J)V", (void*)android_os_Parcel_writeLong},
- {"writeFloat", "(F)V", (void*)android_os_Parcel_writeFloat},
- {"writeDouble", "(D)V", (void*)android_os_Parcel_writeDouble},
- {"writeString", "(Ljava/lang/String;)V", (void*)android_os_Parcel_writeString},
- {"writeStrongBinder", "(Landroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder},
- {"writeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_writeFileDescriptor},
- {"createByteArray", "()[B", (void*)android_os_Parcel_createByteArray},
- {"readInt", "()I", (void*)android_os_Parcel_readInt},
- {"readLong", "()J", (void*)android_os_Parcel_readLong},
- {"readFloat", "()F", (void*)android_os_Parcel_readFloat},
- {"readDouble", "()D", (void*)android_os_Parcel_readDouble},
- {"readString", "()Ljava/lang/String;", (void*)android_os_Parcel_readString},
- {"readStrongBinder", "()Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder},
- {"internalReadFileDescriptor", "()Ljava/io/FileDescriptor;", (void*)android_os_Parcel_readFileDescriptor},
- {"openFileDescriptor", "(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_openFileDescriptor},
- {"dupFileDescriptor", "(Ljava/io/FileDescriptor;)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_dupFileDescriptor},
- {"closeFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_closeFileDescriptor},
- {"clearFileDescriptor", "(Ljava/io/FileDescriptor;)V", (void*)android_os_Parcel_clearFileDescriptor},
- {"freeBuffer", "()V", (void*)android_os_Parcel_freeBuffer},
- {"init", "(I)V", (void*)android_os_Parcel_init},
- {"destroy", "()V", (void*)android_os_Parcel_destroy},
- {"marshall", "()[B", (void*)android_os_Parcel_marshall},
- {"unmarshall", "([BII)V", (void*)android_os_Parcel_unmarshall},
- {"appendFrom", "(Landroid/os/Parcel;II)V", (void*)android_os_Parcel_appendFrom},
- {"hasFileDescriptors", "()Z", (void*)android_os_Parcel_hasFileDescriptors},
- {"writeInterfaceToken", "(Ljava/lang/String;)V", (void*)android_os_Parcel_writeInterfaceToken},
- {"enforceInterface", "(Ljava/lang/String;)V", (void*)android_os_Parcel_enforceInterface},
-};
-
-const char* const kParcelPathName = "android/os/Parcel";
+ if (int_register_android_os_Binder(env) < 0)
+ return -1;
+ if (int_register_android_os_BinderInternal(env) < 0)
+ return -1;
+ if (int_register_android_os_BinderProxy(env) < 0)
+ return -1;
-static int int_register_android_os_Parcel(JNIEnv* env)
-{
jclass clazz;
clazz = env->FindClass("android/util/Log");
@@ -1894,14 +1281,6 @@ static int int_register_android_os_Parcel(JNIEnv* env)
gParcelFileDescriptorOffsets.mConstructor
= env->GetMethodID(clazz, "<init>", "(Ljava/io/FileDescriptor;)V");
- clazz = env->FindClass(kParcelPathName);
- LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Parcel");
-
- gParcelOffsets.mObject
- = env->GetFieldID(clazz, "mObject", "I");
- gParcelOffsets.mOwnObject
- = env->GetFieldID(clazz, "mOwnObject", "I");
-
clazz = env->FindClass("android/os/StrictMode");
LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.StrictMode");
gStrictModeCallbackOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
@@ -1910,20 +1289,5 @@ static int int_register_android_os_Parcel(JNIEnv* env)
LOG_FATAL_IF(gStrictModeCallbackOffsets.mCallback == NULL,
"Unable to find strict mode callback.");
- return AndroidRuntime::registerNativeMethods(
- env, kParcelPathName,
- gParcelMethods, NELEM(gParcelMethods));
-}
-
-int register_android_os_Binder(JNIEnv* env)
-{
- if (int_register_android_os_Binder(env) < 0)
- return -1;
- if (int_register_android_os_BinderInternal(env) < 0)
- return -1;
- if (int_register_android_os_BinderProxy(env) < 0)
- return -1;
- if (int_register_android_os_Parcel(env) < 0)
- return -1;
return 0;
}
diff --git a/core/jni/android_util_Binder.h b/core/jni/android_util_Binder.h
index 0122691b25da..ca320effd69e 100644
--- a/core/jni/android_util_Binder.h
+++ b/core/jni/android_util_Binder.h
@@ -15,6 +15,9 @@
** limitations under the License.
*/
+#ifndef ANDROID_UTIL_BINDER_H
+#define ANDROID_UTIL_BINDER_H
+
#include <binder/IBinder.h>
#include "jni.h"
@@ -25,10 +28,13 @@ namespace android {
extern jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val);
extern sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj);
-// Conversion from Java Parcel Object to C++ Parcel instance.
-// Note: does not type checking; must guarantee jobject is a Java Parcel
-extern Parcel* parcelForJavaObject(JNIEnv* env, jobject obj);
-
extern jobject newParcelFileDescriptor(JNIEnv* env, jobject fileDesc);
+extern void set_dalvik_blockguard_policy(JNIEnv* env, jint strict_policy);
+
+extern void signalExceptionForError(JNIEnv* env, jobject obj, status_t err,
+ bool canThrowRemoteException = false);
+
}
+
+#endif
diff --git a/core/jni/android_view_InputChannel.cpp b/core/jni/android_view_InputChannel.cpp
index 8350e73f91dc..9c44a599a7a8 100644
--- a/core/jni/android_view_InputChannel.cpp
+++ b/core/jni/android_view_InputChannel.cpp
@@ -23,6 +23,7 @@
#include <utils/Log.h>
#include <androidfw/InputTransport.h>
#include "android_view_InputChannel.h"
+#include "android_os_Parcel.h"
#include "android_util_Binder.h"
namespace android {
diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp
index 0fb1b17a2b8e..e69fb74ecf16 100644
--- a/core/jni/android_view_MotionEvent.cpp
+++ b/core/jni/android_view_MotionEvent.cpp
@@ -21,6 +21,7 @@
#include <android_runtime/AndroidRuntime.h>
#include <utils/Log.h>
#include <androidfw/Input.h>
+#include "android_os_Parcel.h"
#include "android_view_MotionEvent.h"
#include "android_util_Binder.h"
#include "android/graphics/Matrix.h"
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index c38775212042..30d4e20dfd68 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -888,7 +888,7 @@ void nativeClassInit(JNIEnv* env, jclass clazz)
no.native_region = env->GetFieldID(region, "mNativeRegion", "I");
jclass parcel = env->FindClass("android/os/Parcel");
- no.native_parcel = env->GetFieldID(parcel, "mObject", "I");
+ no.native_parcel = env->GetFieldID(parcel, "mNativePtr", "I");
jclass rect = env->FindClass("android/graphics/Rect");
ro.l = env->GetFieldID(rect, "left", "I");
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 1a0d47978c0a..8e36948b6a2e 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -671,7 +671,7 @@
<string name="faceunlock_multiple_failures" msgid="754137583022792429">"Se superó el máximo de intentos permitido para el desbloqueo facial del dispositivo."</string>
<string name="lockscreen_plugged_in" msgid="8057762828355572315">"Cargando <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
<string name="lockscreen_charged" msgid="4938930459620989972">"Cargada."</string>
- <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
+ <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
<string name="lockscreen_low_battery" msgid="1482873981919249740">"Conecta tu cargador."</string>
<string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"No hay tarjeta SIM."</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"No hay tarjeta SIM en el tablet."</string>
@@ -768,8 +768,8 @@
<string name="permdesc_serialPort" msgid="2991639985224598193">"Permite acceder a puertos serie a través de la API SerialManager."</string>
<string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"acceder a proveedores externamente"</string>
<string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Permite acceder a los proveedores de contenido desde la interfaz. Las aplicaciones normales nunca deberían necesitarlo."</string>
- <string name="permlab_updateLock" msgid="3527558366616680889">"desalentar a las actualizaciones automáticas de dispositivos"</string>
- <string name="permdesc_updateLock" msgid="1655625832166778492">"Permite a su titular a ofrecer información al sistema acerca de cuándo sería un buen momento para reiniciar el sistema no interactivo para actualizar el dispositivo."</string>
+ <string name="permlab_updateLock" msgid="3527558366616680889">"no realizar actualizaciones automáticas"</string>
+ <string name="permdesc_updateLock" msgid="1655625832166778492">"Permite a su propietario ofrecer información al sistema acerca de cuándo sería adecuado reiniciar el sistema de forma no interactiva y actualizar el dispositivo."</string>
<string name="save_password_message" msgid="767344687139195790">"¿Quieres recordar esta contraseña en el navegador?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Ahora no."</string>
<string name="save_password_remember" msgid="6491879678996749466">"Recuerda"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 5bb95afec18c..385bebb47219 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -769,7 +769,7 @@
<string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"akses pembekal kandungan secara luaran"</string>
<string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Membolehkan pemegang mengakses pembekal kandungan dari luar. Tidak akan sekali-kali diperlukan untuk apl biasa."</string>
<string name="permlab_updateLock" msgid="3527558366616680889">"tidak menggalakkan kemas kini peranti automatik"</string>
- <string name="permdesc_updateLock" msgid="1655625832166778492">"Membenarkan pemegang untuk menawarkan maklumat kepada sistem tentang bila akan menjadi masa yang baik untuk but semula bukan interaktif untuk menaik taraf peranti."</string>
+ <string name="permdesc_updateLock" msgid="1655625832166778492">"Membenarkan aplikasi untuk menawarkan maklumat kepada sistem tentang bila akan menjadi masa yang baik untuk but semula bukan interaktif untuk menaik taraf peranti."</string>
<string name="save_password_message" msgid="767344687139195790">"Adakah anda mahu penyemak imbas mengingati kata laluan ini?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Bukan sekarang"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Ingat"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 6a9f84688386..e70a6649d57d 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -671,7 +671,7 @@
<string name="faceunlock_multiple_failures" msgid="754137583022792429">"Du har overskredet grensen for opplåsingsforsøk med Ansiktslås"</string>
<string name="lockscreen_plugged_in" msgid="8057762828355572315">"Lader, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
<string name="lockscreen_charged" msgid="4938930459620989972">"Fullt ladet"</string>
- <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+ <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
<string name="lockscreen_low_battery" msgid="1482873981919249740">"Koble til en batterilader."</string>
<string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Mangler SIM-kort."</string>
<string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Nettbrettet mangler SIM-kort."</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 286c32c665b1..96dcfa023873 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -768,8 +768,8 @@
<string name="permdesc_serialPort" msgid="2991639985224598193">"Umożliwia posiadaczowi dostęp do portów szeregowych przy użyciu interfejsu API narzędzia SerialManager."</string>
<string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"Dostęp do dostawców treści z zewnątrz"</string>
<string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Pozwala na dostęp do dostawców treści z powłoki. To uprawnienie nie powinno być potrzebne zwykłym aplikacjom."</string>
- <string name="permlab_updateLock" msgid="3527558366616680889">"odradź automatyczne aktualizacje urządzenia"</string>
- <string name="permdesc_updateLock" msgid="1655625832166778492">"Umożliwia posiadaczowi poinformowanie systemu, kiedy będzie dobry moment na nieinteraktywne uruchomienie ponowne wymagane do uaktualnienia urządzenia."</string>
+ <string name="permlab_updateLock" msgid="3527558366616680889">"odradzanie automatycznych aktualizacji urządzenia"</string>
+ <string name="permdesc_updateLock" msgid="1655625832166778492">"Umożliwia posiadaczowi poinformowanie systemu, kiedy będzie dobry moment na ponowne uruchomienie wymagane do uaktualnienia urządzenia."</string>
<string name="save_password_message" msgid="767344687139195790">"Czy chcesz, aby zapamiętać to hasło w przeglądarce?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Nie teraz"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Zapamiętaj"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 286e6d66681a..13053ab22667 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -768,8 +768,8 @@
<string name="permdesc_serialPort" msgid="2991639985224598193">"Inaruhusu mmiliki kufikia vituo tambulishi kwa kutumia KisimamiziTambulishi cha API."</string>
<string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"fikia watoa huduma nje"</string>
<string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Inaruhusu mmiliki kufikia watoa huduma kutoka kwa onyesho. Haifai kuhitajika kamwe kwa programu za kawaida."</string>
- <string name="permlab_updateLock" msgid="3527558366616680889">"katisha tamaa usasishaji kifaa kiotomatiki"</string>
- <string name="permdesc_updateLock" msgid="1655625832166778492">"Inaruhusu mmiliki kutoa maelezo kwa mfumo kuhusu ni lini itakuwa wakati mzuri wa uwashaji upya usiotagusana ili kuboresha kifaa."</string>
+ <string name="permlab_updateLock" msgid="3527558366616680889">"pinga usasishaji kifaa kiotomatiki"</string>
+ <string name="permdesc_updateLock" msgid="1655625832166778492">"Inaruhusu mmiliki kutoa maelezo kwa mfumo kuhusu ni lini itakuwa wakati mzuri wa uwashaji upya usiotagusana ili kupandisha gredi kifaa."</string>
<string name="save_password_message" msgid="767344687139195790">"Unataka kuvinjari ili ukumbuke nenosiri hili?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"Si Sasa"</string>
<string name="save_password_remember" msgid="6491879678996749466">"Kumbuka"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 24b726d3c102..2664ad339558 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -769,7 +769,7 @@
<string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"从外部访问内容提供程序"</string>
<string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"允许持有者通过界面访问内容提供程序。普通应用绝不需要此权限。"</string>
<string name="permlab_updateLock" msgid="3527558366616680889">"阻止自动设备更新"</string>
- <string name="permdesc_updateLock" msgid="1655625832166778492">"允许持有人向系统提供相关信息,以确定什么时候适合执行非交互式重新启动来升级设备。"</string>
+ <string name="permdesc_updateLock" msgid="1655625832166778492">"允许应用向系统提供相关信息,以确定何时适合执行非交互式重启以升级设备。"</string>
<string name="save_password_message" msgid="767344687139195790">"是否希望浏览器记住此密码?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"暂不保存"</string>
<string name="save_password_remember" msgid="6491879678996749466">"记住"</string>
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index d54ab357e86a..cc0a594d164d 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -185,7 +185,7 @@ public:
audio_devices_t device);
static uint32_t getStrategyForStream(audio_stream_type_t stream);
- static uint32_t getDevicesForStream(audio_stream_type_t stream);
+ static audio_devices_t getDevicesForStream(audio_stream_type_t stream);
static audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc);
static status_t registerEffect(effect_descriptor_t *desc,
diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h
index bdd774748a02..04c927aec3bd 100644
--- a/include/media/IAudioPolicyService.h
+++ b/include/media/IAudioPolicyService.h
@@ -79,7 +79,7 @@ public:
int *index,
audio_devices_t device) = 0;
virtual uint32_t getStrategyForStream(audio_stream_type_t stream) = 0;
- virtual uint32_t getDevicesForStream(audio_stream_type_t stream) = 0;
+ virtual audio_devices_t getDevicesForStream(audio_stream_type_t stream) = 0;
virtual audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc) = 0;
virtual status_t registerEffect(effect_descriptor_t *desc,
audio_io_handle_t io,
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 6ec5d2073236..f572f71458fc 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -36,6 +36,7 @@
#include "utils/String8.h"
#include "android_media_Utils.h"
+#include "android_os_Parcel.h"
#include "android_util_Binder.h"
#include <binder/Parcel.h>
#include <gui/ISurfaceTexture.h>
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index e0b186adfde5..a1cbf0f2bd85 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -701,10 +701,10 @@ uint32_t AudioSystem::getStrategyForStream(audio_stream_type_t stream)
return aps->getStrategyForStream(stream);
}
-uint32_t AudioSystem::getDevicesForStream(audio_stream_type_t stream)
+audio_devices_t AudioSystem::getDevicesForStream(audio_stream_type_t stream)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
- if (aps == 0) return 0;
+ if (aps == 0) return (audio_devices_t)0;
return aps->getDevicesForStream(stream);
}
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
index 99385aa4f80a..da7c1244e16e 100644
--- a/media/libmedia/IAudioPolicyService.cpp
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -267,13 +267,13 @@ public:
return reply.readInt32();
}
- virtual uint32_t getDevicesForStream(audio_stream_type_t stream)
+ virtual audio_devices_t getDevicesForStream(audio_stream_type_t stream)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
data.writeInt32(static_cast <uint32_t>(stream));
remote()->transact(GET_DEVICES_FOR_STREAM, data, &reply);
- return (uint32_t) reply.readInt32();
+ return (audio_devices_t) reply.readInt32();
}
virtual audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc)
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index b21e86a68129..9e00bb349144 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -2108,6 +2108,8 @@ status_t AwesomePlayer::finishSetDataSource_l() {
mWVMExtractor = new WVMExtractor(dataSource);
mWVMExtractor->setAdaptiveStreamingMode(true);
+ if (mUIDValid)
+ mWVMExtractor->setUID(mUID);
extractor = mWVMExtractor;
} else {
extractor = MediaExtractor::Create(
diff --git a/media/libstagefright/WVMExtractor.cpp b/media/libstagefright/WVMExtractor.cpp
index c7ad513baf10..dac8106a6858 100644
--- a/media/libstagefright/WVMExtractor.cpp
+++ b/media/libstagefright/WVMExtractor.cpp
@@ -123,6 +123,12 @@ void WVMExtractor::setAdaptiveStreamingMode(bool adaptive) {
}
}
+void WVMExtractor::setUID(uid_t uid) {
+ if (mImpl != NULL) {
+ mImpl->setUID(uid);
+ }
+}
+
bool SniffWVM(
const sp<DataSource> &source, String8 *mimeType, float *confidence,
sp<AMessage> *) {
diff --git a/media/libstagefright/include/WVMExtractor.h b/media/libstagefright/include/WVMExtractor.h
index 9f763f9debef..3c3ca892259a 100644
--- a/media/libstagefright/include/WVMExtractor.h
+++ b/media/libstagefright/include/WVMExtractor.h
@@ -34,6 +34,7 @@ public:
virtual int64_t getCachedDurationUs(status_t *finalStatus) = 0;
virtual void setAdaptiveStreamingMode(bool adaptive) = 0;
+ virtual void setUID(uid_t uid) = 0;
};
class WVMExtractor : public MediaExtractor {
@@ -60,6 +61,8 @@ public:
// is used.
void setAdaptiveStreamingMode(bool adaptive);
+ void setUID(uid_t uid);
+
static bool getVendorLibHandle();
protected:
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 7c1cd18b8a32..1e826469860e 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -26,7 +26,7 @@
<string name="status_bar_recent_remove_item_title" msgid="6026395868129852968">"Hapus dari daftar"</string>
<string name="status_bar_recent_inspect_item_title" msgid="7793624864528818569">"Info apl"</string>
<string name="status_bar_no_recent_apps" msgid="6576392951053994640">"Tidak ada apl terbaru"</string>
- <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Singkirkan aplikasi terbaru"</string>
+ <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Tutup aplikasi terbaru"</string>
<plurals name="status_bar_accessibility_recent_apps">
<item quantity="one" msgid="5854176083865845541">"1 apl terbaru"</item>
<item quantity="other" msgid="1040784359794890744">"%d apl terbaru"</item>
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
index 7487f4bf94e8..d57326b03dad 100644
--- a/services/audioflinger/AudioPolicyService.cpp
+++ b/services/audioflinger/AudioPolicyService.cpp
@@ -430,10 +430,12 @@ uint32_t AudioPolicyService::getStrategyForStream(audio_stream_type_t stream)
return mpAudioPolicy->get_strategy_for_stream(mpAudioPolicy, stream);
}
-uint32_t AudioPolicyService::getDevicesForStream(audio_stream_type_t stream)
+//audio policy: use audio_device_t appropriately
+
+audio_devices_t AudioPolicyService::getDevicesForStream(audio_stream_type_t stream)
{
if (mpAudioPolicy == NULL) {
- return 0;
+ return (audio_devices_t)0;
}
return mpAudioPolicy->get_devices_for_stream(mpAudioPolicy, stream);
}
diff --git a/services/audioflinger/AudioPolicyService.h b/services/audioflinger/AudioPolicyService.h
index 106bf6a9c3a2..7119b901d4a6 100644
--- a/services/audioflinger/AudioPolicyService.h
+++ b/services/audioflinger/AudioPolicyService.h
@@ -95,7 +95,7 @@ public:
audio_devices_t device);
virtual uint32_t getStrategyForStream(audio_stream_type_t stream);
- virtual uint32_t getDevicesForStream(audio_stream_type_t stream);
+ virtual audio_devices_t getDevicesForStream(audio_stream_type_t stream);
virtual audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc);
virtual status_t registerEffect(effect_descriptor_t *desc,
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 2538455f8081..fd968e0b7330 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -4934,7 +4934,7 @@ public final class ActivityManagerService extends ActivityManagerNative
void grantUriPermissionFromIntentLocked(int callingUid,
String targetPkg, Intent intent, UriPermissionOwner owner) {
NeededUriGrants needed = checkGrantUriPermissionFromIntentLocked(callingUid, targetPkg,
- intent, intent.getFlags(), null);
+ intent, intent != null ? intent.getFlags() : 0, null);
if (needed == null) {
return;
}
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index def22a9bc28b..18b51a7fd411 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -9173,7 +9173,7 @@ public class WindowManagerService extends IWindowManager.Stub
void scheduleAnimationLocked() {
if (!mAnimationScheduled) {
- mChoreographer.postAnimationCallback(mAnimationRunnable);
+ mChoreographer.postAnimationCallback(mAnimationRunnable, null);
mAnimationScheduled = true;
}
}