Merge "Revert "Change screen rotation animation""
This commit is contained in:
committed by
Android (Google) Code Review
commit
df42638f04
@@ -50,7 +50,6 @@ message AnimationSpecProto {
|
||||
optional WindowAnimationSpecProto window = 1;
|
||||
optional MoveAnimationSpecProto move = 2;
|
||||
optional AlphaAnimationSpecProto alpha = 3;
|
||||
optional RotationAnimationSpecProto rotate = 4;
|
||||
}
|
||||
|
||||
/* represents WindowAnimationSpec */
|
||||
@@ -77,12 +76,3 @@ message AlphaAnimationSpecProto {
|
||||
optional float to = 2;
|
||||
optional int64 duration_ms = 3;
|
||||
}
|
||||
|
||||
/* represents RotationAnimationSpec */
|
||||
message RotationAnimationSpecProto {
|
||||
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
|
||||
|
||||
optional float start_luma = 1;
|
||||
optional float end_luma = 2;
|
||||
optional int64 duration_ms = 3;
|
||||
}
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2019 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.
|
||||
-->
|
||||
/*
|
||||
** Copyright 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.
|
||||
*/
|
||||
-->
|
||||
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shareInterpolator="false">
|
||||
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
|
||||
android:interpolator="@interpolator/screen_rotation_alpha_in"
|
||||
android:fillEnabled="true"
|
||||
android:fillBefore="true" android:fillAfter="true"
|
||||
android:duration="@android:integer/config_screen_rotation_fade_in" />
|
||||
android:shareInterpolator="false">
|
||||
<alpha android:fromAlpha="1.0" android:toAlpha="1.0"
|
||||
android:interpolator="@interpolator/decelerate_quint"
|
||||
android:duration="@android:integer/config_shortAnimTime" />
|
||||
</set>
|
||||
|
||||
@@ -1,25 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2019 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.
|
||||
-->
|
||||
/*
|
||||
** Copyright 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.
|
||||
*/
|
||||
-->
|
||||
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shareInterpolator="false">
|
||||
<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
|
||||
android:interpolator="@interpolator/screen_rotation_alpha_out"
|
||||
android:fillEnabled="true"
|
||||
android:fillBefore="true" android:fillAfter="true"
|
||||
android:duration="@android:integer/config_screen_rotation_fade_out" />
|
||||
android:shareInterpolator="false">
|
||||
</set>
|
||||
|
||||
25
core/res/res/anim/screen_rotate_0_frame.xml
Normal file
25
core/res/res/anim/screen_rotate_0_frame.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
** Copyright 2012, 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.
|
||||
*/
|
||||
-->
|
||||
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shareInterpolator="false">
|
||||
<alpha android:fromAlpha="1.0" android:toAlpha="1.0"
|
||||
android:interpolator="@interpolator/decelerate_quint"
|
||||
android:duration="@android:integer/config_shortAnimTime" />
|
||||
</set>
|
||||
@@ -18,11 +18,11 @@
|
||||
-->
|
||||
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shareInterpolator="false">
|
||||
android:shareInterpolator="false">
|
||||
<rotate android:fromDegrees="180" android:toDegrees="0"
|
||||
android:pivotX="50%" android:pivotY="50%"
|
||||
android:fillEnabled="true"
|
||||
android:fillBefore="true" android:fillAfter="true"
|
||||
android:interpolator="@interpolator/fast_out_slow_in"
|
||||
android:duration="@android:integer/config_screen_rotation_total_180" />
|
||||
android:pivotX="50%" android:pivotY="50%"
|
||||
android:interpolator="@interpolator/decelerate_quint"
|
||||
android:fillEnabled="true"
|
||||
android:fillBefore="true" android:fillAfter="true"
|
||||
android:duration="@android:integer/config_mediumAnimTime" />
|
||||
</set>
|
||||
|
||||
@@ -18,11 +18,11 @@
|
||||
-->
|
||||
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shareInterpolator="false">
|
||||
android:shareInterpolator="false">
|
||||
<rotate android:fromDegrees="0" android:toDegrees="-180"
|
||||
android:pivotX="50%" android:pivotY="50%"
|
||||
android:fillEnabled="true"
|
||||
android:fillBefore="true" android:fillAfter="true"
|
||||
android:interpolator="@interpolator/fast_out_slow_in"
|
||||
android:duration="@android:integer/config_screen_rotation_total_180" />
|
||||
android:pivotX="50%" android:pivotY="50%"
|
||||
android:interpolator="@interpolator/decelerate_quint"
|
||||
android:fillEnabled="true"
|
||||
android:fillBefore="true" android:fillAfter="true"
|
||||
android:duration="@android:integer/config_mediumAnimTime" />
|
||||
</set>
|
||||
@@ -20,8 +20,8 @@
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shareInterpolator="false">
|
||||
<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
|
||||
android:interpolator="@interpolator/screen_rotation_alpha_out"
|
||||
android:interpolator="@interpolator/decelerate_quint"
|
||||
android:fillEnabled="true"
|
||||
android:fillBefore="true" android:fillAfter="true"
|
||||
android:duration="@android:integer/config_screen_rotation_fade_out" />
|
||||
android:duration="@android:integer/config_mediumAnimTime" />
|
||||
</set>
|
||||
|
||||
@@ -18,17 +18,19 @@
|
||||
-->
|
||||
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shareInterpolator="false">
|
||||
android:shareInterpolator="false">
|
||||
<!-- Version for two-phase anim
|
||||
<rotate android:fromDegrees="-90" android:toDegrees="0"
|
||||
android:pivotX="50%" android:pivotY="50%"
|
||||
android:fillEnabled="true"
|
||||
android:fillBefore="true" android:fillAfter="true"
|
||||
android:interpolator="@interpolator/fast_out_slow_in"
|
||||
android:duration="@android:integer/config_screen_rotation_total_90" />
|
||||
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
|
||||
android:fillEnabled="true"
|
||||
android:fillBefore="true" android:fillAfter="true"
|
||||
android:interpolator="@interpolator/screen_rotation_alpha_in"
|
||||
android:startOffset="@android:integer/config_screen_rotation_fade_in_delay"
|
||||
android:duration="@android:integer/config_screen_rotation_fade_in" />
|
||||
android:pivotX="50%" android:pivotY="50%"
|
||||
android:interpolator="@interpolator/decelerate_quint"
|
||||
android:fillEnabled="true"
|
||||
android:fillBefore="true" android:fillAfter="true"
|
||||
android:duration="@android:integer/config_longAnimTime" />
|
||||
-->
|
||||
<rotate android:fromDegrees="-90" android:toDegrees="0"
|
||||
android:pivotX="50%" android:pivotY="50%"
|
||||
android:fillEnabled="true"
|
||||
android:fillBefore="true" android:fillAfter="true"
|
||||
android:interpolator="@interpolator/decelerate_quint"
|
||||
android:duration="@android:integer/config_mediumAnimTime" />
|
||||
</set>
|
||||
|
||||
@@ -18,16 +18,26 @@
|
||||
-->
|
||||
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shareInterpolator="false">
|
||||
android:shareInterpolator="false">
|
||||
<!-- Version for two-phase animation
|
||||
<rotate android:fromDegrees="0" android:toDegrees="90"
|
||||
android:pivotX="50%" android:pivotY="50%"
|
||||
android:fillEnabled="true"
|
||||
android:fillBefore="true" android:fillAfter="true"
|
||||
android:interpolator="@interpolator/fast_out_slow_in"
|
||||
android:duration="@android:integer/config_screen_rotation_total_90" />
|
||||
<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
|
||||
android:fillEnabled="true"
|
||||
android:fillBefore="true" android:fillAfter="true"
|
||||
android:interpolator="@interpolator/screen_rotation_alpha_out"
|
||||
android:duration="@android:integer/config_screen_rotation_fade_out" />
|
||||
android:pivotX="50%" android:pivotY="50%"
|
||||
android:interpolator="@interpolator/decelerate_quint"
|
||||
android:fillEnabled="true"
|
||||
android:fillBefore="true" android:fillAfter="true"
|
||||
android:duration="@android:integer/config_longAnimTime" />
|
||||
-->
|
||||
<scale android:fromXScale="100%" android:toXScale="100%p"
|
||||
android:fromYScale="100%" android:toYScale="100%p"
|
||||
android:pivotX="50%" android:pivotY="50%"
|
||||
android:interpolator="@interpolator/decelerate_quint"
|
||||
android:fillEnabled="true"
|
||||
android:fillBefore="true" android:fillAfter="true"
|
||||
android:duration="@android:integer/config_mediumAnimTime" />
|
||||
<rotate android:fromDegrees="0" android:toDegrees="90"
|
||||
android:pivotX="50%" android:pivotY="50%"
|
||||
android:interpolator="@interpolator/decelerate_quint"
|
||||
android:fillEnabled="true"
|
||||
android:fillBefore="true" android:fillAfter="true"
|
||||
android:duration="@android:integer/config_mediumAnimTime" />
|
||||
</set>
|
||||
|
||||
@@ -18,16 +18,19 @@
|
||||
-->
|
||||
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shareInterpolator="false">
|
||||
android:shareInterpolator="false">
|
||||
<!-- Version for two-phase animation
|
||||
<rotate android:fromDegrees="90" android:toDegrees="0"
|
||||
android:pivotX="50%" android:pivotY="50%"
|
||||
android:fillEnabled="true"
|
||||
android:fillBefore="true" android:fillAfter="true"
|
||||
android:interpolator="@interpolator/fast_out_slow_in"
|
||||
android:duration="@android:integer/config_screen_rotation_total_90" />
|
||||
<alpha android:fromAlpha="0.0" android:toAlpha="1.0"
|
||||
android:fillEnabled="true"
|
||||
android:interpolator="@interpolator/screen_rotation_alpha_in"
|
||||
android:startOffset="@android:integer/config_screen_rotation_fade_in_delay"
|
||||
android:duration="@android:integer/config_screen_rotation_fade_in" />
|
||||
android:pivotX="50%" android:pivotY="50%"
|
||||
android:interpolator="@interpolator/decelerate_quint"
|
||||
android:fillEnabled="true"
|
||||
android:fillBefore="true" android:fillAfter="true"
|
||||
android:duration="@android:integer/config_longAnimTime" />
|
||||
-->
|
||||
<rotate android:fromDegrees="90" android:toDegrees="0"
|
||||
android:pivotX="50%" android:pivotY="50%"
|
||||
android:interpolator="@interpolator/decelerate_quint"
|
||||
android:fillEnabled="true"
|
||||
android:fillBefore="true" android:fillAfter="true"
|
||||
android:duration="@android:integer/config_mediumAnimTime" />
|
||||
</set>
|
||||
|
||||
@@ -18,16 +18,26 @@
|
||||
-->
|
||||
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shareInterpolator="false">
|
||||
android:shareInterpolator="false">
|
||||
<!-- Version for two-phase animation
|
||||
<rotate android:fromDegrees="0" android:toDegrees="-90"
|
||||
android:pivotX="50%" android:pivotY="50%"
|
||||
android:fillEnabled="true"
|
||||
android:fillBefore="true" android:fillAfter="true"
|
||||
android:interpolator="@interpolator/fast_out_slow_in"
|
||||
android:duration="@android:integer/config_screen_rotation_total_90" />
|
||||
<alpha android:fromAlpha="1.0" android:toAlpha="0.0"
|
||||
android:interpolator="@interpolator/screen_rotation_alpha_out"
|
||||
android:fillEnabled="true"
|
||||
android:fillBefore="true" android:fillAfter="true"
|
||||
android:duration="@android:integer/config_screen_rotation_fade_out" />
|
||||
android:pivotX="50%" android:pivotY="50%"
|
||||
android:interpolator="@interpolator/decelerate_quint"
|
||||
android:fillEnabled="true"
|
||||
android:fillBefore="true" android:fillAfter="true"
|
||||
android:duration="@android:integer/config_longAnimTime" />
|
||||
-->
|
||||
<scale android:fromXScale="100%" android:toXScale="100%p"
|
||||
android:fromYScale="100%" android:toYScale="100%p"
|
||||
android:pivotX="50%" android:pivotY="50%"
|
||||
android:interpolator="@interpolator/decelerate_quint"
|
||||
android:fillEnabled="true"
|
||||
android:fillBefore="true" android:fillAfter="true"
|
||||
android:duration="@android:integer/config_mediumAnimTime" />
|
||||
<rotate android:fromDegrees="0" android:toDegrees="-90"
|
||||
android:pivotX="50%" android:pivotY="50%"
|
||||
android:interpolator="@interpolator/decelerate_quint"
|
||||
android:fillEnabled="true"
|
||||
android:fillBefore="true" android:fillAfter="true"
|
||||
android:duration="@android:integer/config_mediumAnimTime" />
|
||||
</set>
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2019 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.
|
||||
-->
|
||||
|
||||
<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:controlX1="0.15"
|
||||
android:controlY1="0.45"
|
||||
android:controlX2="0.33"
|
||||
android:controlY2="1"/>
|
||||
@@ -1,22 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2019 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.
|
||||
-->
|
||||
|
||||
<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:controlX1="0.57"
|
||||
android:controlY1="0"
|
||||
android:controlX2="0.71"
|
||||
android:controlY2=".43"/>
|
||||
@@ -147,24 +147,6 @@
|
||||
<integer name="config_activityShortDur">150</integer>
|
||||
<integer name="config_activityDefaultDur">220</integer>
|
||||
|
||||
<!-- Fade out time for screen rotation -->
|
||||
<integer name="config_screen_rotation_fade_out">116</integer>
|
||||
|
||||
<!-- Fade in time for screen rotation -->
|
||||
<integer name="config_screen_rotation_fade_in">233</integer>
|
||||
|
||||
<!-- Fade in delay time for screen rotation -->
|
||||
<integer name="config_screen_rotation_fade_in_delay">100</integer>
|
||||
|
||||
<!-- Total time for 90 degree screen rotation animations -->
|
||||
<integer name="config_screen_rotation_total_90">333</integer>
|
||||
|
||||
<!-- Total time for 180 degree screen rotation animation -->
|
||||
<integer name="config_screen_rotation_total_180">433</integer>
|
||||
|
||||
<!-- Total time for the rotation background color transition -->
|
||||
<integer name="config_screen_rotation_color_transition">200</integer>
|
||||
|
||||
<!-- The duration (in milliseconds) of the tooltip show/hide animations. -->
|
||||
<integer name="config_tooltipAnimTime">150</integer>
|
||||
|
||||
|
||||
@@ -1805,6 +1805,7 @@
|
||||
<!-- From services -->
|
||||
<java-symbol type="anim" name="screen_rotate_0_enter" />
|
||||
<java-symbol type="anim" name="screen_rotate_0_exit" />
|
||||
<java-symbol type="anim" name="screen_rotate_0_frame" />
|
||||
<java-symbol type="anim" name="screen_rotate_180_enter" />
|
||||
<java-symbol type="anim" name="screen_rotate_180_exit" />
|
||||
<java-symbol type="anim" name="screen_rotate_180_frame" />
|
||||
@@ -1980,7 +1981,6 @@
|
||||
<java-symbol type="integer" name="config_virtualKeyQuietTimeMillis" />
|
||||
<java-symbol type="integer" name="config_brightness_ramp_rate_fast" />
|
||||
<java-symbol type="integer" name="config_brightness_ramp_rate_slow" />
|
||||
<java-symbol type="integer" name="config_screen_rotation_color_transition" />
|
||||
<java-symbol type="layout" name="am_compat_mode_dialog" />
|
||||
<java-symbol type="layout" name="launch_warning" />
|
||||
<java-symbol type="layout" name="safe_mode" />
|
||||
|
||||
@@ -1305,21 +1305,13 @@ public final class DisplayManagerService extends SystemService {
|
||||
}
|
||||
|
||||
private SurfaceControl.ScreenshotGraphicBuffer screenshotInternal(int displayId) {
|
||||
synchronized (mSyncRoot) {
|
||||
final IBinder token = getDisplayToken(displayId);
|
||||
if (token == null) {
|
||||
return null;
|
||||
}
|
||||
final LogicalDisplay logicalDisplay = mLogicalDisplays.get(displayId);
|
||||
if (logicalDisplay == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final DisplayInfo displayInfo = logicalDisplay.getDisplayInfoLocked();
|
||||
return SurfaceControl.screenshotToBufferWithSecureLayersUnsafe(token, new Rect(),
|
||||
displayInfo.getNaturalWidth(), displayInfo.getNaturalHeight(),
|
||||
false /* useIdentityTransform */, 0 /* rotation */);
|
||||
final IBinder token = getDisplayToken(displayId);
|
||||
if (token == null) {
|
||||
return null;
|
||||
}
|
||||
return SurfaceControl.screenshotToBufferWithSecureLayersUnsafe(
|
||||
token, new Rect(), 0 /* width */, 0 /* height */,
|
||||
false /* useIdentityTransform */, 0 /* rotation */);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
|
||||
@@ -16,12 +16,8 @@
|
||||
|
||||
package com.android.server.wm;
|
||||
|
||||
import static com.android.server.wm.AnimationSpecProto.ROTATE;
|
||||
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
|
||||
import static com.android.server.wm.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
|
||||
import static com.android.server.wm.RotationAnimationSpecProto.DURATION_MS;
|
||||
import static com.android.server.wm.RotationAnimationSpecProto.END_LUMA;
|
||||
import static com.android.server.wm.RotationAnimationSpecProto.START_LUMA;
|
||||
import static com.android.server.wm.ScreenRotationAnimationProto.ANIMATION_RUNNING;
|
||||
import static com.android.server.wm.ScreenRotationAnimationProto.STARTED;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
|
||||
@@ -29,9 +25,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
|
||||
import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
|
||||
import static com.android.server.wm.WindowStateAnimator.WINDOW_FREEZE_LAYER;
|
||||
|
||||
import android.animation.ArgbEvaluator;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
@@ -46,9 +40,7 @@ import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.view.animation.Transformation;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.server.protolog.common.ProtoLog;
|
||||
import com.android.server.wm.utils.RotationAnimationUtils;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
@@ -68,10 +60,10 @@ import java.io.PrintWriter;
|
||||
* animation first rotate the new content into the old orientation to then be able to
|
||||
* animate to the new orientation
|
||||
*
|
||||
* <li> The Background color frame: <p>
|
||||
* To have the animation seem more seamless, we add a color transitioning background behind the
|
||||
* exiting and entering layouts. We compute the brightness of the start and end
|
||||
* layouts and transition from the two brightness values as grayscale underneath the animation
|
||||
* <li> The exiting Blackframe: <p>
|
||||
* Because the change of orientation might change the width and height of the content (i.e
|
||||
* when rotating from portrait to landscape) we "crop" the new content using black frames
|
||||
* around the screenshot so the new content does not go beyond the screenshot's bounds
|
||||
*
|
||||
* <li> The entering Blackframe: <p>
|
||||
* The enter Blackframe is similar to the exit Blackframe but is only used when a custom
|
||||
@@ -89,6 +81,8 @@ class ScreenRotationAnimation {
|
||||
*/
|
||||
private static final int SCREEN_FREEZE_LAYER_BASE = WINDOW_FREEZE_LAYER + TYPE_LAYER_MULTIPLIER;
|
||||
private static final int SCREEN_FREEZE_LAYER_ENTER = SCREEN_FREEZE_LAYER_BASE;
|
||||
private static final int SCREEN_FREEZE_LAYER_SCREENSHOT = SCREEN_FREEZE_LAYER_BASE + 1;
|
||||
private static final int SCREEN_FREEZE_LAYER_EXIT = SCREEN_FREEZE_LAYER_BASE + 2;
|
||||
|
||||
private final Context mContext;
|
||||
private final DisplayContent mDisplayContent;
|
||||
@@ -96,18 +90,16 @@ class ScreenRotationAnimation {
|
||||
private final Transformation mRotateExitTransformation = new Transformation();
|
||||
private final Transformation mRotateEnterTransformation = new Transformation();
|
||||
// Complete transformations being applied.
|
||||
private final Transformation mExitTransformation = new Transformation();
|
||||
private final Transformation mEnterTransformation = new Transformation();
|
||||
private final Matrix mFrameInitialMatrix = new Matrix();
|
||||
private final Matrix mSnapshotInitialMatrix = new Matrix();
|
||||
private final Matrix mSnapshotFinalMatrix = new Matrix();
|
||||
private final Matrix mExitFrameFinalMatrix = new Matrix();
|
||||
private final WindowManagerService mService;
|
||||
/** Only used for custom animations and not screen rotation. */
|
||||
private SurfaceControl mEnterBlackFrameLayer;
|
||||
/** This layer contains the actual screenshot that is to be faded out. */
|
||||
private SurfaceControl mScreenshotLayer;
|
||||
/**
|
||||
* Only used for screen rotation and not custom animations. Layered behind all other layers
|
||||
* to avoid showing any "empty" spots
|
||||
*/
|
||||
private SurfaceControl mBackColorSurface;
|
||||
private SurfaceControl mRotationLayer;
|
||||
private SurfaceControl mSurfaceControl;
|
||||
private BlackFrame mEnteringBlackFrame;
|
||||
private int mWidth, mHeight;
|
||||
|
||||
@@ -128,11 +120,8 @@ class ScreenRotationAnimation {
|
||||
private boolean mFinishAnimReady;
|
||||
private long mFinishAnimStartTime;
|
||||
private boolean mForceDefaultOrientation;
|
||||
private BlackFrame mExitingBlackFrame;
|
||||
private SurfaceRotationAnimationController mSurfaceRotationAnimationController;
|
||||
/** Intensity of light/whiteness of the layout before rotation occurs. */
|
||||
private float mStartLuma;
|
||||
/** Intensity of light/whiteness of the layout after rotation occurs. */
|
||||
private float mEndLuma;
|
||||
|
||||
public ScreenRotationAnimation(Context context, DisplayContent displayContent,
|
||||
boolean fixedToUserRotation, boolean isSecure, WindowManagerService service) {
|
||||
@@ -173,15 +162,9 @@ class ScreenRotationAnimation {
|
||||
|
||||
final SurfaceControl.Transaction t = mService.mTransactionFactory.get();
|
||||
try {
|
||||
mBackColorSurface = displayContent.makeChildSurface(null)
|
||||
.setName("BackColorSurface")
|
||||
.setColorLayer()
|
||||
.build();
|
||||
|
||||
mScreenshotLayer = displayContent.makeOverlay()
|
||||
mRotationLayer = displayContent.makeOverlay()
|
||||
.setName("RotationLayer")
|
||||
.setBufferSize(mWidth, mHeight)
|
||||
.setSecure(isSecure)
|
||||
.setContainerLayer()
|
||||
.build();
|
||||
|
||||
mEnterBlackFrameLayer = displayContent.makeOverlay()
|
||||
@@ -189,21 +172,26 @@ class ScreenRotationAnimation {
|
||||
.setContainerLayer()
|
||||
.build();
|
||||
|
||||
mSurfaceControl = mService.makeSurfaceBuilder(null)
|
||||
.setName("ScreenshotSurface")
|
||||
.setParent(mRotationLayer)
|
||||
.setBufferSize(mWidth, mHeight)
|
||||
.setSecure(isSecure)
|
||||
.build();
|
||||
|
||||
// In case display bounds change, screenshot buffer and surface may mismatch so set a
|
||||
// scaling mode.
|
||||
SurfaceControl.Transaction t2 = mService.mTransactionFactory.get();
|
||||
t2.setOverrideScalingMode(mScreenshotLayer, Surface.SCALING_MODE_SCALE_TO_WINDOW);
|
||||
t2.setOverrideScalingMode(mSurfaceControl, Surface.SCALING_MODE_SCALE_TO_WINDOW);
|
||||
t2.apply(true /* sync */);
|
||||
|
||||
// Capture a screenshot into the surface we just created.
|
||||
final int displayId = display.getDisplayId();
|
||||
final Surface surface = mService.mSurfaceFactory.get();
|
||||
surface.copyFrom(mScreenshotLayer);
|
||||
surface.copyFrom(mSurfaceControl);
|
||||
SurfaceControl.ScreenshotGraphicBuffer gb =
|
||||
mService.mDisplayManagerInternal.screenshot(displayId);
|
||||
if (gb != null) {
|
||||
mStartLuma = RotationAnimationUtils.getAvgBorderLuma(gb.getGraphicBuffer(),
|
||||
gb.getColorSpace());
|
||||
try {
|
||||
surface.attachAndQueueBufferWithColorSpace(gb.getGraphicBuffer(),
|
||||
gb.getColorSpace());
|
||||
@@ -214,15 +202,13 @@ class ScreenRotationAnimation {
|
||||
// screenshot surface we display it in also has FLAG_SECURE so that
|
||||
// the user can not screenshot secure layers via the screenshot surface.
|
||||
if (gb.containsSecureLayers()) {
|
||||
t.setSecure(mScreenshotLayer, true);
|
||||
t.setSecure(mSurfaceControl, true);
|
||||
}
|
||||
t.setLayer(mScreenshotLayer, SCREEN_FREEZE_LAYER_BASE);
|
||||
t.reparent(mBackColorSurface, displayContent.getSurfaceControl());
|
||||
t.setLayer(mBackColorSurface, -1);
|
||||
t.setColor(mBackColorSurface, new float[]{mStartLuma, mStartLuma, mStartLuma});
|
||||
t.setAlpha(mBackColorSurface, 1);
|
||||
t.show(mScreenshotLayer);
|
||||
t.show(mBackColorSurface);
|
||||
t.setLayer(mRotationLayer, SCREEN_FREEZE_LAYER_BASE);
|
||||
t.setLayer(mSurfaceControl, SCREEN_FREEZE_LAYER_SCREENSHOT);
|
||||
t.setAlpha(mSurfaceControl, 0);
|
||||
t.show(mRotationLayer);
|
||||
t.show(mSurfaceControl);
|
||||
} else {
|
||||
Slog.w(TAG, "Unable to take screenshot of display " + displayId);
|
||||
}
|
||||
@@ -232,11 +218,32 @@ class ScreenRotationAnimation {
|
||||
}
|
||||
|
||||
ProtoLog.i(WM_SHOW_SURFACE_ALLOC,
|
||||
" FREEZE %s: CREATE", mScreenshotLayer);
|
||||
" FREEZE %s: CREATE", mSurfaceControl);
|
||||
setRotation(t, originalRotation);
|
||||
t.apply();
|
||||
}
|
||||
|
||||
private static void createRotationMatrix(int rotation, int width, int height,
|
||||
Matrix outMatrix) {
|
||||
switch (rotation) {
|
||||
case Surface.ROTATION_0:
|
||||
outMatrix.reset();
|
||||
break;
|
||||
case Surface.ROTATION_90:
|
||||
outMatrix.setRotate(90, 0, 0);
|
||||
outMatrix.postTranslate(height, 0);
|
||||
break;
|
||||
case Surface.ROTATION_180:
|
||||
outMatrix.setRotate(180, 0, 0);
|
||||
outMatrix.postTranslate(width, height);
|
||||
break;
|
||||
case Surface.ROTATION_270:
|
||||
outMatrix.setRotate(270, 0, 0);
|
||||
outMatrix.postTranslate(0, width);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void dumpDebug(ProtoOutputStream proto, long fieldId) {
|
||||
final long token = proto.start(fieldId);
|
||||
proto.write(STARTED, mStarted);
|
||||
@@ -245,11 +252,11 @@ class ScreenRotationAnimation {
|
||||
}
|
||||
|
||||
boolean hasScreenshot() {
|
||||
return mScreenshotLayer != null;
|
||||
return mSurfaceControl != null;
|
||||
}
|
||||
|
||||
private void setRotationTransform(SurfaceControl.Transaction t, Matrix matrix) {
|
||||
if (mScreenshotLayer == null) {
|
||||
if (mRotationLayer == null) {
|
||||
return;
|
||||
}
|
||||
matrix.getValues(mTmpFloats);
|
||||
@@ -260,19 +267,24 @@ class ScreenRotationAnimation {
|
||||
x -= mCurrentDisplayRect.left;
|
||||
y -= mCurrentDisplayRect.top;
|
||||
}
|
||||
t.setPosition(mScreenshotLayer, x, y);
|
||||
t.setMatrix(mScreenshotLayer,
|
||||
t.setPosition(mRotationLayer, x, y);
|
||||
t.setMatrix(mRotationLayer,
|
||||
mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_Y],
|
||||
mTmpFloats[Matrix.MSKEW_X], mTmpFloats[Matrix.MSCALE_Y]);
|
||||
|
||||
t.setAlpha(mScreenshotLayer, (float) 1.0);
|
||||
t.show(mScreenshotLayer);
|
||||
t.setAlpha(mSurfaceControl, (float) 1.0);
|
||||
t.setAlpha(mRotationLayer, (float) 1.0);
|
||||
t.show(mRotationLayer);
|
||||
}
|
||||
|
||||
public void printTo(String prefix, PrintWriter pw) {
|
||||
pw.print(prefix); pw.print("mSurface="); pw.print(mScreenshotLayer);
|
||||
pw.print(prefix); pw.print("mSurface="); pw.print(mSurfaceControl);
|
||||
pw.print(" mWidth="); pw.print(mWidth);
|
||||
pw.print(" mHeight="); pw.println(mHeight);
|
||||
pw.print(prefix); pw.print("mExitingBlackFrame="); pw.println(mExitingBlackFrame);
|
||||
if (mExitingBlackFrame != null) {
|
||||
mExitingBlackFrame.printTo(prefix + " ", pw);
|
||||
}
|
||||
pw.print(prefix);
|
||||
pw.print("mEnteringBlackFrame=");
|
||||
pw.println(mEnteringBlackFrame);
|
||||
@@ -291,10 +303,20 @@ class ScreenRotationAnimation {
|
||||
pw.print(" "); mRotateExitTransformation.printShortString(pw); pw.println();
|
||||
pw.print(prefix); pw.print("mRotateEnterAnimation="); pw.print(mRotateEnterAnimation);
|
||||
pw.print(" "); mRotateEnterTransformation.printShortString(pw); pw.println();
|
||||
pw.print(prefix); pw.print("mExitTransformation=");
|
||||
mExitTransformation.printShortString(pw); pw.println();
|
||||
pw.print(prefix); pw.print("mEnterTransformation=");
|
||||
mEnterTransformation.printShortString(pw); pw.println();
|
||||
pw.print(prefix); pw.print("mFrameInitialMatrix=");
|
||||
mFrameInitialMatrix.printShortString(pw);
|
||||
pw.println();
|
||||
pw.print(prefix); pw.print("mSnapshotInitialMatrix=");
|
||||
mSnapshotInitialMatrix.printShortString(pw);pw.println();
|
||||
mSnapshotInitialMatrix.printShortString(pw);
|
||||
pw.print(" mSnapshotFinalMatrix="); mSnapshotFinalMatrix.printShortString(pw);
|
||||
pw.println();
|
||||
pw.print(prefix); pw.print("mExitFrameFinalMatrix=");
|
||||
mExitFrameFinalMatrix.printShortString(pw);
|
||||
pw.println();
|
||||
pw.print(prefix); pw.print("mForceDefaultOrientation="); pw.print(mForceDefaultOrientation);
|
||||
if (mForceDefaultOrientation) {
|
||||
pw.print(" mOriginalDisplayRect="); pw.print(mOriginalDisplayRect.toShortString());
|
||||
@@ -309,7 +331,7 @@ class ScreenRotationAnimation {
|
||||
// to the snapshot to make it stay in the same original position
|
||||
// with the current screen rotation.
|
||||
int delta = DisplayContent.deltaRotation(rotation, Surface.ROTATION_0);
|
||||
RotationAnimationUtils.createRotationMatrix(delta, mWidth, mHeight, mSnapshotInitialMatrix);
|
||||
createRotationMatrix(delta, mWidth, mHeight, mSnapshotInitialMatrix);
|
||||
|
||||
setRotationTransform(t, mSnapshotInitialMatrix);
|
||||
}
|
||||
@@ -319,7 +341,7 @@ class ScreenRotationAnimation {
|
||||
*/
|
||||
private boolean startAnimation(SurfaceControl.Transaction t, long maxAnimationDuration,
|
||||
float animationScale, int finalWidth, int finalHeight, int exitAnim, int enterAnim) {
|
||||
if (mScreenshotLayer == null) {
|
||||
if (mSurfaceControl == null) {
|
||||
// Can't do animation.
|
||||
return false;
|
||||
}
|
||||
@@ -332,58 +354,89 @@ class ScreenRotationAnimation {
|
||||
// Figure out how the screen has moved from the original rotation.
|
||||
int delta = DisplayContent.deltaRotation(mCurRotation, mOriginalRotation);
|
||||
|
||||
mRotateAlphaAnimation = AnimationUtils.loadAnimation(mContext,
|
||||
com.android.internal.R.anim.screen_rotate_alpha);
|
||||
|
||||
final boolean customAnim;
|
||||
if (exitAnim != 0 && enterAnim != 0) {
|
||||
customAnim = true;
|
||||
mRotateExitAnimation = AnimationUtils.loadAnimation(mContext, exitAnim);
|
||||
mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext, enterAnim);
|
||||
mRotateAlphaAnimation = AnimationUtils.loadAnimation(mContext,
|
||||
R.anim.screen_rotate_alpha);
|
||||
} else {
|
||||
customAnim = false;
|
||||
switch (delta) { /* Counter-Clockwise Rotations */
|
||||
switch (delta) {
|
||||
case Surface.ROTATION_0:
|
||||
mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
|
||||
R.anim.screen_rotate_0_exit);
|
||||
com.android.internal.R.anim.screen_rotate_0_exit);
|
||||
mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
|
||||
R.anim.screen_rotate_0_enter);
|
||||
com.android.internal.R.anim.screen_rotate_0_enter);
|
||||
break;
|
||||
case Surface.ROTATION_90:
|
||||
mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
|
||||
R.anim.screen_rotate_plus_90_exit);
|
||||
com.android.internal.R.anim.screen_rotate_plus_90_exit);
|
||||
mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
|
||||
R.anim.screen_rotate_plus_90_enter);
|
||||
com.android.internal.R.anim.screen_rotate_plus_90_enter);
|
||||
break;
|
||||
case Surface.ROTATION_180:
|
||||
mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
|
||||
R.anim.screen_rotate_180_exit);
|
||||
com.android.internal.R.anim.screen_rotate_180_exit);
|
||||
mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
|
||||
R.anim.screen_rotate_180_enter);
|
||||
com.android.internal.R.anim.screen_rotate_180_enter);
|
||||
break;
|
||||
case Surface.ROTATION_270:
|
||||
mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
|
||||
R.anim.screen_rotate_minus_90_exit);
|
||||
com.android.internal.R.anim.screen_rotate_minus_90_exit);
|
||||
mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
|
||||
R.anim.screen_rotate_minus_90_enter);
|
||||
com.android.internal.R.anim.screen_rotate_minus_90_enter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mRotateExitAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
|
||||
mRotateExitAnimation.restrictDuration(maxAnimationDuration);
|
||||
mRotateExitAnimation.scaleCurrentDuration(animationScale);
|
||||
// Initialize the animations. This is a hack, redefining what "parent"
|
||||
// means to allow supplying the last and next size. In this definition
|
||||
// "%p" is the original (let's call it "previous") size, and "%" is the
|
||||
// screen's current/new size.
|
||||
mRotateEnterAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
|
||||
mRotateEnterAnimation.restrictDuration(maxAnimationDuration);
|
||||
mRotateEnterAnimation.scaleCurrentDuration(animationScale);
|
||||
|
||||
mRotateExitAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
|
||||
mAnimRunning = false;
|
||||
mFinishAnimReady = false;
|
||||
mFinishAnimStartTime = -1;
|
||||
|
||||
if (customAnim) {
|
||||
mRotateAlphaAnimation.restrictDuration(maxAnimationDuration);
|
||||
mRotateAlphaAnimation.scaleCurrentDuration(animationScale);
|
||||
mRotateExitAnimation.restrictDuration(maxAnimationDuration);
|
||||
mRotateExitAnimation.scaleCurrentDuration(animationScale);
|
||||
mRotateEnterAnimation.restrictDuration(maxAnimationDuration);
|
||||
mRotateEnterAnimation.scaleCurrentDuration(animationScale);
|
||||
mRotateAlphaAnimation.restrictDuration(maxAnimationDuration);
|
||||
mRotateAlphaAnimation.scaleCurrentDuration(animationScale);
|
||||
|
||||
if (!customAnim && mExitingBlackFrame == null) {
|
||||
try {
|
||||
// Compute the transformation matrix that must be applied
|
||||
// the the black frame to make it stay in the initial position
|
||||
// before the new screen rotation. This is different than the
|
||||
// snapshot transformation because the snapshot is always based
|
||||
// of the native orientation of the screen, not the orientation
|
||||
// we were last in.
|
||||
createRotationMatrix(delta, mOriginalWidth, mOriginalHeight, mFrameInitialMatrix);
|
||||
|
||||
final Rect outer;
|
||||
final Rect inner;
|
||||
if (mForceDefaultOrientation) {
|
||||
// Going from a smaller Display to a larger Display, add curtains to sides
|
||||
// or top and bottom. Going from a larger to smaller display will result in
|
||||
// no BlackSurfaces being constructed.
|
||||
outer = mCurrentDisplayRect;
|
||||
inner = mOriginalDisplayRect;
|
||||
} else {
|
||||
outer = new Rect(-mWidth, -mHeight, mWidth * 2, mHeight * 2);
|
||||
inner = new Rect(0, 0, mWidth, mHeight);
|
||||
}
|
||||
mExitingBlackFrame = new BlackFrame(mService.mTransactionFactory, t, outer, inner,
|
||||
SCREEN_FREEZE_LAYER_EXIT, mDisplayContent, mForceDefaultOrientation,
|
||||
mRotationLayer);
|
||||
} catch (OutOfResourcesException e) {
|
||||
Slog.w(TAG, "Unable to allocate black surface", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (customAnim && mEnteringBlackFrame == null) {
|
||||
@@ -398,12 +451,7 @@ class ScreenRotationAnimation {
|
||||
}
|
||||
}
|
||||
|
||||
if (customAnim) {
|
||||
mSurfaceRotationAnimationController.startCustomAnimation();
|
||||
} else {
|
||||
mSurfaceRotationAnimationController.startScreenRotationAnimation();
|
||||
}
|
||||
|
||||
mSurfaceRotationAnimationController.startAnimation();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -412,13 +460,11 @@ class ScreenRotationAnimation {
|
||||
*/
|
||||
public boolean dismiss(SurfaceControl.Transaction t, long maxAnimationDuration,
|
||||
float animationScale, int finalWidth, int finalHeight, int exitAnim, int enterAnim) {
|
||||
if (mScreenshotLayer == null) {
|
||||
if (mSurfaceControl == null) {
|
||||
// Can't do animation.
|
||||
return false;
|
||||
}
|
||||
if (!mStarted) {
|
||||
mEndLuma = RotationAnimationUtils.getLumaOfSurfaceControl(mDisplayContent.getDisplay(),
|
||||
mDisplayContent.getWindowingLayer());
|
||||
startAnimation(t, maxAnimationDuration, animationScale, finalWidth, finalHeight,
|
||||
exitAnim, enterAnim);
|
||||
}
|
||||
@@ -434,28 +480,28 @@ class ScreenRotationAnimation {
|
||||
mSurfaceRotationAnimationController.cancel();
|
||||
mSurfaceRotationAnimationController = null;
|
||||
}
|
||||
|
||||
if (mScreenshotLayer != null) {
|
||||
ProtoLog.i(WM_SHOW_SURFACE_ALLOC, " FREEZE %s: DESTROY", mScreenshotLayer);
|
||||
if (mSurfaceControl != null) {
|
||||
ProtoLog.i(WM_SHOW_SURFACE_ALLOC, " FREEZE %s: DESTROY", mSurfaceControl);
|
||||
mSurfaceControl = null;
|
||||
SurfaceControl.Transaction t = mService.mTransactionFactory.get();
|
||||
if (mScreenshotLayer.isValid()) {
|
||||
t.remove(mScreenshotLayer);
|
||||
if (mRotationLayer != null) {
|
||||
if (mRotationLayer.isValid()) {
|
||||
t.remove(mRotationLayer);
|
||||
}
|
||||
mRotationLayer = null;
|
||||
}
|
||||
mScreenshotLayer = null;
|
||||
|
||||
if (mEnterBlackFrameLayer != null) {
|
||||
if (mEnterBlackFrameLayer.isValid()) {
|
||||
t.remove(mEnterBlackFrameLayer);
|
||||
}
|
||||
mEnterBlackFrameLayer = null;
|
||||
}
|
||||
if (mBackColorSurface != null) {
|
||||
t.remove(mBackColorSurface);
|
||||
mBackColorSurface = null;
|
||||
}
|
||||
t.apply();
|
||||
}
|
||||
|
||||
if (mExitingBlackFrame != null) {
|
||||
mExitingBlackFrame.kill();
|
||||
mExitingBlackFrame = null;
|
||||
}
|
||||
if (mEnteringBlackFrame != null) {
|
||||
mEnteringBlackFrame.kill();
|
||||
mEnteringBlackFrame = null;
|
||||
@@ -491,28 +537,18 @@ class ScreenRotationAnimation {
|
||||
* Utility class that runs a {@link ScreenRotationAnimation} on the {@link
|
||||
* SurfaceAnimationRunner}.
|
||||
* <p>
|
||||
* The rotation animation supports both screen rotation and custom animations
|
||||
*
|
||||
* For custom animations:
|
||||
* The rotation animation is divided into the following hierarchy:
|
||||
* <ul>
|
||||
* <li>
|
||||
* The screenshot layer which has an added animation of it's alpha channel
|
||||
* ("screen_rotate_alpha") and that will be applied along with the custom animation.
|
||||
* </li>
|
||||
* <li> A device layer that is animated with the provided custom animation </li>
|
||||
* </ul>
|
||||
*
|
||||
* For screen rotation:
|
||||
* <ul>
|
||||
* <li> A rotation layer that is both rotated and faded out during a single animation </li>
|
||||
* <li> A device layer that is both rotated and faded in during a single animation </li>
|
||||
* <li> A background color layer that transitions colors behind the first two layers </li>
|
||||
* </ul>
|
||||
*
|
||||
* <li> A first rotation layer, containing the blackframes. This layer is animated by the
|
||||
* "screen_rotate_X_exit" that applies a scale and rotate and where X is value of the rotation.
|
||||
* <ul>
|
||||
* <li> A child layer containing the screenshot on which is added an animation of it's
|
||||
* alpha channel ("screen_rotate_alpha") and that will rotate with his parent layer.</li>
|
||||
* </ul>
|
||||
* <li> A second rotation layer used when custom animations are passed in
|
||||
* {@link ScreenRotationAnimation#startAnimation(
|
||||
* SurfaceControl.Transaction, long, float, int, int, int, int)}.
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* Thus an {@link LocalAnimationAdapter.AnimationSpec} is created for each of
|
||||
* this three {@link SurfaceControl}s which then delegates the animation to the
|
||||
@@ -520,35 +556,22 @@ class ScreenRotationAnimation {
|
||||
*/
|
||||
class SurfaceRotationAnimationController {
|
||||
private SurfaceAnimator mDisplayAnimator;
|
||||
private SurfaceAnimator mEnterBlackFrameAnimator;
|
||||
private SurfaceAnimator mScreenshotRotationAnimator;
|
||||
private SurfaceAnimator mRotateScreenAnimator;
|
||||
private SurfaceAnimator mEnterBlackFrameAnimator;
|
||||
|
||||
void startCustomAnimation() {
|
||||
try {
|
||||
mService.mSurfaceAnimationRunner.deferStartingAnimations();
|
||||
mRotateScreenAnimator = startScreenshotAlphaAnimation();
|
||||
mDisplayAnimator = startDisplayRotation();
|
||||
if (mEnteringBlackFrame != null) {
|
||||
mEnterBlackFrameAnimator = startEnterBlackFrameAnimation();
|
||||
}
|
||||
} finally {
|
||||
mService.mSurfaceAnimationRunner.continueStartingAnimations();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the rotation animation of the display and the screenshot on the
|
||||
* {@link SurfaceAnimationRunner}.
|
||||
*/
|
||||
void startScreenRotationAnimation() {
|
||||
try {
|
||||
mService.mSurfaceAnimationRunner.deferStartingAnimations();
|
||||
mDisplayAnimator = startDisplayRotation();
|
||||
void startAnimation() {
|
||||
mRotateScreenAnimator = startScreenshotAlphaAnimation();
|
||||
mDisplayAnimator = startDisplayRotation();
|
||||
if (mExitingBlackFrame != null) {
|
||||
mScreenshotRotationAnimator = startScreenshotRotationAnimation();
|
||||
startColorAnimation();
|
||||
} finally {
|
||||
mService.mSurfaceAnimationRunner.continueStartingAnimations();
|
||||
}
|
||||
if (mEnteringBlackFrame != null) {
|
||||
mEnterBlackFrameAnimator = startEnterBlackFrameAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -573,8 +596,8 @@ class ScreenRotationAnimation {
|
||||
|
||||
private SurfaceAnimator startScreenshotAlphaAnimation() {
|
||||
return startAnimation(initializeBuilder()
|
||||
.setSurfaceControl(mScreenshotLayer)
|
||||
.setAnimationLeashParent(mDisplayContent.getOverlayLayer())
|
||||
.setSurfaceControl(mSurfaceControl)
|
||||
.setAnimationLeashParent(mRotationLayer)
|
||||
.setWidth(mWidth)
|
||||
.setHeight(mHeight)
|
||||
.build(),
|
||||
@@ -593,67 +616,13 @@ class ScreenRotationAnimation {
|
||||
|
||||
private SurfaceAnimator startScreenshotRotationAnimation() {
|
||||
return startAnimation(initializeBuilder()
|
||||
.setSurfaceControl(mScreenshotLayer)
|
||||
.setSurfaceControl(mRotationLayer)
|
||||
.setAnimationLeashParent(mDisplayContent.getOverlayLayer())
|
||||
.build(),
|
||||
createWindowAnimationSpec(mRotateExitAnimation),
|
||||
this::onAnimationEnd);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Applies the color change from {@link #mStartLuma} to {@link #mEndLuma} as a
|
||||
* grayscale color
|
||||
*/
|
||||
private void startColorAnimation() {
|
||||
int colorTransitionMs = mContext.getResources().getInteger(
|
||||
R.integer.config_screen_rotation_color_transition);
|
||||
final SurfaceAnimationRunner runner = mService.mSurfaceAnimationRunner;
|
||||
final float[] rgbTmpFloat = new float[3];
|
||||
final int startColor = Color.rgb(mStartLuma, mStartLuma, mStartLuma);
|
||||
final int endColor = Color.rgb(mEndLuma, mEndLuma, mEndLuma);
|
||||
final long duration = colorTransitionMs * (long) mService.getCurrentAnimatorScale();
|
||||
final ArgbEvaluator va = ArgbEvaluator.getInstance();
|
||||
runner.startAnimation(
|
||||
new LocalAnimationAdapter.AnimationSpec() {
|
||||
@Override
|
||||
public long getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(SurfaceControl.Transaction t, SurfaceControl leash,
|
||||
long currentPlayTime) {
|
||||
float fraction = (float)currentPlayTime / (float)getDuration();
|
||||
int color = (Integer) va.evaluate(fraction, startColor, endColor);
|
||||
Color middleColor = Color.valueOf(color);
|
||||
rgbTmpFloat[0] = middleColor.red();
|
||||
rgbTmpFloat[1] = middleColor.green();
|
||||
rgbTmpFloat[2] = middleColor.blue();
|
||||
if (leash.isValid()) {
|
||||
t.setColor(leash, rgbTmpFloat);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(PrintWriter pw, String prefix) {
|
||||
pw.println(prefix + "startLuma=" + mStartLuma
|
||||
+ " endLuma=" + mEndLuma
|
||||
+ " durationMs=" + colorTransitionMs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dumpDebugInner(ProtoOutputStream proto) {
|
||||
final long token = proto.start(ROTATE);
|
||||
proto.write(START_LUMA, mStartLuma);
|
||||
proto.write(END_LUMA, mEndLuma);
|
||||
proto.write(DURATION_MS, colorTransitionMs);
|
||||
proto.end(token);
|
||||
}
|
||||
},
|
||||
mBackColorSurface, mDisplayContent.getPendingTransaction(), null);
|
||||
}
|
||||
|
||||
private WindowAnimationSpec createWindowAnimationSpec(Animation mAnimation) {
|
||||
return new WindowAnimationSpec(mAnimation, new Point(0, 0) /* position */,
|
||||
false /* canSkipFirstFrame */, 0 /* WindowCornerRadius */);
|
||||
@@ -677,6 +646,7 @@ class ScreenRotationAnimation {
|
||||
|
||||
LocalAnimationAdapter localAnimationAdapter = new LocalAnimationAdapter(
|
||||
animationSpec, mService.mSurfaceAnimationRunner);
|
||||
|
||||
animator.startAnimation(mDisplayContent.getPendingTransaction(),
|
||||
localAnimationAdapter, false);
|
||||
return animator;
|
||||
@@ -722,6 +692,7 @@ class ScreenRotationAnimation {
|
||||
if (mEnterBlackFrameAnimator != null) {
|
||||
mEnterBlackFrameAnimator.cancelAnimation();
|
||||
}
|
||||
|
||||
if (mScreenshotRotationAnimator != null) {
|
||||
mScreenshotRotationAnimator.cancelAnimation();
|
||||
}
|
||||
|
||||
@@ -78,10 +78,6 @@ class SurfaceAnimationRunner {
|
||||
@GuardedBy("mLock")
|
||||
private boolean mAnimationStartDeferred;
|
||||
|
||||
/**
|
||||
* There should only ever be one instance of this class. Usual spot for it is with
|
||||
* {@link WindowManagerService}
|
||||
*/
|
||||
SurfaceAnimationRunner(Supplier<Transaction> transactionFactory,
|
||||
PowerManagerInternal powerManagerInternal) {
|
||||
this(null /* callbackProvider */, null /* animatorFactory */,
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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.server.wm.utils;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.ColorSpace;
|
||||
import android.graphics.GraphicBuffer;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.view.Display;
|
||||
import android.view.Surface;
|
||||
import android.view.SurfaceControl;
|
||||
|
||||
|
||||
/** Helper functions for the {@link com.android.server.wm.ScreenRotationAnimation} class*/
|
||||
public class RotationAnimationUtils {
|
||||
|
||||
/**
|
||||
* Converts the provided {@link GraphicBuffer} and converts it to a bitmap to then sample the
|
||||
* luminance at the borders of the bitmap
|
||||
* @return the average luminance of all the pixels at the borders of the bitmap
|
||||
*/
|
||||
public static float getAvgBorderLuma(GraphicBuffer graphicBuffer, ColorSpace colorSpace) {
|
||||
Bitmap hwBitmap = Bitmap.wrapHardwareBuffer(graphicBuffer, colorSpace);
|
||||
if (hwBitmap == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Bitmap swaBitmap = hwBitmap.copy(Bitmap.Config.ARGB_8888, false);
|
||||
float totalLuma = 0;
|
||||
int height = swaBitmap.getHeight();
|
||||
int width = swaBitmap.getWidth();
|
||||
int i;
|
||||
for (i = 0; i < width; i++) {
|
||||
totalLuma += swaBitmap.getColor(i, 0).luminance();
|
||||
totalLuma += swaBitmap.getColor(i, height - 1).luminance();
|
||||
}
|
||||
for (i = 0; i < height; i++) {
|
||||
totalLuma += swaBitmap.getColor(0, i).luminance();
|
||||
totalLuma += swaBitmap.getColor(width - 1, i).luminance();
|
||||
}
|
||||
return totalLuma / (2 * width + 2 * height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the average border luma by taking a screenshot of the {@param surfaceControl}.
|
||||
* @see #getAvgBorderLuma(GraphicBuffer, ColorSpace)
|
||||
*/
|
||||
public static float getLumaOfSurfaceControl(Display display, SurfaceControl surfaceControl) {
|
||||
if (surfaceControl == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Point size = new Point();
|
||||
display.getSize(size);
|
||||
Rect crop = new Rect(0, 0, size.x, size.y);
|
||||
SurfaceControl.ScreenshotGraphicBuffer buffer =
|
||||
SurfaceControl.captureLayers(surfaceControl, crop, 1);
|
||||
return RotationAnimationUtils.getAvgBorderLuma(buffer.getGraphicBuffer(),
|
||||
buffer.getColorSpace());
|
||||
}
|
||||
|
||||
public static void createRotationMatrix(int rotation, int width, int height, Matrix outMatrix) {
|
||||
switch (rotation) {
|
||||
case Surface.ROTATION_0:
|
||||
outMatrix.reset();
|
||||
break;
|
||||
case Surface.ROTATION_90:
|
||||
outMatrix.setRotate(90, 0, 0);
|
||||
outMatrix.postTranslate(height, 0);
|
||||
break;
|
||||
case Surface.ROTATION_180:
|
||||
outMatrix.setRotate(180, 0, 0);
|
||||
outMatrix.postTranslate(width, height);
|
||||
break;
|
||||
case Surface.ROTATION_270:
|
||||
outMatrix.setRotate(270, 0, 0);
|
||||
outMatrix.postTranslate(0, width);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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.server.wm.utils;
|
||||
|
||||
import static android.graphics.Bitmap.Config.ARGB_8888;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorSpace;
|
||||
import android.graphics.GraphicBuffer;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.PointF;
|
||||
import android.view.Surface;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class RotationAnimationUtilsTest {
|
||||
|
||||
private static final int BITMAP_HEIGHT = 100;
|
||||
private static final int BITMAP_WIDTH = 100;
|
||||
private static final int POINT_WIDTH = 1000;
|
||||
private static final int POINT_HEIGHT = 2000;
|
||||
|
||||
private ColorSpace mColorSpace = ColorSpace.get(ColorSpace.Named.DISPLAY_P3);
|
||||
private Matrix mMatrix;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
mMatrix = new Matrix();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void blackLuma() {
|
||||
Bitmap swBitmap = createBitmap(0);
|
||||
GraphicBuffer gb = swBitmapToGraphicsBuffer(swBitmap);
|
||||
float borderLuma = RotationAnimationUtils.getAvgBorderLuma(gb, mColorSpace);
|
||||
assertEquals(0, borderLuma, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whiteLuma() {
|
||||
Bitmap swBitmap = createBitmap(1);
|
||||
GraphicBuffer gb = swBitmapToGraphicsBuffer(swBitmap);
|
||||
float borderLuma = RotationAnimationUtils.getAvgBorderLuma(gb, mColorSpace);
|
||||
assertEquals(1, borderLuma, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whiteImageBlackBorderLuma() {
|
||||
Bitmap swBitmap = createBitmap(1);
|
||||
setBorderLuma(swBitmap, 0);
|
||||
GraphicBuffer gb = swBitmapToGraphicsBuffer(swBitmap);
|
||||
float borderLuma = RotationAnimationUtils.getAvgBorderLuma(gb, mColorSpace);
|
||||
assertEquals(0, borderLuma, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void blackImageWhiteBorderLuma() {
|
||||
Bitmap swBitmap = createBitmap(0);
|
||||
setBorderLuma(swBitmap, 1);
|
||||
GraphicBuffer gb = swBitmapToGraphicsBuffer(swBitmap);
|
||||
float borderLuma = RotationAnimationUtils.getAvgBorderLuma(gb, mColorSpace);
|
||||
assertEquals(1, borderLuma, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rotate_0_bottomRight() {
|
||||
RotationAnimationUtils.createRotationMatrix(Surface.ROTATION_0,
|
||||
POINT_WIDTH, POINT_HEIGHT, mMatrix);
|
||||
PointF newPoints = checkMappedPoints(POINT_WIDTH, POINT_HEIGHT);
|
||||
assertEquals(POINT_WIDTH, newPoints.x, 0);
|
||||
assertEquals(POINT_HEIGHT, newPoints.y, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rotate_90_bottomRight() {
|
||||
RotationAnimationUtils.createRotationMatrix(Surface.ROTATION_90,
|
||||
POINT_WIDTH, POINT_HEIGHT, mMatrix);
|
||||
PointF newPoints = checkMappedPoints(POINT_WIDTH, POINT_HEIGHT);
|
||||
assertEquals(0, newPoints.x, 0);
|
||||
assertEquals(POINT_WIDTH, newPoints.y, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rotate_180_bottomRight() {
|
||||
RotationAnimationUtils.createRotationMatrix(Surface.ROTATION_180,
|
||||
POINT_WIDTH, POINT_HEIGHT, mMatrix);
|
||||
PointF newPoints = checkMappedPoints(POINT_WIDTH, POINT_HEIGHT);
|
||||
assertEquals(0, newPoints.x, 0);
|
||||
assertEquals(0, newPoints.y, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rotate_270_bottomRight() {
|
||||
RotationAnimationUtils.createRotationMatrix(Surface.ROTATION_270,
|
||||
POINT_WIDTH, POINT_HEIGHT, mMatrix);
|
||||
PointF newPoints = checkMappedPoints(POINT_WIDTH, POINT_HEIGHT);
|
||||
assertEquals(POINT_HEIGHT, newPoints.x, 0);
|
||||
assertEquals(0, newPoints.y, 0);
|
||||
}
|
||||
|
||||
private PointF checkMappedPoints(int x, int y) {
|
||||
final float[] fs = new float[] {x, y};
|
||||
mMatrix.mapPoints(fs);
|
||||
return new PointF(fs[0], fs[1]);
|
||||
}
|
||||
|
||||
private Bitmap createBitmap(float luma) {
|
||||
Bitmap bitmap = Bitmap.createBitmap(BITMAP_WIDTH, BITMAP_HEIGHT, ARGB_8888);
|
||||
for (int i = 0; i < BITMAP_WIDTH; i++) {
|
||||
for (int j = 0; j < BITMAP_HEIGHT; j++) {
|
||||
bitmap.setPixel(i, j, Color.argb(1, luma, luma, luma));
|
||||
}
|
||||
}
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
private GraphicBuffer swBitmapToGraphicsBuffer(Bitmap swBitmap) {
|
||||
Bitmap hwBitmap = swBitmap.copy(Bitmap.Config.HARDWARE, false);
|
||||
return hwBitmap.createGraphicBufferHandle();
|
||||
}
|
||||
|
||||
private void setBorderLuma(Bitmap swBitmap, float luma) {
|
||||
int i;
|
||||
int width = swBitmap.getWidth();
|
||||
int height = swBitmap.getHeight();
|
||||
for (i = 0; i < width; i++) {
|
||||
swBitmap.setPixel(i, 0, Color.argb(1, luma, luma, luma));
|
||||
swBitmap.setPixel(i, height - 1, Color.argb(1, luma, luma, luma));
|
||||
}
|
||||
for (i = 0; i < height; i++) {
|
||||
swBitmap.setPixel(0, i, Color.argb(1, luma, luma, luma));
|
||||
swBitmap.setPixel(width - 1, i, Color.argb(1, luma, luma, luma));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user