Merge "Fix ClipboardManager#hasText"
diff --git a/api/current.xml b/api/current.xml
index 9422552..3ccb4e9 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -58662,6 +58662,21 @@
<parameter name="flags" type="int">
</parameter>
</method>
+<method name="setInstallerPackageName"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="targetPackage" type="java.lang.String">
+</parameter>
+<parameter name="installerPackageName" type="java.lang.String">
+</parameter>
+</method>
<field name="COMPONENT_ENABLED_STATE_DEFAULT"
type="int"
transient="false"
@@ -175729,6 +175744,21 @@
<parameter name="flags" type="int">
</parameter>
</method>
+<method name="setInstallerPackageName"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="targetPackage" type="java.lang.String">
+</parameter>
+<parameter name="installerPackageName" type="java.lang.String">
+</parameter>
+</method>
<method name="setPackageObbPath"
return="void"
abstract="false"
@@ -194129,53 +194159,6 @@
visibility="public"
>
</method>
-<method name="obtain"
- return="android.view.DragEvent"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="action" type="int">
-</parameter>
-<parameter name="x" type="float">
-</parameter>
-<parameter name="y" type="float">
-</parameter>
-<parameter name="description" type="android.content.ClipDescription">
-</parameter>
-<parameter name="data" type="android.content.ClipData">
-</parameter>
-<parameter name="result" type="boolean">
-</parameter>
-</method>
-<method name="obtain"
- return="android.view.DragEvent"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="source" type="android.view.DragEvent">
-</parameter>
-</method>
-<method name="recycle"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
<method name="writeToParcel"
return="void"
abstract="false"
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index ce9501a..abb26e3 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -914,6 +914,16 @@
}
@Override
+ public void setInstallerPackageName(String targetPackage,
+ String installerPackageName) {
+ try {
+ mPM.setInstallerPackageName(targetPackage, installerPackageName);
+ } catch (RemoteException e) {
+ // Should never happen!
+ }
+ }
+
+ @Override
public void movePackage(String packageName, IPackageMoveObserver observer, int flags) {
try {
mPM.movePackage(packageName, observer, flags);
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index a18fdac..f169cd7 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -691,8 +691,6 @@
*
* <p>To disable password expiration, a value of 0 may be used for timeout.
*
- * <p>Timeout must be at least 1 day or IllegalArgumentException will be thrown.
- *
* <p>The calling device admin must have requested
* {@link DeviceAdminInfo#USES_POLICY_EXPIRE_PASSWORD} to be able to call this
* method; if it has not, a security exception will be thrown.
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 4cff3bb..d01a68a 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -158,6 +158,8 @@
void finishPackageInstall(int token);
+ void setInstallerPackageName(in String targetPackage, in String installerPackageName);
+
/**
* Delete a package.
*
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index b5d1653..ac7a95a 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1918,6 +1918,24 @@
String installerPackageName);
/**
+ * Change the installer associated with a given package. There are limitations
+ * on how the installer package can be changed; in particular:
+ * <ul>
+ * <li> A SecurityException will be thrown if <var>installerPackageName</var>
+ * is not signed with the same certificate as the calling application.
+ * <li> A SecurityException will be thrown if <var>targetPackage</var> already
+ * has an installer package, and that installer package is not signed with
+ * the same certificate as the calling application.
+ * </ul>
+ *
+ * @param targetPackage The installed package whose installer will be changed.
+ * @param installerPackageName The package name of the new installer. May be
+ * null to clear the association.
+ */
+ public abstract void setInstallerPackageName(String targetPackage,
+ String installerPackageName);
+
+ /**
* Attempts to delete a package. Since this may take a little while, the result will
* be posted back to the given observer. A deletion will fail if the calling context
* lacks the {@link android.Manifest.permission#DELETE_PACKAGES} permission, if the
diff --git a/core/java/android/view/DragEvent.java b/core/java/android/view/DragEvent.java
index bbac14c..07e87d6 100644
--- a/core/java/android/view/DragEvent.java
+++ b/core/java/android/view/DragEvent.java
@@ -41,16 +41,90 @@
private static DragEvent gRecyclerTop = null;
/**
- * action constants for DragEvent dispatch
+ * Action constant returned by {@link #getAction()}. Delivery of a DragEvent whose
+ * action is ACTION_DRAG_STARTED means that a drag operation has been initiated. The
+ * view receiving this DragEvent should inspect the metadata of the dragged content,
+ * available via {@link #getClipDescription()}, and return {@code true} from
+ * {@link View#onDragEvent(DragEvent)} if the view is prepared to accept a drop of
+ * that clip data. If the view chooses to present a visual indication that it is
+ * a valid target of the ongoing drag, then it should draw that indication in response
+ * to this event.
+ * <p>
+ * A view will only receive ACTION_DRAG_ENTERED, ACTION_DRAG_LOCATION, ACTION_DRAG_EXITED,
+ * and ACTION_DRAG_LOCATION events if it returns {@code true} in response to the
+ * ACTION_DRAG_STARTED event.
*/
public static final int ACTION_DRAG_STARTED = 1;
- public static final int ACTION_DRAG_LOCATION = 2;
- public static final int ACTION_DROP = 3;
- public static final int ACTION_DRAG_ENDED = 4;
- public static final int ACTION_DRAG_ENTERED = 5;
- public static final int ACTION_DRAG_EXITED = 6;
- /* hide the constructor behind package scope */
+ /**
+ * Action constant returned by {@link #getAction()}. Delivery of a DragEvent whose
+ * action is ACTION_DRAG_LOCATION means that the drag operation is currently hovering
+ * over the view. The {@link #getX()} and {@link #getY()} methods supply the location
+ * of the drag point within the view's coordinate system.
+ * <p>
+ * A view will receive an ACTION_DRAG_ENTERED event before receiving any
+ * ACTION_DRAG_LOCATION events. If the drag point leaves the view, then an
+ * ACTION_DRAG_EXITED event is delivered to the view, after which no more
+ * ACTION_DRAG_LOCATION events will be sent (unless the drag re-enters the view,
+ * of course).
+ */
+ public static final int ACTION_DRAG_LOCATION = 2;
+
+ /**
+ * Action constant returned by {@link #getAction()}. Delivery of a DragEvent whose
+ * action is ACTION_DROP means that the dragged content has been dropped on this view.
+ * The view should retrieve the content via {@link #getClipData()} and act on it
+ * appropriately. The {@link #getX()} and {@link #getY()} methods supply the location
+ * of the drop point within the view's coordinate system.
+ * <p>
+ * The view should return {@code true} from its {@link View#onDragEvent(DragEvent)}
+ * method in response to this event if it accepted the content, and {@code false}
+ * if it ignored the drop.
+ */
+ public static final int ACTION_DROP = 3;
+
+ /**
+ * Action constant returned by {@link #getAction()}. Delivery of a DragEvent whose
+ * action is ACTION_DRAG_ENDED means that the drag operation has concluded. A view
+ * that is drawing a visual indication of drag acceptance should return to its usual
+ * drawing state in response to this event.
+ * <p>
+ * All views that received an ACTION_DRAG_STARTED event will receive the
+ * ACTION_DRAG_ENDED event even if they are not currently visible when the drag
+ * ends.
+ */
+ public static final int ACTION_DRAG_ENDED = 4;
+
+ /**
+ * Action constant returned by {@link #getAction()}. Delivery of a DragEvent whose
+ * action is ACTION_DRAG_ENTERED means that the drag point has entered the view's
+ * bounds. If the view changed its visual state in response to the ACTION_DRAG_ENTERED
+ * event, it should return to its normal drag-in-progress visual state in response to
+ * this event.
+ * <p>
+ * A view will receive an ACTION_DRAG_ENTERED event before receiving any
+ * ACTION_DRAG_LOCATION events. If the drag point leaves the view, then an
+ * ACTION_DRAG_EXITED event is delivered to the view, after which no more
+ * ACTION_DRAG_LOCATION events will be sent (unless the drag re-enters the view,
+ * of course).
+ */
+ public static final int ACTION_DRAG_ENTERED = 5;
+
+ /**
+ * Action constant returned by {@link #getAction()}. Delivery of a DragEvent whose
+ * action is ACTION_DRAG_ENTERED means that the drag point has entered the view's
+ * bounds. If the view chooses to present a visual indication that it will receive
+ * the drop if it occurs now, then it should draw that indication in response to
+ * this event.
+ * <p>
+ * A view will receive an ACTION_DRAG_ENTERED event before receiving any
+ * ACTION_DRAG_LOCATION events. If the drag point leaves the view, then an
+ * ACTION_DRAG_EXITED event is delivered to the view, after which no more
+ * ACTION_DRAG_LOCATION events will be sent (unless the drag re-enters the view,
+ * of course).
+ */
+public static final int ACTION_DRAG_EXITED = 6;
+
private DragEvent() {
}
@@ -68,6 +142,7 @@
return DragEvent.obtain(0, 0f, 0f, null, null, false);
}
+ /** @hide */
public static DragEvent obtain(int action, float x, float y,
ClipDescription description, ClipData data, boolean result) {
final DragEvent ev;
@@ -90,31 +165,64 @@
return ev;
}
+ /** @hide */
public static DragEvent obtain(DragEvent source) {
return obtain(source.mAction, source.mX, source.mY,
source.mClipDescription, source.mClipData, source.mDragResult);
}
+ /**
+ * Inspect the action value of this event.
+ * @return One of {@link #ACTION_DRAG_STARTED}, {@link #ACTION_DRAG_ENDED},
+ * {@link #ACTION_DROP}, {@link #ACTION_DRAG_ENTERED}, {@link #ACTION_DRAG_EXITED},
+ * or {@link #ACTION_DRAG_LOCATION}.
+ */
public int getAction() {
return mAction;
}
+ /**
+ * For ACTION_DRAG_LOCATION and ACTION_DROP events, returns the x coordinate of the
+ * drag point.
+ * @return The current drag point's x coordinate, when relevant.
+ */
public float getX() {
return mX;
}
+ /**
+ * For ACTION_DRAG_LOCATION and ACTION_DROP events, returns the y coordinate of the
+ * drag point.
+ * @return The current drag point's y coordinate, when relevant.
+ */
public float getY() {
return mY;
}
+ /**
+ * Provides the data payload of the drag operation. This payload is only available
+ * for events whose action value is ACTION_DROP.
+ * @return The ClipData containing the data being dropped on the view.
+ */
public ClipData getClipData() {
return mClipData;
}
+ /**
+ * Provides a description of the drag operation's data payload. This payload is
+ * available for all DragEvents other than ACTION_DROP.
+ * @return A ClipDescription describing the contents of the data being dragged.
+ */
public ClipDescription getClipDescription() {
return mClipDescription;
}
+ /**
+ * Provides an indication of whether the drag operation concluded successfully.
+ * This method is only available on ACTION_DRAG_ENDED events.
+ * @return {@code true} if the drag operation ended with an accepted drop; {@code false}
+ * otherwise.
+ */
public boolean getResult() {
return mDragResult;
}
@@ -122,6 +230,8 @@
/**
* Recycle the DragEvent, to be re-used by a later caller. After calling
* this function you must never touch the event again.
+ *
+ * @hide
*/
public final void recycle() {
// Ensure recycle is only called once!
diff --git a/core/java/android/view/animation/Animation.java b/core/java/android/view/animation/Animation.java
index c6fae9d..13d0ec1 100644
--- a/core/java/android/view/animation/Animation.java
+++ b/core/java/android/view/animation/Animation.java
@@ -18,9 +18,11 @@
import android.content.Context;
import android.content.res.TypedArray;
+import android.graphics.RectF;
+import android.os.SystemProperties;
import android.util.AttributeSet;
import android.util.TypedValue;
-import android.graphics.RectF;
+import dalvik.system.CloseGuard;
/**
* Abstraction for an Animation that can be applied to Views, Surfaces, or
@@ -86,7 +88,10 @@
* content for the duration of the animation.
*/
public static final int ZORDER_BOTTOM = -1;
-
+
+ private static final boolean USE_CLOSEGUARD
+ = SystemProperties.getBoolean("log.closeguard.Animation", false);
+
/**
* Set by {@link #getTransformation(long, Transformation)} when the animation ends.
*/
@@ -194,6 +199,8 @@
Transformation mTransformation = new Transformation();
Transformation mPreviousTransformation = new Transformation();
+ private final CloseGuard guard = CloseGuard.get();
+
/**
* Creates a new animation with a duration of 0ms, the default interpolator, with
* fillBefore set to true and fillAfter set to false
@@ -276,6 +283,7 @@
if (mStarted && !mEnded) {
if (mListener != null) mListener.onAnimationEnd(this);
mEnded = true;
+ guard.close();
}
// Make sure we move the animation to the end
mStartTime = Long.MIN_VALUE;
@@ -288,6 +296,7 @@
public void detach() {
if (mStarted && !mEnded) {
mEnded = true;
+ guard.close();
if (mListener != null) mListener.onAnimationEnd(this);
}
}
@@ -781,6 +790,9 @@
mListener.onAnimationStart(this);
}
mStarted = true;
+ if (USE_CLOSEGUARD) {
+ guard.open("cancel or detach or getTransformation");
+ }
}
if (mFillEnabled) normalizedTime = Math.max(Math.min(normalizedTime, 1.0f), 0.0f);
@@ -797,6 +809,7 @@
if (mRepeatCount == mRepeated) {
if (!mEnded) {
mEnded = true;
+ guard.close();
if (mListener != null) {
mListener.onAnimationEnd(this);
}
@@ -953,6 +966,16 @@
}
}
+ protected void finalize() throws Throwable {
+ try {
+ if (guard != null) {
+ guard.warnIfOpen();
+ }
+ } finally {
+ super.finalize();
+ }
+ }
+
/**
* Utility class to parse a string description of a size.
*/
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 383e977..5bf2ad4 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2187,14 +2187,6 @@
private View mTitleBar;
/**
- * Since we draw the title bar ourselves, we removed the shadow from the
- * browser's activity. We do want a shadow at the bottom of the title bar,
- * or at the top of the screen if the title bar is not visible. This
- * drawable serves that purpose.
- */
- private Drawable mTitleShadow;
-
- /**
* Add or remove a title bar to be embedded into the WebView, and scroll
* along with it vertically, while remaining in view horizontally. Pass
* null to remove the title bar from the WebView, and return to drawing
@@ -2220,10 +2212,6 @@
addView(v, new AbsoluteLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT, 0, 0));
- if (mTitleShadow == null) {
- mTitleShadow = (Drawable) mContext.getResources().getDrawable(
- com.android.internal.R.drawable.title_bar_shadow);
- }
}
mTitleBar = v;
}
@@ -3470,15 +3458,6 @@
drawContent(canvas);
canvas.restoreToCount(saveCount);
- // Now draw the shadow.
- int titleH = getVisibleTitleHeight();
- if (mTitleBar != null && titleH == 0) {
- int height = (int) (5f * getContext().getResources()
- .getDisplayMetrics().density);
- mTitleShadow.setBounds(mScrollX, mScrollY, mScrollX + getWidth(),
- mScrollY + height);
- mTitleShadow.draw(canvas);
- }
if (AUTO_REDRAW_HACK && mAutoRedraw) {
invalidate();
}
diff --git a/core/res/res/drawable-hdpi/title_bar_shadow.9.png b/core/res/res/drawable-hdpi/title_bar_shadow.9.png
deleted file mode 100644
index e6dab63..0000000
--- a/core/res/res/drawable-hdpi/title_bar_shadow.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-ldpi/title_bar_shadow.9.png b/core/res/res/drawable-ldpi/title_bar_shadow.9.png
deleted file mode 100644
index fc45ee8..0000000
--- a/core/res/res/drawable-ldpi/title_bar_shadow.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/title_bar_shadow.9.png b/core/res/res/drawable-mdpi/title_bar_shadow.9.png
deleted file mode 100644
index dbcefee..0000000
--- a/core/res/res/drawable-mdpi/title_bar_shadow.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/layout/grant_credentials_permission.xml b/core/res/res/layout/grant_credentials_permission.xml
index 4133ea9..0ffe8de 100644
--- a/core/res/res/layout/grant_credentials_permission.xml
+++ b/core/res/res/layout/grant_credentials_permission.xml
@@ -47,8 +47,7 @@
android:layout_height="wrap_content"
android:fillViewport="true"
android:layout_weight="1"
- android:gravity="top|center_horizontal"
- android:foreground="@drawable/title_bar_shadow">
+ android:gravity="top|center_horizontal">
<LinearLayout
android:layout_width="match_parent"
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index 3e546a1..04c6538 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -67,7 +67,6 @@
<item>@drawable/text_select_handle_middle</item>
<item>@drawable/text_select_handle_right</item>
<item>@drawable/title_bar</item>
- <item>@drawable/title_bar_shadow</item>
<!-- Visual lock screen -->
<item>@drawable/indicator_code_lock_drag_direction_green_up</item>
<item>@drawable/indicator_code_lock_drag_direction_red_up</item>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index f5dca47..9215bf2 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -130,7 +130,7 @@
<item name="windowNoTitle">false</item>
<item name="windowFullscreen">false</item>
<item name="windowIsFloating">false</item>
- <item name="windowContentOverlay">@android:drawable/title_bar_shadow</item>
+ <item name="windowContentOverlay">@null</item>
<item name="windowShowWallpaper">false</item>
<item name="windowTitleStyle">@android:style/WindowTitle</item>
<item name="windowTitleSize">25dip</item>
diff --git a/include/media/AudioEffect.h b/include/media/AudioEffect.h
index c967efb..cda2be0 100644
--- a/include/media/AudioEffect.h
+++ b/include/media/AudioEffect.h
@@ -403,7 +403,7 @@
static status_t guidToString(const effect_uuid_t *guid, char *str, size_t maxLen);
protected:
- volatile int32_t mEnabled; // enable state
+ bool mEnabled; // enable state
int32_t mSessionId; // audio session ID
int32_t mPriority; // priority for effect control
status_t mStatus; // effect status
@@ -412,6 +412,7 @@
void* mUserData; // client context for callback function
effect_descriptor_t mDescriptor; // effect descriptor
int32_t mId; // system wide unique effect engine instance ID
+ Mutex mLock; // Mutex for mEnabled access
private:
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index 38e3d44..5f7cd90 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -356,7 +356,7 @@
sp<IAudioRecord> mAudioRecord;
sp<IMemory> mCblkMemory;
sp<ClientRecordThread> mClientRecordThread;
- Mutex mRecordThreadLock;
+ Mutex mLock;
uint32_t mFrameCount;
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index 4475d4a..813a905 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -480,6 +480,7 @@
uint32_t mFlags;
int mSessionId;
int mAuxEffectId;
+ Mutex mLock;
};
diff --git a/include/media/stagefright/AMRWriter.h b/include/media/stagefright/AMRWriter.h
index d8410a9..62d57b4 100644
--- a/include/media/stagefright/AMRWriter.h
+++ b/include/media/stagefright/AMRWriter.h
@@ -44,7 +44,6 @@
virtual ~AMRWriter();
private:
- FILE *mFile;
int mFd;
status_t mInitCheck;
sp<MediaSource> mSource;
diff --git a/include/media/stagefright/FileSource.h b/include/media/stagefright/FileSource.h
index a7f7181..72a0403 100644
--- a/include/media/stagefright/FileSource.h
+++ b/include/media/stagefright/FileSource.h
@@ -46,7 +46,6 @@
virtual ~FileSource();
private:
- FILE *mFile;
int mFd;
int64_t mOffset;
int64_t mLength;
diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h
index e6d8a26..f7618e9 100644
--- a/include/media/stagefright/MPEG4Writer.h
+++ b/include/media/stagefright/MPEG4Writer.h
@@ -61,8 +61,8 @@
private:
class Track;
- FILE *mFile;
int mFd;
+ status_t mInitCheck;
bool mUse4ByteNalLength;
bool mUse32BitOffset;
bool mIsFileSizeLimitExplicitlyRequested;
@@ -149,7 +149,7 @@
off64_t addSample_l(MediaBuffer *buffer);
off64_t addLengthPrefixedSample_l(MediaBuffer *buffer);
- inline size_t write(const void *ptr, size_t size, size_t nmemb, FILE* stream);
+ inline size_t write(const void *ptr, size_t size, size_t nmemb);
bool exceedsFileSizeLimit();
bool use32BitFileOffset() const;
bool exceedsFileDurationLimit();
diff --git a/media/jni/soundpool/SoundPool.h b/media/jni/soundpool/SoundPool.h
index 42037af..1b0fd38 100644
--- a/media/jni/soundpool/SoundPool.h
+++ b/media/jni/soundpool/SoundPool.h
@@ -22,7 +22,6 @@
#include <utils/Vector.h>
#include <utils/KeyedVector.h>
#include <media/AudioTrack.h>
-#include <cutils/atomic.h>
namespace android {
diff --git a/media/libmedia/AudioEffect.cpp b/media/libmedia/AudioEffect.cpp
index 88b8c86..aadeba5 100644
--- a/media/libmedia/AudioEffect.cpp
+++ b/media/libmedia/AudioEffect.cpp
@@ -27,7 +27,6 @@
#include <media/AudioEffect.h>
#include <utils/Log.h>
-#include <cutils/atomic.h>
#include <binder/IPCThreadState.h>
@@ -207,18 +206,22 @@
return INVALID_OPERATION;
}
- if (enabled) {
- LOGV("enable %p", this);
- if (android_atomic_or(1, &mEnabled) == 0) {
- return mIEffect->enable();
+ status_t status = NO_ERROR;
+
+ AutoMutex lock(mLock);
+ if (enabled != mEnabled) {
+ if (enabled) {
+ LOGV("enable %p", this);
+ status = mIEffect->enable();
+ } else {
+ LOGV("disable %p", this);
+ status = mIEffect->disable();
}
- } else {
- LOGV("disable %p", this);
- if (android_atomic_and(~1, &mEnabled) == 1) {
- return mIEffect->disable();
+ if (status == NO_ERROR) {
+ mEnabled = enabled;
}
}
- return NO_ERROR;
+ return status;
}
status_t AudioEffect::command(uint32_t cmdCode,
@@ -232,26 +235,26 @@
return INVALID_OPERATION;
}
- if ((cmdCode == EFFECT_CMD_ENABLE || cmdCode == EFFECT_CMD_DISABLE) &&
- (replySize == NULL || *replySize != sizeof(status_t) || replyData == NULL)) {
- return BAD_VALUE;
+ if (cmdCode == EFFECT_CMD_ENABLE || cmdCode == EFFECT_CMD_DISABLE) {
+ if (mEnabled == (cmdCode == EFFECT_CMD_ENABLE)) {
+ return NO_ERROR;
+ }
+ if (replySize == NULL || *replySize != sizeof(status_t) || replyData == NULL) {
+ return BAD_VALUE;
+ }
+ mLock.lock();
}
status_t status = mIEffect->command(cmdCode, cmdSize, cmdData, replySize, replyData);
- if (status != NO_ERROR) {
- return status;
- }
if (cmdCode == EFFECT_CMD_ENABLE || cmdCode == EFFECT_CMD_DISABLE) {
- status = *(status_t *)replyData;
- if (status != NO_ERROR) {
- return status;
+ if (status == NO_ERROR) {
+ status = *(status_t *)replyData;
}
- if (cmdCode == EFFECT_CMD_ENABLE) {
- android_atomic_or(1, &mEnabled);
- } else {
- android_atomic_and(~1, &mEnabled);
+ if (status == NO_ERROR) {
+ mEnabled = (cmdCode == EFFECT_CMD_ENABLE);
}
+ mLock.unlock();
}
return status;
@@ -370,11 +373,7 @@
{
LOGV("enableStatusChanged %p enabled %d mCbf %p", this, enabled, mCbf);
if (mStatus == ALREADY_EXISTS) {
- if (enabled) {
- android_atomic_or(1, &mEnabled);
- } else {
- android_atomic_and(~1, &mEnabled);
- }
+ mEnabled = enabled;
if (mCbf) {
mCbf(EVENT_ENABLE_STATUS_CHANGED, mUserData, &enabled);
}
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index a6c515c..1d6ffa0 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -35,7 +35,6 @@
#include <binder/Parcel.h>
#include <binder/IPCThreadState.h>
#include <utils/Timers.h>
-#include <cutils/atomic.h>
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
@@ -282,7 +281,9 @@
t->mLock.lock();
}
- if (android_atomic_or(1, &mActive) == 0) {
+ AutoMutex lock(mLock);
+ if (mActive == 0) {
+ mActive = 1;
ret = mAudioRecord->start();
if (ret == DEAD_OBJECT) {
LOGV("start() dead IAudioRecord: creating a new one");
@@ -302,8 +303,7 @@
setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
}
} else {
- LOGV("start() failed");
- android_atomic_and(~1, &mActive);
+ mActive = 0;
}
}
@@ -322,9 +322,11 @@
if (t != 0) {
t->mLock.lock();
- }
+ }
- if (android_atomic_and(~1, &mActive) == 1) {
+ AutoMutex lock(mLock);
+ if (mActive == 1) {
+ mActive = 0;
mCblk->cv.signal();
mAudioRecord->stop();
// the record head position will reset to 0, so if a marker is set, we need
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 587c8ff..c1bed59 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -35,7 +35,6 @@
#include <binder/Parcel.h>
#include <binder/IPCThreadState.h>
#include <utils/Timers.h>
-#include <cutils/atomic.h>
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
@@ -312,7 +311,9 @@
t->mLock.lock();
}
- if (android_atomic_or(1, &mActive) == 0) {
+ AutoMutex lock(mLock);
+ if (mActive == 0) {
+ mActive = 1;
mNewPosition = mCblk->server + mUpdatePeriod;
mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
mCblk->waitTimeMs = 0;
@@ -344,7 +345,7 @@
}
if (status != NO_ERROR) {
LOGV("start() failed");
- android_atomic_and(~1, &mActive);
+ mActive = 0;
if (t != 0) {
t->requestExit();
} else {
@@ -367,7 +368,9 @@
t->mLock.lock();
}
- if (android_atomic_and(~1, &mActive) == 1) {
+ AutoMutex lock(mLock);
+ if (mActive == 1) {
+ mActive = 0;
mCblk->cv.signal();
mAudioTrack->stop();
// Cancel loops (If we are in the middle of a loop, playback
@@ -407,7 +410,6 @@
mMarkerReached = false;
mUpdatePeriod = 0;
-
if (!mActive) {
mAudioTrack->flush();
// Release AudioTrack callback thread in case it was waiting for new buffers
@@ -419,7 +421,9 @@
void AudioTrack::pause()
{
LOGV("pause");
- if (android_atomic_and(~1, &mActive) == 1) {
+ AutoMutex lock(mLock);
+ if (mActive == 1) {
+ mActive = 0;
mAudioTrack->pause();
}
}
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index dadd1db..ec3b5a2 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -864,7 +864,7 @@
return UNKNOWN_ERROR;
}
- mWriter = new AMRWriter(dup(mOutputFd));
+ mWriter = new AMRWriter(mOutputFd);
mWriter->addSource(audioEncoder);
if (mMaxFileDurationUs != 0) {
@@ -912,7 +912,7 @@
}
}
- mWriter = new ARTPWriter(dup(mOutputFd));
+ mWriter = new ARTPWriter(mOutputFd);
mWriter->addSource(source);
mWriter->setListener(mListener);
@@ -922,7 +922,7 @@
status_t StagefrightRecorder::startMPEG2TSRecording() {
CHECK_EQ(mOutputFormat, OUTPUT_FORMAT_MPEG2TS);
- sp<MediaWriter> writer = new MPEG2TSWriter(dup(mOutputFd));
+ sp<MediaWriter> writer = new MPEG2TSWriter(mOutputFd);
if (mAudioSource != AUDIO_SOURCE_LIST_END) {
if (mAudioEncoder != AUDIO_ENCODER_AAC) {
@@ -1204,7 +1204,7 @@
mediaWriter->clear();
*totalBitRate = 0;
status_t err = OK;
- sp<MediaWriter> writer = new MPEG4Writer(dup(outputFd));
+ sp<MediaWriter> writer = new MPEG4Writer(outputFd);
// Add audio source first if it exists
if (!mCaptureTimeLapse && (mAudioSource != AUDIO_SOURCE_LIST_END)) {
diff --git a/media/libstagefright/AMRWriter.cpp b/media/libstagefright/AMRWriter.cpp
index ecbd96c..0db3d1d 100644
--- a/media/libstagefright/AMRWriter.cpp
+++ b/media/libstagefright/AMRWriter.cpp
@@ -24,22 +24,28 @@
#include <media/mediarecorder.h>
#include <sys/prctl.h>
#include <sys/resource.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
namespace android {
AMRWriter::AMRWriter(const char *filename)
- : mFile(fopen(filename, "wb")),
- mFd(mFile == NULL? -1: fileno(mFile)),
- mInitCheck(mFile != NULL ? OK : NO_INIT),
+ : mFd(-1),
+ mInitCheck(NO_INIT),
mStarted(false),
mPaused(false),
mResumed(false) {
+
+ mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC);
+ if (mFd >= 0) {
+ mInitCheck = OK;
+ }
}
AMRWriter::AMRWriter(int fd)
- : mFile(fdopen(fd, "wb")),
- mFd(mFile == NULL? -1: fileno(mFile)),
- mInitCheck(mFile != NULL ? OK : NO_INIT),
+ : mFd(dup(fd)),
+ mInitCheck(mFd < 0? NO_INIT: OK),
mStarted(false),
mPaused(false),
mResumed(false) {
@@ -50,9 +56,9 @@
stop();
}
- if (mFile != NULL) {
- fclose(mFile);
- mFile = NULL;
+ if (mFd != -1) {
+ close(mFd);
+ mFd = -1;
}
}
@@ -92,7 +98,7 @@
mSource = source;
const char *kHeader = isWide ? "#!AMR-WB\n" : "#!AMR\n";
- size_t n = strlen(kHeader);
+ ssize_t n = strlen(kHeader);
if (write(mFd, kHeader, n) != n) {
return ERROR_IO;
}
@@ -266,9 +272,8 @@
notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_COMPLETION_STATUS, UNKNOWN_ERROR);
}
- fflush(mFile);
- fclose(mFile);
- mFile = NULL;
+ close(mFd);
+ mFd = -1;
mReachedEOS = true;
if (err == ERROR_END_OF_STREAM) {
return OK;
diff --git a/media/libstagefright/FileSource.cpp b/media/libstagefright/FileSource.cpp
index c9f68e9..98d5b50 100644
--- a/media/libstagefright/FileSource.cpp
+++ b/media/libstagefright/FileSource.cpp
@@ -18,12 +18,14 @@
#include <media/stagefright/MediaDebug.h>
#include <sys/types.h>
#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
namespace android {
FileSource::FileSource(const char *filename)
- : mFile(fopen(filename, "rb")),
- mFd(mFile == NULL ? -1 : fileno(mFile)),
+ : mFd(-1),
mOffset(0),
mLength(-1),
mDecryptHandle(NULL),
@@ -31,11 +33,12 @@
mDrmBufOffset(0),
mDrmBufSize(0),
mDrmBuf(NULL){
+
+ mFd = open(filename, O_LARGEFILE | O_RDONLY);
}
FileSource::FileSource(int fd, int64_t offset, int64_t length)
- : mFile(fdopen(fd, "rb")),
- mFd(fd),
+ : mFd(fd),
mOffset(offset),
mLength(length),
mDecryptHandle(NULL),
@@ -48,9 +51,9 @@
}
FileSource::~FileSource() {
- if (mFile != NULL) {
- fclose(mFile);
- mFile = NULL;
+ if (mFd >= 0) {
+ close(mFd);
+ mFd = -1;
}
if (mDrmBuf != NULL) {
@@ -60,11 +63,11 @@
}
status_t FileSource::initCheck() const {
- return mFile != NULL ? OK : NO_INIT;
+ return mFd >= 0 ? OK : NO_INIT;
}
ssize_t FileSource::readAt(off64_t offset, void *data, size_t size) {
- if (mFile == NULL) {
+ if (mFd < 0) {
return NO_INIT;
}
@@ -95,7 +98,7 @@
}
status_t FileSource::getSize(off64_t *size) {
- if (mFile == NULL) {
+ if (mFd < 0) {
return NO_INIT;
}
diff --git a/media/libstagefright/MPEG2TSWriter.cpp b/media/libstagefright/MPEG2TSWriter.cpp
index 81a2b0d..4d8165e 100644
--- a/media/libstagefright/MPEG2TSWriter.cpp
+++ b/media/libstagefright/MPEG2TSWriter.cpp
@@ -410,7 +410,7 @@
////////////////////////////////////////////////////////////////////////////////
MPEG2TSWriter::MPEG2TSWriter(int fd)
- : mFile(fdopen(fd, "wb")),
+ : mFile(fdopen(dup(fd), "wb")),
mStarted(false),
mNumSourcesDone(0),
mNumTSPacketsWritten(0),
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 19e3eae..6760707 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -33,6 +33,10 @@
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/Utils.h>
#include <media/mediarecorder.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
#include "include/ESDS.h"
@@ -214,8 +218,8 @@
};
MPEG4Writer::MPEG4Writer(const char *filename)
- : mFile(fopen(filename, "wb")),
- mFd(mFile == NULL? -1: fileno(mFile)),
+ : mFd(-1),
+ mInitCheck(NO_INIT),
mUse4ByteNalLength(true),
mUse32BitOffset(true),
mIsFileSizeLimitExplicitlyRequested(false),
@@ -225,12 +229,16 @@
mMdatOffset(0),
mEstimatedMoovBoxSize(0),
mInterleaveDurationUs(1000000) {
- CHECK(mFile != NULL);
+
+ mFd = open(filename, O_CREAT | O_LARGEFILE | O_TRUNC);
+ if (mFd >= 0) {
+ mInitCheck = OK;
+ }
}
MPEG4Writer::MPEG4Writer(int fd)
- : mFile(fdopen(fd, "wb")),
- mFd(mFile == NULL? -1: fileno(mFile)),
+ : mFd(dup(fd)),
+ mInitCheck(mFd < 0? NO_INIT: OK),
mUse4ByteNalLength(true),
mUse32BitOffset(true),
mIsFileSizeLimitExplicitlyRequested(false),
@@ -240,7 +248,6 @@
mMdatOffset(0),
mEstimatedMoovBoxSize(0),
mInterleaveDurationUs(1000000) {
- CHECK(mFile != NULL);
}
MPEG4Writer::~MPEG4Writer() {
@@ -370,7 +377,7 @@
}
status_t MPEG4Writer::start(MetaData *param) {
- if (mFile == NULL) {
+ if (mInitCheck != OK) {
return UNKNOWN_ERROR;
}
@@ -493,7 +500,7 @@
}
status_t MPEG4Writer::pause() {
- if (mFile == NULL) {
+ if (mInitCheck != OK) {
return OK;
}
mPaused = true;
@@ -577,7 +584,7 @@
status_t MPEG4Writer::stop() {
- if (mFile == NULL) {
+ if (mInitCheck != OK) {
return OK;
}
@@ -600,9 +607,9 @@
// Do not write out movie header on error.
if (err != OK) {
- fflush(mFile);
- fclose(mFile);
- mFile = NULL;
+ close(mFd);
+ mFd = -1;
+ mInitCheck = NO_INIT;
mStarted = false;
return err;
}
@@ -665,7 +672,7 @@
// Moov box
lseek64(mFd, mFreeBoxOffset, SEEK_SET);
mOffset = mFreeBoxOffset;
- write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset, mFile);
+ write(mMoovBoxBuffer, 1, mMoovBoxBufferOffset);
// Free box
lseek64(mFd, mOffset, SEEK_SET);
@@ -682,9 +689,9 @@
CHECK(mBoxes.empty());
- fflush(mFile);
- fclose(mFile);
- mFile = NULL;
+ close(mFd);
+ mFd = -1;
+ mInitCheck = NO_INIT;
mStarted = false;
return err;
}
@@ -763,20 +770,21 @@
}
size_t MPEG4Writer::write(
- const void *ptr, size_t size, size_t nmemb, FILE *stream) {
+ const void *ptr, size_t size, size_t nmemb) {
const size_t bytes = size * nmemb;
- int fd = fileno(stream);
if (mWriteMoovBoxToMemory) {
+ // This happens only when we write the moov box at the end of
+ // recording, not for each output video/audio frame we receive.
off64_t moovBoxSize = 8 + mMoovBoxBufferOffset + bytes;
if (moovBoxSize > mEstimatedMoovBoxSize) {
for (List<off64_t>::iterator it = mBoxes.begin();
it != mBoxes.end(); ++it) {
(*it) += mOffset;
}
- lseek64(fd, mOffset, SEEK_SET);
- ::write(fd, mMoovBoxBuffer, mMoovBoxBufferOffset);
- ::write(fd, ptr, size * nmemb);
+ lseek64(mFd, mOffset, SEEK_SET);
+ ::write(mFd, mMoovBoxBuffer, mMoovBoxBufferOffset);
+ ::write(mFd, ptr, size * nmemb);
mOffset += (bytes + mMoovBoxBufferOffset);
free(mMoovBoxBuffer);
mMoovBoxBuffer = NULL;
@@ -788,7 +796,7 @@
mMoovBoxBufferOffset += bytes;
}
} else {
- ::write(fd, ptr, size * nmemb);
+ ::write(mFd, ptr, size * nmemb);
mOffset += bytes;
}
return bytes;
@@ -822,36 +830,36 @@
}
void MPEG4Writer::writeInt8(int8_t x) {
- write(&x, 1, 1, mFile);
+ write(&x, 1, 1);
}
void MPEG4Writer::writeInt16(int16_t x) {
x = htons(x);
- write(&x, 1, 2, mFile);
+ write(&x, 1, 2);
}
void MPEG4Writer::writeInt32(int32_t x) {
x = htonl(x);
- write(&x, 1, 4, mFile);
+ write(&x, 1, 4);
}
void MPEG4Writer::writeInt64(int64_t x) {
x = hton64(x);
- write(&x, 1, 8, mFile);
+ write(&x, 1, 8);
}
void MPEG4Writer::writeCString(const char *s) {
size_t n = strlen(s);
- write(s, 1, n + 1, mFile);
+ write(s, 1, n + 1);
}
void MPEG4Writer::writeFourcc(const char *s) {
CHECK_EQ(strlen(s), 4);
- write(s, 1, 4, mFile);
+ write(s, 1, 4);
}
void MPEG4Writer::write(const void *data, size_t size) {
- write(data, 1, size, mFile);
+ write(data, 1, size);
}
bool MPEG4Writer::isFileStreamable() const {
diff --git a/media/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp
index 155fd96..5a033e1 100644
--- a/media/libstagefright/rtsp/ARTPWriter.cpp
+++ b/media/libstagefright/rtsp/ARTPWriter.cpp
@@ -46,7 +46,7 @@
ARTPWriter::ARTPWriter(int fd)
: mFlags(0),
- mFd(fd),
+ mFd(dup(fd)),
mLooper(new ALooper),
mReflector(new AHandlerReflector<ARTPWriter>(this)) {
CHECK_GE(fd, 0);
diff --git a/media/tests/CameraBrowser/Android.mk b/media/tests/CameraBrowser/Android.mk
index 1d81129..295b3e6 100644
--- a/media/tests/CameraBrowser/Android.mk
+++ b/media/tests/CameraBrowser/Android.mk
@@ -1,7 +1,7 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-subdir-java-files)
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
index 34dbace..82753b2 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
@@ -43,13 +43,6 @@
public KeyguardViewBase(Context context) {
super(context);
-
- // drop shadow below status bar in keyguard too
- mForegroundInPadding = false;
- setForegroundGravity(Gravity.FILL_HORIZONTAL | Gravity.TOP);
- setForeground(
- context.getResources().getDrawable(
- com.android.internal.R.drawable.title_bar_shadow));
}
// used to inject callback
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 84dd022..51b5947 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -343,7 +343,7 @@
lSessionId = *sessionId;
} else {
// if no audio session id is provided, create one here
- lSessionId = nextUniqueId();
+ lSessionId = nextUniqueId_l();
if (sessionId != NULL) {
*sessionId = lSessionId;
}
@@ -3699,7 +3699,7 @@
if (sessionId != NULL && *sessionId != AudioSystem::SESSION_OUTPUT_MIX) {
lSessionId = *sessionId;
} else {
- lSessionId = nextUniqueId();
+ lSessionId = nextUniqueId_l();
if (sessionId != NULL) {
*sessionId = lSessionId;
}
@@ -4300,7 +4300,7 @@
mHardwareStatus = AUDIO_HW_IDLE;
if (output != 0) {
- int id = nextUniqueId();
+ int id = nextUniqueId_l();
if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ||
(format != AudioSystem::PCM_16_BIT) ||
(channels != AudioSystem::CHANNEL_OUT_STEREO)) {
@@ -4348,7 +4348,7 @@
return 0;
}
- int id = nextUniqueId();
+ int id = nextUniqueId_l();
DuplicatingThread *thread = new DuplicatingThread(this, thread1, id);
thread->addOutputTrack(thread2);
mPlaybackThreads.add(id, thread);
@@ -4473,7 +4473,7 @@
}
if (input != 0) {
- int id = nextUniqueId();
+ int id = nextUniqueId_l();
// Start record thread
thread = new RecordThread(this, input, reqSamplingRate, reqChannels, id);
mRecordThreads.add(id, thread);
@@ -4543,7 +4543,8 @@
int AudioFlinger::newAudioSessionId()
{
- return nextUniqueId();
+ AutoMutex _l(mLock);
+ return nextUniqueId_l();
}
// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
@@ -4578,9 +4579,10 @@
return thread;
}
-int AudioFlinger::nextUniqueId()
+// nextUniqueId_l() must be called with AudioFlinger::mLock held
+int AudioFlinger::nextUniqueId_l()
{
- return android_atomic_inc(&mNextUniqueId);
+ return mNextUniqueId++;
}
// ----------------------------------------------------------------------------
@@ -4967,7 +4969,7 @@
LOGV("createEffect_l() got effect %p on chain %p", effect == 0 ? 0 : effect.get(), chain.get());
if (effect == 0) {
- int id = mAudioFlinger->nextUniqueId();
+ int id = mAudioFlinger->nextUniqueId_l();
// Check CPU and memory usage
lStatus = AudioSystem::registerEffect(desc, mId, chain->strategy(), sessionId, id);
if (lStatus != NO_ERROR) {
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 5917632..f0ef867 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -785,7 +785,7 @@
float streamVolumeInternal(int stream) const { return mStreamTypes[stream].volume; }
void audioConfigChanged_l(int event, int ioHandle, void *param2);
- int nextUniqueId();
+ int nextUniqueId_l();
status_t moveEffectChain_l(int session,
AudioFlinger::PlaybackThread *srcThread,
AudioFlinger::PlaybackThread *dstThread,
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java
index 2b43b013..53a19f5 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -41,9 +41,8 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
import android.content.pm.PackageManager.NameNotFoundException;
-import android.net.ConnectivityManager;
+import android.content.pm.ResolveInfo;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
@@ -55,9 +54,9 @@
import android.os.ServiceManager;
import android.os.SystemClock;
import android.provider.Settings;
-import android.util.Slog;
import android.util.PrintWriterPrinter;
import android.util.Printer;
+import android.util.Slog;
import android.util.Xml;
import android.view.WindowManagerPolicy;
@@ -89,9 +88,6 @@
= "com.android.server.ACTION_EXPIRED_PASSWORD_NOTIFICATION";
private static final long MS_PER_DAY = 86400 * 1000;
- private static final long MS_PER_HOUR = 3600 * 1000;
- private static final long MS_PER_MINUTE = 60 * 1000;
- private static final long MIN_TIMEOUT = 86400 * 1000; // minimum expiration timeout is 1 day
final Context mContext;
final MyPackageMonitor mMonitor;
@@ -364,6 +360,7 @@
}
class MyPackageMonitor extends PackageMonitor {
+ @Override
public void onSomePackagesChanged() {
synchronized (DevicePolicyManagerService.this) {
boolean removed = false;
@@ -410,13 +407,6 @@
context.registerReceiver(mReceiver, filter);
}
- static String countdownString(long time) {
- long days = time / MS_PER_DAY;
- long hours = (time / MS_PER_HOUR) % 24;
- long minutes = (time / MS_PER_MINUTE) % 60;
- return days + "d" + hours + "h" + minutes + "m";
- }
-
protected void setExpirationAlarmCheckLocked(Context context) {
final long expiration = getPasswordExpirationLocked(null);
final long now = System.currentTimeMillis();
@@ -430,12 +420,17 @@
alarmTime = now + MS_PER_DAY;
}
- AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
- PendingIntent pi = PendingIntent.getBroadcast(context, REQUEST_EXPIRE_PASSWORD,
- new Intent(ACTION_EXPIRED_PASSWORD_NOTIFICATION),
- PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT);
- am.cancel(pi);
- am.set(AlarmManager.RTC, alarmTime, pi);
+ long token = Binder.clearCallingIdentity();
+ try {
+ AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+ PendingIntent pi = PendingIntent.getBroadcast(context, REQUEST_EXPIRE_PASSWORD,
+ new Intent(ACTION_EXPIRED_PASSWORD_NOTIFICATION),
+ PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT);
+ am.cancel(pi);
+ am.set(AlarmManager.RTC, alarmTime, pi);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
private IPowerManager getIPowerManager() {
@@ -993,8 +988,8 @@
if (who == null) {
throw new NullPointerException("ComponentName is null");
}
- if (timeout != 0L && timeout < MIN_TIMEOUT) {
- throw new IllegalArgumentException("Timeout must be > " + MIN_TIMEOUT + "ms");
+ if (timeout < 0) {
+ throw new IllegalArgumentException("Timeout must be >= 0 ms");
}
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD);
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index a0a1974..c121808 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -4578,6 +4578,80 @@
mHandler.sendMessage(msg);
}
+ public void setInstallerPackageName(String targetPackage,
+ String installerPackageName) {
+ PackageSetting pkgSetting;
+ final int uid = Binder.getCallingUid();
+ final int permission = mContext.checkCallingPermission(
+ android.Manifest.permission.INSTALL_PACKAGES);
+ final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
+ synchronized (mPackages) {
+ PackageSetting targetPackageSetting = mSettings.mPackages.get(targetPackage);
+ if (targetPackageSetting == null) {
+ throw new IllegalArgumentException("Unknown target package: " + targetPackage);
+ }
+
+ PackageSetting installerPackageSetting;
+ if (installerPackageName != null) {
+ installerPackageSetting = mSettings.mPackages.get(installerPackageName);
+ if (installerPackageSetting == null) {
+ throw new IllegalArgumentException("Unknown installer package: "
+ + installerPackageName);
+ }
+ } else {
+ installerPackageSetting = null;
+ }
+
+ Signature[] callerSignature;
+ Object obj = mSettings.getUserIdLP(uid);
+ if (obj != null) {
+ if (obj instanceof SharedUserSetting) {
+ callerSignature = ((SharedUserSetting)obj).signatures.mSignatures;
+ } else if (obj instanceof PackageSetting) {
+ callerSignature = ((PackageSetting)obj).signatures.mSignatures;
+ } else {
+ throw new SecurityException("Bad object " + obj + " for uid " + uid);
+ }
+ } else {
+ throw new SecurityException("Unknown calling uid " + uid);
+ }
+
+ // Verify: can't set installerPackageName to a package that is
+ // not signed with the same cert as the caller.
+ if (installerPackageSetting != null) {
+ if (checkSignaturesLP(callerSignature,
+ installerPackageSetting.signatures.mSignatures)
+ != PackageManager.SIGNATURE_MATCH) {
+ throw new SecurityException(
+ "Caller does not have same cert as new installer package "
+ + installerPackageName);
+ }
+ }
+
+ // Verify: if target already has an installer package, it must
+ // be signed with the same cert as the caller.
+ if (targetPackageSetting.installerPackageName != null) {
+ PackageSetting setting = mSettings.mPackages.get(
+ targetPackageSetting.installerPackageName);
+ // If the currently set package isn't valid, then it's always
+ // okay to change it.
+ if (setting != null) {
+ if (checkSignaturesLP(callerSignature,
+ setting.signatures.mSignatures)
+ != PackageManager.SIGNATURE_MATCH) {
+ throw new SecurityException(
+ "Caller does not have same cert as old installer package "
+ + targetPackageSetting.installerPackageName);
+ }
+ }
+ }
+
+ // Okay!
+ targetPackageSetting.installerPackageName = installerPackageName;
+ scheduleWriteSettingsLocked();
+ }
+ }
+
public void setPackageObbPath(String packageName, String path) {
if (DEBUG_OBB)
Log.v(TAG, "Setting .obb path for " + packageName + " to: " + path);
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index f0cbaa0..615870b1 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -341,6 +341,12 @@
throw new UnsupportedOperationException();
}
+ @Override
+ public void setInstallerPackageName(String targetPackage,
+ String installerPackageName) {
+ throw new UnsupportedOperationException();
+ }
+
/**
* @hide - to match hiding in superclass
*/
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index a5f3456..cea07af 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -18,6 +18,7 @@
import com.android.layoutlib.api.ILayoutLog;
import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.layoutlib.bridge.impl.Stack;
import android.graphics.Paint_Delegate.FontInfo;
import android.text.TextUtils;
@@ -32,7 +33,6 @@
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.util.List;
-import java.util.Stack;
/**
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index ac7fada..2ddabdf 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -22,6 +22,7 @@
import com.android.layoutlib.api.IStyleResourceValue;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.BridgeConstants;
+import com.android.layoutlib.bridge.impl.Stack;
import com.android.layoutlib.bridge.impl.TempResourceValue;
import android.app.Activity;
@@ -65,7 +66,6 @@
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Map;
-import java.util.Stack;
import java.util.TreeMap;
import java.util.Map.Entry;
@@ -191,14 +191,33 @@
return mDefaultPropMaps.get(key);
}
+ /**
+ * Adds a parser to the stack.
+ * @param parser the parser to add.
+ */
public void pushParser(BridgeXmlBlockParser parser) {
mParserStack.push(parser);
}
+ /**
+ * Removes the parser at the top of the stack
+ */
public void popParser() {
mParserStack.pop();
}
+ /**
+ * Returns the current parser at the top the of the stack.
+ * @return a parser or null.
+ */
+ public BridgeXmlBlockParser getCurrentParser() {
+ return mParserStack.peek();
+ }
+
+ /**
+ * Returns the previous parser.
+ * @return a parser or null if there isn't any previous parser
+ */
public BridgeXmlBlockParser getPreviousParser() {
if (mParserStack.size() < 2) {
return null;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
index bfbb01a8..1011173 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
@@ -220,24 +220,37 @@
IResourceValue value = getResourceValue(id, mPlatformResourceFlag);
if (value != null) {
- File xml = new File(value.getValue());
- if (xml.isFile()) {
- // we need to create a pull parser around the layout XML file, and then
- // give that to our XmlBlockParser
- try {
- KXmlParser parser = new KXmlParser();
- parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
- parser.setInput(new FileReader(xml));
+ XmlPullParser parser = null;
- return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]);
- } catch (XmlPullParserException e) {
- mContext.getLogger().error(e);
-
- // we'll return null below.
- } catch (FileNotFoundException e) {
- // this shouldn't happen since we check above.
+ try {
+ // check if the current parser can provide us with a custom parser.
+ BridgeXmlBlockParser currentParser = mContext.getCurrentParser();
+ if (currentParser != null) {
+ parser = currentParser.getParser(value.getName());
}
+
+ // create a new one manually if needed.
+ if (parser == null) {
+ File xml = new File(value.getValue());
+ if (xml.isFile()) {
+ // we need to create a pull parser around the layout XML file, and then
+ // give that to our XmlBlockParser
+ parser = new KXmlParser();
+ parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
+ parser.setInput(new FileReader(xml));
+ }
+ }
+
+ if (parser != null) {
+ return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]);
+ }
+ } catch (XmlPullParserException e) {
+ mContext.getLogger().error(e);
+ // we'll return null below.
+ } catch (FileNotFoundException e) {
+ // this shouldn't happen since we check above.
}
+
}
// id was not found or not resolved. Throw a NotFoundException.
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java
index 073a019..c3d0b14a 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java
@@ -56,13 +56,23 @@
mPlatformFile = platformFile;
mAttrib = new BridgeXmlPullAttributes(parser, context, mPlatformFile);
- mContext.pushParser(this);
+ if (mContext != null) {
+ mContext.pushParser(this);
+ }
}
public boolean isPlatformFile() {
return mPlatformFile;
}
+ public IXmlPullParser getParser(String layoutName) {
+ if (mParser instanceof IXmlPullParser) {
+ return ((IXmlPullParser)mParser).getParser(layoutName);
+ }
+
+ return null;
+ }
+
public Object getViewKey() {
if (mParser instanceof IXmlPullParser) {
return ((IXmlPullParser)mParser).getViewKey();
@@ -238,7 +248,7 @@
}
int ev = mParser.next();
- if (ev == END_TAG && mParser.getDepth() == 1) {
+ if (ev == END_TAG && mParser.getDepth() == 1 && mContext != null) {
// done with parser remove it from the context stack.
mContext.popParser();
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java
index b0316a3..2e3f9a8 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java
@@ -25,6 +25,7 @@
import com.android.layoutlib.api.SceneResult;
import com.android.layoutlib.api.ViewInfo;
import com.android.layoutlib.api.IDensityBasedResourceValue.Density;
+import com.android.layoutlib.api.SceneParams.RenderingMode;
import com.android.layoutlib.bridge.BridgeConstants;
import com.android.layoutlib.bridge.android.BridgeContext;
import com.android.layoutlib.bridge.android.BridgeInflater;
@@ -259,22 +260,32 @@
int renderScreenWidth = mParams.getScreenWidth();
int renderScreenHeight = mParams.getScreenHeight();
- if (mParams.getRenderFullSize()) {
+ RenderingMode renderingMode = mParams.getRenderingMode();
+
+ if (renderingMode != RenderingMode.NORMAL) {
// measure the full size needed by the layout.
w_spec = MeasureSpec.makeMeasureSpec(renderScreenWidth,
- MeasureSpec.UNSPECIFIED); // this lets us know the actual needed size
+ renderingMode.isHorizExpand() ?
+ MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
+ : MeasureSpec.EXACTLY);
h_spec = MeasureSpec.makeMeasureSpec(renderScreenHeight - mScreenOffset,
- MeasureSpec.UNSPECIFIED); // this lets us know the actual needed size
+ renderingMode.isVertExpand() ?
+ MeasureSpec.UNSPECIFIED // this lets us know the actual needed size
+ : MeasureSpec.EXACTLY);
mViewRoot.measure(w_spec, h_spec);
- int neededWidth = mViewRoot.getChildAt(0).getMeasuredWidth();
- if (neededWidth > renderScreenWidth) {
- renderScreenWidth = neededWidth;
+ if (renderingMode.isHorizExpand()) {
+ int neededWidth = mViewRoot.getChildAt(0).getMeasuredWidth();
+ if (neededWidth > renderScreenWidth) {
+ renderScreenWidth = neededWidth;
+ }
}
- int neededHeight = mViewRoot.getChildAt(0).getMeasuredHeight();
- if (neededHeight > renderScreenHeight - mScreenOffset) {
- renderScreenHeight = neededHeight + mScreenOffset;
+ if (renderingMode.isVertExpand()) {
+ int neededHeight = mViewRoot.getChildAt(0).getMeasuredHeight();
+ if (neededHeight > renderScreenHeight - mScreenOffset) {
+ renderScreenHeight = neededHeight + mScreenOffset;
+ }
}
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Stack.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Stack.java
new file mode 100644
index 0000000..9bd0015
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Stack.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.layoutlib.bridge.impl;
+
+import java.util.ArrayList;
+
+/**
+ * Custom Stack implementation on top of an {@link ArrayList} instead of
+ * using {@link java.util.Stack} which is on top of a vector.
+ *
+ * @param <T>
+ */
+public class Stack<T> extends ArrayList<T> {
+
+ private static final long serialVersionUID = 1L;
+
+ public Stack() {
+ super();
+ }
+
+ public Stack(int size) {
+ super(size);
+ }
+
+ /**
+ * Pushes the given object to the stack
+ * @param object the object to push
+ */
+ public void push(T object) {
+ add(object);
+ }
+
+ /**
+ * Remove the object at the top of the stack and returns it.
+ * @return the removed object or null if the stack was empty.
+ */
+ public T pop() {
+ if (size() > 0) {
+ return remove(size() - 1);
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the object at the top of the stack.
+ * @return the object at the top or null if the stack is empty.
+ */
+ public T peek() {
+ if (size() > 0) {
+ return get(size() - 1);
+ }
+
+ return null;
+ }
+}