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