• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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.inputmethod;
18 
19 import android.annotation.AnyThread;
20 import android.annotation.NonNull;
21 import android.annotation.UserIdInt;
22 
23 import java.util.function.Consumer;
24 import java.util.function.IntFunction;
25 
26 final class UserDataRepository {
27 
28     private final Object mMutationLock = new Object();
29 
30     @NonNull
31     private volatile ImmutableSparseArray<UserData> mUserData = ImmutableSparseArray.empty();
32 
33     @NonNull
34     private final IntFunction<InputMethodBindingController> mBindingControllerFactory;
35     @NonNull
36     private final IntFunction<ImeVisibilityStateComputer> mVisibilityStateComputerFactory;
37 
38     @AnyThread
39     @NonNull
getOrCreate(@serIdInt int userId)40     UserData getOrCreate(@UserIdInt int userId) {
41         // Do optimistic read first for optimization.
42         final var userData = mUserData.get(userId);
43         if (userData != null) {
44             return userData;
45         }
46         // Note that the below line can be called concurrently. Here we assume that
47         // instantiating UserData for the same user multiple times would have no side effect.
48         final var newUserData = new UserData(userId, mBindingControllerFactory.apply(userId),
49                 mVisibilityStateComputerFactory.apply(userId));
50         synchronized (mMutationLock) {
51             mUserData = mUserData.cloneWithPutOrSelf(userId, newUserData);
52             return newUserData;
53         }
54     }
55 
56     @AnyThread
forAllUserData(Consumer<UserData> consumer)57     void forAllUserData(Consumer<UserData> consumer) {
58         mUserData.forEach(consumer);
59     }
60 
UserDataRepository(@onNull IntFunction<InputMethodBindingController> bindingControllerFactory, @NonNull IntFunction<ImeVisibilityStateComputer> visibilityStateComputerFactory)61     UserDataRepository(@NonNull IntFunction<InputMethodBindingController> bindingControllerFactory,
62             @NonNull IntFunction<ImeVisibilityStateComputer> visibilityStateComputerFactory) {
63         mBindingControllerFactory = bindingControllerFactory;
64         mVisibilityStateComputerFactory = visibilityStateComputerFactory;
65     }
66 
67     @AnyThread
remove(@serIdInt int userId)68     void remove(@UserIdInt int userId) {
69         synchronized (mMutationLock) {
70             mUserData = mUserData.cloneWithRemoveOrSelf(userId);
71         }
72     }
73 }
74