• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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.server.location.injector;
18 
19 import static com.android.server.location.LocationManagerService.D;
20 import static com.android.server.location.LocationManagerService.TAG;
21 import static com.android.server.location.eventlog.LocationEventLog.EVENT_LOG;
22 import static com.android.server.location.injector.UserInfoHelper.UserListener.CURRENT_USER_CHANGED;
23 import static com.android.server.location.injector.UserInfoHelper.UserListener.USER_STARTED;
24 import static com.android.server.location.injector.UserInfoHelper.UserListener.USER_STOPPED;
25 
26 import android.annotation.IntDef;
27 import android.annotation.UserIdInt;
28 import android.util.IndentingPrintWriter;
29 import android.util.Log;
30 
31 import java.io.FileDescriptor;
32 import java.lang.annotation.Retention;
33 import java.lang.annotation.RetentionPolicy;
34 import java.util.Arrays;
35 import java.util.concurrent.CopyOnWriteArrayList;
36 
37 /**
38  * Provides accessors and listeners for all user info.
39  */
40 public abstract class UserInfoHelper {
41 
42     /**
43      * Listener for current user changes.
44      */
45     public interface UserListener {
46 
47         int CURRENT_USER_CHANGED = 1;
48         int USER_STARTED = 2;
49         int USER_STOPPED = 3;
50 
51         @IntDef({CURRENT_USER_CHANGED, USER_STARTED, USER_STOPPED})
52         @Retention(RetentionPolicy.SOURCE)
53         @interface UserChange {}
54 
55         /**
56          * Called when something has changed about the given user.
57          */
onUserChanged(@serIdInt int userId, @UserChange int change)58         void onUserChanged(@UserIdInt int userId, @UserChange int change);
59     }
60 
61     private final CopyOnWriteArrayList<UserListener> mListeners;
62 
UserInfoHelper()63     public UserInfoHelper() {
64         mListeners = new CopyOnWriteArrayList<>();
65     }
66 
67     /**
68      * Adds a listener for user changed events. Callbacks occur on an unspecified thread.
69      */
addListener(UserListener listener)70     public final void addListener(UserListener listener) {
71         mListeners.add(listener);
72     }
73 
74     /**
75      * Removes a listener for user changed events.
76      */
removeListener(UserListener listener)77     public final void removeListener(UserListener listener) {
78         mListeners.remove(listener);
79     }
80 
dispatchOnUserStarted(@serIdInt int userId)81     protected final void dispatchOnUserStarted(@UserIdInt int userId) {
82         if (D) {
83             Log.d(TAG, "u" + userId + " started");
84         }
85 
86         for (UserListener listener : mListeners) {
87             listener.onUserChanged(userId, USER_STARTED);
88         }
89     }
90 
dispatchOnUserStopped(@serIdInt int userId)91     protected final void dispatchOnUserStopped(@UserIdInt int userId) {
92         if (D) {
93             Log.d(TAG, "u" + userId + " stopped");
94         }
95 
96         for (UserListener listener : mListeners) {
97             listener.onUserChanged(userId, USER_STOPPED);
98         }
99     }
100 
dispatchOnCurrentUserChanged(@serIdInt int fromUserId, @UserIdInt int toUserId)101     protected final void dispatchOnCurrentUserChanged(@UserIdInt int fromUserId,
102             @UserIdInt int toUserId) {
103         int[] fromUserIds = getProfileIds(fromUserId);
104         int[] toUserIds = getProfileIds(toUserId);
105         if (D) {
106             Log.d(TAG, "current user changed from u" + Arrays.toString(fromUserIds) + " to u"
107                     + Arrays.toString(toUserIds));
108         }
109         EVENT_LOG.logUserSwitched(fromUserId, toUserId);
110 
111         for (UserListener listener : mListeners) {
112             for (int userId : fromUserIds) {
113                 listener.onUserChanged(userId, CURRENT_USER_CHANGED);
114             }
115         }
116 
117         for (UserListener listener : mListeners) {
118             for (int userId : toUserIds) {
119                 listener.onUserChanged(userId, CURRENT_USER_CHANGED);
120             }
121         }
122     }
123 
124     /**
125      * Returns an array of running user ids. This will include all running users, and will also
126      * include any profiles of the running users. The caller must never mutate the returned
127      * array.
128      */
getRunningUserIds()129     public abstract int[] getRunningUserIds();
130 
131     /**
132      * Returns true if the given user id is either the current user or a profile of the current
133      * user.
134      */
isCurrentUserId(@serIdInt int userId)135     public abstract boolean isCurrentUserId(@UserIdInt int userId);
136 
137     /**
138      * Returns the current user id. Where possible, prefer to use {@link #isCurrentUserId(int)}
139      * instead, as that method has more flexibility.
140      */
getCurrentUserId()141     public abstract @UserIdInt int getCurrentUserId();
142 
getProfileIds(@serIdInt int userId)143     protected abstract int[] getProfileIds(@UserIdInt int userId);
144 
145     /**
146      * Dump info for debugging.
147      */
dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args)148     public abstract void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args);
149 }
150