1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5  * except in compliance with the License. You may obtain a copy of the License at
6  *
7  *      http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the
10  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11  * KIND, either express or implied. See the License for the specific language governing
12  * permissions and limitations under the License.
13  */
14 
15 package com.android.systemui.statusbar.phone;
16 
17 import android.app.StatusBarManager;
18 import android.content.Context;
19 import android.content.pm.UserInfo;
20 import android.os.UserHandle;
21 import android.os.UserManager;
22 
23 import androidx.annotation.NonNull;
24 
25 import com.android.systemui.dagger.SysUISingleton;
26 import com.android.systemui.dagger.qualifiers.Main;
27 import com.android.systemui.settings.UserTracker;
28 
29 import java.util.ArrayList;
30 import java.util.LinkedList;
31 import java.util.List;
32 import java.util.concurrent.Executor;
33 
34 import javax.inject.Inject;
35 
36 @SysUISingleton
37 public class ManagedProfileControllerImpl implements ManagedProfileController {
38 
39     private final List<Callback> mCallbacks = new ArrayList<>();
40     private final UserTrackerCallback mUserTrackerCallback = new UserTrackerCallback();
41     private final Context mContext;
42     private final Executor mMainExecutor;
43     private final UserManager mUserManager;
44     private final UserTracker mUserTracker;
45     private final LinkedList<UserInfo> mProfiles;
46 
47     private boolean mListening;
48     private int mCurrentUser;
49 
50     @Inject
ManagedProfileControllerImpl(Context context, @Main Executor mainExecutor, UserTracker userTracker, UserManager userManager)51     public ManagedProfileControllerImpl(Context context, @Main Executor mainExecutor,
52             UserTracker userTracker, UserManager userManager) {
53         mContext = context;
54         mMainExecutor = mainExecutor;
55         mUserManager = userManager;
56         mUserTracker = userTracker;
57         mProfiles = new LinkedList<>();
58     }
59 
60     @Override
addCallback(@onNull Callback callback)61     public void addCallback(@NonNull Callback callback) {
62         mCallbacks.add(callback);
63         if (mCallbacks.size() == 1) {
64             setListening(true);
65         }
66         callback.onManagedProfileChanged();
67     }
68 
69     @Override
removeCallback(@onNull Callback callback)70     public void removeCallback(@NonNull Callback callback) {
71         if (mCallbacks.remove(callback) && mCallbacks.size() == 0) {
72             setListening(false);
73         }
74     }
75 
setWorkModeEnabled(boolean enableWorkMode)76     public void setWorkModeEnabled(boolean enableWorkMode) {
77         synchronized (mProfiles) {
78             for (UserInfo ui : mProfiles) {
79                 if (!mUserManager.requestQuietModeEnabled(!enableWorkMode, UserHandle.of(ui.id))) {
80                     StatusBarManager statusBarManager = (StatusBarManager) mContext
81                             .getSystemService(android.app.Service.STATUS_BAR_SERVICE);
82                     statusBarManager.collapsePanels();
83                 }
84             }
85         }
86     }
87 
reloadManagedProfiles()88     private void reloadManagedProfiles() {
89         synchronized (mProfiles) {
90             boolean hadProfile = mProfiles.size() > 0;
91             int user = mUserTracker.getUserId();
92             mProfiles.clear();
93 
94             for (UserInfo ui : mUserManager.getEnabledProfiles(user)) {
95                 if (ui.isManagedProfile()) {
96                     mProfiles.add(ui);
97                 }
98             }
99             if (mProfiles.size() == 0 && hadProfile && (user == mCurrentUser)) {
100                 mMainExecutor.execute(this::notifyManagedProfileRemoved);
101             }
102             mCurrentUser = user;
103         }
104     }
105 
notifyManagedProfileRemoved()106     private void notifyManagedProfileRemoved() {
107         for (Callback callback : mCallbacks) {
108             callback.onManagedProfileRemoved();
109         }
110     }
111 
hasActiveProfile()112     public boolean hasActiveProfile() {
113         if (!mListening || mUserTracker.getUserId() != mCurrentUser) {
114             reloadManagedProfiles();
115         }
116         synchronized (mProfiles) {
117             return mProfiles.size() > 0;
118         }
119     }
120 
isWorkModeEnabled()121     public boolean isWorkModeEnabled() {
122         if (!mListening) reloadManagedProfiles();
123         synchronized (mProfiles) {
124             for (UserInfo ui : mProfiles) {
125                 if (ui.isQuietModeEnabled()) {
126                     return false;
127                 }
128             }
129             return true;
130         }
131     }
132 
setListening(boolean listening)133     private void setListening(boolean listening) {
134         if (mListening == listening) {
135             return;
136         }
137         mListening = listening;
138         if (listening) {
139             reloadManagedProfiles();
140             mUserTracker.addCallback(mUserTrackerCallback, mMainExecutor);
141         } else {
142             mUserTracker.removeCallback(mUserTrackerCallback);
143         }
144     }
145 
146     private final class UserTrackerCallback implements UserTracker.Callback {
147 
148         @Override
onUserChanged(int newUser, @NonNull Context userContext)149         public void onUserChanged(int newUser, @NonNull Context userContext) {
150             reloadManagedProfiles();
151             for (Callback callback : mCallbacks) {
152                 callback.onManagedProfileChanged();
153             }
154         }
155 
156         @Override
onProfilesChanged(@onNull List<UserInfo> profiles)157         public void onProfilesChanged(@NonNull List<UserInfo> profiles) {
158             reloadManagedProfiles();
159             for (Callback callback : mCallbacks) {
160                 callback.onManagedProfileChanged();
161             }
162         }
163     }
164 }
165