Create end of animation callback for Activity

Activities cannot draw while their entering animations are active.
This change introduces a callback, onEnterAnimationComplete() so
that activities can know when their draws will be effective.

Fixes bug 13658460.

Change-Id: Ic48540cd4c7e37538f10cb2dc0852aa3f55d11e1
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index fed68f9..314e906 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1158,6 +1158,7 @@
     static final int UPDATE_TIME = 41;
     static final int SYSTEM_USER_START_MSG = 42;
     static final int SYSTEM_USER_CURRENT_MSG = 43;
+    static final int ENTER_ANIMATION_COMPLETE_MSG = 44;
 
     static final int FIRST_ACTIVITY_STACK_MSG = 100;
     static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -1813,6 +1814,18 @@
                 mSystemServiceManager.switchUser(msg.arg1);
                 break;
             }
+            case ENTER_ANIMATION_COMPLETE_MSG: {
+                synchronized (ActivityManagerService.this) {
+                    ActivityRecord r = ActivityRecord.forToken((IBinder) msg.obj);
+                    if (r != null && r.app != null && r.app.thread != null) {
+                        try {
+                            r.app.thread.scheduleEnterAnimationComplete(r.appToken);
+                        } catch (RemoteException e) {
+                        }
+                    }
+                }
+                break;
+            }
             }
         }
     };
@@ -5699,6 +5712,11 @@
     }
 
     @Override
+    public final void notifyEnterAnimationComplete(IBinder token) {
+        mHandler.sendMessage(mHandler.obtainMessage(ENTER_ANIMATION_COMPLETE_MSG, token));
+    }
+
+    @Override
     public String getCallingPackage(IBinder token) {
         synchronized (this) {
             ActivityRecord r = getCallingRecordLocked(token);
diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java
index 874e105..9b69ce2 100644
--- a/services/core/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java
@@ -297,6 +297,13 @@
             mAppToken.mLaunchTaskBehind = false;
         } else {
             mAppToken.updateReportedVisibilityLocked();
+            if (mAppToken.mEnteringAnimation) {
+                mAppToken.mEnteringAnimation = false;
+                try {
+                    mService.mActivityManager.notifyEnterAnimationComplete(mAppToken.token);
+                } catch (RemoteException e) {
+                }
+            }
         }
 
         return false;
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 312689b..3fcd067 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -110,6 +110,7 @@
     boolean mDeferRemoval;
 
     boolean mLaunchTaskBehind;
+    boolean mEnteringAnimation;
 
     AppWindowToken(WindowManagerService _service, IApplicationToken _token,
             boolean _voiceInteraction) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 170ecbd..670ba55 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -4450,6 +4450,7 @@
                 if (visible) {
                     mOpeningApps.add(wtoken);
                     wtoken.startingMoved = false;
+                    wtoken.mEnteringAnimation = true;
 
                     // If the token is currently hidden (should be the
                     // common case), then we need to set up to wait for
@@ -4472,6 +4473,7 @@
                     }
                 } else {
                     mClosingApps.add(wtoken);
+                    wtoken.mEnteringAnimation = false;
 
                     // If the token is currently visible (should be the
                     // common case), then set up to wait for it to be hidden.