• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.launcher3.uioverrides;
18 
19 import static android.view.View.VISIBLE;
20 import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
21 import static com.android.launcher3.AbstractFloatingView.TYPE_HIDE_BACK_BUTTON;
22 import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
23 import static com.android.launcher3.LauncherState.ALL_APPS;
24 import static com.android.launcher3.LauncherState.NORMAL;
25 import static com.android.launcher3.LauncherState.OVERVIEW;
26 import static com.android.launcher3.allapps.DiscoveryBounce.HOME_BOUNCE_SEEN;
27 import static com.android.launcher3.allapps.DiscoveryBounce.SHELF_BOUNCE_SEEN;
28 import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
29 
30 import android.animation.AnimatorSet;
31 import android.animation.ValueAnimator;
32 import android.app.Activity;
33 import android.content.Context;
34 import android.os.CancellationSignal;
35 import android.util.Base64;
36 
37 import com.android.launcher3.AbstractFloatingView;
38 import com.android.launcher3.DeviceProfile;
39 import com.android.launcher3.Launcher;
40 import com.android.launcher3.LauncherAppTransitionManagerImpl;
41 import com.android.launcher3.LauncherState;
42 import com.android.launcher3.LauncherStateManager;
43 import com.android.launcher3.LauncherStateManager.StateHandler;
44 import com.android.launcher3.Utilities;
45 import com.android.launcher3.anim.AnimatorPlaybackController;
46 import com.android.launcher3.util.TouchController;
47 import com.android.quickstep.OverviewInteractionState;
48 import com.android.quickstep.RecentsModel;
49 import com.android.quickstep.util.RemoteAnimationTargetSet;
50 import com.android.quickstep.util.RemoteFadeOutAnimationListener;
51 import com.android.quickstep.views.RecentsView;
52 import com.android.systemui.shared.system.ActivityCompat;
53 import com.android.systemui.shared.system.WindowManagerWrapper;
54 
55 import java.io.ByteArrayOutputStream;
56 import java.io.PrintWriter;
57 import java.util.zip.Deflater;
58 
59 public class UiFactory {
60 
createTouchControllers(Launcher launcher)61     public static TouchController[] createTouchControllers(Launcher launcher) {
62         boolean swipeUpEnabled = OverviewInteractionState.getInstance(launcher)
63                 .isSwipeUpGestureEnabled();
64         if (!swipeUpEnabled) {
65             return new TouchController[] {
66                     launcher.getDragController(),
67                     new OverviewToAllAppsTouchController(launcher),
68                     new LauncherTaskViewController(launcher)};
69         }
70         if (launcher.getDeviceProfile().isVerticalBarLayout()) {
71             return new TouchController[] {
72                     launcher.getDragController(),
73                     new OverviewToAllAppsTouchController(launcher),
74                     new LandscapeEdgeSwipeController(launcher),
75                     new LauncherTaskViewController(launcher)};
76         } else {
77             return new TouchController[] {
78                     launcher.getDragController(),
79                     new PortraitStatesTouchController(launcher),
80                     new LauncherTaskViewController(launcher)};
81         }
82     }
83 
setOnTouchControllersChangedListener(Context context, Runnable listener)84     public static void setOnTouchControllersChangedListener(Context context, Runnable listener) {
85         OverviewInteractionState.getInstance(context).setOnSwipeUpSettingChangedListener(listener);
86     }
87 
getStateHandler(Launcher launcher)88     public static StateHandler[] getStateHandler(Launcher launcher) {
89         return new StateHandler[] {launcher.getAllAppsController(), launcher.getWorkspace(),
90                 new RecentsViewStateController(launcher), new BackButtonAlphaHandler(launcher)};
91     }
92 
93     /**
94      * Sets the back button visibility based on the current state/window focus.
95      */
onLauncherStateOrFocusChanged(Launcher launcher)96     public static void onLauncherStateOrFocusChanged(Launcher launcher) {
97         boolean shouldBackButtonBeHidden = launcher != null
98                 && launcher.getStateManager().getState().hideBackButton
99                 && launcher.hasWindowFocus();
100         if (shouldBackButtonBeHidden) {
101             // Show the back button if there is a floating view visible.
102             shouldBackButtonBeHidden = AbstractFloatingView.getTopOpenViewWithType(launcher,
103                     TYPE_ALL & ~TYPE_HIDE_BACK_BUTTON) == null;
104         }
105         OverviewInteractionState.getInstance(launcher)
106                 .setBackButtonAlpha(shouldBackButtonBeHidden ? 0 : 1, true /* animate */);
107     }
108 
resetOverview(Launcher launcher)109     public static void resetOverview(Launcher launcher) {
110         RecentsView recents = launcher.getOverviewPanel();
111         recents.reset();
112     }
113 
onCreate(Launcher launcher)114     public static void onCreate(Launcher launcher) {
115         if (!launcher.getSharedPrefs().getBoolean(HOME_BOUNCE_SEEN, false)) {
116             launcher.getStateManager().addStateListener(new LauncherStateManager.StateListener() {
117                 @Override
118                 public void onStateSetImmediately(LauncherState state) {
119                 }
120 
121                 @Override
122                 public void onStateTransitionStart(LauncherState toState) {
123                 }
124 
125                 @Override
126                 public void onStateTransitionComplete(LauncherState finalState) {
127                     boolean swipeUpEnabled = OverviewInteractionState.getInstance(launcher)
128                             .isSwipeUpGestureEnabled();
129                     LauncherState prevState = launcher.getStateManager().getLastState();
130 
131                     if (((swipeUpEnabled && finalState == OVERVIEW) || (!swipeUpEnabled
132                             && finalState == ALL_APPS && prevState == NORMAL))) {
133                         launcher.getSharedPrefs().edit().putBoolean(HOME_BOUNCE_SEEN, true).apply();
134                         launcher.getStateManager().removeStateListener(this);
135                     }
136                 }
137             });
138         }
139 
140         if (!launcher.getSharedPrefs().getBoolean(SHELF_BOUNCE_SEEN, false)) {
141             launcher.getStateManager().addStateListener(new LauncherStateManager.StateListener() {
142                 @Override
143                 public void onStateSetImmediately(LauncherState state) {
144                 }
145 
146                 @Override
147                 public void onStateTransitionStart(LauncherState toState) {
148                 }
149 
150                 @Override
151                 public void onStateTransitionComplete(LauncherState finalState) {
152                     LauncherState prevState = launcher.getStateManager().getLastState();
153 
154                     if (finalState == ALL_APPS && prevState == OVERVIEW) {
155                         launcher.getSharedPrefs().edit().putBoolean(SHELF_BOUNCE_SEEN, true).apply();
156                         launcher.getStateManager().removeStateListener(this);
157                     }
158                 }
159             });
160         }
161     }
162 
onStart(Context context)163     public static void onStart(Context context) {
164         RecentsModel model = RecentsModel.getInstance(context);
165         if (model != null) {
166             model.onStart();
167         }
168     }
169 
onLauncherStateOrResumeChanged(Launcher launcher)170     public static void onLauncherStateOrResumeChanged(Launcher launcher) {
171         LauncherState state = launcher.getStateManager().getState();
172         DeviceProfile profile = launcher.getDeviceProfile();
173         WindowManagerWrapper.getInstance().setShelfHeight(
174                 state != ALL_APPS && launcher.isUserActive() && !profile.isVerticalBarLayout(),
175                 profile.hotseatBarSizePx);
176 
177         if (state == NORMAL) {
178             launcher.<RecentsView>getOverviewPanel().setSwipeDownShouldLaunchApp(false);
179         }
180     }
181 
onTrimMemory(Context context, int level)182     public static void onTrimMemory(Context context, int level) {
183         RecentsModel model = RecentsModel.getInstance(context);
184         if (model != null) {
185             model.onTrimMemory(level);
186         }
187     }
188 
useFadeOutAnimationForLauncherStart(Launcher launcher, CancellationSignal cancellationSignal)189     public static void useFadeOutAnimationForLauncherStart(Launcher launcher,
190             CancellationSignal cancellationSignal) {
191         LauncherAppTransitionManagerImpl appTransitionManager =
192                 (LauncherAppTransitionManagerImpl) launcher.getAppTransitionManager();
193         appTransitionManager.setRemoteAnimationProvider((targets) -> {
194 
195             // On the first call clear the reference.
196             cancellationSignal.cancel();
197 
198             ValueAnimator fadeAnimation = ValueAnimator.ofFloat(1, 0);
199             fadeAnimation.addUpdateListener(new RemoteFadeOutAnimationListener(targets));
200             AnimatorSet anim = new AnimatorSet();
201             anim.play(fadeAnimation);
202             return anim;
203         }, cancellationSignal);
204     }
205 
dumpActivity(Activity activity, PrintWriter writer)206     public static boolean dumpActivity(Activity activity, PrintWriter writer) {
207         if (!Utilities.IS_DEBUG_DEVICE) {
208             return false;
209         }
210         ByteArrayOutputStream out = new ByteArrayOutputStream();
211         if (!(new ActivityCompat(activity).encodeViewHierarchy(out))) {
212             return false;
213         }
214 
215         Deflater deflater = new Deflater();
216         deflater.setInput(out.toByteArray());
217         deflater.finish();
218 
219         out.reset();
220         byte[] buffer = new byte[1024];
221         while (!deflater.finished()) {
222             int count = deflater.deflate(buffer); // returns the generated code... index
223             out.write(buffer, 0, count);
224         }
225 
226         writer.println("--encoded-view-dump-v0--");
227         writer.println(Base64.encodeToString(
228                 out.toByteArray(), Base64.NO_WRAP | Base64.NO_PADDING));
229         return true;
230     }
231 
prepareToShowOverview(Launcher launcher)232     public static void prepareToShowOverview(Launcher launcher) {
233         RecentsView overview = launcher.getOverviewPanel();
234         if (overview.getVisibility() != VISIBLE || overview.getContentAlpha() == 0) {
235             SCALE_PROPERTY.set(overview, 1.33f);
236         }
237     }
238 
239     private static class LauncherTaskViewController extends TaskViewTouchController<Launcher> {
240 
LauncherTaskViewController(Launcher activity)241         public LauncherTaskViewController(Launcher activity) {
242             super(activity);
243         }
244 
245         @Override
isRecentsInteractive()246         protected boolean isRecentsInteractive() {
247             return mActivity.isInState(OVERVIEW);
248         }
249 
250         @Override
onUserControlledAnimationCreated(AnimatorPlaybackController animController)251         protected void onUserControlledAnimationCreated(AnimatorPlaybackController animController) {
252             mActivity.getStateManager().setCurrentUserControlledAnimation(animController);
253         }
254     }
255 }
256