Merge "Fix bug 5226097 - App compatibility issues around new ListView fixes"
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 029d107..be9070d 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -189,6 +189,7 @@
public static final String KEY_ERROR_CODE = "errorCode";
public static final String KEY_ERROR_MESSAGE = "errorMessage";
public static final String KEY_USERDATA = "userdata";
+
/**
* Authenticators using 'customTokens' option will also get the UID of the
* caller
@@ -814,11 +815,13 @@
final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) {
if (account == null) throw new IllegalArgumentException("account is null");
if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
+ final Bundle optionsIn = options == null ? new Bundle() : options;
+ optionsIn.putString(KEY_ANDROID_PACKAGE_NAME, mContext.getPackageName());
return new AmsTask(activity, handler, callback) {
public void doWork() throws RemoteException {
mService.getAuthToken(mResponse, account, authTokenType,
false /* notifyOnAuthFailure */, true /* expectActivityLaunch */,
- options);
+ optionsIn);
}
}.start();
}
@@ -895,16 +898,11 @@
*/
@Deprecated
public AccountManagerFuture<Bundle> getAuthToken(
- final Account account, final String authTokenType, final boolean notifyAuthFailure,
+ final Account account, final String authTokenType,
+ final boolean notifyAuthFailure,
AccountManagerCallback<Bundle> callback, Handler handler) {
- if (account == null) throw new IllegalArgumentException("account is null");
- if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
- return new AmsTask(null, handler, callback) {
- public void doWork() throws RemoteException {
- mService.getAuthToken(mResponse, account, authTokenType,
- notifyAuthFailure, false /* expectActivityLaunch */, null /* options */);
- }
- }.start();
+ return getAuthToken(account, authTokenType, null, notifyAuthFailure, callback,
+ handler);
}
/**
@@ -978,15 +976,18 @@
* account before requesting an auth token.
*/
public AccountManagerFuture<Bundle> getAuthToken(
- final Account account, final String authTokenType,
- final Bundle options, final boolean notifyAuthFailure,
+ final Account account, final String authTokenType, final Bundle options,
+ final boolean notifyAuthFailure,
AccountManagerCallback<Bundle> callback, Handler handler) {
+
if (account == null) throw new IllegalArgumentException("account is null");
if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
+ final Bundle optionsIn = options == null ? new Bundle() : options;
+ optionsIn.putString(KEY_ANDROID_PACKAGE_NAME, mContext.getPackageName());
return new AmsTask(null, handler, callback) {
public void doWork() throws RemoteException {
mService.getAuthToken(mResponse, account, authTokenType,
- notifyAuthFailure, false /* expectActivityLaunch */, options);
+ notifyAuthFailure, false /* expectActivityLaunch */, optionsIn);
}
}.start();
}
@@ -1044,10 +1045,14 @@
final Bundle addAccountOptions,
final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) {
if (accountType == null) throw new IllegalArgumentException("accountType is null");
+ final Bundle options = (addAccountOptions == null) ? new Bundle() :
+ addAccountOptions;
+ options.putString(KEY_ANDROID_PACKAGE_NAME, mContext.getPackageName());
+
return new AmsTask(activity, handler, callback) {
public void doWork() throws RemoteException {
mService.addAcount(mResponse, accountType, authTokenType,
- requiredFeatures, activity != null, addAccountOptions);
+ requiredFeatures, activity != null, options);
}
}.start();
}
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index 20d5b96..173da8d 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -16,10 +16,6 @@
package android.accounts;
-import com.android.internal.R;
-import com.android.internal.telephony.ITelephony;
-import com.android.internal.telephony.TelephonyIntents;
-
import android.Manifest;
import android.app.ActivityManager;
import android.app.Notification;
@@ -51,13 +47,13 @@
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.SystemClock;
-import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
+import com.android.internal.R;
+
import java.io.File;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -924,9 +920,6 @@
if (account == null) throw new IllegalArgumentException("account is null");
if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
checkBinderPermission(Manifest.permission.USE_CREDENTIALS);
- final int callerUid = Binder.getCallingUid();
- final int callerPid = Binder.getCallingPid();
-
AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo =
mAuthenticatorCache.getServiceInfo(
AuthenticatorDescription.newKey(account.type));
@@ -934,20 +927,19 @@
authenticatorInfo != null && authenticatorInfo.type.customTokens;
// skip the check if customTokens
+ final int callerUid = Binder.getCallingUid();
final boolean permissionGranted = customTokens ||
permissionIsGranted(account, authTokenType, callerUid);
final Bundle loginOptions = (loginOptionsIn == null) ? new Bundle() :
loginOptionsIn;
- if (customTokens) {
- // let authenticator know the identity of the caller
- loginOptions.putInt(AccountManager.KEY_CALLER_UID, callerUid);
- loginOptions.putInt(AccountManager.KEY_CALLER_PID, callerPid);
- if (notifyOnAuthFailure) {
- loginOptions.putBoolean(AccountManager.KEY_NOTIFY_ON_FAILURE, true);
- }
+ // let authenticator know the identity of the caller
+ loginOptions.putInt(AccountManager.KEY_CALLER_UID, callerUid);
+ loginOptions.putInt(AccountManager.KEY_CALLER_PID, Binder.getCallingPid());
+ if (notifyOnAuthFailure) {
+ loginOptions.putBoolean(AccountManager.KEY_NOTIFY_ON_FAILURE, true);
}
-
+
long identityToken = clearCallingIdentity();
try {
// if the caller has permission, do the peek. otherwise go the more expensive
@@ -1120,7 +1112,7 @@
public void addAcount(final IAccountManagerResponse response, final String accountType,
final String authTokenType, final String[] requiredFeatures,
- final boolean expectActivityLaunch, final Bundle options) {
+ final boolean expectActivityLaunch, final Bundle optionsIn) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "addAccount: accountType " + accountType
+ ", response " + response
@@ -1133,6 +1125,13 @@
if (response == null) throw new IllegalArgumentException("response is null");
if (accountType == null) throw new IllegalArgumentException("accountType is null");
checkManageAccountsPermission();
+
+ final int pid = Binder.getCallingPid();
+ final int uid = Binder.getCallingUid();
+ final Bundle options = (optionsIn == null) ? new Bundle() : optionsIn;
+ options.putInt(AccountManager.KEY_CALLER_UID, uid);
+ options.putInt(AccountManager.KEY_CALLER_PID, pid);
+
long identityToken = clearCallingIdentity();
try {
new Session(response, accountType, expectActivityLaunch,
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index 68a6b3e..a52d48e 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -723,7 +723,7 @@
float ret = 0;
int contextLen = contextEnd - contextStart;
- if (needWidth || (c != null && (wp.bgColor != 0 || wp.underlineCount != 0 || runIsRtl))) {
+ if (needWidth || (c != null && (wp.bgColor != 0 || wp.underlineColor != 0 || runIsRtl))) {
int flags = runIsRtl ? Paint.DIRECTION_RTL : Paint.DIRECTION_LTR;
if (mCharsValid) {
ret = wp.getTextRunAdvances(mChars, start, runLen,
@@ -753,7 +753,7 @@
wp.setColor(previousColor);
}
- if (wp.underlineCount != 0) {
+ if (wp.underlineColor != 0) {
// kStdUnderline_Offset = 1/9, defined in SkTextFormatParams.h
float underlineTop = y + wp.baselineShift + (1.0f / 9.0f) * wp.getTextSize();
@@ -764,11 +764,8 @@
wp.setStyle(Paint.Style.FILL);
wp.setAntiAlias(true);
- for (int i = 0; i < wp.underlineCount; i++) {
- wp.setColor(wp.underlineColors[i]);
- c.drawRect(x, underlineTop, x + ret, underlineTop + wp.underlineThicknesses[i],
- wp);
- }
+ wp.setColor(wp.underlineColor);
+ c.drawRect(x, underlineTop, x + ret, underlineTop + wp.underlineThickness, wp);
wp.setStyle(previousStyle);
wp.setColor(previousColor);
diff --git a/core/java/android/text/TextPaint.java b/core/java/android/text/TextPaint.java
index afd9892..0447117 100644
--- a/core/java/android/text/TextPaint.java
+++ b/core/java/android/text/TextPaint.java
@@ -24,8 +24,6 @@
*/
public class TextPaint extends Paint {
- private static final int DEFAULT_UNDERLINE_SIZE = 3;
-
// Special value 0 means no background paint
public int bgColor;
public int baselineShift;
@@ -36,17 +34,12 @@
* Special value 0 means no custom underline
* @hide
*/
- public int[] underlineColors;
+ public int underlineColor = 0;
/**
* Defined as a multiplier of the default underline thickness. Use 1.0f for default thickness.
* @hide
*/
- public float[] underlineThicknesses;
- /**
- * The number of underlines currently stored in the array. If 0, no underline is drawn.
- * @hide
- */
- public int underlineCount;
+ public float underlineThickness;
public TextPaint() {
super();
@@ -72,16 +65,8 @@
linkColor = tp.linkColor;
drawableState = tp.drawableState;
density = tp.density;
-
- if (tp.underlineColors != null) {
- if (underlineColors == null || underlineColors.length < tp.underlineCount) {
- underlineColors = new int[tp.underlineCount];
- underlineThicknesses = new float[tp.underlineCount];
- }
- System.arraycopy(tp.underlineColors, 0, underlineColors, 0, tp.underlineCount);
- System.arraycopy(tp.underlineThicknesses, 0, underlineThicknesses, 0, tp.underlineCount);
- }
- underlineCount = tp.underlineCount;
+ underlineColor = tp.underlineColor;
+ underlineThickness = tp.underlineThickness;
}
/**
@@ -91,31 +76,7 @@
* @hide
*/
public void setUnderlineText(int color, float thickness) {
- if (color == 0) {
- // No underline
- return;
- }
-
- if (underlineCount == 0) {
- underlineColors = new int[DEFAULT_UNDERLINE_SIZE];
- underlineThicknesses = new float[DEFAULT_UNDERLINE_SIZE];
- underlineColors[underlineCount] = color;
- underlineThicknesses[underlineCount] = thickness;
- underlineCount++;
- } else {
- if (underlineCount == underlineColors.length) {
- int[] newColors = new int[underlineColors.length + DEFAULT_UNDERLINE_SIZE];
- float[] newThickness = new float[underlineThicknesses.length
- + DEFAULT_UNDERLINE_SIZE];
- System.arraycopy(underlineColors, 0, newColors, 0, underlineColors.length);
- System.arraycopy(
- underlineThicknesses, 0, newThickness, 0, underlineThicknesses.length);
- underlineColors = newColors;
- underlineThicknesses = newThickness;
- }
- underlineColors[underlineCount] = color;
- underlineThicknesses[underlineCount] = thickness;
- underlineCount++;
- }
+ underlineColor = color;
+ underlineThickness = thickness;
}
}
diff --git a/core/java/android/text/style/SuggestionSpan.java b/core/java/android/text/style/SuggestionSpan.java
index 51e9d7d..1379dd2d 100644
--- a/core/java/android/text/style/SuggestionSpan.java
+++ b/core/java/android/text/style/SuggestionSpan.java
@@ -108,7 +108,8 @@
/**
* @param context Context for the application
* @param locale locale Locale of the suggestions
- * @param suggestions Suggestions for the string under the span
+ * @param suggestions Suggestions for the string under the span. Only the first up to
+ * {@link SuggestionSpan#SUGGESTIONS_MAX_SIZE} will be considered.
* @param flags Additional flags indicating how this span is handled in TextView
* @param notificationTargetClass if not null, this class will get notified when the user
* selects one of the suggestions.
@@ -258,10 +259,16 @@
@Override
public void updateDrawState(TextPaint tp) {
- if ((mFlags & FLAG_MISSPELLED) != 0) {
- tp.setUnderlineText(mMisspelledUnderlineColor, mMisspelledUnderlineThickness);
- } else if ((mFlags & FLAG_EASY_CORRECT) != 0) {
- tp.setUnderlineText(mEasyCorrectUnderlineColor, mEasyCorrectUnderlineThickness);
+ final boolean misspelled = (mFlags & FLAG_MISSPELLED) != 0;
+ final boolean easy = (mFlags & FLAG_EASY_CORRECT) != 0;
+ if (easy) {
+ if (!misspelled) {
+ tp.setUnderlineText(mEasyCorrectUnderlineColor, mEasyCorrectUnderlineThickness);
+ } else if (tp.underlineColor == 0) {
+ // Spans are rendered in an arbitrary order. Since misspelled is less prioritary
+ // than just easy, do not apply misspelled if an easy (or a mispelled) has been set
+ tp.setUnderlineText(mMisspelledUnderlineColor, mMisspelledUnderlineThickness);
+ }
}
}
@@ -272,8 +279,15 @@
*/
public int getUnderlineColor() {
// The order here should match what is used in updateDrawState
- if ((mFlags & FLAG_MISSPELLED) != 0) return mMisspelledUnderlineColor;
- if ((mFlags & FLAG_EASY_CORRECT) != 0) return mEasyCorrectUnderlineColor;
+ final boolean misspelled = (mFlags & FLAG_MISSPELLED) != 0;
+ final boolean easy = (mFlags & FLAG_EASY_CORRECT) != 0;
+ if (easy) {
+ if (!misspelled) {
+ return mEasyCorrectUnderlineColor;
+ } else {
+ return mMisspelledUnderlineColor;
+ }
+ }
return 0;
}
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index fb3f6e8..81f9d78 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -164,11 +164,14 @@
final W mWindow;
+ final int mTargetSdkVersion;
+
View mView;
View mFocusedView;
View mRealFocusedView; // this is not set to null in touch mode
int mViewVisibility;
boolean mAppVisible = true;
+ int mOrigWindowType = -1;
// Set to true if the owner of this window is in the stopped state,
// so the window should no longer be active.
@@ -331,6 +334,7 @@
mVisRect = new Rect();
mWinFrame = new Rect();
mWindow = new W(this);
+ mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
mInputMethodCallback = new InputMethodCallback(this);
mViewVisibility = View.GONE;
mTransparentRegion = new Region();
@@ -461,6 +465,7 @@
mInputChannel = new InputChannel();
}
try {
+ mOrigWindowType = mWindowAttributes.type;
res = sWindowSession.add(mWindow, mWindowAttributes,
getHostVisibility(), mAttachInfo.mContentInsets,
mInputChannel);
@@ -3481,6 +3486,14 @@
}
mPendingConfiguration.seq = 0;
//Log.d(TAG, ">>>>>> CALLING relayout");
+ if (params != null && mOrigWindowType != params.type) {
+ // For compatibility with old apps, don't crash here.
+ if (mTargetSdkVersion < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
+ Slog.w(TAG, "Window type can not be changed after "
+ + "the window is added; ignoring change of " + mView);
+ params.type = mOrigWindowType;
+ }
+ }
int relayoutResult = sWindowSession.relayout(
mWindow, params,
(int) (mView.getMeasuredWidth() * appScale + 0.5f),
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 70d2bd7..ecd99b2 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -9560,6 +9560,9 @@
private int mNumberOfSuggestions;
private boolean mCursorWasVisibleBeforeSuggestions;
private SuggestionAdapter mSuggestionsAdapter;
+ private final Comparator<SuggestionSpan> mSuggestionSpanComparator;
+ private final HashMap<SuggestionSpan, Integer> mSpansLengths;
+
private class CustomPopupWindow extends PopupWindow {
public CustomPopupWindow(Context context, int defStyle) {
@@ -9585,6 +9588,8 @@
public SuggestionsPopupWindow() {
mCursorWasVisibleBeforeSuggestions = mCursorVisible;
+ mSuggestionSpanComparator = new SuggestionSpanComparator();
+ mSpansLengths = new HashMap<SuggestionSpan, Integer>();
}
@Override
@@ -9663,6 +9668,26 @@
}
}
+ private class SuggestionSpanComparator implements Comparator<SuggestionSpan> {
+ public int compare(SuggestionSpan span1, SuggestionSpan span2) {
+ final int flag1 = span1.getFlags();
+ final int flag2 = span2.getFlags();
+ if (flag1 != flag2) {
+ // The order here should match what is used in updateDrawState
+ final boolean easy1 = (flag1 & SuggestionSpan.FLAG_EASY_CORRECT) != 0;
+ final boolean easy2 = (flag2 & SuggestionSpan.FLAG_EASY_CORRECT) != 0;
+ final boolean misspelled1 = (flag1 & SuggestionSpan.FLAG_MISSPELLED) != 0;
+ final boolean misspelled2 = (flag2 & SuggestionSpan.FLAG_MISSPELLED) != 0;
+ if (easy1 && !misspelled1) return -1;
+ if (easy2 && !misspelled2) return 1;
+ if (misspelled1) return -1;
+ if (misspelled2) return 1;
+ }
+
+ return mSpansLengths.get(span1).intValue() - mSpansLengths.get(span2).intValue();
+ }
+ }
+
/**
* Returns the suggestion spans that cover the current cursor position. The suggestion
* spans are sorted according to the length of text that they are attached to.
@@ -9672,24 +9697,16 @@
Spannable spannable = (Spannable) TextView.this.mText;
SuggestionSpan[] suggestionSpans = spannable.getSpans(pos, pos, SuggestionSpan.class);
- // Cache the span length for performance reason.
- final HashMap<SuggestionSpan, Integer> spansLengths =
- new HashMap<SuggestionSpan, Integer>();
-
+ mSpansLengths.clear();
for (SuggestionSpan suggestionSpan : suggestionSpans) {
int start = spannable.getSpanStart(suggestionSpan);
int end = spannable.getSpanEnd(suggestionSpan);
- spansLengths.put(suggestionSpan, Integer.valueOf(end - start));
+ mSpansLengths.put(suggestionSpan, Integer.valueOf(end - start));
}
- // The suggestions are sorted according to the lenght of the text that they cover
- // (shorter first)
- Arrays.sort(suggestionSpans, new Comparator<SuggestionSpan>() {
- public int compare(SuggestionSpan span1, SuggestionSpan span2) {
- return spansLengths.get(span1).intValue() - spansLengths.get(span2).intValue();
- }
- });
-
+ // The suggestions are sorted according to their types (easy correction first, then
+ // misspelled) and to the length of the text that they cover (shorter first).
+ Arrays.sort(suggestionSpans, mSuggestionSpanComparator);
return suggestionSpans;
}
diff --git a/media/libstagefright/AVIExtractor.cpp b/media/libstagefright/AVIExtractor.cpp
index 62d17da..4e46414 100644
--- a/media/libstagefright/AVIExtractor.cpp
+++ b/media/libstagefright/AVIExtractor.cpp
@@ -117,14 +117,12 @@
}
}
- int64_t timeUs =
- (mSampleIndex * 1000000ll * mTrack.mRate) / mTrack.mScale;
-
off64_t offset;
size_t size;
bool isKey;
+ int64_t timeUs;
status_t err = mExtractor->getSampleInfo(
- mTrackIndex, mSampleIndex, &offset, &size, &isKey);
+ mTrackIndex, mSampleIndex, &offset, &size, &isKey, &timeUs);
++mSampleIndex;
@@ -396,6 +394,8 @@
uint32_t rate = U32LE_AT(&data[20]);
uint32_t scale = U32LE_AT(&data[24]);
+ uint32_t sampleSize = U32LE_AT(&data[44]);
+
const char *mime = NULL;
Track::Kind kind = Track::OTHER;
@@ -427,6 +427,7 @@
track->mMeta = meta;
track->mRate = rate;
track->mScale = scale;
+ track->mBytesPerSample = sampleSize;
track->mKind = kind;
track->mNumSyncSamples = 0;
track->mThumbnailSampleSize = 0;
@@ -612,11 +613,12 @@
off64_t offset;
size_t size;
bool isKey;
- status_t err = getSampleInfo(0, 0, &offset, &size, &isKey);
+ int64_t timeUs;
+ status_t err = getSampleInfo(0, 0, &offset, &size, &isKey, &timeUs);
if (err != OK) {
mOffsetsAreAbsolute = !mOffsetsAreAbsolute;
- err = getSampleInfo(0, 0, &offset, &size, &isKey);
+ err = getSampleInfo(0, 0, &offset, &size, &isKey, &timeUs);
if (err != OK) {
return err;
@@ -630,8 +632,9 @@
for (size_t i = 0; i < mTracks.size(); ++i) {
Track *track = &mTracks.editItemAt(i);
- int64_t durationUs =
- (track->mSamples.size() * 1000000ll * track->mRate) / track->mScale;
+ int64_t durationUs;
+ CHECK_EQ((status_t)OK,
+ getSampleTime(i, track->mSamples.size() - 1, &durationUs));
LOGV("track %d duration = %.2f secs", i, durationUs / 1E6);
@@ -645,9 +648,10 @@
if (!strncasecmp("video/", mime.c_str(), 6)
&& track->mThumbnailSampleIndex >= 0) {
- int64_t thumbnailTimeUs =
- (track->mThumbnailSampleIndex * 1000000ll * track->mRate)
- / track->mScale;
+ int64_t thumbnailTimeUs;
+ CHECK_EQ((status_t)OK,
+ getSampleTime(i, track->mThumbnailSampleIndex,
+ &thumbnailTimeUs));
track->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs);
@@ -659,6 +663,21 @@
}
}
}
+
+ if (track->mBytesPerSample != 0) {
+ // Assume all chunks are the same size for now.
+
+ off64_t offset;
+ size_t size;
+ bool isKey;
+ int64_t sampleTimeUs;
+ CHECK_EQ((status_t)OK,
+ getSampleInfo(
+ i, 0,
+ &offset, &size, &isKey, &sampleTimeUs));
+
+ track->mRate *= size / track->mBytesPerSample;
+ }
}
mFoundIndex = true;
@@ -720,7 +739,9 @@
off64_t offset;
size_t size;
bool isKey;
- status_t err = getSampleInfo(trackIndex, 0, &offset, &size, &isKey);
+ int64_t timeUs;
+ status_t err =
+ getSampleInfo(trackIndex, 0, &offset, &size, &isKey, &timeUs);
if (err != OK) {
return err;
@@ -762,7 +783,8 @@
status_t AVIExtractor::getSampleInfo(
size_t trackIndex, size_t sampleIndex,
- off64_t *offset, size_t *size, bool *isKey) {
+ off64_t *offset, size_t *size, bool *isKey,
+ int64_t *sampleTimeUs) {
if (trackIndex >= mTracks.size()) {
return -ERANGE;
}
@@ -801,9 +823,20 @@
*isKey = info.mIsKey;
+ *sampleTimeUs = (sampleIndex * 1000000ll * track.mRate) / track.mScale;
+
return OK;
}
+status_t AVIExtractor::getSampleTime(
+ size_t trackIndex, size_t sampleIndex, int64_t *sampleTimeUs) {
+ off64_t offset;
+ size_t size;
+ bool isKey;
+ return getSampleInfo(
+ trackIndex, sampleIndex, &offset, &size, &isKey, sampleTimeUs);
+}
+
status_t AVIExtractor::getSampleIndexAtTime(
size_t trackIndex,
int64_t timeUs, MediaSource::ReadOptions::SeekMode mode,
diff --git a/media/libstagefright/include/AVIExtractor.h b/media/libstagefright/include/AVIExtractor.h
index 375a94d..b575347 100644
--- a/media/libstagefright/include/AVIExtractor.h
+++ b/media/libstagefright/include/AVIExtractor.h
@@ -54,6 +54,11 @@
uint32_t mRate;
uint32_t mScale;
+ // If bytes per sample == 0, each chunk represents a single sample,
+ // otherwise each chunk should me a multiple of bytes-per-sample in
+ // size.
+ uint32_t mBytesPerSample;
+
enum Kind {
AUDIO,
VIDEO,
@@ -84,7 +89,11 @@
status_t getSampleInfo(
size_t trackIndex, size_t sampleIndex,
- off64_t *offset, size_t *size, bool *isKey);
+ off64_t *offset, size_t *size, bool *isKey,
+ int64_t *sampleTimeUs);
+
+ status_t getSampleTime(
+ size_t trackIndex, size_t sampleIndex, int64_t *sampleTimeUs);
status_t getSampleIndexAtTime(
size_t trackIndex,
diff --git a/packages/SystemUI/res/drawable/notification_list_shadow.xml b/packages/SystemUI/res/drawable/notification_list_shadow.xml
new file mode 100644
index 0000000..7f33153
--- /dev/null
+++ b/packages/SystemUI/res/drawable/notification_list_shadow.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ >
+ <gradient
+ android:angle="90"
+ android:endColor="@color/notification_list_shadow_top"
+ android:startColor="#00000000"
+ android:type="linear"
+ />
+</shape>
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 0b3fb98..f9f31ca 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -32,6 +32,7 @@
android:paddingTop="3dp"
android:paddingBottom="5dp"
android:paddingRight="3dp"
+ android:background="@drawable/notification_header_bg"
>
<com.android.systemui.statusbar.policy.DateView android:id="@+id/date"
android:textAppearance="@style/TextAppearance.StatusBar.Clock"
@@ -104,12 +105,25 @@
android:fadingEdge="none"
android:overScrollMode="ifContentScrolls"
>
- <com.android.systemui.statusbar.policy.NotificationRowLayout
- android:id="@+id/latestItems"
+ <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- systemui:rowHeight="@dimen/notification_height"
+ android:orientation="vertical"
+ >
+ <com.android.systemui.statusbar.policy.NotificationRowLayout
+ android:id="@+id/latestItems"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ systemui:rowHeight="@dimen/notification_height"
+ android:background="@color/notification_list_shadow_top"
+ />
+ <ImageView
+ android:layout_width="match_parent"
+ android:layout_height="16dp"
+ android:src="@drawable/notification_list_shadow"
+ android:scaleType="fitXY"
/>
+ </LinearLayout>
</ScrollView>
<ImageView
diff --git a/packages/SystemUI/res/layout/status_bar_tracking.xml b/packages/SystemUI/res/layout/status_bar_tracking.xml
index 894248e..25c0237 100644
--- a/packages/SystemUI/res/layout/status_bar_tracking.xml
+++ b/packages/SystemUI/res/layout/status_bar_tracking.xml
@@ -30,7 +30,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:background="@drawable/status_bar_bg"
+ android:background="@drawable/notification_tracking_bg"
/>
<com.android.systemui.statusbar.phone.CloseDragHandle android:id="@+id/close"
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 670ee54..298536b4 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -25,4 +25,7 @@
<drawable name="status_bar_recents_app_thumbnail_background">#88000000</drawable>
<color name="status_bar_recents_app_label_color">#ffffffff</color>
<drawable name="status_bar_notification_row_background_color">#ff000000</drawable>
+ <drawable name="notification_header_bg">#FF000000</drawable>
+ <drawable name="notification_tracking_bg">#cc111315</drawable>
+ <color name="notification_list_shadow_top">#80000000</color>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index b153613..0b65d01 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1845,7 +1845,7 @@
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
| WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
- PixelFormat.OPAQUE);
+ PixelFormat.TRANSLUCENT);
if (ActivityManager.isHighEndGfx(mDisplay)) {
lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
}
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 94efa74..a58f64c 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -87,6 +87,8 @@
// RecordThread loop sleep time upon application overrun or audio HAL read error
static const int kRecordThreadSleepUs = 5000;
+static const nsecs_t kSetParametersTimeout = seconds(2);
+
// ----------------------------------------------------------------------------
static bool recordingAllowed() {
@@ -1032,7 +1034,7 @@
mWaitWorkCV.signal();
// wait condition with timeout in case the thread loop has exited
// before the request could be processed
- if (mParamCond.waitRelative(mLock, seconds(2)) == NO_ERROR) {
+ if (mParamCond.waitRelative(mLock, kSetParametersTimeout) == NO_ERROR) {
status = mParamStatus;
mWaitWorkCV.signal();
} else {
@@ -2349,7 +2351,9 @@
mParamStatus = status;
mParamCond.signal();
- mWaitWorkCV.wait(mLock);
+ // wait for condition with time out in case the thread calling ThreadBase::setParameters()
+ // already timed out waiting for the status and will never signal the condition.
+ mWaitWorkCV.waitRelative(mLock, kSetParametersTimeout);
}
return reconfig;
}
@@ -2828,7 +2832,9 @@
mParamStatus = status;
mParamCond.signal();
- mWaitWorkCV.wait(mLock);
+ // wait for condition with time out in case the thread calling ThreadBase::setParameters()
+ // already timed out waiting for the status and will never signal the condition.
+ mWaitWorkCV.waitRelative(mLock, kSetParametersTimeout);
}
return reconfig;
}
@@ -4669,7 +4675,9 @@
mParamStatus = status;
mParamCond.signal();
- mWaitWorkCV.wait(mLock);
+ // wait for condition with time out in case the thread calling ThreadBase::setParameters()
+ // already timed out waiting for the status and will never signal the condition.
+ mWaitWorkCV.waitRelative(mLock, kSetParametersTimeout);
}
return reconfig;
}