From 9d69c8da9a4f933cc700ef1672b4e60d34a2fb10 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Mon, 19 Mar 2018 13:41:31 -0700 Subject: [PATCH] Abstracting out all the Laucher related logic > Enabling swipe up geture for fallback activity > Using a preferecens for showing back button Bug: 75979063 Change-Id: I8bbb44d8e250428c3da9bde57975dc4f952624be --- quickstep/AndroidManifest.xml | 3 +- quickstep/libs/sysui_shared.jar | Bin 118469 -> 118610 bytes .../launcher3/LauncherInitListener.java | 54 +++ .../launcher3/uioverrides/UiFactory.java | 12 +- .../quickstep/ActivityControlHelper.java | 308 ++++++++++++++++++ .../quickstep/FallbackActivityOptions.java | 82 +++++ .../quickstep/FallbackRecentsView.java | 13 +- .../quickstep/OtherActivityTouchConsumer.java | 20 +- .../quickstep/OverviewCommandHelper.java | 28 +- .../quickstep/OverviewInteractionState.java | 138 +++++--- .../android/quickstep/RecentsActivity.java | 20 ++ .../quickstep/RecentsActivityTracker.java | 65 ++++ .../quickstep/TouchInteractionService.java | 11 +- .../WindowTransformSwipeHandler.java | 175 ++++------ .../{ => views}/LauncherLayoutListener.java | 18 +- .../launcher3/BaseDraggingActivity.java | 26 ++ src/com/android/launcher3/Launcher.java | 18 +- 17 files changed, 791 insertions(+), 200 deletions(-) create mode 100644 quickstep/src/com/android/launcher3/LauncherInitListener.java create mode 100644 quickstep/src/com/android/quickstep/ActivityControlHelper.java create mode 100644 quickstep/src/com/android/quickstep/FallbackActivityOptions.java create mode 100644 quickstep/src/com/android/quickstep/RecentsActivityTracker.java rename quickstep/src/com/android/quickstep/{ => views}/LauncherLayoutListener.java (83%) diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml index 4a26494b6d..8b28597dd1 100644 --- a/quickstep/AndroidManifest.xml +++ b/quickstep/AndroidManifest.xml @@ -47,7 +47,8 @@ + android:exported="true" + android:excludeFromRecents="true" /> 5EzjM#M_14cn_v7>ZJm2-4^NiD;x_2;bFYS39GIACa6%`e#%-Jz4)KAN zU`|C$SUfs{2(Ivs0kRT*7pwxG2@yd2wbW##{w~lG6_AE_uz(U9B{o4xps-FdI3f^G zNTDGNgSISy2y~?q&_O;$fEUZBNlk&c6W4P=ykK*THTEE5S1wip0)Pu4x`ix@0WDqo$egDz)SlJssdk8e79P=vxET_kUo7Y$g0pdU>BBz0hN&ySD){h>^9#YgM%9)@; zWq=OL9#BAzMDGaJ--kpO*E=0onn(^Um4W?n*J9@hfN|fZuVMpt^E6&CbMI zWQe0vDfYxN#72+=Sg|Xq^%O`2q?BkOwhF+A-IJY1Y(-JNHW^aNuU;L*Di&!GCnT&m zfEh^(k4C)h#p<+5BkH&uV`(T72WaBXbkbo5+C_;2K<5+{;*3yeTxmNqB#HyHSg`?V zq+M`ZlpqL4=*VCKkr5lw!lt~6M*hKyjcgKGLcDDpT$tN z2K4@9aj=4kC{XVGg9AGmYRN&XExW{LOLUR9OJ$@3|uBirIke z-@1diYaApFe)2@1Xg0uwW8(q}|1Znp0WQcC{}I-j50w7D?&>kHfp9oWAyCJROh%ao zF;Ob0xdkxe927wqQS$Q)s6!qX2u4y+WGi69k*R<|q-MfnCxzRu4lo*5N#5CZ?)QjkckRJqFnW5-TK#A+T0)7xBEmuJ@ z1@h)t-T;>|n?p${lW*%iy)RR}zIcC5^|Hlm&gWX9j?ZDGL}%QU z)K{iZpRZhM(?)Ae7_~Xl7TUkxW>M6>O}L?opDYwjdBF)mRkS=x|#Jy^n{4{I*!I4!)Mw%@yx5vVlwHr$&TcXN4jz{_SS zqcreX8?$S-#&p=H(L3=kyBD}5`1bjli|>zj)OVxNiQk%YBV4piP`8+tl&2>bd;wSv=Wj>~s4wS%~B3Ee_hvAMp(qIGUu`d2=zdDcpx zH7oypUrvpUme-qve&LDv)4Yia_Sz5GuisuCXr>obE5?YmFF*-53Z4vq(v%c@rG{4{lpkS~ynK*$ zywD`e``M}=FWZ#j(dEqmZ9WG9^lsyq!R~z4o(DZg&A*xX^M_UO*4~-ow=^_*Ht!bk zp*mCt&9#__>FC^#+nL`MuuK=%O-WNbbnR}WRlVkcOef9h#n&MjgN3sh504kf70;o~ zXBpKF)0***l+Nwva8{2ze@D>uvdMu$3~uBm)hN%awz+J>OluC72>iJcJRN={hy26E z^A@5W4Hc`7&#gQTNwDmMs1KbV`YM>G7+iPj#r;pYt(lmj&i$h%BC|&d-d7ebJKDEm z@SGY`0WOtBMf4sOW`pj%xICn4MSU)P)o;yQ{Ji0khsCO}3&fkVsSDG@CxkA#;M(W1`ee?Gtm0IXc-VA?1 z^tY-#Q_aa3DdBnC)p=gKV>iwT&u>lW@YQljE@pg{+>Wvth#Ku0YOiwtsO7^Rn2pNO z!hTxi9~JC*y5*s%yAzs5F0|UjyLuuvy`THZ4~oI%Rg{mVNu#oT1!iY&Hn)c=W5J!A zn7Ho6E(b!(Y@~~Suy0#p%loG`@u^#cqlrLK{F}gjXpp7$5`u^d^IZNb$sSIaVDYG-!8{; z9E&-gqAfXW#?P)8XPs)D%qKF?&7o=_4_SXbsTDRjmcPEV$nyl_`qnGLH+AX?0S#pg*xFbi^znQhLuI*Bs*V#*Ded$uvNpcj*j~a#g?=VEznvp%=MHk?L&O3q) zWVMCY92tnA2hif8oxls?ifQf)G>Dr}Q9fx|EA0lHxF4=SA5p|P$^6ID<03o&d@h04 z)i{X%4<0(y1DGJ;dtd?Cm4Dm(dca|vofkNTY&gG{RNN>ATq3UTgf$o935GWpKYwtW zD1-MK988T-5uD++9|C3Kt^n6`oEllPZzq9E#KXg{RXX7b;Kcki;dsN^*iWTHRmSGv zKF%EXx>aXb#%YM{O)WM|7gbZVjB-CYv8mzXJh7jL@`sOtS2`F|6JKlyCW%gsAuu*eb;(%p9pn2 z>&uB+qSVJ7);e?=PBZFmliA(%^L}o}Hi{u?)c!6$(5^~eE_y&cs z0Y4eC%EMVJnfNFRylY=$SQ|sC>2(%OHvYRGb#B%Q z$=Y)iJT{Rj5K`h-zmQ)nl+#g$Wh)g2yUo-poo)udR6s}iaD{NsFm!T;wI}OnPin0M zls!$#F*bmV8Uni+O5UvIWSXIWGz{mBnKlLp^+|sWrv7GzS2-d3DzjkR*g?k-cg^c^ zyIWDt3Ut|A#8l5?sIlgeCr9f^KHg z%<4tOQXF<&4uvfOJ6)e=IkzCaEc?alm2d4bn6qwZUK&lh&}-CJ!J+MTVe*n+k#UOQ zE2ff*29L0T*aH~WP0oKNgDgfCgzVj1lwZAIO}=2ec27Ic!7kzG7;gOE9u<=?qxYpD zF6wQ^3tZ4|(2gD~=`&tJGG&je7h@E{BF@#Fy?9dca&oe1ja3+VS)W(0t#qMQM5frI z9jej32QvEc{rA_xskUQ%S+gxQ7G>AQsT4GtRK_cHCq?6z`()y0%*z|p<1?id1w_ZZ z4HipdW!gQHYLBZe{*Z63W85IymNowyV)6Q8-DQ}hN?IOe_QX9K>kCU*32pHw7nK9vn(qo6zfAb=6vV4 zFJ5eO3)<~DBO%Y8mim4ww^<=$O*iBWslm5^>W%}ury$w1FI%Ko{pZEO`EO*x*3Cs^UJ1}n%%n%cO zmd)DhOv6EZi1KOSyKX3tSxK|KmUrE%zv4cud9H8l*O8oaH-ibSWe(c@!gC}v6sTr#xa)+0va3#_+a>j0RvR|n0Sq!iRlBeaCgd}T?Un>iV?uYIItBRsm^?{jUWrkH2Y z;#bzIBf`(ct1(VhG%@bgGq(5J-qGoji9!#|(eFgKVw5TCq<5O>FswH{N;lB8OK#65 zS><207>P-pihAfHpLS4wJ^8`I({o?GG3Xw@b@Qkijq2oXcJa3#c5}CeJ#S45HU#fh zo%|NL3kYYP<#S}4!+TMvCMLp}2kc=%{rUt1T%hP&a1uG}^yC611kmPza|p1=15OC& z&jU9QAeRrWA>c_q$;4PdGI&RTDVE$ zjO38KoMdt;her{jPnH8O1ejrgJyK2=mgMJT1-Okcg%xmO@Tm>ruLRbJIHHnN>5ob{ zLxSmc6+DUnW~$&21fY#0F||07=VR3*@Ti(Je772I3qkB$1MVT{PXU=4u@Ya=mhZNL{{+@1qJ1gt*?o(OPl zC*?fXPU?nU2mB-uhPQN(8h*Ny=54%$P%TU*gOo8h3^SyqA$WE zbM(Tdlm0|gV;?vO!FL8q$gB{KMX*00*uMw;wzEM>!EhTs^pflw1Uo9~54%x(CFC=KFRdb7$&PKmW}4e$V%u=bUpN&vM_UGBu?zv6~svGw>piNF-v_!|y)33O(h= z;5z+^hhItCK0x`!9pX6xrR4%{TrdwCUYkyY31+(mU>1chV-BJ+4trsS9q-Ro3wz=Z z@ua{ee78U>6*%l2qMFpjtf>GJuV$tMgr<=|3A$GR81ZojM;Iv--scE`3Z&GNSzyuT z1t16AD+B-FJdIiKY#Xo{@b}#Hj0^C z6U>U>HQfSX2gv+BEiyD$2srS-(}@pO0+JFWUjl^j)i*idh>(T>RmqKK4XVIRmEylKLcLW$0FR!JqgKGaQbToGI;&Lr&Hguz z|0ani{-~t(BzSXznlrfr@!xhpKX(A`@#9^28E?rx5|k z0r+8#@)8uG3q&AHxXcC6e{=i40ajl|T+a^B^0%;9Lj=#vq)Yi#$n<5P$qxLibMt z4Z;m`Ku2}`_cSo34ngjtT*Vnc{ZGbq3&0gK5gKhlJuJXUsZ%LP-X8Em@+81Pcz+%U zQsa;(Dw-OHk{d)`XAlUYJjE*){Nf;c(;anu);!P{rcs z>!ysv@!K~=tv_8*TAI(Ra*er;_p?9Sfcto;+BqHF^v$cPO&+?w;;q1eiVv=nL9NGB zNLC0gV39JRBrcX-LgmU$rivs|L&oz#(Z);Nm@nt?(~_YA1|N@jDLh|3p*T6wid`Yv zPR8d%t@($!o|NTmVD%(EUs_^rG^mgd%p;9+YffNQAeVuk4!7moJtcV8U*;(iAmYR$l}N{GLxvn$cfdr6CB@N4G4 zW;2HS3f}`2etlaO%eQj!s}IEqsSmEHznO?IYYDgZ)r;2fs@yxU+C%3qiI3~~==Mz7 zAr6(LU;D6wh2v@jTmPw!Z+V}kL}t~}kc?Ncx2x;2#*m)T&2_UipOniTmHq24yFARk zJm|~tXrPp@KNF8#h|Y7|?dxPt3byO=GmQ$vbfSDVNfxIoG+a@t%8-iA($2=Io%5WQ zTI)JB25b+V*}q>2y;+L2Y46s&D#hYHAkz`aH#vBF#p71I;Zvsz^JjlTL| z`_ExQTJBwccXGi@eYV-GpS66f&h0*ScFM@xGK$`KKC)~#erhpq;dqF9s!VPV9mYOo z@e7;Mc??=~Ccr~WrKxnjZ+A(Dr9!N;E4Jnl$rO;p)DexVXT;>QSQOUNP11aiqWD&% z?m8(B?+p$oPLF`I3tw2pQgy4x6)$z2O4r1gwuyzvM=&R)9PepXy~clg>;1m`p6!gI zyM{wGH+tSQjl}82Zig2#7~t#nt;ojPcLv271opYUf$GxIkkS#sD ziiZyiSE=caZ%kz_B%a*)E}>p1fXf6s8p7-l-N#dQSX*Tf>0c62skg3N8j`q0>iWup zaT3TPD2i>Lx$l7z3%UE^P;Y`i@n)OFN!;M1SH;ym-7EZdD?fcuGvxHQr7g z>-zm8)JH@xQaCIpt{@{tcal)W?e~j8y zT|*w{<;EPW@961Q+C@ADmA6yt5N3u<$XlY_3sMXSgcdV`{QT=sL)n7iHFvZHa6+!F z;2+4r8?3{79eJTS0v&GyLWCk8K;4T7-u^(By5SV$%0XtWfSIBYfZntLMgsd4pbxLE zIG-a_BOxvboS{;XI89Hc*rB}FfE!W`0TZOX zZwKa|dX}fc4YORa^$R*j1-Op6eRE(P79C;6T$GGG+E6K2|M;40IQp7uc+t4v>8%cV zqIh=Q?t0Z9*yJ@I)CXMWV$?GITIkW(?|WC>qn5P7u#N#%4)SQ*;kVpM9nU3Lu-*y1 z(qZo(xEvAcxNKE+&O-9Q0r9{Hqmr^@*^C&vz3-Oow-}zK?twZpRV$g0$zLYoa~&^< zTVU*DKl8s+mR36;A9^C8ZGyE;QOvIaw-Xl;{9(V*BQyh1KgdBzTzbM#!EnvaoMj)K z1n%?J>`)M&FTeft3z`E0q)g`k2^nIGHmVrlypW}n)CR{%md3PX8QEggmz;KQ-g>TLHp9V%i2GMYS>mB;YqS7kxP$v zo5LsyUB|nN2?!NkRK1T_EVq(I-`&y{uj|20o?S22D(6Evo~Fw*zBdRmd& zHj) ztcnQ{&+PS>W!s5vzo;GT6D3viAhSbMkPE4l;JhA?!i2UMZ7}cl-Cg!_wfj&Iz94hn zSJtL`2J4gkyra6$AmieO8GG0#r<&}*FZN{xNiJ4jql=o1ViiOKhx*t%E*$d8&h4G} znxZ@;@OjtyqL$m4md9kDmshGx-dixfRrJsk<1??rV)gF8tU_e_V0WX;?5<$#8KZL> zX1YXO^U-9Jm|j~O{`Bt&wZV$aQ_mM%%-V~-M)oNAJwAUlC;yxGU`cehnU=-y;k>pz z6@`N(U$e&jDxY%SJ;1;?#FuPe*Kt9L6MZeO9n<&xNAS92w{`l|oM}|Kc3&QgU5rR*jA}quVfv4T%+9ifj@* zj^4u=_tv#Y<8VsmPB*kO?){~gBgDr_Zk}zo-@M|Ot&F;|(3<9$Wm$efpj*~P9M|8>MQkZ9TL2-+RJPIVI|mt;#K&HPO*a3%H;-#=4kEUM zmhm7o;>QZu+%Yyu_ao+2C)1MUST2I7vzduO5KT5uBI@*#*+vClf_jW4Qlyce-+MHpY>HM5sRq0Mu!*mYXqsP*K;8_+5cAP zy9JT2Zj0RJdeMwuroV4#*O0RomSDzsqVsrn?Kdu+?a0E74Ue%?TfTV$3foMS1IXhm z+{M;R2t+Cu?3Q+^O_363z8HAJ;Cu;ig#oDq*uy}&los%QDb2J|O7rr- z12n9e!UGQ&SeDV^G?f8Am^oHXORTgUIK#}Y3RGd@cGN{|8&2+cpf79bGIUeME4APL#D0x1!Sw4p2VT_PO< z@oEPGq5qfk1eDea&ccapv;sjoGk=P!7F6dC7$M{<0DqZ-{MyK-q{|eOCgt4C4JROE zJfX}_j;cqFs`pn^wIGUA5lRjs_nnPd9HljwY9gP;h2ddeQ&=W6l@)5IvFhz) zHUUFn#VJQ|33$X3xo5A;$QO!f76jtNUn5F|QKg1&06#=Np)*3Q4S)@Hnvqn`OGF|N zjojp$$X`wq5x<>KkY5Mjh4t7dn_~^+o*tw}AkO@yU&8*Ow}}J0p!E(~ZOm`T`6}N3 zZI^*V^~Z`xtdjH1=RqJ;{tD%kM3q**0sCO-pG%ecU(&iKR4Mu5AONX#0#3%TY;t;t F{{gjh>MZ~O diff --git a/quickstep/src/com/android/launcher3/LauncherInitListener.java b/quickstep/src/com/android/launcher3/LauncherInitListener.java new file mode 100644 index 0000000000..0d1038a2d9 --- /dev/null +++ b/quickstep/src/com/android/launcher3/LauncherInitListener.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 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. + */ +package com.android.launcher3; + +import static com.android.launcher3.states.RotationHelper.REQUEST_LOCK; + +import android.annotation.TargetApi; +import android.os.Build; + +import com.android.launcher3.states.InternalStateHandler; +import com.android.quickstep.ActivityControlHelper.ActivityInitListener; + +import java.util.function.BiPredicate; + +@TargetApi(Build.VERSION_CODES.P) +public class LauncherInitListener extends InternalStateHandler implements ActivityInitListener { + + private final BiPredicate mOnInitListener; + + public LauncherInitListener(BiPredicate onInitListener) { + mOnInitListener = onInitListener; + } + + @Override + protected boolean init(Launcher launcher, boolean alreadyOnHome) { + // For the duration of the gesture, lock the screen orientation to ensure that we do not + // rotate mid-quickscrub + launcher.getRotationHelper().setStateHandlerRequest(REQUEST_LOCK); + return mOnInitListener.test(launcher, alreadyOnHome); + } + + @Override + public void register() { + initWhenReady(); + } + + @Override + public void unregister() { + clearReference(); + } +} diff --git a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java index 789185a395..637ce60a28 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java +++ b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java @@ -18,6 +18,7 @@ package com.android.launcher3.uioverrides; import static com.android.launcher3.LauncherState.NORMAL; +import android.content.Context; import android.view.View; import android.view.View.AccessibilityDelegate; @@ -73,7 +74,8 @@ public class UiFactory { } } } - OverviewInteractionState.setBackButtonVisible(launcher, shouldBackButtonBeVisible); + OverviewInteractionState.getInstance(launcher) + .setBackButtonVisible(shouldBackButtonBeVisible); } public static void resetOverview(Launcher launcher) { @@ -81,15 +83,15 @@ public class UiFactory { recents.reset(); } - public static void onStart(Launcher launcher) { - RecentsModel model = RecentsModel.getInstance(launcher); + public static void onStart(Context context) { + RecentsModel model = RecentsModel.getInstance(context); if (model != null) { model.onStart(); } } - public static void onTrimMemory(Launcher launcher, int level) { - RecentsModel model = RecentsModel.getInstance(launcher); + public static void onTrimMemory(Context context, int level) { + RecentsModel model = RecentsModel.getInstance(context); if (model != null) { model.onTrimMemory(level); } diff --git a/quickstep/src/com/android/quickstep/ActivityControlHelper.java b/quickstep/src/com/android/quickstep/ActivityControlHelper.java new file mode 100644 index 0000000000..a9da4f916f --- /dev/null +++ b/quickstep/src/com/android/quickstep/ActivityControlHelper.java @@ -0,0 +1,308 @@ +/* + * Copyright (C) 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. + */ +package com.android.quickstep; + +import static com.android.launcher3.LauncherState.FAST_OVERVIEW; +import static com.android.launcher3.LauncherState.OVERVIEW; +import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS; +import static com.android.launcher3.anim.Interpolators.LINEAR; + +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.app.ActivityOptions; +import android.content.Context; +import android.content.Intent; +import android.graphics.Rect; +import android.os.Handler; +import android.os.Looper; +import android.view.View; + +import com.android.launcher3.BaseDraggingActivity; +import com.android.launcher3.DeviceProfile; +import com.android.launcher3.Launcher; +import com.android.launcher3.LauncherInitListener; +import com.android.launcher3.LauncherState; +import com.android.launcher3.allapps.AllAppsTransitionController; +import com.android.launcher3.anim.AnimatorPlaybackController; +import com.android.launcher3.util.ViewOnDrawExecutor; +import com.android.quickstep.views.LauncherLayoutListener; +import com.android.quickstep.views.RecentsView; +import com.android.quickstep.views.TaskView; +import com.android.systemui.shared.system.ActivityManagerWrapper; +import com.android.systemui.shared.system.ActivityOptionsCompat; +import com.android.systemui.shared.system.AssistDataReceiver; +import com.android.systemui.shared.system.RecentsAnimationListener; +import com.android.systemui.shared.system.RemoteAnimationAdapterCompat; + +import java.util.function.BiPredicate; + +/** + * Utility class which abstracts out the logical differences between Launcher and RecentsActivity. + */ +public interface ActivityControlHelper { + + LayoutListener createLayoutListener(T activity); + + void onQuickstepGestureStarted(T activity, boolean activityVisible); + + void onQuickInteractionStart(T activity, boolean activityVisible); + + void executeOnNextDraw(T activity, TaskView targetView, Runnable action); + + void onTransitionCancelled(T activity, boolean activityVisible); + + int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect); + + void onSwipeUpComplete(T activity); + + void prepareRecentsUI(T activity, boolean activityVisible); + + AnimatorPlaybackController createControllerForVisibleActivity(T activity); + + AnimatorPlaybackController createControllerForHiddenActivity(T activity, int transitionLength); + + ActivityInitListener createActivityInitListener(BiPredicate onInitListener); + + void startRecents(Context context, Intent intent, AssistDataReceiver assistDataReceiver, + RecentsAnimationListener remoteAnimationListener); + + class LauncherActivityControllerHelper implements ActivityControlHelper { + + @Override + public LayoutListener createLayoutListener(Launcher activity) { + return new LauncherLayoutListener(activity); + } + + @Override + public void onQuickstepGestureStarted(Launcher activity, boolean activityVisible) { + activity.onQuickstepGestureStarted(activityVisible); + } + + @Override + public void onQuickInteractionStart(Launcher activity, boolean activityVisible) { + activity.getStateManager().goToState(FAST_OVERVIEW, activityVisible); + } + + @Override + public void executeOnNextDraw(Launcher activity, TaskView targetView, Runnable action) { + ViewOnDrawExecutor executor = new ViewOnDrawExecutor() { + @Override + public void onViewDetachedFromWindow(View v) { + if (!isCompleted()) { + runAllTasks(); + } + } + }; + executor.attachTo(activity, targetView, false /* waitForLoadAnimation */); + executor.execute(action); + } + + @Override + public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect) { + RecentsView.getPageRect(dp, context, outRect); + if (dp.isVerticalBarLayout()) { + Rect targetInsets = dp.getInsets(); + int hotseatInset = dp.isSeascape() ? targetInsets.left : targetInsets.right; + return dp.hotseatBarSizePx + dp.hotseatBarSidePaddingPx + hotseatInset; + } else { + return dp.heightPx - outRect.bottom; + } + } + + @Override + public void onTransitionCancelled(Launcher activity, boolean activityVisible) { + LauncherState startState = activity.getStateManager().getRestState(); + activity.getStateManager().goToState(startState, activityVisible); + } + + @Override + public void onSwipeUpComplete(Launcher activity) { + // Re apply state in case we did something funky during the transition. + activity.getStateManager().reapplyState(); + } + + @Override + public void prepareRecentsUI(Launcher activity, boolean activityVisible) { + LauncherState startState = activity.getStateManager().getState(); + if (startState.disableRestore) { + startState = activity.getStateManager().getRestState(); + } + activity.getStateManager().setRestState(startState); + + if (!activityVisible) { + activity.getStateManager().goToState(OVERVIEW, false); + + // Optimization, hide the all apps view to prevent layout while initializing + activity.getAppsView().setVisibility(View.GONE); + } + } + + @Override + public AnimatorPlaybackController createControllerForVisibleActivity(Launcher activity) { + DeviceProfile dp = activity.getDeviceProfile(); + long accuracy = 2 * Math.max(dp.widthPx, dp.heightPx); + return activity.getStateManager().createAnimationToNewWorkspace(OVERVIEW, accuracy); + } + + @Override + public AnimatorPlaybackController createControllerForHiddenActivity( + Launcher activity, int transitionLength) { + float startProgress; + AllAppsTransitionController controller = activity.getAllAppsController(); + + if (activity.getDeviceProfile().isVerticalBarLayout()) { + startProgress = 1; + } else { + float scrollRange = Math.max(controller.getShiftRange(), 1); + startProgress = (transitionLength / scrollRange) + 1; + } + AnimatorSet anim = new AnimatorSet(); + ObjectAnimator shiftAnim = ObjectAnimator.ofFloat(controller, ALL_APPS_PROGRESS, + startProgress, OVERVIEW.getVerticalProgress(activity)); + shiftAnim.setInterpolator(LINEAR); + anim.play(shiftAnim); + + // TODO: Link this animation to state animation, so that it is cancelled + // automatically on state change + anim.setDuration(transitionLength * 2); + return AnimatorPlaybackController.wrap(anim, transitionLength * 2); + } + + @Override + public ActivityInitListener createActivityInitListener( + BiPredicate onInitListener) { + return new LauncherInitListener(onInitListener); + } + + @Override + public void startRecents(Context context, Intent intent, + AssistDataReceiver assistDataReceiver, + RecentsAnimationListener remoteAnimationListener) { + ActivityManagerWrapper.getInstance().startRecentsActivity( + intent, assistDataReceiver, remoteAnimationListener, null, null); + } + } + + class FallbackActivityControllerHelper implements ActivityControlHelper { + + @Override + public void onQuickstepGestureStarted(RecentsActivity activity, boolean activityVisible) { + // TODO: + } + + @Override + public void onQuickInteractionStart(RecentsActivity activity, boolean activityVisible) { + // TODO: + } + + @Override + public void executeOnNextDraw(RecentsActivity activity, TaskView targetView, + Runnable action) { + // TODO: + new Handler(Looper.getMainLooper()).post(action); + } + + @Override + public void onTransitionCancelled(RecentsActivity activity, boolean activityVisible) { + // TODO: + } + + @Override + public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect) { + FallbackRecentsView.getCenterPageRect(dp, context, outRect); + if (dp.isVerticalBarLayout()) { + Rect targetInsets = dp.getInsets(); + int hotseatInset = dp.isSeascape() ? targetInsets.left : targetInsets.right; + return dp.hotseatBarSizePx + dp.hotseatBarSidePaddingPx + hotseatInset; + } else { + return dp.heightPx - outRect.bottom; + } + } + + @Override + public void onSwipeUpComplete(RecentsActivity activity) { + // TODO: + } + + @Override + public void prepareRecentsUI(RecentsActivity activity, boolean activityVisible) { + // TODO: + } + + @Override + public AnimatorPlaybackController createControllerForVisibleActivity( + RecentsActivity activity) { + DeviceProfile dp = activity.getDeviceProfile(); + return createControllerForHiddenActivity(activity, Math.max(dp.widthPx, dp.heightPx)); + } + + @Override + public AnimatorPlaybackController createControllerForHiddenActivity( + RecentsActivity activity, int transitionLength) { + // We do not animate anything. Create a empty controller + AnimatorSet anim = new AnimatorSet(); + return AnimatorPlaybackController.wrap(anim, transitionLength * 2); + } + + @Override + public LayoutListener createLayoutListener(RecentsActivity activity) { + // We do not change anything as part of layout changes in fallback activity. Return a + // default layout listener. + return new LayoutListener() { + @Override + public void open() { } + + @Override + public void setHandler(WindowTransformSwipeHandler handler) { } + + @Override + public void finish() { } + }; + } + + @Override + public ActivityInitListener createActivityInitListener( + BiPredicate onInitListener) { + return new RecentsActivityTracker(onInitListener); + } + + @Override + public void startRecents(Context context, Intent intent, + AssistDataReceiver assistDataReceiver, + final RecentsAnimationListener remoteAnimationListener) { + ActivityOptions options = + ActivityOptionsCompat.makeRemoteAnimation(new RemoteAnimationAdapterCompat( + new FallbackActivityOptions(remoteAnimationListener), 10000, 10000)); + context.startActivity(intent, options.toBundle()); + } + } + + interface LayoutListener { + + void open(); + + void setHandler(WindowTransformSwipeHandler handler); + + void finish(); + } + + interface ActivityInitListener { + + void register(); + + void unregister(); + } +} diff --git a/quickstep/src/com/android/quickstep/FallbackActivityOptions.java b/quickstep/src/com/android/quickstep/FallbackActivityOptions.java new file mode 100644 index 0000000000..3a7fb2db6d --- /dev/null +++ b/quickstep/src/com/android/quickstep/FallbackActivityOptions.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 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. + */ +package com.android.quickstep; + +import android.graphics.Rect; +import android.util.Log; + +import com.android.systemui.shared.recents.model.ThumbnailData; +import com.android.systemui.shared.system.RecentsAnimationControllerCompat; +import com.android.systemui.shared.system.RecentsAnimationListener; +import com.android.systemui.shared.system.RemoteAnimationRunnerCompat; +import com.android.systemui.shared.system.RemoteAnimationTargetCompat; +import com.android.systemui.shared.system.WindowManagerWrapper; + +/** + * Temporary class to create activity options to emulate recents transition for fallback activtiy. + */ +public class FallbackActivityOptions implements RemoteAnimationRunnerCompat { + + private final RecentsAnimationListener mListener; + + public FallbackActivityOptions(RecentsAnimationListener listener) { + mListener = listener; + } + + @Override + public void onAnimationStart(RemoteAnimationTargetCompat[] targetCompats, + Runnable runnable) { + DummyRecentsAnimationControllerCompat dummyRecentsAnim = + new DummyRecentsAnimationControllerCompat(runnable); + + Rect insets = new Rect(); + WindowManagerWrapper.getInstance().getStableInsets(insets); + mListener.onAnimationStart(dummyRecentsAnim, targetCompats, insets, null); + } + + @Override + public void onAnimationCancelled() { + mListener.onAnimationCanceled(); + } + + private static class DummyRecentsAnimationControllerCompat + extends RecentsAnimationControllerCompat { + + final Runnable mFinishCallback; + + public DummyRecentsAnimationControllerCompat(Runnable finishCallback) { + mFinishCallback = finishCallback; + } + + @Override + public ThumbnailData screenshotTask(int taskId) { + return new ThumbnailData(); + } + + @Override + public void setInputConsumerEnabled(boolean enabled) { } + + @Override + public void setAnimationTargetsBehindSystemBars(boolean behindSystemBars) { } + + @Override + public void finish(boolean toHome) { + if (toHome) { + mFinishCallback.run(); + } + } + } +} diff --git a/quickstep/src/com/android/quickstep/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/FallbackRecentsView.java index 22f6e0cc25..032d753a68 100644 --- a/quickstep/src/com/android/quickstep/FallbackRecentsView.java +++ b/quickstep/src/com/android/quickstep/FallbackRecentsView.java @@ -48,10 +48,21 @@ public class FallbackRecentsView extends RecentsView implements setPadding(padding.left, padding.top, padding.right, padding.bottom); } - public static void verticalCenter(Rect padding, DeviceProfile dp) { + private static void verticalCenter(Rect padding, DeviceProfile dp) { Rect insets = dp.getInsets(); int totalSpace = (padding.top + padding.bottom - insets.top - insets.bottom) / 2; padding.top = insets.top + totalSpace; padding.bottom = insets.bottom + totalSpace; } + + public static void getCenterPageRect(DeviceProfile grid, Context context, Rect outRect) { + Rect targetPadding = getPadding(grid, context); + verticalCenter(targetPadding, grid); + Rect insets = grid.getInsets(); + outRect.set( + targetPadding.left + insets.left, + targetPadding.top + insets.top, + grid.widthPx - targetPadding.right - insets.right, + grid.heightPx - targetPadding.bottom - insets.bottom); + } } diff --git a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java index 69e7933b9d..ab19c6e774 100644 --- a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java +++ b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java @@ -22,7 +22,6 @@ import static android.view.MotionEvent.ACTION_POINTER_UP; import static android.view.MotionEvent.ACTION_UP; import static android.view.MotionEvent.INVALID_POINTER_ID; -import static com.android.quickstep.TouchInteractionService.DEBUG_SHOW_OVERVIEW_BUTTON; import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_BACK; import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_OVERVIEW; @@ -36,6 +35,7 @@ import android.graphics.Rect; import android.os.Build; import android.os.Bundle; import android.os.Looper; +import android.util.Log; import android.view.Choreographer; import android.view.Display; import android.view.MotionEvent; @@ -46,7 +46,6 @@ import android.view.WindowManager; import com.android.launcher3.MainThreadExecutor; import com.android.launcher3.util.TraceHelper; -import com.android.systemui.shared.recents.ISystemUiProxy; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.AssistDataReceiver; import com.android.systemui.shared.system.BackgroundExecutor; @@ -67,13 +66,13 @@ import java.util.concurrent.TimeUnit; public class OtherActivityTouchConsumer extends ContextWrapper implements TouchConsumer { private static final long LAUNCHER_DRAW_TIMEOUT_MS = 150; - private static final int[] DEFERRED_HIT_TARGETS = DEBUG_SHOW_OVERVIEW_BUTTON + private static final int[] DEFERRED_HIT_TARGETS = false ? new int[] {HIT_TARGET_BACK, HIT_TARGET_OVERVIEW} : new int[] {HIT_TARGET_BACK}; private final RunningTaskInfo mRunningTask; private final RecentsModel mRecentsModel; private final Intent mHomeIntent; - private final ISystemUiProxy mISystemUiProxy; + private final ActivityControlHelper mActivityControlHelper; private final MainThreadExecutor mMainThreadExecutor; private final Choreographer mBackgroundThreadChoreographer; @@ -93,7 +92,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC private boolean mIsGoingToHome; public OtherActivityTouchConsumer(Context base, RunningTaskInfo runningTaskInfo, - RecentsModel recentsModel, Intent homeIntent, ISystemUiProxy systemUiProxy, + RecentsModel recentsModel, Intent homeIntent, ActivityControlHelper activityControl, MainThreadExecutor mainThreadExecutor, Choreographer backgroundThreadChoreographer, @HitTarget int downHitTarget, VelocityTracker velocityTracker) { super(base); @@ -101,7 +100,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC mRecentsModel = recentsModel; mHomeIntent = homeIntent; mVelocityTracker = velocityTracker; - mISystemUiProxy = systemUiProxy; + mActivityControlHelper = activityControl; mMainThreadExecutor = mainThreadExecutor; mBackgroundThreadChoreographer = backgroundThreadChoreographer; mIsDeferredDownTarget = Arrays.binarySearch(DEFERRED_HIT_TARGETS, downHitTarget) >= 0; @@ -205,8 +204,8 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC private void startTouchTrackingForWindowAnimation(long touchTimeMs) { // Create the shared handler - final WindowTransformSwipeHandler handler = - new WindowTransformSwipeHandler(mRunningTask, this, touchTimeMs); + final WindowTransformSwipeHandler handler = new WindowTransformSwipeHandler( + mRunningTask, this, touchTimeMs, mActivityControlHelper); // Preload the plan mRecentsModel.loadTasks(mRunningTask.id, null); @@ -223,8 +222,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC handler.initWhenReady(); TraceHelper.beginSection("RecentsController"); - Runnable startActivity = () -> ActivityManagerWrapper.getInstance() - .startRecentsActivity(mHomeIntent, + Runnable startActivity = () -> mActivityControlHelper.startRecents(this, mHomeIntent, new AssistDataReceiver() { @Override public void onHandleAssistData(Bundle bundle) { @@ -253,7 +251,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC handler.onRecentsAnimationCanceled(); } } - }, null, null); + }); if (Looper.myLooper() != Looper.getMainLooper()) { startActivity.run(); diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java index ef58fad29b..38c25a341b 100644 --- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java +++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java @@ -16,7 +16,6 @@ package com.android.quickstep; import static com.android.launcher3.LauncherState.OVERVIEW; -import static com.android.quickstep.TouchInteractionService.DEBUG_SHOW_OVERVIEW_BUTTON; import android.annotation.TargetApi; import android.app.ActivityManager.RecentTaskInfo; @@ -33,6 +32,8 @@ import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppState; import com.android.launcher3.states.InternalStateHandler; +import com.android.quickstep.ActivityControlHelper.FallbackActivityControllerHelper; +import com.android.quickstep.ActivityControlHelper.LauncherActivityControllerHelper; import com.android.quickstep.views.RecentsView; import com.android.systemui.shared.system.ActivityManagerWrapper; @@ -42,7 +43,7 @@ import com.android.systemui.shared.system.ActivityManagerWrapper; @TargetApi(Build.VERSION_CODES.P) public class OverviewCommandHelper extends InternalStateHandler { - private static final boolean DEBUG_START_FALLBACK_ACTIVITY = DEBUG_SHOW_OVERVIEW_BUTTON; + private static final boolean DEBUG_START_FALLBACK_ACTIVITY = false; private final Context mContext; private final ActivityManagerWrapper mAM; @@ -61,7 +62,15 @@ public class OverviewCommandHelper extends InternalStateHandler { .setPackage(context.getPackageName()) .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); ResolveInfo info = context.getPackageManager().resolveActivity(homeIntent, 0); - launcher = new ComponentName(context.getPackageName(), info.activityInfo.name); + + if (DEBUG_START_FALLBACK_ACTIVITY) { + launcher = new ComponentName(context, RecentsActivity.class); + homeIntent.addCategory(Intent.CATEGORY_DEFAULT) + .removeCategory(Intent.CATEGORY_HOME); + } else { + launcher = new ComponentName(context.getPackageName(), info.activityInfo.name); + } + // Clear the packageName as system can fail to dedupe it b/64108432 homeIntent.setComponent(launcher).setPackage(null); } @@ -74,7 +83,7 @@ public class OverviewCommandHelper extends InternalStateHandler { public void onOverviewToggle() { getLauncher().runOnUiThread(() -> { - if (DEBUG_START_FALLBACK_ACTIVITY) { + if (isUsingFallbackActivity()) { mContext.startActivity(new Intent(mContext, RecentsActivity.class) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent .FLAG_ACTIVITY_CLEAR_TASK)); @@ -147,4 +156,15 @@ public class OverviewCommandHelper extends InternalStateHandler { return false; } + public boolean isUsingFallbackActivity() { + return DEBUG_START_FALLBACK_ACTIVITY; + } + + public ActivityControlHelper getActivityControlHelper() { + if (DEBUG_START_FALLBACK_ACTIVITY) { + return new FallbackActivityControllerHelper(); + } else { + return new LauncherActivityControllerHelper(); + } + } } diff --git a/quickstep/src/com/android/quickstep/OverviewInteractionState.java b/quickstep/src/com/android/quickstep/OverviewInteractionState.java index 4af89bf46b..522a88369f 100644 --- a/quickstep/src/com/android/quickstep/OverviewInteractionState.java +++ b/quickstep/src/com/android/quickstep/OverviewInteractionState.java @@ -15,20 +15,28 @@ */ package com.android.quickstep; -import static com.android.quickstep.TouchInteractionService.DEBUG_SHOW_OVERVIEW_BUTTON; +import static com.android.launcher3.Utilities.getPrefs; +import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_QUICK_SCRUB; +import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_SWIPE_UP; import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_HIDE_BACK_BUTTON; import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_SHOW_OVERVIEW_BUTTON; import android.content.Context; +import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.RemoteException; +import android.support.annotation.WorkerThread; import android.util.Log; +import com.android.launcher3.MainThreadExecutor; import com.android.launcher3.util.UiThreadHelper; import com.android.systemui.shared.recents.ISystemUiProxy; +import java.util.concurrent.ExecutionException; + /** * Sets overview interaction flags, such as: * @@ -39,55 +47,109 @@ import com.android.systemui.shared.recents.ISystemUiProxy; * * @see com.android.systemui.shared.system.NavigationBarCompat.InteractionType and associated flags. */ -public class OverviewInteractionState { +public class OverviewInteractionState implements OnSharedPreferenceChangeListener { private static final String TAG = "OverviewFlags"; - private static final Handler sUiHandler = new Handler(Looper.getMainLooper()) { - @Override - public void handleMessage(Message msg) { - updateOverviewInteractionFlag((Context) msg.obj, msg.what, msg.arg1 == 1); - } - }; - private static final Handler sBackgroundHandler = new Handler( - UiThreadHelper.getBackgroundLooper()) { - @Override - public void handleMessage(Message msg) { - ISystemUiProxy systemUiProxy = (ISystemUiProxy) msg.obj; - int flags = msg.what; - try { - systemUiProxy.setInteractionState(flags); - } catch (RemoteException e) { - Log.w(TAG, "Unable to update overview interaction flags", e); + + // We do not need any synchronization for this variable as its only written on UI thread. + private static OverviewInteractionState INSTANCE; + + public static OverviewInteractionState getInstance(final Context context) { + if (INSTANCE == null) { + if (Looper.myLooper() == Looper.getMainLooper()) { + INSTANCE = new OverviewInteractionState(context.getApplicationContext()); + } else { + try { + return new MainThreadExecutor().submit( + () -> OverviewInteractionState.getInstance(context)).get(); + } catch (InterruptedException|ExecutionException e) { + throw new RuntimeException(e); + } } } - }; - - private static int sFlags = DEBUG_SHOW_OVERVIEW_BUTTON ? FLAG_SHOW_OVERVIEW_BUTTON : 0; - - public static void setBackButtonVisible(Context context, boolean visible) { - updateFlagOnUi(context, FLAG_HIDE_BACK_BUTTON, !visible); + return INSTANCE; } - private static void updateFlagOnUi(Context context, int flag, boolean enabled) { - sUiHandler.removeMessages(flag); - sUiHandler.sendMessage(sUiHandler.obtainMessage(flag, enabled ? 1 : 0, 0, context)); + private static final String KEY_SWIPE_UP_ENABLED = "pref_enable_quickstep"; + + private static final int MSG_SET_PROXY = 200; + private static final int MSG_SET_BACK_BUTTON_VISIBLE = 201; + private static final int MSG_SET_SWIPE_UP_ENABLED = 202; + + private final Handler mUiHandler; + private final Handler mBgHandler; + + // These are updated on the background thread + private ISystemUiProxy mISystemUiProxy; + private boolean mBackButtonVisible = true; + private boolean mSwipeUpEnabled = true; + + private OverviewInteractionState(Context context) { + mUiHandler = new Handler(this::handleUiMessage); + mBgHandler = new Handler(UiThreadHelper.getBackgroundLooper(), this::handleBgMessage); + + SharedPreferences prefs = getPrefs(context); + prefs.registerOnSharedPreferenceChangeListener(this); + onSharedPreferenceChanged(prefs, KEY_SWIPE_UP_ENABLED); } - private static void updateOverviewInteractionFlag(Context context, int flag, boolean enabled) { - if (enabled) { - sFlags |= flag; - } else { - sFlags &= ~flag; + @Override + public void onSharedPreferenceChanged(SharedPreferences prefs, String s) { + if (KEY_SWIPE_UP_ENABLED.equals(s)) { + mUiHandler.removeMessages(MSG_SET_SWIPE_UP_ENABLED); + boolean swipeUpEnabled = prefs.getBoolean(s, true); + mUiHandler.obtainMessage(MSG_SET_SWIPE_UP_ENABLED, + swipeUpEnabled ? 1 : 0, 0).sendToTarget(); } + } - ISystemUiProxy systemUiProxy = RecentsModel.getInstance(context).getSystemUiProxy(); - if (systemUiProxy == null) { - Log.w(TAG, "Unable to update overview interaction flags; not bound to service"); + public void setBackButtonVisible(boolean visible) { + mUiHandler.removeMessages(MSG_SET_BACK_BUTTON_VISIBLE); + mUiHandler.obtainMessage(MSG_SET_BACK_BUTTON_VISIBLE, visible ? 1 : 0, 0) + .sendToTarget(); + } + + public void setSystemUiProxy(ISystemUiProxy proxy) { + mBgHandler.obtainMessage(MSG_SET_PROXY, proxy).sendToTarget(); + } + + private boolean handleUiMessage(Message msg) { + mBgHandler.obtainMessage(msg.what, msg.arg1, msg.arg2).sendToTarget(); + return true; + } + + private boolean handleBgMessage(Message msg) { + switch (msg.what) { + case MSG_SET_PROXY: + mISystemUiProxy = (ISystemUiProxy) msg.obj; + break; + case MSG_SET_BACK_BUTTON_VISIBLE: + mBackButtonVisible = msg.arg1 != 0; + break; + case MSG_SET_SWIPE_UP_ENABLED: + mSwipeUpEnabled = msg.arg1 != 0; + break; + } + applyFlags(); + return true; + } + + @WorkerThread + private void applyFlags() { + if (mISystemUiProxy == null) { return; } - // If we aren't already setting these flags, do so now on the background thread. - if (!sBackgroundHandler.hasMessages(sFlags)) { - sBackgroundHandler.sendMessage(sBackgroundHandler.obtainMessage(sFlags, systemUiProxy)); + + int flags; + if (mSwipeUpEnabled) { + flags = mBackButtonVisible ? 0 : FLAG_HIDE_BACK_BUTTON; + } else { + flags = FLAG_DISABLE_SWIPE_UP | FLAG_DISABLE_QUICK_SCRUB | FLAG_SHOW_OVERVIEW_BUTTON; + } + try { + mISystemUiProxy.setInteractionState(flags); + } catch (RemoteException e) { + Log.w(TAG, "Unable to update overview interaction flags", e); } } } diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java index 1d443fd2af..12e1a2bd8e 100644 --- a/quickstep/src/com/android/quickstep/RecentsActivity.java +++ b/quickstep/src/com/android/quickstep/RecentsActivity.java @@ -25,6 +25,7 @@ import com.android.launcher3.ItemInfo; import com.android.launcher3.LauncherAppState; import com.android.launcher3.R; import com.android.launcher3.badge.BadgeInfo; +import com.android.launcher3.uioverrides.UiFactory; import com.android.launcher3.views.BaseDragLayer; /** @@ -49,6 +50,8 @@ public class RecentsActivity extends BaseDraggingActivity { setContentView(R.layout.fallback_recents_activity); mRecentsRootView = findViewById(R.id.drag_layer); mFallbackRecentsView = findViewById(R.id.overview_panel); + + RecentsActivityTracker.onRecentsActivityCreate(this); } @Override @@ -56,6 +59,11 @@ public class RecentsActivity extends BaseDraggingActivity { return mRecentsRootView; } + @Override + public View getRootView() { + return mRecentsRootView; + } + @Override public T getOverviewPanel() { return (T) mFallbackRecentsView; @@ -73,4 +81,16 @@ public class RecentsActivity extends BaseDraggingActivity { @Override public void invalidateParent(ItemInfo info) { } + + @Override + protected void onStart() { + super.onStart(); + UiFactory.onStart(this); + } + + @Override + public void onTrimMemory(int level) { + super.onTrimMemory(level); + UiFactory.onTrimMemory(this, level); + } } diff --git a/quickstep/src/com/android/quickstep/RecentsActivityTracker.java b/quickstep/src/com/android/quickstep/RecentsActivityTracker.java new file mode 100644 index 0000000000..6a82dc0d00 --- /dev/null +++ b/quickstep/src/com/android/quickstep/RecentsActivityTracker.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 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. + */ +package com.android.quickstep; + +import android.annotation.TargetApi; +import android.os.Build; + +import com.android.quickstep.ActivityControlHelper.ActivityInitListener; + +import java.lang.ref.WeakReference; +import java.util.function.BiPredicate; + +/** + * Utility class to track create/destroy for RecentsActivity + */ +@TargetApi(Build.VERSION_CODES.P) +public class RecentsActivityTracker implements ActivityInitListener { + + private static final Object LOCK = new Object(); + private static WeakReference sTracker = new WeakReference<>(null); + + private final BiPredicate mOnInitListener; + + public RecentsActivityTracker(BiPredicate onInitListener) { + mOnInitListener = onInitListener; + } + + @Override + public void register() { + synchronized (LOCK) { + sTracker = new WeakReference<>(this); + } + } + + @Override + public void unregister() { + synchronized (LOCK) { + if (sTracker.get() == this) { + sTracker.clear(); + } + } + } + + public static void onRecentsActivityCreate(RecentsActivity activity) { + synchronized (LOCK) { + RecentsActivityTracker tracker = sTracker.get(); + if (tracker != null && tracker.mOnInitListener.test(activity, false)) { + sTracker.clear(); + } + } + } +} diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index ecd6c26493..df7214e2f4 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -47,7 +47,6 @@ import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherState; import com.android.launcher3.MainThreadExecutor; import com.android.launcher3.R; -import com.android.launcher3.uioverrides.UiFactory; import com.android.launcher3.util.TraceHelper; import com.android.quickstep.views.RecentsView; import com.android.systemui.shared.recents.IOverviewProxy; @@ -61,7 +60,6 @@ import com.android.systemui.shared.system.NavigationBarCompat.HitTarget; @TargetApi(Build.VERSION_CODES.O) public class TouchInteractionService extends Service { - public static final boolean DEBUG_SHOW_OVERVIEW_BUTTON = false; public static final boolean DEBUG_OPEN_OVERVIEW_VIA_ALT_TAB = false; private static final SparseArray sMotionEventNames; @@ -107,9 +105,7 @@ public class TouchInteractionService extends Service { mRecentsModel.setSystemUiProxy(mISystemUiProxy); RemoteRunnable.executeSafely(() -> mISystemUiProxy.setRecentsOnboardingText( getResources().getString(R.string.recents_swipe_up_onboarding))); - Launcher launcher = (Launcher) LauncherAppState.getInstance( - TouchInteractionService.this).getModel().getCallback(); - UiFactory.onLauncherStateOrFocusChanged(launcher); + mOverviewInteractionState.setSystemUiProxy(mISystemUiProxy); } @Override @@ -174,6 +170,7 @@ public class TouchInteractionService extends Service { private MainThreadExecutor mMainThreadExecutor; private ISystemUiProxy mISystemUiProxy; private OverviewCommandHelper mOverviewCommandHelper; + private OverviewInteractionState mOverviewInteractionState; private Choreographer mMainThreadChoreographer; private Choreographer mBackgroundThreadChoreographer; @@ -187,6 +184,7 @@ public class TouchInteractionService extends Service { mOverviewCommandHelper = new OverviewCommandHelper(this); mMainThreadChoreographer = Choreographer.getInstance(); mEventQueue = new MotionEventQueue(mMainThreadChoreographer, mNoOpTouchConsumer); + mOverviewInteractionState = OverviewInteractionState.getInstance(this); sConnected = true; @@ -235,7 +233,8 @@ public class TouchInteractionService extends Service { tracker = VelocityTracker.obtain(); } return new OtherActivityTouchConsumer(this, runningTaskInfo, mRecentsModel, - mOverviewCommandHelper.homeIntent, mISystemUiProxy, mMainThreadExecutor, + mOverviewCommandHelper.homeIntent, + mOverviewCommandHelper.getActivityControlHelper(), mMainThreadExecutor, mBackgroundThreadChoreographer, downHitTarget, tracker); } } diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java index 060d680fd0..96cd4a0243 100644 --- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -15,22 +15,16 @@ */ package com.android.quickstep; -import static com.android.launcher3.LauncherState.FAST_OVERVIEW; -import static com.android.launcher3.LauncherState.OVERVIEW; -import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS; -import static com.android.launcher3.anim.Interpolators.LINEAR; -import static com.android.launcher3.states.RotationHelper.REQUEST_LOCK; -import static com.android.launcher3.states.RotationHelper.REQUEST_NONE; import static com.android.quickstep.QuickScrubController.QUICK_SWITCH_START_DURATION; import static com.android.quickstep.TouchConsumer.INTERACTION_NORMAL; import static com.android.quickstep.TouchConsumer.INTERACTION_QUICK_SCRUB; import static com.android.quickstep.TouchConsumer.INTERACTION_QUICK_SWITCH; import static com.android.quickstep.TouchConsumer.isInteractionQuick; -import static com.android.systemui.shared.recents.utilities.Utilities.postAtFrontOfQueueAsynchronously; +import static com.android.systemui.shared.recents.utilities.Utilities + .postAtFrontOfQueueAsynchronously; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING; import android.animation.Animator; -import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.annotation.TargetApi; import android.app.ActivityManager.RunningTaskInfo; @@ -53,24 +47,22 @@ import android.view.View; import android.view.ViewTreeObserver.OnDrawListener; import com.android.launcher3.AbstractFloatingView; +import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.DeviceProfile; -import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppState; -import com.android.launcher3.LauncherState; import com.android.launcher3.MainThreadExecutor; import com.android.launcher3.R; import com.android.launcher3.Utilities; -import com.android.launcher3.allapps.AllAppsTransitionController; import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.logging.UserEventDispatcher; -import com.android.launcher3.states.InternalStateHandler; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.launcher3.util.TraceHelper; -import com.android.launcher3.util.ViewOnDrawExecutor; +import com.android.quickstep.ActivityControlHelper.ActivityInitListener; +import com.android.quickstep.ActivityControlHelper.LayoutListener; import com.android.quickstep.TouchConsumer.InteractionType; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; @@ -120,7 +112,7 @@ class MetricsLogger { } @TargetApi(Build.VERSION_CODES.O) -public class WindowTransformSwipeHandler extends InternalStateHandler { +public class WindowTransformSwipeHandler { private static final String TAG = WindowTransformSwipeHandler.class.getSimpleName(); private static final boolean DEBUG_STATES = false; @@ -209,12 +201,14 @@ public class WindowTransformSwipeHandler extends InternalStateHandler { private final Context mContext; private final int mRunningTaskId; + private final ActivityControlHelper mActivityControlHelper; + private final ActivityInitListener mActivityInitListener; private MultiStateCallback mStateCallback; private AnimatorPlaybackController mLauncherTransitionController; - private Launcher mLauncher; - private LauncherLayoutListener mLauncherLayoutListener; + private T mActivity; + private LayoutListener mLayoutListener; private RecentsView mRecentsView; private QuickScrubController mQuickScrubController; @@ -237,10 +231,15 @@ public class WindowTransformSwipeHandler extends InternalStateHandler { private long mLauncherFrameDrawnTime; private final MetricsLogger mMetricsLogger = new MetricsLogger(); - WindowTransformSwipeHandler(RunningTaskInfo runningTaskInfo, Context context, long touchTimeMs) { + WindowTransformSwipeHandler(RunningTaskInfo runningTaskInfo, Context context, long touchTimeMs, + ActivityControlHelper controller) { mContext = context; mRunningTaskId = runningTaskInfo.id; mTouchTimeMs = touchTimeMs; + mActivityControlHelper = controller; + mActivityInitListener = mActivityControlHelper + .createActivityInitListener(this::onActivityInit); + // Register the input consumer on the UI thread, to ensure that it runs after any pending // unregister calls mMainExecutor.execute(mInputConsumer::registerInputConsumer); @@ -313,7 +312,8 @@ public class WindowTransformSwipeHandler extends InternalStateHandler { mSourceStackBounds.height() - mSourceInsets.bottom); Rect tempRect = new Rect(); - RecentsView.getPageRect(dp, mContext, tempRect); + mTransitionDragLength = mActivityControlHelper + .getSwipeUpDestinationAndLength(dp, mContext, tempRect); mTargetRect.set(tempRect); mTargetRect.offset(mHomeStackBounds.left - mSourceStackBounds.left, @@ -334,14 +334,6 @@ public class WindowTransformSwipeHandler extends InternalStateHandler { Math.max(mSourceStackBounds.width() - scaledTargetRect.right, 0), Math.max(mSourceStackBounds.height() - scaledTargetRect.bottom, 0)); mSourceRect.set(scaledTargetRect); - - Rect targetInsets = dp.getInsets(); - if (dp.isVerticalBarLayout()) { - int hotseatInset = dp.isSeascape() ? targetInsets.left : targetInsets.right; - mTransitionDragLength = dp.hotseatBarSizePx + dp.hotseatBarSidePaddingPx + hotseatInset; - } else { - mTransitionDragLength = dp.heightPx - tempRect.bottom; - } } private long getFadeInDuration() { @@ -356,40 +348,39 @@ public class WindowTransformSwipeHandler extends InternalStateHandler { } } - @Override - protected boolean init(final Launcher launcher, boolean alreadyOnHome) { - if (launcher == mLauncher) { + public void initWhenReady() { + mActivityInitListener.register(); + } + + private boolean onActivityInit(final T activity, Boolean alreadyOnHome) { + if (mActivity == activity) { return true; } - if (mLauncher != null) { + if (mActivity != null) { // The launcher may have been recreated as a result of device rotation. int oldState = mStateCallback.getState() & ~LAUNCHER_UI_STATES; initStateCallbacks(); mStateCallback.setState(oldState); - mLauncherLayoutListener.setHandler(null); + mLayoutListener.setHandler(null); } mWasLauncherAlreadyVisible = alreadyOnHome; - mLauncher = launcher; + mActivity = activity; - // For the duration of the gesture, lock the screen orientation to ensure that we do not - // rotate mid-quickscrub - mLauncher.getRotationHelper().setStateHandlerRequest(REQUEST_LOCK); - - mRecentsView = mLauncher.getOverviewPanel(); + mRecentsView = activity.getOverviewPanel(); mQuickScrubController = mRecentsView.getQuickScrubController(); - mLauncherLayoutListener = new LauncherLayoutListener(mLauncher); + mLayoutListener = mActivityControlHelper.createLayoutListener(mActivity); mStateCallback.setState(STATE_LAUNCHER_PRESENT); if (alreadyOnHome) { - onLauncherStart(launcher); + onLauncherStart(activity); } else { - launcher.setOnStartCallback(this::onLauncherStart); + activity.setOnStartCallback(this::onLauncherStart); } return true; } - private void onLauncherStart(final Launcher launcher) { - if (mLauncher != launcher) { + private void onLauncherStart(final T activity) { + if (mActivity != activity) { return; } if ((mStateCallback.getState() & STATE_HANDLER_INVALIDATED) != 0) { @@ -397,31 +388,21 @@ public class WindowTransformSwipeHandler extends InternalStateHandler { } mStateCallback.setState(STATE_LAUNCHER_STARTED); - LauncherState startState = mLauncher.getStateManager().getState(); - if (startState.disableRestore) { - startState = mLauncher.getStateManager().getRestState(); - } - mLauncher.getStateManager().setRestState(startState); - - AbstractFloatingView.closeAllOpenViews(mLauncher, mWasLauncherAlreadyVisible); + mActivityControlHelper.prepareRecentsUI(mActivity, mWasLauncherAlreadyVisible); + AbstractFloatingView.closeAllOpenViews(activity, mWasLauncherAlreadyVisible); - if (mWasLauncherAlreadyVisible && !mLauncher.getAppTransitionManager().isAnimating()) { - DeviceProfile dp = mLauncher.getDeviceProfile(); - long accuracy = 2 * Math.max(dp.widthPx, dp.heightPx); - mLauncherTransitionController = mLauncher.getStateManager() - .createAnimationToNewWorkspace(OVERVIEW, accuracy); + if (mWasLauncherAlreadyVisible) { + mLauncherTransitionController = mActivityControlHelper + .createControllerForVisibleActivity(activity); mLauncherTransitionController.dispatchOnStart(); mLauncherTransitionController.setPlayFraction(mCurrentShift.value); mStateCallback.setState(STATE_ACTIVITY_MULTIPLIER_COMPLETE | STATE_LAUNCHER_DRAWN); } else { TraceHelper.beginSection("WTS-init"); - mLauncher.getStateManager().goToState(OVERVIEW, false); - TraceHelper.partitionSection("WTS-init", "State changed"); - // TODO: Implement a better animation for fading in - View rootView = mLauncher.getRootView(); + View rootView = activity.getRootView(); rootView.setAlpha(0); rootView.getViewTreeObserver().addOnDrawListener(new OnDrawListener() { @@ -430,21 +411,18 @@ public class WindowTransformSwipeHandler extends InternalStateHandler { TraceHelper.endSection("WTS-init", "Launcher frame is drawn"); rootView.post(() -> rootView.getViewTreeObserver().removeOnDrawListener(this)); - if (launcher != mLauncher) { + if (activity != mActivity) { return; } mStateCallback.setState(STATE_LAUNCHER_DRAWN); } }); - - // Optimization, hide the all apps view to prevent layout while initializing - mLauncher.getAppsView().setVisibility(View.GONE); } mRecentsView.showTask(mRunningTaskId); mRecentsView.setFirstTaskIconScaledDown(true /* isScaledDown */, false /* animate */); - mLauncherLayoutListener.open(); + mLayoutListener.open(); } public void setLauncherOnDrawCallback(Runnable callback) { @@ -452,7 +430,7 @@ public class WindowTransformSwipeHandler extends InternalStateHandler { } private void launcherFrameDrawn() { - View rootView = mLauncher.getRootView(); + View rootView = mActivity.getRootView(); if (rootView.getAlpha() < 1) { if (mGestureStarted) { final MultiStateCallback callback = mStateCallback; @@ -471,7 +449,7 @@ public class WindowTransformSwipeHandler extends InternalStateHandler { } private void initializeLauncherAnimationController() { - mLauncherLayoutListener.setHandler(this); + mLayoutListener.setHandler(this); onLauncherLayoutChanged(); final long transitionDelay = mLauncherFrameDrawnTime - mTouchTimeMs; @@ -508,7 +486,7 @@ public class WindowTransformSwipeHandler extends InternalStateHandler { } private void onQuickInteractionStart() { - mLauncher.getStateManager().goToState(FAST_OVERVIEW, + mActivityControlHelper.onQuickInteractionStart(mActivity, mWasLauncherAlreadyVisible || mGestureStarted); mQuickScrubController.onQuickScrubStart(false); } @@ -523,32 +501,14 @@ public class WindowTransformSwipeHandler extends InternalStateHandler { } /** - * Called by {@link #mLauncherLayoutListener} when launcher layout changes + * Called by {@link #mLayoutListener} when launcher layout changes */ public void onLauncherLayoutChanged() { - initTransitionEndpoints(mLauncher.getDeviceProfile()); + initTransitionEndpoints(mActivity.getDeviceProfile()); if (!mWasLauncherAlreadyVisible) { - float startProgress; - AllAppsTransitionController controller = mLauncher.getAllAppsController(); - - if (mLauncher.getDeviceProfile().isVerticalBarLayout()) { - startProgress = 1; - } else { - float scrollRange = Math.max(controller.getShiftRange(), 1); - startProgress = (mTransitionDragLength / scrollRange) + 1; - } - AnimatorSet anim = new AnimatorSet(); - ObjectAnimator shiftAnim = ObjectAnimator.ofFloat(controller, ALL_APPS_PROGRESS, - startProgress, OVERVIEW.getVerticalProgress(mLauncher)); - shiftAnim.setInterpolator(LINEAR); - anim.play(shiftAnim); - - // TODO: Link this animation to state animation, so that it is cancelled - // automatically on state change - anim.setDuration(mTransitionDragLength * 2); - mLauncherTransitionController = - AnimatorPlaybackController.wrap(anim, mTransitionDragLength * 2); + mLauncherTransitionController = mActivityControlHelper + .createControllerForHiddenActivity(mActivity, mTransitionDragLength); mLauncherTransitionController.setPlayFraction(mCurrentShift.value); } } @@ -661,14 +621,13 @@ public class WindowTransformSwipeHandler extends InternalStateHandler { } } } - mRecentsAnimationWrapper.setController(controller, apps); setStateOnUiThread(STATE_APP_CONTROLLER_RECEIVED); } public void onRecentsAnimationCanceled() { mRecentsAnimationWrapper.setController(null, null); - clearReference(); + mActivityInitListener.unregister(); setStateOnUiThread(STATE_GESTURE_CANCELLED | STATE_HANDLER_INVALIDATED); } @@ -684,9 +643,10 @@ public class WindowTransformSwipeHandler extends InternalStateHandler { * on both background and UI threads */ private void notifyGestureStarted() { - final Launcher curLauncher = mLauncher; - if (curLauncher != null) { - curLauncher.onQuickstepGestureStarted(mWasLauncherAlreadyVisible); + final T curActivity = mActivity; + if (curActivity != null) { + mActivityControlHelper.onQuickstepGestureStarted( + curActivity, mWasLauncherAlreadyVisible); } } @@ -770,25 +730,20 @@ public class WindowTransformSwipeHandler extends InternalStateHandler { mGestureEndCallback.run(); } - clearReference(); + mActivityInitListener.unregister(); mInputConsumer.unregisterInputConsumer(); } private void invalidateHandlerWithLauncher() { mLauncherTransitionController = null; - mLauncherLayoutListener.setHandler(null); - mLauncherLayoutListener.close(false); - - // Restore the requested orientation to the user preference after the gesture has ended - mLauncher.getRotationHelper().setStateHandlerRequest(REQUEST_NONE); + mLayoutListener.finish(); mRecentsView.setFirstTaskIconScaledDown(false /* isScaledDown */, false /* animate */); } private void resetStateForAnimationCancel() { - LauncherState startState = mLauncher.getStateManager().getRestState(); - boolean animate = mWasLauncherAlreadyVisible || mGestureStarted; - mLauncher.getStateManager().goToState(startState, animate); + boolean wasVisible = mWasLauncherAlreadyVisible || mGestureStarted; + mActivityControlHelper.onTransitionCancelled(mActivity, wasVisible); } public void layoutListenerClosed() { @@ -817,17 +772,8 @@ public class WindowTransformSwipeHandler extends InternalStateHandler { if (taskView != null) { // Defer finishing the animation until the next launcher frame with the // new thumbnail - ViewOnDrawExecutor executor = new ViewOnDrawExecutor() { - @Override - public void onViewDetachedFromWindow(View v) { - if (!isCompleted()) { - runAllTasks(); - } - } - }; - executor.attachTo(mLauncher, taskView, - false /* waitForLoadAnimation */); - executor.execute(finishTransitionRunnable); + mActivityControlHelper.executeOnNextDraw(mActivity, taskView, + finishTransitionRunnable); finishTransitionPosted = true; } } @@ -843,8 +789,7 @@ public class WindowTransformSwipeHandler extends InternalStateHandler { } private void setupLauncherUiAfterSwipeUpAnimation() { - // Re apply state in case we did something funky during the transition. - mLauncher.getStateManager().reapplyState(); + mActivityControlHelper.onSwipeUpComplete(mActivity); // Animate the first icon. mRecentsView.setFirstTaskIconScaledDown(false /* isScaledDown */, true /* animate */); diff --git a/quickstep/src/com/android/quickstep/LauncherLayoutListener.java b/quickstep/src/com/android/quickstep/views/LauncherLayoutListener.java similarity index 83% rename from quickstep/src/com/android/quickstep/LauncherLayoutListener.java rename to quickstep/src/com/android/quickstep/views/LauncherLayoutListener.java index fbdbe7a141..6b7143d048 100644 --- a/quickstep/src/com/android/quickstep/LauncherLayoutListener.java +++ b/quickstep/src/com/android/quickstep/views/LauncherLayoutListener.java @@ -13,7 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.android.quickstep; +package com.android.quickstep.views; + +import static com.android.launcher3.states.RotationHelper.REQUEST_NONE; import android.graphics.Rect; import android.view.MotionEvent; @@ -21,11 +23,14 @@ import android.view.MotionEvent; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.Insettable; import com.android.launcher3.Launcher; +import com.android.quickstep.ActivityControlHelper.LayoutListener; +import com.android.quickstep.WindowTransformSwipeHandler; /** * Floating view which shows the task snapshot allowing it to be dragged and placed. */ -public class LauncherLayoutListener extends AbstractFloatingView implements Insettable { +public class LauncherLayoutListener extends AbstractFloatingView + implements Insettable, LayoutListener { private final Launcher mLauncher; private WindowTransformSwipeHandler mHandler; @@ -36,6 +41,7 @@ public class LauncherLayoutListener extends AbstractFloatingView implements Inse setVisibility(INVISIBLE); } + @Override public void setHandler(WindowTransformSwipeHandler handler) { mHandler = handler; } @@ -65,6 +71,7 @@ public class LauncherLayoutListener extends AbstractFloatingView implements Inse } } + @Override public void open() { if (!mIsOpen) { mLauncher.getDragLayer().addView(this); @@ -86,4 +93,11 @@ public class LauncherLayoutListener extends AbstractFloatingView implements Inse protected boolean isOfType(int type) { return (type & TYPE_QUICKSTEP_PREVIEW) != 0; } + + @Override + public void finish() { + setHandler(null); + close(false); + mLauncher.getRotationHelper().setStateHandlerRequest(REQUEST_NONE); + } } diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java index 35edaf4668..458f7b280f 100644 --- a/src/com/android/launcher3/BaseDraggingActivity.java +++ b/src/com/android/launcher3/BaseDraggingActivity.java @@ -55,6 +55,8 @@ public abstract class BaseDraggingActivity extends BaseActivity { private ActionMode mCurrentActionMode; protected boolean mIsSafeModeEnabled; + private OnStartCallback mOnStartCallback; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -85,6 +87,8 @@ public abstract class BaseDraggingActivity extends BaseActivity { public abstract T getOverviewPanel(); + public abstract View getRootView(); + public abstract BadgeInfo getBadgeInfoForItem(ItemInfo info); public abstract void invalidateParent(ItemInfo info); @@ -188,4 +192,26 @@ public abstract class BaseDraggingActivity extends BaseActivity { protected boolean onErrorStartingShortcut(Intent intent, ItemInfo info) { return false; } + + @Override + protected void onStart() { + super.onStart(); + + if (mOnStartCallback != null) { + mOnStartCallback.onActivityStart(this); + mOnStartCallback = null; + } + } + + public void setOnStartCallback(OnStartCallback callback) { + mOnStartCallback = callback; + } + + /** + * Callback for listening for onStart + */ + public interface OnStartCallback { + + void onActivityStart(T activity); + } } diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index a38ce078ab..ee6dd591c1 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -209,7 +209,6 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, L @Thunk boolean mWorkspaceLoading = true; - private OnStartCallback mOnStartCallback; private OnResumeCallback mOnResumeCallback; private ViewOnDrawExecutor mPendingExecutor; @@ -767,10 +766,6 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, L super.onStart(); FirstFrameAnimatorHelper.setIsVisible(true); - if (mOnStartCallback != null) { - mOnStartCallback.onLauncherStart(this); - mOnStartCallback = null; - } if (mLauncherCallbacks != null) { mLauncherCallbacks.onStart(); } @@ -1177,6 +1172,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, L return mAllAppsController; } + @Override public LauncherRootView getRootView() { return (LauncherRootView) mLauncherView; } @@ -1775,10 +1771,6 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, L mOnResumeCallback = callback; } - public void setOnStartCallback(OnStartCallback callback) { - mOnStartCallback = callback; - } - /** * Implementation of the method from LauncherModel.Callbacks. */ @@ -2450,12 +2442,4 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, L void onLauncherResume(); } - - /** - * Callback for listening for onStart - */ - public interface OnStartCallback { - - void onLauncherStart(Launcher launcher); - } }