1 /*
2  * Copyright (C) 2018 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;
18 
19 import static com.android.launcher3.util.DisplayController.CHANGE_ROTATION;
20 
21 import android.content.Context;
22 import android.content.res.Configuration;
23 import android.os.Bundle;
24 import android.view.ActionMode;
25 import android.view.View;
26 
27 import androidx.annotation.MainThread;
28 import androidx.annotation.NonNull;
29 import androidx.annotation.Nullable;
30 
31 import com.android.launcher3.model.data.ItemInfo;
32 import com.android.launcher3.touch.ItemClickHandler;
33 import com.android.launcher3.util.ActivityOptionsWrapper;
34 import com.android.launcher3.util.DisplayController;
35 import com.android.launcher3.util.DisplayController.DisplayInfoChangeListener;
36 import com.android.launcher3.util.DisplayController.Info;
37 import com.android.launcher3.util.OnColorHintListener;
38 import com.android.launcher3.util.Themes;
39 import com.android.launcher3.util.WallpaperColorHints;
40 import com.android.launcher3.util.WindowBounds;
41 
42 /**
43  * Extension of BaseActivity allowing support for drag-n-drop
44  */
45 @SuppressWarnings("NewApi")
46 public abstract class BaseDraggingActivity extends BaseActivity
47         implements OnColorHintListener, DisplayInfoChangeListener {
48 
49     // When starting an action mode, setting this tag will cause the action mode to be cancelled
50     // automatically when user interacts with the launcher.
51     public static final Object AUTO_CANCEL_ACTION_MODE = new Object();
52 
53     private ActionMode mCurrentActionMode;
54 
55     private int mThemeRes = R.style.AppTheme;
56 
57     @Override
onCreate(Bundle savedInstanceState)58     protected void onCreate(Bundle savedInstanceState) {
59         super.onCreate(savedInstanceState);
60         DisplayController.INSTANCE.get(this).addChangeListener(this);
61 
62         // Update theme
63         WallpaperColorHints.get(this).registerOnColorHintsChangedListener(this);
64         int themeRes = Themes.getActivityThemeRes(this);
65         if (themeRes != mThemeRes) {
66             mThemeRes = themeRes;
67             setTheme(themeRes);
68         }
69     }
70 
71     @MainThread
72     @Override
onColorHintsChanged(int colorHints)73     public void onColorHintsChanged(int colorHints) {
74         updateTheme();
75     }
76 
77     @Override
onConfigurationChanged(Configuration newConfig)78     public void onConfigurationChanged(Configuration newConfig) {
79         super.onConfigurationChanged(newConfig);
80         updateTheme();
81     }
82 
updateTheme()83     private void updateTheme() {
84         if (mThemeRes != Themes.getActivityThemeRes(this)) {
85             recreate();
86         }
87     }
88 
89     @Override
onActionModeStarted(ActionMode mode)90     public void onActionModeStarted(ActionMode mode) {
91         super.onActionModeStarted(mode);
92         mCurrentActionMode = mode;
93     }
94 
95     @Override
onActionModeFinished(ActionMode mode)96     public void onActionModeFinished(ActionMode mode) {
97         super.onActionModeFinished(mode);
98         mCurrentActionMode = null;
99     }
100 
isInAutoCancelActionMode()101     protected boolean isInAutoCancelActionMode() {
102         return mCurrentActionMode != null && AUTO_CANCEL_ACTION_MODE == mCurrentActionMode.getTag();
103     }
104 
105     @Override
finishAutoCancelActionMode()106     public boolean finishAutoCancelActionMode() {
107         if (isInAutoCancelActionMode()) {
108             mCurrentActionMode.finish();
109             return true;
110         }
111         return false;
112     }
113 
getRootView()114     public abstract View getRootView();
115 
returnToHomescreen()116     public void returnToHomescreen() {
117         // no-op
118     }
119 
120     @Override
121     @NonNull
getActivityLaunchOptions(View v, @Nullable ItemInfo item)122     public ActivityOptionsWrapper getActivityLaunchOptions(View v, @Nullable ItemInfo item) {
123         ActivityOptionsWrapper wrapper = super.getActivityLaunchOptions(v, item);
124         addEventCallback(EVENT_RESUMED, wrapper.onEndCallback::executeAllAndDestroy);
125         return wrapper;
126     }
127 
128     @Override
makeDefaultActivityOptions(int splashScreenStyle)129     public ActivityOptionsWrapper makeDefaultActivityOptions(int splashScreenStyle) {
130         ActivityOptionsWrapper wrapper = super.makeDefaultActivityOptions(splashScreenStyle);
131         addEventCallback(EVENT_RESUMED, wrapper.onEndCallback::executeAllAndDestroy);
132         return wrapper;
133     }
134 
135     @Override
onDestroy()136     protected void onDestroy() {
137         super.onDestroy();
138         DisplayController.INSTANCE.get(this).removeChangeListener(this);
139         WallpaperColorHints.get(this).unregisterOnColorsChangedListener(this);
140     }
141 
onDeviceProfileInitiated()142     protected void onDeviceProfileInitiated() {
143         if (mDeviceProfile.isVerticalBarLayout()) {
144             mDeviceProfile.updateIsSeascape(this);
145         }
146     }
147 
148     @Override
onDisplayInfoChanged(Context context, Info info, int flags)149     public void onDisplayInfoChanged(Context context, Info info, int flags) {
150         if ((flags & CHANGE_ROTATION) != 0 && mDeviceProfile.isVerticalBarLayout()) {
151             mDeviceProfile.updateIsSeascape(this);
152             reapplyUi();
153         }
154     }
155 
156     @Override
getItemOnClickListener()157     public View.OnClickListener getItemOnClickListener() {
158         return ItemClickHandler.INSTANCE;
159     }
160 
reapplyUi()161     protected abstract void reapplyUi();
162 
getMultiWindowDisplaySize()163     protected WindowBounds getMultiWindowDisplaySize() {
164         return WindowBounds.fromWindowMetrics(getWindowManager().getCurrentWindowMetrics());
165     }
166 
167     @Override
isAppBlockedForSafeMode()168     public boolean isAppBlockedForSafeMode() {
169         return LauncherAppState.getInstance(this).isSafeModeEnabled();
170     }
171 }
172