1 /* 2 * Copyright (C) 2021 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 package com.android.launcher3.allapps; 17 18 import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_HAS_SHORTCUT_PERMISSION; 19 import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_CHANGE_PERMISSION; 20 import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_ENABLED; 21 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; 22 23 import android.content.SharedPreferences; 24 import android.os.Build; 25 import android.os.Process; 26 import android.os.UserHandle; 27 import android.os.UserManager; 28 import android.util.Log; 29 30 import androidx.annotation.IntDef; 31 import androidx.annotation.Nullable; 32 import androidx.annotation.RequiresApi; 33 34 import com.android.launcher3.R; 35 import com.android.launcher3.util.ItemInfoMatcher; 36 import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip; 37 38 import java.lang.annotation.Retention; 39 import java.lang.annotation.RetentionPolicy; 40 41 /** 42 * Companion class for {@link AllAppsContainerView} to manage work tab and personal tab related 43 * logic based on {@link WorkProfileState}? 44 */ 45 public class WorkProfileManager implements PersonalWorkSlidingTabStrip.OnActivePageChangedListener { 46 private static final String TAG = "WorkProfileManager"; 47 48 49 public static final int STATE_ENABLED = 1; 50 public static final int STATE_DISABLED = 2; 51 public static final int STATE_TRANSITION = 3; 52 53 54 private final UserManager mUserManager; 55 56 /** 57 * Work profile manager states 58 */ 59 @IntDef(value = { 60 STATE_ENABLED, 61 STATE_DISABLED, 62 STATE_TRANSITION 63 }) 64 @Retention(RetentionPolicy.SOURCE) 65 public @interface WorkProfileState { 66 } 67 68 private final AllAppsContainerView mAllApps; 69 private final WorkAdapterProvider mAdapterProvider; 70 private final ItemInfoMatcher mMatcher; 71 72 private WorkModeSwitch mWorkModeSwitch; 73 74 @WorkProfileState 75 private int mCurrentState; 76 77 WorkProfileManager(UserManager userManager, AllAppsContainerView allApps, SharedPreferences preferences)78 public WorkProfileManager(UserManager userManager, AllAppsContainerView allApps, 79 SharedPreferences preferences) { 80 mUserManager = userManager; 81 mAllApps = allApps; 82 mAdapterProvider = new WorkAdapterProvider(preferences); 83 mMatcher = mAllApps.mPersonalMatcher.negate(); 84 } 85 86 /** 87 * Posts quite mode enable/disable call for work profile user 88 */ 89 @RequiresApi(Build.VERSION_CODES.P) setWorkProfileEnabled(boolean enabled)90 public void setWorkProfileEnabled(boolean enabled) { 91 updateCurrentState(STATE_TRANSITION); 92 UI_HELPER_EXECUTOR.post(() -> { 93 for (UserHandle userProfile : mUserManager.getUserProfiles()) { 94 if (Process.myUserHandle().equals(userProfile)) { 95 continue; 96 } 97 mUserManager.requestQuietModeEnabled(!enabled, userProfile); 98 } 99 }); 100 } 101 102 @Override onActivePageChanged(int page)103 public void onActivePageChanged(int page) { 104 if (mWorkModeSwitch != null) { 105 mWorkModeSwitch.onActivePageChanged(page); 106 } 107 } 108 109 /** 110 * Requests work profile state from {@link AllAppsStore} and updates work profile related views 111 */ reset()112 public void reset() { 113 boolean isEnabled = !mAllApps.getAppsStore().hasModelFlag(FLAG_QUIET_MODE_ENABLED); 114 updateCurrentState(isEnabled ? STATE_ENABLED : STATE_DISABLED); 115 } 116 updateCurrentState(@orkProfileState int currentState)117 private void updateCurrentState(@WorkProfileState int currentState) { 118 mCurrentState = currentState; 119 mAdapterProvider.updateCurrentState(currentState); 120 if (getAH() != null) { 121 getAH().appsList.updateAdapterItems(); 122 } 123 if (mWorkModeSwitch != null) { 124 mWorkModeSwitch.updateCurrentState(currentState == STATE_ENABLED); 125 } 126 } 127 128 /** 129 * Creates and attaches for profile toggle button to {@link AllAppsContainerView} 130 */ attachWorkModeSwitch()131 public boolean attachWorkModeSwitch() { 132 if (!mAllApps.getAppsStore().hasModelFlag( 133 FLAG_HAS_SHORTCUT_PERMISSION | FLAG_QUIET_MODE_CHANGE_PERMISSION)) { 134 Log.e(TAG, "unable to attach work mode switch; Missing required permissions"); 135 return false; 136 } 137 if (mWorkModeSwitch == null) { 138 mWorkModeSwitch = (WorkModeSwitch) mAllApps.getLayoutInflater().inflate( 139 R.layout.work_mode_fab, mAllApps, false); 140 } 141 if (mWorkModeSwitch.getParent() != mAllApps) { 142 mAllApps.addView(mWorkModeSwitch); 143 } 144 if (getAH() != null) { 145 getAH().applyPadding(); 146 } 147 mWorkModeSwitch.updateCurrentState(mCurrentState == STATE_ENABLED); 148 return true; 149 } 150 151 /** 152 * Removes work profile toggle button from {@link AllAppsContainerView} 153 */ detachWorkModeSwitch()154 public void detachWorkModeSwitch() { 155 if (mWorkModeSwitch != null && mWorkModeSwitch.getParent() == mAllApps) { 156 mAllApps.removeView(mWorkModeSwitch); 157 } 158 mWorkModeSwitch = null; 159 } 160 161 getAdapterProvider()162 public WorkAdapterProvider getAdapterProvider() { 163 return mAdapterProvider; 164 } 165 getMatcher()166 public ItemInfoMatcher getMatcher() { 167 return mMatcher; 168 } 169 170 @Nullable getWorkModeSwitch()171 public WorkModeSwitch getWorkModeSwitch() { 172 return mWorkModeSwitch; 173 } 174 getAH()175 private AllAppsContainerView.AdapterHolder getAH() { 176 return mAllApps.mAH[AllAppsContainerView.AdapterHolder.WORK]; 177 } 178 getCurrentState()179 public int getCurrentState() { 180 return mCurrentState; 181 } 182 } 183