From eb52419282fecb88a2d5ac049f9807c564fd488e Mon Sep 17 00:00:00 2001 From: y Date: Tue, 31 Aug 2021 20:24:33 -0700 Subject: [PATCH] [Refactor] Extract work profile related logic from AllAppsContainerView to WorkProfileManager Bug: 195623679 Test: presubmit Change-Id: I9954fb40034d1804aaf19f0778f95477e48ccc8f --- res/values/dimens.xml | 1 - .../allapps/AllAppsContainerView.java | 109 +++-------- .../allapps/WorkAdapterProvider.java | 28 ++- .../launcher3/allapps/WorkModeSwitch.java | 117 +++++++----- .../launcher3/allapps/WorkPausedCard.java | 3 +- .../launcher3/allapps/WorkProfileManager.java | 175 ++++++++++++++++++ .../anim/KeyboardInsetAnimationCallback.java | 27 ++- 7 files changed, 313 insertions(+), 147 deletions(-) create mode 100644 src/com/android/launcher3/allapps/WorkProfileManager.java diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 5fc048093e..3d14681c4c 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -127,7 +127,6 @@ 52dp 16dp 20dp - 16sp 16dp 28dp diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java index ee5f7e4a71..6d3f309520 100644 --- a/src/com/android/launcher3/allapps/AllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java @@ -17,15 +17,11 @@ package com.android.launcher3.allapps; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_TAP_ON_PERSONAL_TAB; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_TAP_ON_WORK_TAB; -import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_HAS_SHORTCUT_PERMISSION; -import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_CHANGE_PERMISSION; -import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_ENABLED; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.content.Context; -import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; @@ -34,7 +30,7 @@ import android.graphics.Rect; import android.os.Bundle; import android.os.Parcelable; import android.os.Process; -import android.text.Selection; +import android.os.UserManager; import android.text.SpannableStringBuilder; import android.util.AttributeSet; import android.util.Log; @@ -88,11 +84,12 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo public static final float FLING_VELOCITY_MULTIPLIER = 1200f; private final Paint mHeaderPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Rect mInsets = new Rect(); protected final BaseDraggingActivity mLauncher; protected final AdapterHolder[] mAH; - private final ItemInfoMatcher mPersonalMatcher = ItemInfoMatcher.ofUser(Process.myUserHandle()); - private final ItemInfoMatcher mWorkMatcher = mPersonalMatcher.negate(); + protected final ItemInfoMatcher mPersonalMatcher = ItemInfoMatcher.ofUser( + Process.myUserHandle()); private final AllAppsStore mAllAppsStore = new AllAppsStore(); private final RecyclerView.OnScrollListener mScrollListener = @@ -102,6 +99,8 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo updateHeaderScroll(((AllAppsRecyclerView) recyclerView).getCurrentScrollY()); } }; + private final WorkProfileManager mWorkManager; + private final Paint mNavBarScrimPaint; private int mNavBarScrimHeight = 0; @@ -111,8 +110,6 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo private AllAppsPagedView mViewPager; protected FloatingHeaderView mHeader; - private float mHeaderTop; - private WorkModeSwitch mWorkModeSwitch; private SpannableStringBuilder mSearchQueryBuilder = null; @@ -124,10 +121,7 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo protected RecyclerViewFastScroller mTouchHandler; protected final Point mFastScrollerOffset = new Point(); - private Rect mInsets = new Rect(); - private SearchAdapterProvider mSearchAdapterProvider; - private WorkAdapterProvider mWorkAdapterProvider; private final int mScrimColor; private final int mHeaderProtectionColor; private final float mHeaderThreshold; @@ -156,15 +150,11 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo mLauncher.addOnDeviceProfileChangeListener(this); mSearchAdapterProvider = mLauncher.createSearchAdapterProvider(this); - mSearchQueryBuilder = new SpannableStringBuilder(); - Selection.setSelection(mSearchQueryBuilder, 0); mAH = new AdapterHolder[2]; - mWorkAdapterProvider = new WorkAdapterProvider(mLauncher, () -> { - if (mAH[AdapterHolder.WORK] != null) { - mAH[AdapterHolder.WORK].appsList.updateAdapterItems(); - } - }); + + mWorkManager = new WorkProfileManager(mLauncher.getSystemService(UserManager.class), this, + Utilities.getPrefs(mLauncher)); mAH[AdapterHolder.MAIN] = new AdapterHolder(false /* isWork */); mAH[AdapterHolder.WORK] = new AdapterHolder(true /* isWork */); @@ -220,8 +210,8 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo return mAllAppsStore; } - public WorkModeSwitch getWorkModeSwitch() { - return mWorkModeSwitch; + public WorkProfileManager getWorkManager() { + return mWorkManager; } @Override @@ -240,7 +230,7 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo private void onAppsUpdated() { boolean hasWorkApps = false; for (AppInfo app : mAllAppsStore.getApps()) { - if (mWorkMatcher.matches(app, null)) { + if (mWorkManager.getMatcher().matches(app, null)) { hasWorkApps = true; break; } @@ -248,20 +238,12 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo mHasWorkApps = hasWorkApps; if (!mAH[AdapterHolder.MAIN].appsList.hasFilter()) { rebindAdapters(); - if (mHasWorkApps) { - resetWorkProfile(); + if (hasWorkApps) { + mWorkManager.reset(); } } } - private void resetWorkProfile() { - boolean isEnabled = !mAllAppsStore.hasModelFlag(FLAG_QUIET_MODE_ENABLED); - if (mWorkModeSwitch != null) { - mWorkModeSwitch.updateCurrentState(isEnabled); - } - mWorkAdapterProvider.updateCurrentState(isEnabled); - } - /** * Returns whether the view itself will handle the touch event or not. */ @@ -461,7 +443,7 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo if (mUsingTabs) { mAH[AdapterHolder.MAIN].setup(mViewPager.getChildAt(0), mPersonalMatcher); - mAH[AdapterHolder.WORK].setup(mViewPager.getChildAt(1), mWorkMatcher); + mAH[AdapterHolder.WORK].setup(mViewPager.getChildAt(1), mWorkManager.getMatcher()); mAH[AdapterHolder.WORK].recyclerView.setId(R.id.apps_list_view_work); mViewPager.getPageIndicator().setActiveMarker(AdapterHolder.MAIN); findViewById(R.id.tab_personal) @@ -489,34 +471,12 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo mAllAppsStore.registerIconContainer(mAH[AdapterHolder.WORK].recyclerView); } - private void setupWorkToggle() { - removeWorkToggle(); - if (Utilities.ATLEAST_P) { - mWorkModeSwitch = (WorkModeSwitch) mLauncher.getLayoutInflater().inflate( - R.layout.work_mode_fab, this, false); - this.addView(mWorkModeSwitch); - mWorkModeSwitch.setInsets(mInsets); - mWorkModeSwitch.post(() -> { - mAH[AdapterHolder.WORK].applyPadding(); - resetWorkProfile(); - }); - } - } - - private void removeWorkToggle() { - if (mWorkModeSwitch == null) return; - if (mWorkModeSwitch.getParent() == this) { - this.removeView(mWorkModeSwitch); - } - mWorkModeSwitch = null; - } private void replaceRVContainer(boolean showTabs) { - for (int i = 0; i < mAH.length; i++) { - AllAppsRecyclerView rv = mAH[i].recyclerView; - if (rv != null) { - rv.setLayoutManager(null); - rv.setAdapter(null); + for (AdapterHolder adapterHolder : mAH) { + if (adapterHolder.recyclerView != null) { + adapterHolder.recyclerView.setLayoutManager(null); + adapterHolder.recyclerView.setAdapter(null); } } View oldView = getRecyclerViewContainer(); @@ -533,10 +493,10 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo mViewPager = (AllAppsPagedView) newView; mViewPager.initParentViews(this); mViewPager.getPageIndicator().setOnActivePageChangedListener(this); - setupWorkToggle(); + mWorkManager.attachWorkModeSwitch(); } else { + mWorkManager.detachWorkModeSwitch(); mViewPager = null; - removeWorkToggle(); } } @@ -551,11 +511,8 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo mAH[currentActivePage].recyclerView.bindFastScrollbar(); } reset(true /* animate */); - if (mWorkModeSwitch != null) { - mWorkModeSwitch.setWorkTabVisible(currentActivePage == AdapterHolder.WORK - && mAllAppsStore.hasModelFlag( - FLAG_HAS_SHORTCUT_PERMISSION | FLAG_QUIET_MODE_CHANGE_PERMISSION)); - } + + mWorkManager.onActivePageChanged(currentActivePage); } // Used by tests only @@ -627,7 +584,6 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo mAH[i].recyclerView.scrollToTop(); } } - mHeaderTop = mHeader.getTop(); } public void setLastSearchQuery(String query) { @@ -731,7 +687,6 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo public static final int MAIN = 0; public static final int WORK = 1; - private ItemInfoMatcher mInfoMatcher; private final boolean mIsWork; public final AllAppsGridAdapter adapter; final LinearLayoutManager layoutManager; @@ -739,17 +694,16 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo final Rect padding = new Rect(); AllAppsRecyclerView recyclerView; boolean verticalFadingEdge; - private View mOverlay; - boolean mWorkDisabled; AdapterHolder(boolean isWork) { mIsWork = isWork; appsList = new AlphabeticalAppsList(mLauncher, mAllAppsStore, - isWork ? mWorkAdapterProvider : null); + isWork ? mWorkManager.getAdapterProvider() : null); BaseAdapterProvider[] adapterProviders = - isWork ? new BaseAdapterProvider[]{mSearchAdapterProvider, mWorkAdapterProvider} + isWork ? new BaseAdapterProvider[]{mSearchAdapterProvider, + mWorkManager.getAdapterProvider()} : new BaseAdapterProvider[]{mSearchAdapterProvider}; adapter = new AllAppsGridAdapter(mLauncher, getLayoutInflater(), appsList, @@ -759,7 +713,6 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo } void setup(@NonNull View rv, @Nullable ItemInfoMatcher matcher) { - mInfoMatcher = matcher; appsList.updateItemFilter(matcher); recyclerView = (AllAppsRecyclerView) rv; recyclerView.setEdgeEffectFactory(createEdgeEffectFactory()); @@ -782,12 +735,10 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo void applyPadding() { if (recyclerView != null) { - Resources res = getResources(); - int switchH = res.getDimensionPixelSize(R.dimen.work_profile_footer_padding) * 2 - + mInsets.bottom + Utilities.calculateTextHeight( - res.getDimension(R.dimen.work_profile_footer_text_size)); - - int bottomOffset = mWorkModeSwitch != null && mIsWork ? switchH : 0; + int bottomOffset = 0; + if (mIsWork && mWorkManager.getWorkModeSwitch() != null) { + bottomOffset = mInsets.bottom + mWorkManager.getWorkModeSwitch().getHeight(); + } recyclerView.setPadding(padding.left, padding.top, padding.right, padding.bottom + bottomOffset); } diff --git a/src/com/android/launcher3/allapps/WorkAdapterProvider.java b/src/com/android/launcher3/allapps/WorkAdapterProvider.java index 13444dd185..331320d6ed 100644 --- a/src/com/android/launcher3/allapps/WorkAdapterProvider.java +++ b/src/com/android/launcher3/allapps/WorkAdapterProvider.java @@ -15,12 +15,11 @@ */ package com.android.launcher3.allapps; +import android.content.SharedPreferences; import android.view.LayoutInflater; import android.view.ViewGroup; -import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.R; -import com.android.launcher3.Utilities; import java.util.ArrayList; @@ -33,13 +32,13 @@ public class WorkAdapterProvider extends BaseAdapterProvider { private static final int VIEW_TYPE_WORK_EDU_CARD = 1 << 20; private static final int VIEW_TYPE_WORK_DISABLED_CARD = 1 << 21; - private final Runnable mRefreshCB; - private final BaseDraggingActivity mLauncher; - private boolean mEnabled; - WorkAdapterProvider(BaseDraggingActivity launcher, Runnable refreshCallback) { - mLauncher = launcher; - mRefreshCB = refreshCallback; + @WorkProfileManager.WorkProfileState + private int mState; + private SharedPreferences mPreferences; + + WorkAdapterProvider(SharedPreferences prefs) { + mPreferences = prefs; } @Override @@ -61,19 +60,19 @@ public class WorkAdapterProvider extends BaseAdapterProvider { * returns whether or not work apps should be visible in work tab. */ public boolean shouldShowWorkApps() { - return mEnabled; + return mState != WorkProfileManager.STATE_DISABLED; } /** * Adds work profile specific adapter items to adapterItems and returns number of items added */ public int addWorkItems(ArrayList adapterItems) { - if (!mEnabled) { + if (mState == WorkProfileManager.STATE_DISABLED) { //add disabled card here. AllAppsGridAdapter.AdapterItem disabledCard = new AllAppsGridAdapter.AdapterItem(); disabledCard.viewType = VIEW_TYPE_WORK_DISABLED_CARD; adapterItems.add(disabledCard); - } else if (!isEduSeen()) { + } else if (mState == WorkProfileManager.STATE_ENABLED && !isEduSeen()) { AllAppsGridAdapter.AdapterItem eduCard = new AllAppsGridAdapter.AdapterItem(); eduCard.viewType = VIEW_TYPE_WORK_EDU_CARD; adapterItems.add(eduCard); @@ -85,9 +84,8 @@ public class WorkAdapterProvider extends BaseAdapterProvider { /** * Sets the current state of work profile */ - public void updateCurrentState(boolean isEnabled) { - mEnabled = isEnabled; - mRefreshCB.run(); + public void updateCurrentState(@WorkProfileManager.WorkProfileState int state) { + mState = state; } @Override @@ -101,6 +99,6 @@ public class WorkAdapterProvider extends BaseAdapterProvider { } private boolean isEduSeen() { - return Utilities.getPrefs(mLauncher).getInt(KEY_WORK_EDU_STEP, 0) != 0; + return mPreferences.getInt(KEY_WORK_EDU_STEP, 0) != 0; } } diff --git a/src/com/android/launcher3/allapps/WorkModeSwitch.java b/src/com/android/launcher3/allapps/WorkModeSwitch.java index 5d3af08b46..5d640412be 100644 --- a/src/com/android/launcher3/allapps/WorkModeSwitch.java +++ b/src/com/android/launcher3/allapps/WorkModeSwitch.java @@ -16,43 +16,41 @@ package com.android.launcher3.allapps; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TURN_OFF_WORK_APPS_TAP; -import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import android.content.Context; import android.graphics.Insets; import android.graphics.Rect; -import android.os.Build; -import android.os.Process; -import android.os.UserHandle; -import android.os.UserManager; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.view.WindowInsets; import android.widget.Button; -import androidx.annotation.Nullable; -import androidx.annotation.RequiresApi; - +import com.android.launcher3.BaseDraggingActivity; +import com.android.launcher3.DeviceProfile; import com.android.launcher3.Insettable; import com.android.launcher3.Launcher; import com.android.launcher3.Utilities; import com.android.launcher3.anim.KeyboardInsetAnimationCallback; -import com.android.launcher3.pm.UserCache; +import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip; /** * Work profile toggle switch shown at the bottom of AllApps work tab */ -public class WorkModeSwitch extends Button implements Insettable, View.OnClickListener { +public class WorkModeSwitch extends Button implements Insettable, View.OnClickListener, + KeyboardInsetAnimationCallback.KeyboardInsetListener, + PersonalWorkSlidingTabStrip.OnActivePageChangedListener { - private Rect mInsets = new Rect(); + private static final int FLAG_FADE_ONGOING = 1 << 1; + private static final int FLAG_TRANSLATION_ONGOING = 1 << 2; + private static final int FLAG_PROFILE_TOGGLE_ONGOING = 1 << 3; + + private final Rect mInsets = new Rect(); + private int mFlags; private boolean mWorkEnabled; + private boolean mOnWorkTab; - @Nullable - private KeyboardInsetAnimationCallback mKeyboardInsetAnimationCallback; - private boolean mWorkTabVisible; - public WorkModeSwitch(Context context) { this(context, null, 0); } @@ -71,9 +69,12 @@ public class WorkModeSwitch extends Button implements Insettable, View.OnClickLi setSelected(true); setOnClickListener(this); if (Utilities.ATLEAST_R) { - mKeyboardInsetAnimationCallback = new KeyboardInsetAnimationCallback(this); - setWindowInsetsAnimationCallback(mKeyboardInsetAnimationCallback); + KeyboardInsetAnimationCallback keyboardInsetAnimationCallback = + new KeyboardInsetAnimationCallback(this); + setWindowInsetsAnimationCallback(keyboardInsetAnimationCallback); } + DeviceProfile grid = BaseDraggingActivity.fromContext(getContext()).getDeviceProfile(); + setInsets(grid.getInsets()); } @Override @@ -87,57 +88,57 @@ public class WorkModeSwitch extends Button implements Insettable, View.OnClickLi } } - /** - * Animates in/out work profile toggle panel based on the tab user is on - */ - public void setWorkTabVisible(boolean workTabVisible) { - clearAnimation(); - mWorkTabVisible = workTabVisible; - if (workTabVisible && mWorkEnabled) { - setEnabled(true); - setVisibility(VISIBLE); - setAlpha(0); - animate().alpha(1).start(); - } else { - animate().alpha(0).withEndAction(() -> this.setVisibility(GONE)).start(); - } + + @Override + public void onActivePageChanged(int page) { + mOnWorkTab = page == AllAppsContainerView.AdapterHolder.WORK; + updateVisibility(); } @Override public void onClick(View view) { - if (Utilities.ATLEAST_P && mWorkTabVisible) { - setEnabled(false); - Launcher.fromContext(getContext()).getStatsLogManager().logger().log( - LAUNCHER_TURN_OFF_WORK_APPS_TAP); - UI_HELPER_EXECUTOR.post(() -> setWorkProfileEnabled(getContext(), false)); + if (Utilities.ATLEAST_P && isEnabled()) { + setFlag(FLAG_PROFILE_TOGGLE_ONGOING); + Launcher launcher = Launcher.getLauncher(getContext()); + launcher.getStatsLogManager().logger().log(LAUNCHER_TURN_OFF_WORK_APPS_TAP); + launcher.getAppsView().getWorkManager().setWorkProfileEnabled(false); } } + @Override + public boolean isEnabled() { + return super.isEnabled() && getVisibility() == VISIBLE && mFlags == 0; + } + /** * Sets the enabled or disabled state of the button */ public void updateCurrentState(boolean active) { + removeFlag(FLAG_PROFILE_TOGGLE_ONGOING); mWorkEnabled = active; - setEnabled(true); - setVisibility(active ? VISIBLE : GONE); + updateVisibility(); } - @RequiresApi(Build.VERSION_CODES.P) - public static Boolean setWorkProfileEnabled(Context context, boolean enabled) { - UserManager userManager = context.getSystemService(UserManager.class); - boolean showConfirm = false; - for (UserHandle userProfile : UserCache.INSTANCE.get(context).getUserProfiles()) { - if (Process.myUserHandle().equals(userProfile)) { - continue; - } - showConfirm |= !userManager.requestQuietModeEnabled(!enabled, userProfile); + + private void updateVisibility() { + clearAnimation(); + if (mWorkEnabled && mOnWorkTab) { + setFlag(FLAG_FADE_ONGOING); + setVisibility(VISIBLE); + setAlpha(0); + animate().alpha(1).withEndAction(() -> removeFlag(FLAG_FADE_ONGOING)).start(); + } else if (getVisibility() != GONE) { + setFlag(FLAG_FADE_ONGOING); + animate().alpha(0).withEndAction(() -> { + removeFlag(FLAG_FADE_ONGOING); + this.setVisibility(GONE); + }).start(); } - return showConfirm; } @Override public WindowInsets onApplyWindowInsets(WindowInsets insets) { - if (Utilities.ATLEAST_R && mWorkTabVisible) { + if (Utilities.ATLEAST_R && isEnabled()) { setTranslationY(0); if (insets.isVisible(WindowInsets.Type.ime())) { Insets keyboardInsets = insets.getInsets(WindowInsets.Type.ime()); @@ -146,4 +147,22 @@ public class WorkModeSwitch extends Button implements Insettable, View.OnClickLi } return insets; } + + @Override + public void onTranslationStart() { + setFlag(FLAG_TRANSLATION_ONGOING); + } + + @Override + public void onTranslationEnd() { + removeFlag(FLAG_TRANSLATION_ONGOING); + } + + private void setFlag(int flag) { + mFlags |= flag; + } + + private void removeFlag(int flag) { + mFlags &= ~flag; + } } diff --git a/src/com/android/launcher3/allapps/WorkPausedCard.java b/src/com/android/launcher3/allapps/WorkPausedCard.java index 7908b63ec2..7593ca7427 100644 --- a/src/com/android/launcher3/allapps/WorkPausedCard.java +++ b/src/com/android/launcher3/allapps/WorkPausedCard.java @@ -16,7 +16,6 @@ package com.android.launcher3.allapps; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TURN_ON_WORK_APPS_TAP; -import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import android.content.Context; import android.content.res.Configuration; @@ -62,8 +61,8 @@ public class WorkPausedCard extends LinearLayout implements View.OnClickListener public void onClick(View view) { if (Utilities.ATLEAST_P) { setEnabled(false); + mLauncher.getAppsView().getWorkManager().setWorkProfileEnabled(true); mLauncher.getStatsLogManager().logger().log(LAUNCHER_TURN_ON_WORK_APPS_TAP); - UI_HELPER_EXECUTOR.post(() -> WorkModeSwitch.setWorkProfileEnabled(getContext(), true)); } } diff --git a/src/com/android/launcher3/allapps/WorkProfileManager.java b/src/com/android/launcher3/allapps/WorkProfileManager.java new file mode 100644 index 0000000000..c53360a204 --- /dev/null +++ b/src/com/android/launcher3/allapps/WorkProfileManager.java @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2021 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.allapps; + +import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_HAS_SHORTCUT_PERMISSION; +import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_CHANGE_PERMISSION; +import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_ENABLED; +import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; + +import android.content.SharedPreferences; +import android.os.Build; +import android.os.Process; +import android.os.UserHandle; +import android.os.UserManager; +import android.util.Log; + +import androidx.annotation.IntDef; +import androidx.annotation.RequiresApi; + +import com.android.launcher3.R; +import com.android.launcher3.util.ItemInfoMatcher; +import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Companion class for {@link AllAppsContainerView} to manage work tab and personal tab related + * logic based on {@link WorkProfileState}? + */ +public class WorkProfileManager implements PersonalWorkSlidingTabStrip.OnActivePageChangedListener { + private static final String TAG = "WorkProfileManager"; + + + public static final int STATE_ENABLED = 1; + public static final int STATE_DISABLED = 2; + public static final int STATE_TRANSITION = 3; + + + private final UserManager mUserManager; + + /** + * Work profile manager states + */ + @IntDef(value = { + STATE_ENABLED, + STATE_DISABLED, + STATE_TRANSITION + }) + @Retention(RetentionPolicy.SOURCE) + public @interface WorkProfileState { + } + + private final AllAppsContainerView mAllApps; + private final WorkAdapterProvider mAdapterProvider; + private final ItemInfoMatcher mMatcher; + + private WorkModeSwitch mWorkModeSwitch; + + @WorkProfileState + private int mCurrentState; + + + public WorkProfileManager(UserManager userManager, AllAppsContainerView allApps, + SharedPreferences preferences) { + mUserManager = userManager; + mAllApps = allApps; + mAdapterProvider = new WorkAdapterProvider(preferences); + mMatcher = mAllApps.mPersonalMatcher.negate(); + } + + /** + * Posts quite mode enable/disable call for work profile user + */ + @RequiresApi(Build.VERSION_CODES.P) + public void setWorkProfileEnabled(boolean enabled) { + updateCurrentState(STATE_TRANSITION); + UI_HELPER_EXECUTOR.post(() -> { + for (UserHandle userProfile : mUserManager.getUserProfiles()) { + if (Process.myUserHandle().equals(userProfile)) { + continue; + } + mUserManager.requestQuietModeEnabled(!enabled, userProfile); + } + }); + } + + @Override + public void onActivePageChanged(int page) { + if (mWorkModeSwitch != null) { + mWorkModeSwitch.onActivePageChanged(page); + } + } + + /** + * Requests work profile state from {@link AllAppsStore} and updates work profile related views + */ + public void reset() { + boolean isEnabled = !mAllApps.getAppsStore().hasModelFlag(FLAG_QUIET_MODE_ENABLED); + updateCurrentState(isEnabled ? STATE_ENABLED : STATE_DISABLED); + } + + private void updateCurrentState(@WorkProfileState int currentState) { + mCurrentState = currentState; + mAdapterProvider.updateCurrentState(currentState); + if (getAH() != null) { + getAH().appsList.updateAdapterItems(); + } + if (mWorkModeSwitch != null) { + mWorkModeSwitch.updateCurrentState(currentState == STATE_ENABLED); + } + } + + /** + * Creates and attaches for profile toggle button to {@link AllAppsContainerView} + */ + public void attachWorkModeSwitch() { + if (!mAllApps.getAppsStore().hasModelFlag( + FLAG_HAS_SHORTCUT_PERMISSION | FLAG_QUIET_MODE_CHANGE_PERMISSION)) { + Log.e(TAG, "Unable to attach widget; Missing required permissions"); + return; + } + if (mWorkModeSwitch == null) { + mWorkModeSwitch = (WorkModeSwitch) mAllApps.getLayoutInflater().inflate( + R.layout.work_mode_fab, mAllApps, false); + } + if (mWorkModeSwitch.getParent() != mAllApps) { + mAllApps.addView(mWorkModeSwitch); + } + if (getAH() != null) { + getAH().applyPadding(); + } + mWorkModeSwitch.updateCurrentState(mCurrentState == STATE_ENABLED); + } + + /** + * Removes work profile toggle button from {@link AllAppsContainerView} + */ + public void detachWorkModeSwitch() { + if (mWorkModeSwitch != null && mWorkModeSwitch.getParent() == mAllApps) { + mAllApps.removeView(mWorkModeSwitch); + } + mWorkModeSwitch = null; + } + + + public WorkAdapterProvider getAdapterProvider() { + return mAdapterProvider; + } + + public ItemInfoMatcher getMatcher() { + return mMatcher; + } + + public WorkModeSwitch getWorkModeSwitch() { + return mWorkModeSwitch; + } + + private AllAppsContainerView.AdapterHolder getAH() { + return mAllApps.mAH[AllAppsContainerView.AdapterHolder.WORK]; + } +} diff --git a/src/com/android/launcher3/anim/KeyboardInsetAnimationCallback.java b/src/com/android/launcher3/anim/KeyboardInsetAnimationCallback.java index ef4ada3cd9..9d96365acc 100644 --- a/src/com/android/launcher3/anim/KeyboardInsetAnimationCallback.java +++ b/src/com/android/launcher3/anim/KeyboardInsetAnimationCallback.java @@ -65,7 +65,32 @@ public class KeyboardInsetAnimationCallback extends WindowInsetsAnimation.Callba public WindowInsetsAnimation.Bounds onStart(WindowInsetsAnimation animation, WindowInsetsAnimation.Bounds bounds) { mTerminalTranslation = mView.getTranslationY(); - mView.setTranslationY(mInitialTranslation); + if (mView instanceof KeyboardInsetListener) { + ((KeyboardInsetListener) mView).onTranslationStart(); + } return super.onStart(animation, bounds); } + + @Override + public void onEnd(WindowInsetsAnimation animation) { + if (mView instanceof KeyboardInsetListener) { + ((KeyboardInsetListener) mView).onTranslationEnd(); + } + super.onEnd(animation); + } + + /** + * Interface Allowing views to listen for keyboard translation events + */ + public interface KeyboardInsetListener { + /** + * Called from {@link KeyboardInsetAnimationCallback#onStart} + */ + void onTranslationStart(); + + /** + * Called from {@link KeyboardInsetAnimationCallback#onEnd} + */ + void onTranslationEnd(); + } }