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.car.settings.users;
18 
19 import android.car.drivingstate.CarUxRestrictions;
20 import android.car.userlib.CarUserManagerHelper;
21 import android.content.BroadcastReceiver;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.content.IntentFilter;
25 import android.content.pm.UserInfo;
26 
27 import androidx.annotation.CallSuper;
28 import androidx.preference.Preference;
29 import androidx.preference.PreferenceGroup;
30 
31 import com.android.car.settings.common.FragmentController;
32 import com.android.car.settings.common.PreferenceController;
33 
34 import java.util.ArrayList;
35 import java.util.List;
36 import java.util.Objects;
37 
38 /** Shared business logic between {@link UsersListFragment} and {@link ChooseNewAdminFragment}. */
39 public abstract class UsersBasePreferenceController extends PreferenceController<PreferenceGroup> {
40 
41     private UsersPreferenceProvider mPreferenceProvider;
42     private CarUserManagerHelper mCarUserManagerHelper;
43     private List<Preference> mUsersToDisplay = new ArrayList<>();
44 
45     private final BroadcastReceiver mUserUpdateReceiver = new BroadcastReceiver() {
46         @Override
47         public void onReceive(Context context, Intent intent) {
48             /** Update screen when users list is updated. */
49             refreshUi();
50         }
51     };
52 
UsersBasePreferenceController(Context context, String preferenceKey, FragmentController fragmentController, CarUxRestrictions uxRestrictions)53     public UsersBasePreferenceController(Context context, String preferenceKey,
54             FragmentController fragmentController, CarUxRestrictions uxRestrictions) {
55         super(context, preferenceKey, fragmentController, uxRestrictions);
56         mCarUserManagerHelper = new CarUserManagerHelper(context);
57         UsersPreferenceProvider.UserClickListener userClickListener = this::userClicked;
58         mPreferenceProvider = new UsersPreferenceProvider(context, userClickListener);
59     }
60 
61     @Override
getPreferenceType()62     protected Class<PreferenceGroup> getPreferenceType() {
63         return PreferenceGroup.class;
64     }
65 
66     /**
67      * Ensure that helper is set by the time onCreate is called. Register a listener to refresh
68      * screen on updates.
69      */
70     @Override
71     @CallSuper
onCreateInternal()72     protected void onCreateInternal() {
73         registerForUserEvents();
74     }
75 
76     /** Unregister listener to refresh screen on updates. */
77     @Override
78     @CallSuper
onDestroyInternal()79     protected void onDestroyInternal() {
80         unregisterForUserEvents();
81     }
82 
83     @Override
updateState(PreferenceGroup preferenceGroup)84     protected void updateState(PreferenceGroup preferenceGroup) {
85         List<Preference> newUsers = mPreferenceProvider.createUserList();
86         if (userListsAreDifferent(mUsersToDisplay, newUsers)) {
87             mUsersToDisplay = newUsers;
88             preferenceGroup.removeAll();
89 
90             for (Preference preference : mUsersToDisplay) {
91                 preferenceGroup.addPreference(preference);
92             }
93         }
94     }
95 
96     /** Gets the car user manager helper. */
getCarUserManagerHelper()97     protected CarUserManagerHelper getCarUserManagerHelper() {
98         return mCarUserManagerHelper;
99     }
100 
101     /** Handles the user click on a preference for a certain user. */
userClicked(UserInfo userInfo)102     protected abstract void userClicked(UserInfo userInfo);
103 
104 
105     /** Gets the preference provider to set additional arguments if necessary. */
getPreferenceProvider()106     protected UsersPreferenceProvider getPreferenceProvider() {
107         return mPreferenceProvider;
108     }
109 
userListsAreDifferent(List<Preference> currentList, List<Preference> newList)110     private boolean userListsAreDifferent(List<Preference> currentList,
111             List<Preference> newList) {
112         if (currentList.size() != newList.size()) {
113             return true;
114         }
115 
116         for (int i = 0; i < currentList.size(); i++) {
117             // Cannot use "compareTo" on preference, since it uses the order attribute to compare.
118             if (preferencesAreDifferent(currentList.get(i), newList.get(i))) {
119                 return true;
120             }
121         }
122 
123         return false;
124     }
125 
preferencesAreDifferent(Preference lhs, Preference rhs)126     private boolean preferencesAreDifferent(Preference lhs, Preference rhs) {
127         return !Objects.equals(lhs.getTitle(), rhs.getTitle())
128                 || !Objects.equals(lhs.getSummary(), rhs.getSummary());
129     }
130 
registerForUserEvents()131     private void registerForUserEvents() {
132         IntentFilter filter = new IntentFilter(Intent.ACTION_USER_INFO_CHANGED);
133         getContext().registerReceiver(mUserUpdateReceiver, filter);
134     }
135 
unregisterForUserEvents()136     private void unregisterForUserEvents() {
137         getContext().unregisterReceiver(mUserUpdateReceiver);
138     }
139 }
140