From 4eb3b97ceb287f98fdf068ef6c433fe1bd42e876 Mon Sep 17 00:00:00 2001 From: Antonio Kantek Date: Thu, 14 Mar 2024 00:11:53 +0000 Subject: Add UserData to store user related information This is a preparation CL for changing IMMS to store InputBindingController per user. This is a refactoring CL, no regression is expected. Bug: 325515685 Test: atest CtsInputMethodTestCases FrameworksServicesTests Change-Id: I20ba680a8755df794e477502f85ee0d970b709fb --- .../inputmethod/InputMethodBindingController.java | 26 +------ .../inputmethod/InputMethodManagerService.java | 7 +- .../com/android/server/inputmethod/Sequence.java | 45 +++++++++++ .../com/android/server/inputmethod/UserData.java | 88 ++++++++++++++++++++++ 4 files changed, 141 insertions(+), 25 deletions(-) create mode 100644 services/core/java/com/android/server/inputmethod/Sequence.java create mode 100644 services/core/java/com/android/server/inputmethod/UserData.java diff --git a/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java index a100fe06c407..29cccdf9e2c6 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java @@ -74,7 +74,6 @@ final class InputMethodBindingController { @GuardedBy("ImfLock.class") @Nullable private IInputMethodInvoker mCurMethod; @GuardedBy("ImfLock.class") private int mCurMethodUid = Process.INVALID_UID; @GuardedBy("ImfLock.class") @Nullable private IBinder mCurToken; - @GuardedBy("ImfLock.class") private int mCurSeq; @GuardedBy("ImfLock.class") private boolean mVisibleBound; @GuardedBy("ImfLock.class") private boolean mSupportsStylusHw; @GuardedBy("ImfLock.class") private boolean mSupportsConnectionlessStylusHw; @@ -194,27 +193,6 @@ final class InputMethodBindingController { return mCurIntent; } - /** - * The current binding sequence number, incremented every time there is - * a new bind performed. - */ - @GuardedBy("ImfLock.class") - int getSequenceNumber() { - return mCurSeq; - } - - /** - * Increase the current binding sequence number by one. - * Reset to 1 on overflow. - */ - @GuardedBy("ImfLock.class") - void advanceSequenceNumber() { - mCurSeq += 1; - if (mCurSeq <= 0) { - mCurSeq = 1; - } - } - /** * If non-null, this is the input method service we are currently connected * to. @@ -435,9 +413,11 @@ final class InputMethodBindingController { mLastBindTime = SystemClock.uptimeMillis(); addFreshWindowToken(); + final UserData monitor = UserData.getOrCreate( + mService.getCurrentImeUserIdLocked()); return new InputBindResult( InputBindResult.ResultCode.SUCCESS_WAITING_IME_BINDING, - null, null, null, mCurId, mCurSeq, false); + null, null, null, mCurId, monitor.mSequence.getSequenceNumber(), false); } Slog.w(InputMethodManagerService.TAG, diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 50d2c63a8378..ca80e203d5a1 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -479,7 +479,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub */ @GuardedBy("ImfLock.class") private int getSequenceNumberLocked() { - return mBindingController.getSequenceNumber(); + final UserData monitor = UserData.getOrCreate(mCurrentUserId); + return monitor.mSequence.getSequenceNumber(); } /** @@ -488,7 +489,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub */ @GuardedBy("ImfLock.class") private void advanceSequenceNumberLocked() { - mBindingController.advanceSequenceNumber(); + final UserData monitor = UserData.getOrCreate(mCurrentUserId); + monitor.mSequence.advanceSequenceNumber(); } @GuardedBy("ImfLock.class") @@ -1366,6 +1368,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub // InputMethodSettingsRepository should be initialized before buildInputMethodListLocked InputMethodSettingsRepository.initialize(mHandler, mContext); AdditionalSubtypeMapRepository.initialize(mHandler, mContext); + UserData.initialize(mHandler); mCurrentUserId = mActivityManagerInternal.getCurrentUserId(); diff --git a/services/core/java/com/android/server/inputmethod/Sequence.java b/services/core/java/com/android/server/inputmethod/Sequence.java new file mode 100644 index 000000000000..05e31ce1c682 --- /dev/null +++ b/services/core/java/com/android/server/inputmethod/Sequence.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.inputmethod; + +import com.android.internal.annotations.GuardedBy; + +/** + * A sequence number utility class that only generate positive numbers. + */ +final class Sequence { + + private final Object mLock = new Object(); + + private int mSequence; + + int getSequenceNumber() { + synchronized (mLock) { + return mSequence; + } + } + + @GuardedBy("ImfLock.class") + void advanceSequenceNumber() { + synchronized (mLock) { + mSequence++; + if (mSequence <= 0) { + mSequence = 1; + } + } + } +} diff --git a/services/core/java/com/android/server/inputmethod/UserData.java b/services/core/java/com/android/server/inputmethod/UserData.java new file mode 100644 index 000000000000..fc2a422e136f --- /dev/null +++ b/services/core/java/com/android/server/inputmethod/UserData.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.inputmethod; + +import android.annotation.NonNull; +import android.annotation.UserIdInt; +import android.content.pm.UserInfo; +import android.os.Handler; +import android.util.SparseArray; + +import com.android.internal.annotations.GuardedBy; +import com.android.server.LocalServices; +import com.android.server.pm.UserManagerInternal; + +final class UserData { + + @NonNull + private static final SparseArray sPerUserMonitor = new SparseArray<>(); + + @UserIdInt + final int mUserId; + + @GuardedBy("ImfLock.class") + final Sequence mSequence = new Sequence(); + + /** + * Not intended to be instantiated. + */ + private UserData(int userId) { + mUserId = userId; + } + + @GuardedBy("ImfLock.class") + static UserData getOrCreate(@UserIdInt int userId) { + UserData monitor = sPerUserMonitor.get(userId); + if (monitor == null) { + monitor = new UserData(userId); + sPerUserMonitor.put(userId, monitor); + } + return monitor; + } + + static void initialize(Handler handler) { + final UserManagerInternal userManagerInternal = + LocalServices.getService(UserManagerInternal.class); + userManagerInternal.addUserLifecycleListener( + new UserManagerInternal.UserLifecycleListener() { + @Override + public void onUserRemoved(UserInfo user) { + final int userId = user.id; + handler.post(() -> { + synchronized (ImfLock.class) { + sPerUserMonitor.remove(userId); + } + }); + } + + @Override + public void onUserCreated(UserInfo user, Object unusedToken) { + final int userId = user.id; + handler.post(() -> { + synchronized (ImfLock.class) { + getOrCreate(userId); + } + }); + } + }); + synchronized (ImfLock.class) { + for (int userId : userManagerInternal.getUserIds()) { + getOrCreate(userId); + } + } + } +} -- cgit v1.2.3-59-g8ed1b