Merge "Fix NPE." into mnc-dev
diff --git a/core/java/android/util/Log.java b/core/java/android/util/Log.java
index 121485a..fe41932 100644
--- a/core/java/android/util/Log.java
+++ b/core/java/android/util/Log.java
@@ -289,7 +289,10 @@
static int wtf(int logId, String tag, String msg, Throwable tr, boolean localStack,
boolean system) {
TerribleFailure what = new TerribleFailure(msg, tr);
- int bytes = println_native(logId, ASSERT, tag, msg + '\n'
+ // Only mark this as ERROR, do not use ASSERT since that should be
+ // reserved for cases where the system is guaranteed to abort.
+ // The onTerribleFailure call does not always cause a crash.
+ int bytes = println_native(logId, ERROR, tag, msg + '\n'
+ getStackTraceString(localStack ? what : tr));
sWtfHandler.onTerribleFailure(tag, what, system);
return bytes;
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index eec4960..a79dd04 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -1455,15 +1455,6 @@
@Retention(RetentionPolicy.SOURCE)
public @interface BufferFlag {}
- private static class FrameRenderedInfo {
- public long mPresentationTimeUs;
- public long mNanoTime;
- public FrameRenderedInfo(long presentationTimeUs, long nanoTime) {
- mPresentationTimeUs = presentationTimeUs;
- mNanoTime = nanoTime;
- }
- }
-
private EventHandler mEventHandler;
private EventHandler mOnFrameRenderedHandler;
private EventHandler mCallbackHandler;
@@ -1503,10 +1494,16 @@
}
case EVENT_FRAME_RENDERED:
synchronized (mListenerLock) {
- FrameRenderedInfo info = (FrameRenderedInfo)msg.obj;
- if (mOnFrameRenderedListener != null) {
+ Map<String, Object> map = (Map<String, Object>)msg.obj;
+ for (int i = 0; ; ++i) {
+ Object mediaTimeUs = map.get(i + "-media-time-us");
+ Object systemNano = map.get(i + "-system-nano");
+ if (mediaTimeUs == null || systemNano == null
+ || mOnFrameRenderedListener == null) {
+ break;
+ }
mOnFrameRenderedListener.onFrameRendered(
- mCodec, info.mPresentationTimeUs, info.mNanoTime);
+ mCodec, (long)mediaTimeUs, (long)systemNano);
}
break;
}
@@ -2362,26 +2359,9 @@
info = mDequeuedOutputInfos.remove(index);
}
}
- // TODO
- // until codec and libgui supports callback, assume frame is rendered within 50 ms
- postRenderedCallback(render, info, 50 /* delayMs */);
releaseOutputBuffer(index, render, false /* updatePTS */, 0 /* dummy */);
}
- private void postRenderedCallback(boolean render, @Nullable BufferInfo info, long delayMs) {
- if (render && info != null) {
- synchronized (mListenerLock) {
- if (mOnFrameRenderedListener != null) {
- FrameRenderedInfo obj = new FrameRenderedInfo(
- info.presentationTimeUs, System.nanoTime() + delayMs * 1000000);
- Message msg = mOnFrameRenderedHandler.obtainMessage(
- EVENT_FRAME_RENDERED, obj);
- mOnFrameRenderedHandler.sendMessageDelayed(msg, delayMs);
- }
- }
- }
- }
-
/**
* If you are done with a buffer, use this call to update its surface timestamp
* and return it to the codec to render it on the output surface. If you
@@ -2440,12 +2420,6 @@
info = mDequeuedOutputInfos.remove(index);
}
}
- // TODO
- // until codec and libgui supports callback, assume frame is rendered at the
- // render time or 16 ms from now, whichever is later.
- postRenderedCallback(
- true /* render */, info,
- Math.max(renderTimestampNs - System.nanoTime(), 16666666) / 1000000);
releaseOutputBuffer(
index, true /* render */, true /* updatePTS */, renderTimestampNs);
}
@@ -3049,9 +3023,12 @@
} else if (mOnFrameRenderedHandler != null) {
mOnFrameRenderedHandler.removeMessages(EVENT_FRAME_RENDERED);
}
+ native_enableOnFrameRenderedListener(listener != null);
}
}
+ private native void native_enableOnFrameRenderedListener(boolean enable);
+
private EventHandler getEventHandlerOn(
@Nullable Handler handler, @NonNull EventHandler lastHandler) {
if (handler == null) {
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 93b8ec7..ce7f7e5 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -56,6 +56,7 @@
enum {
EVENT_CALLBACK = 1,
EVENT_SET_CALLBACK = 2,
+ EVENT_FRAME_RENDERED = 3,
};
static struct CryptoErrorCodes {
@@ -226,6 +227,18 @@
mByteBufferLimitMethodID = NULL;
}
+status_t JMediaCodec::enableOnFrameRenderedListener(jboolean enable) {
+ if (enable) {
+ if (mOnFrameRenderedNotification == NULL) {
+ mOnFrameRenderedNotification = new AMessage(kWhatFrameRendered, this);
+ }
+ } else {
+ mOnFrameRenderedNotification.clear();
+ }
+
+ return mCodec->setOnFrameRenderedNotification(mOnFrameRenderedNotification);
+}
+
status_t JMediaCodec::setCallback(jobject cb) {
if (cb != NULL) {
if (mCallbackNotification == NULL) {
@@ -728,6 +741,27 @@
env->DeleteLocalRef(obj);
}
+void JMediaCodec::handleFrameRenderedNotification(const sp<AMessage> &msg) {
+ int32_t arg1 = 0, arg2 = 0;
+ jobject obj = NULL;
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+
+ sp<AMessage> data;
+ CHECK(msg->findMessage("data", &data));
+
+ status_t err = ConvertMessageToMap(env, data, &obj);
+ if (err != OK) {
+ jniThrowException(env, "java/lang/IllegalStateException", NULL);
+ return;
+ }
+
+ env->CallVoidMethod(
+ mObject, gFields.postEventFromNativeID,
+ EVENT_FRAME_RENDERED, arg1, arg2, obj);
+
+ env->DeleteLocalRef(obj);
+}
+
void JMediaCodec::onMessageReceived(const sp<AMessage> &msg) {
switch (msg->what()) {
case kWhatCallbackNotify:
@@ -735,6 +769,11 @@
handleCallback(msg);
break;
}
+ case kWhatFrameRendered:
+ {
+ handleFrameRenderedNotification(msg);
+ break;
+ }
default:
TRESPASS();
}
@@ -848,6 +887,22 @@
}
}
+static void android_media_MediaCodec_native_enableOnFrameRenderedListener(
+ JNIEnv *env,
+ jobject thiz,
+ jboolean enabled) {
+ sp<JMediaCodec> codec = getMediaCodec(env, thiz);
+
+ if (codec == NULL) {
+ throwExceptionAsNecessary(env, INVALID_OPERATION);
+ return;
+ }
+
+ status_t err = codec->enableOnFrameRenderedListener(enabled);
+
+ throwExceptionAsNecessary(env, err);
+}
+
static void android_media_MediaCodec_native_setCallback(
JNIEnv *env,
jobject thiz,
@@ -1744,6 +1799,9 @@
{ "native_setInputSurface", "(Landroid/view/Surface;)V",
(void *)android_media_MediaCodec_setInputSurface },
+ { "native_enableOnFrameRenderedListener", "(Z)V",
+ (void *)android_media_MediaCodec_native_enableOnFrameRenderedListener },
+
{ "native_setCallback",
"(Landroid/media/MediaCodec$Callback;)V",
(void *)android_media_MediaCodec_native_setCallback },
diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h
index a4ed67b..6650cf9 100644
--- a/media/jni/android_media_MediaCodec.h
+++ b/media/jni/android_media_MediaCodec.h
@@ -46,6 +46,8 @@
void registerSelf();
void release();
+ status_t enableOnFrameRenderedListener(jboolean enable);
+
status_t setCallback(jobject cb);
status_t configure(
@@ -116,11 +118,11 @@
virtual ~JMediaCodec();
virtual void onMessageReceived(const sp<AMessage> &msg);
- void handleCallback(const sp<AMessage> &msg);
private:
enum {
kWhatCallbackNotify,
+ kWhatFrameRendered,
};
jclass mClass;
@@ -139,6 +141,7 @@
sp<MediaCodec> mCodec;
sp<AMessage> mCallbackNotification;
+ sp<AMessage> mOnFrameRenderedNotification;
status_t mInitStatus;
@@ -148,6 +151,8 @@
void cacheJavaObjects(JNIEnv *env);
void deleteJavaObjects(JNIEnv *env);
+ void handleCallback(const sp<AMessage> &msg);
+ void handleFrameRenderedNotification(const sp<AMessage> &msg);
DISALLOW_EVIL_CONSTRUCTORS(JMediaCodec);
};
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 6888d0e..6acd137 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -22,10 +22,8 @@
import android.app.ActivityManager;
import android.app.WallpaperManager;
import android.content.ComponentCallbacks2;
-import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
-import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region.Op;
@@ -35,6 +33,7 @@
import android.service.wallpaper.WallpaperService;
import android.util.Log;
import android.view.Display;
+import android.view.DisplayInfo;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.WindowManager;
@@ -111,6 +110,9 @@
float mYOffset = 0.5f;
float mScale = 1f;
+ private Display mDefaultDisplay;
+ private final DisplayInfo mTmpDisplayInfo = new DisplayInfo();
+
boolean mVisible = true;
boolean mRedrawNeeded;
boolean mOffsetsChanged;
@@ -172,7 +174,9 @@
super.onCreate(surfaceHolder);
- updateSurfaceSize(surfaceHolder);
+ mDefaultDisplay = getSystemService(WindowManager.class).getDefaultDisplay();
+
+ updateSurfaceSize(surfaceHolder, getDefaultDisplayInfo());
setOffsetNotificationsEnabled(false);
}
@@ -184,9 +188,7 @@
mWallpaperManager.forgetLoadedWallpaper();
}
- void updateSurfaceSize(SurfaceHolder surfaceHolder) {
- Point p = getDefaultDisplaySize();
-
+ void updateSurfaceSize(SurfaceHolder surfaceHolder, DisplayInfo displayInfo) {
// Load background image dimensions, if we haven't saved them yet
if (mBackgroundWidth <= 0 || mBackgroundHeight <= 0) {
// Need to load the image to get dimensions
@@ -194,14 +196,14 @@
updateWallpaperLocked();
if (mBackgroundWidth <= 0 || mBackgroundHeight <= 0) {
// Default to the display size if we can't find the dimensions
- mBackgroundWidth = p.x;
- mBackgroundHeight = p.y;
+ mBackgroundWidth = displayInfo.logicalWidth;
+ mBackgroundHeight = displayInfo.logicalHeight;
}
}
// Force the wallpaper to cover the screen in both dimensions
- int surfaceWidth = Math.max(p.x, mBackgroundWidth);
- int surfaceHeight = Math.max(p.y, mBackgroundHeight);
+ int surfaceWidth = Math.max(displayInfo.logicalWidth, mBackgroundWidth);
+ int surfaceHeight = Math.max(displayInfo.logicalHeight, mBackgroundHeight);
// If the surface dimensions haven't changed, then just return
final Rect frame = surfaceHolder.getSurfaceFrame();
@@ -297,26 +299,22 @@
drawFrame();
}
- private Point getDefaultDisplaySize() {
- Point p = new Point();
- Context c = ImageWallpaper.this.getApplicationContext();
- WindowManager wm = (WindowManager)c.getSystemService(Context.WINDOW_SERVICE);
- Display d = wm.getDefaultDisplay();
- d.getRealSize(p);
- return p;
+ private DisplayInfo getDefaultDisplayInfo() {
+ mDefaultDisplay.getDisplayInfo(mTmpDisplayInfo);
+ return mTmpDisplayInfo;
}
void drawFrame() {
try {
- int newRotation = ((WindowManager) getSystemService(WINDOW_SERVICE)).
- getDefaultDisplay().getRotation();
+ DisplayInfo displayInfo = getDefaultDisplayInfo();
+ int newRotation = displayInfo.rotation;
// Sometimes a wallpaper is not large enough to cover the screen in one dimension.
// Call updateSurfaceSize -- it will only actually do the update if the dimensions
// should change
if (newRotation != mLastRotation) {
// Update surface size (if necessary)
- updateSurfaceSize(getSurfaceHolder());
+ updateSurfaceSize(getSurfaceHolder(), displayInfo);
}
SurfaceHolder sh = getSurfaceHolder();
final Rect frame = sh.getSurfaceFrame();
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 08d386b..095b7d7 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -589,6 +589,10 @@
if (ActivityManager.isLowRamDeviceStatic()) {
return false;
}
+ if (!mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_MANAGED_USERS)) {
+ return false;
+ }
synchronized(mPackagesLock) {
// Limit number of managed profiles that can be created
if (numberOfUsersOfTypeLocked(UserInfo.FLAG_MANAGED_PROFILE, true)
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 38e2765..4861050 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2734,15 +2734,12 @@
}
}
final AppWindowToken appToken = win.mAppToken;
- // Prevent an immediate window exit only for a real animation, ignoring e.g.
- // dummy animations.
- final boolean inAnimation = win.mWinAnimator.isWindowAnimatingNow();
// The starting window is the last window in this app token and it isn't animating.
// Allow it to be removed now as there is no additional window or animation that will
// trigger its removal.
final boolean lastWinStartingNotAnimating = startingWindow && appToken!= null
- && appToken.allAppWindows.size() == 1 && !inAnimation;
- if (!lastWinStartingNotAnimating && (win.mExiting || inAnimation)) {
+ && appToken.allAppWindows.size() == 1 && !win.mWinAnimator.isAnimating();
+ if (!lastWinStartingNotAnimating && (win.mExiting || win.mWinAnimator.isAnimating())) {
// The exit animation is running... wait for it!
win.mExiting = true;
win.mRemoveOnExit = true;
@@ -4675,7 +4672,12 @@
// If we are preparing an app transition, then delay changing
// the visibility of this token until we execute that transition.
if (okToDisplay() && mAppTransition.isTransitionSet()) {
- if (!wtoken.startingDisplayed || mSkipAppTransitionAnimation) {
+ // A dummy animation is a placeholder animation which informs others that an
+ // animation is going on (in this case an application transition). If the animation
+ // was transferred from another application/animator, no dummy animator should be
+ // created since an animation is already in progress.
+ if (!wtoken.mAppAnimator.usingTransferredAnimation &&
+ (!wtoken.startingDisplayed || mSkipAppTransitionAnimation)) {
if (DEBUG_APP_TRANSITIONS) Slog.v(
TAG, "Setting dummy animation on: " + wtoken);
wtoken.mAppAnimator.setDummyAnimation();
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index b42c8eb..5064d8f 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -251,21 +251,11 @@
&& mAppAnimator.animation == AppWindowAnimator.sDummyAnimation;
}
- /** Is this window currently set to animate or currently animating?
- * NOTE: The method will return true for cases where the window isn't currently animating, but
- * is set to animate. i.e. if the window animation is currently set to a dummy placeholder
- * animation. Use {@link #isWindowAnimatingNow} to know if the window is currently running a
- * real animation. */
+ /** Is this window currently set to animate or currently animating? */
boolean isWindowAnimating() {
return mAnimation != null;
}
- /** Is the window performing a real animation and not a dummy which is only waiting for an
- * an animation to start? */
- boolean isWindowAnimatingNow() {
- return isWindowAnimating() && !isDummyAnimation();
- }
-
void cancelExitAnimationForNextAnimationLocked() {
if (mAnimation != null) {
mAnimation.cancel();