Merge "Cross profile apps animation part 2"

This commit is contained in:
TreeHugger Robot
2018-01-09 21:27:23 +00:00
committed by Android (Google) Code Review
9 changed files with 188 additions and 20 deletions

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
** Copyright 2018, 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.
*/
-->
<!-- This should be kept in sync with task_open_enter.xml -->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false" android:zAdjustment="top">
<alpha android:fromAlpha="0" android:toAlpha="1.0"
android:startOffset="300"
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
android:interpolator="@interpolator/decelerate_quart"
android:duration="167"/>
<translate android:fromYDelta="110%" android:toYDelta="0"
android:startOffset="300"
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
android:interpolator="@interpolator/decelerate_quint"
android:duration="417"/>
<!-- To keep the thumbnail around longer -->
<alpha android:fromAlpha="1.0" android:toAlpha="0"
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
android:interpolator="@interpolator/decelerate_quint"
android:startOffset="717"
android:duration="200"/>
</set>

View File

@@ -16,7 +16,7 @@
** limitations under the License.
*/
-->
<!-- This should in sync with task_open_enter_cross_profile_apps.xml -->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false" android:zAdjustment="top">

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
** Copyright 2018, 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.
*/
-->
<!-- This should in sync with task_open_enter.xml -->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false" android:zAdjustment="top">
<alpha android:fromAlpha="0" android:toAlpha="1.0"
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
android:interpolator="@interpolator/decelerate_quart"
android:startOffset="300"
android:duration="167"/>
<translate android:fromYDelta="110%" android:toYDelta="0"
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
android:interpolator="@interpolator/decelerate_quint"
android:startOffset="300"
android:duration="417"/>
<!-- To keep the transition around longer for the thumbnail, should be kept in sync with
cross_profile_apps_thumbmail.xml -->
<alpha android:fromAlpha="1.0" android:toAlpha="1.0"
android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
android:startOffset="717"
android:duration="200"/>
</set>

View File

@@ -631,4 +631,8 @@
<!-- Default dialog corner radius -->
<dimen name="dialog_corner_radius">2dp</dimen>
<!-- Size of thumbnail used in the cross profile apps animation -->
<dimen name="cross_profile_apps_thumbnail_size">72dp</dimen>
</resources>

View File

@@ -1578,8 +1578,10 @@
<java-symbol type="anim" name="voice_activity_close_enter" />
<java-symbol type="anim" name="voice_activity_open_exit" />
<java-symbol type="anim" name="voice_activity_open_enter" />
<java-symbol type="anim" name="activity_open_exit" />
<java-symbol type="anim" name="activity_open_enter" />
<java-symbol type="anim" name="task_open_exit" />
<java-symbol type="anim" name="task_open_enter" />
<java-symbol type="anim" name="cross_profile_apps_thumbnail_enter" />
<java-symbol type="anim" name="task_open_enter_cross_profile_apps" />
<java-symbol type="array" name="config_autoRotationTiltTolerance" />
<java-symbol type="array" name="config_keyboardTapVibePattern" />
@@ -1726,6 +1728,7 @@
<java-symbol type="style" name="Theme.ExpandedMenu" />
<java-symbol type="string" name="forward_intent_to_owner" />
<java-symbol type="string" name="forward_intent_to_work" />
<java-symbol type="dimen" name="cross_profile_apps_thumbnail_size" />
<!-- From services -->
<java-symbol type="anim" name="screen_rotate_0_enter" />

View File

@@ -49,14 +49,17 @@ import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE;
import static com.android.server.wm.proto.AppTransitionProto.APP_TRANSITION_STATE;
import static com.android.server.wm.proto.AppTransitionProto.LAST_USED_APP_TRANSITION;
import android.annotation.DrawableRes;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Color;
import android.graphics.GraphicBuffer;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Binder;
import android.os.Debug;
import android.os.IBinder;
@@ -70,7 +73,10 @@ import android.util.Slog;
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
import android.view.AppTransitionAnimationSpec;
import android.view.DisplayListCanvas;
import android.view.IAppTransitionAnimationSpecsFuture;
import android.view.RenderNode;
import android.view.ThreadedRenderer;
import android.view.WindowManager;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
@@ -391,6 +397,11 @@ public class AppTransition implements Dump {
mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN;
}
boolean isNextAppTransitionOpenCrossProfileApps() {
return mNextAppTransitionType == NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS;
}
/**
* @return true if and only if we are currently fetching app transition specs from the future
* passed into {@link #overridePendingAppTransitionMultiThumbFuture}
@@ -977,6 +988,43 @@ public class AppTransition implements Dump {
}
}
/**
* Creates an overlay with a background color and a thumbnail for the cross profile apps
* animation.
*/
GraphicBuffer createCrossProfileAppsThumbnail(
@DrawableRes int thumbnailDrawableRes, Rect frame) {
final int width = frame.width();
final int height = frame.height();
final RenderNode node = RenderNode.create("CrossProfileAppsThumbnail", null);
node.setLeftTopRightBottom(0, 0, width, height);
node.setClipToBounds(false);
final DisplayListCanvas canvas = node.start(width, height);
canvas.drawColor(Color.argb(0.6f, 0, 0, 0));
final int thumbnailSize = mService.mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.cross_profile_apps_thumbnail_size);
final Drawable drawable = mService.mContext.getDrawable(thumbnailDrawableRes);
drawable.setBounds(
(width - thumbnailSize) / 2,
(height - thumbnailSize) / 2,
(width + thumbnailSize) / 2,
(height + thumbnailSize) / 2);
drawable.draw(canvas);
node.end(canvas);
return ThreadedRenderer.createHardwareBitmap(node, width, height)
.createGraphicBufferHandle();
}
Animation createCrossProfileAppsThumbnailAnimationLocked(Rect appRect) {
final Animation animation = loadAnimationRes(
"android", com.android.internal.R.anim.cross_profile_apps_thumbnail_enter);
return prepareThumbnailAnimationWithDuration(animation, appRect.width(),
appRect.height(), 0, null);
}
/**
* This animation runs for the thumbnail that gets cross faded with the enter/exit activity
* when a thumbnail is specified with the pending animation override.
@@ -1624,9 +1672,10 @@ public class AppTransition implements Dump {
&& (transit == TRANSIT_ACTIVITY_OPEN
|| transit == TRANSIT_TASK_OPEN
|| transit == TRANSIT_TASK_TO_FRONT)) {
a = loadAnimationRes("android", enter
? com.android.internal.R.anim.activity_open_enter
: com.android.internal.R.anim.activity_open_exit);
? com.android.internal.R.anim.task_open_enter_cross_profile_apps
: com.android.internal.R.anim.task_open_exit);
Slog.v(TAG,
"applyAnimation NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS:"
+ " anim=" + a + " transit=" + appTransitionToString(transit)
@@ -2007,6 +2056,8 @@ public class AppTransition implements Dump {
return "NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP";
case NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN:
return "NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN";
case NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS:
return "NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS";
default:
return "unknown type=" + mNextAppTransitionType;
}

View File

@@ -85,10 +85,14 @@ class AppWindowThumbnail implements Animatable {
}
void startAnimation(Transaction t, Animation anim) {
startAnimation(t, anim, null /* position */);
}
void startAnimation(Transaction t, Animation anim, Point position) {
anim.restrictDuration(MAX_ANIMATION_DURATION);
anim.scaleCurrentDuration(mAppToken.mService.getTransitionAnimationScaleLocked());
mSurfaceAnimator.startAnimation(t, new LocalAnimationAdapter(
new WindowAnimationSpec(anim, null /* position */,
new WindowAnimationSpec(anim, position,
mAppToken.mService.mAppTransition.canSkipFirstFrame()),
mAppToken.mService.mSurfaceAnimationRunner), false /* hidden */);
}

View File

@@ -16,7 +16,6 @@
package com.android.server.wm;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
@@ -31,6 +30,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
@@ -56,7 +56,6 @@ import static com.android.server.wm.proto.AppWindowTokenProto.WINDOW_TOKEN;
import android.annotation.CallSuper;
import android.app.Activity;
import android.app.WindowConfiguration.WindowingMode;
import android.content.res.Configuration;
import android.graphics.GraphicBuffer;
import android.graphics.Point;
@@ -69,13 +68,14 @@ import android.os.Trace;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import android.view.DisplayInfo;
import android.view.SurfaceControl.Transaction;
import android.view.animation.Animation;
import android.view.IApplicationToken;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.animation.Animation;
import com.android.internal.R;
import com.android.internal.util.ToBooleanFunction;
import com.android.server.input.InputApplicationHandle;
import com.android.server.policy.WindowManagerPolicy.StartingSurface;
@@ -1775,6 +1775,37 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
mThumbnail.startAnimation(getPendingTransaction(), loadThumbnailAnimation(thumbnailHeader));
}
/**
* Attaches a surface with a thumbnail for the
* {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation.
*/
void attachCrossProfileAppsThumbnailAnimation() {
if (!isReallyAnimating()) {
return;
}
clearThumbnail();
final WindowState win = findMainWindow();
if (win == null) {
return;
}
final Rect frame = win.mFrame;
final int thumbnailDrawableRes = getTask().mUserId == mService.mCurrentUserId
? R.drawable.ic_account_circle
: R.drawable.ic_corp_badge_no_background;
final GraphicBuffer thumbnail =
mService.mAppTransition
.createCrossProfileAppsThumbnail(thumbnailDrawableRes, frame);
if (thumbnail == null) {
return;
}
mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnail);
final Animation animation =
mService.mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(win.mFrame);
mThumbnail.startAnimation(getPendingTransaction(), animation, new Point(frame.left,
frame.top));
}
private Animation loadThumbnailAnimation(GraphicBuffer thumbnailHeader) {
final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();

View File

@@ -20,6 +20,7 @@ import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManagerInternal.APP_TRANSITION_SNAPSHOT;
import static android.app.ActivityManagerInternal.APP_TRANSITION_SPLASH_SCREEN;
import static android.app.ActivityManagerInternal.APP_TRANSITION_WINDOWS_DRAWN;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_CLOSE;
@@ -43,28 +44,19 @@ import static com.android.server.wm.AppTransition.isKeyguardGoingAwayTransit;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.H.NOTIFY_APP_TRANSITION_STARTING;
import static com.android.server.wm.WindowManagerService.H.REPORT_WINDOWS_CHANGE;
import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD;
import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
import android.content.res.Configuration;
import android.graphics.GraphicBuffer;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.Binder;
import android.os.Debug;
import android.os.Trace;
import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseIntArray;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.WindowManager.LayoutParams;
import android.view.animation.Animation;
@@ -414,7 +406,6 @@ class WindowSurfacePlacer {
}
wtoken.updateReportedVisibilityLocked();
wtoken.waitingToShow = false;
if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
">>> OPEN TRANSACTION handleAppTransitionReadyLocked()");
mService.openSurfaceTransaction();
@@ -435,6 +426,8 @@ class WindowSurfacePlacer {
}
if (mService.mAppTransition.isNextAppTransitionThumbnailUp()) {
wtoken.attachThumbnailAnimation();
} else if (mService.mAppTransition.isNextAppTransitionOpenCrossProfileApps()) {
wtoken.attachCrossProfileAppsThumbnailAnimation();
}
}
return topOpeningApp;