InputMethodManager has been a per-process singleton object. In order
to support behavior changes for multi-display support in Android Q,
however, InputMethodManager now needs to be per-display objects.
With this CL, context.getSystemService(InputMethodManager.class) will
start returning per-display InputMethodManager (IMM) instance.
Why?
There are two major reasons.
1. To support per-display focused window.
2. To support more simplified API for multi-session IME.
Currently per-process InputMethodManager instance directly receives
callback from ViewRootImpl upon windowFocusChanged, then it keeps
track of which Window is focused by storing its root view into
InputMethodManager#mCurRootView.
This design assumes that (within the same process) at most one Window
can have window focus, which is no longer true once we start
supporting per-display focused window (Bug 111361570).
Why we need to do this to support per-display focused window:
For traditional non multi-session IME cases (e.g. apps that use
Virtual Display APIs on phones), internal state of IMM can be easily
messed up once the system starts sending per-display
windowFocusChanged events to the same process, because IMM still
doesn't know that now each display has focused window. It is hard to
precisely predict what kind of issues we would see simply because such
a use case is most likely not expected in the original design.
Why we need to do this for multi-session IME:
For multi-session IME scenarios, in addition to the above concern in
InputMethodManager, the current design allows at most one IME session
per process. This means that if a process X is showing Activities to 3
different displays, only one Activity can interact with the
multi-session IME at the same time. If we do not change the current
design, the only way to work around is to ask app developers to
explicitly use different processes for each Activity, which may
require a lot of work (e.g. SharedPreference is not optimized for
multi-process use cases). This would also make multi-session IME
development complicated because the IME cannot know on which display
the IME is interacting until startInputOrWindowGainedFocus() is
actually called, and needs to do all the preparation and cleanup tasks
whenever startInputOrWindowGainedFocus() is called for a different
display than it's currently interacting with.
Alternative solutions considered:
Another possible approach is to update InputMethodManager singleton to
be able to maintain multiple mCurRootView and mServedView for each
display. This approach was abandoned because those fields and methods
are already marked as @UnsupportedAppUsage. I concluded that touching
@UnsupportedAppUsage things would have bigger compatibility risks than
per-display instance model.
Implementation note:
* Public APIs in IMM that take View instance as the first parameter
will verify whether the given View and IMM are associated with the
same display ID or not. If there is a display ID mismatch, such an
API call will be automatically forwarded to the correct IMM instance
IMM with a clear warning in logcat which tells that app developers
should use the correct IMM instance to avoid unnecessary performance
overhead.
* As a general rule, system server process cannot trust display ID
reported from applications. In order to enable IMMS to verify the
reported display ID, this CL also exposes display ID verification
logic from WMS to other system components via WindowManagerInternal.
* isInputMethodClientFocus() in WindowManagerService (WMS) is updated
to use top-focused-display to determine whether a given IME client
has IME focus or not. This is now necessary because with a recent
change [1] each display can have focused window. The previous logic
to check all the displays that belong to the given pid/uid [2] no
longer makes sense.
* Currently per-display InputMethodManager instances will not be
garbage collected because InputMethodManager#sInstanceMap keeps
holding strong references to them. Freeing those instances is
technically possible, but we need to be careful because multiple
processes (app, system, IME) are involved and at least system
process has a strict verification logic that lets the calling
process crash with SecurityException. We need to carefully
implement such a cleanup logic to avoid random process crash due to
race condition. Bug 116699479 will take care of this task.
Also to make sure that the performance regression (Bug 117434607) we
observed after my initial attempt [3] no longer exists, here are the
benchmark results with and without this CL.
testExpandNotificationsLatency on taimen-userdebug
without this CL:
results=[55, 46, 61, 67, 50, 48, 57, 50, 55, 63]
min:46.0, max:67.0, avg:55.2, median:55.0, std_dev:6.539
with this CL:
results=[45, 55, 58, 57, 47, 60, 59, 60, 56, 53]
min:45.0, max:60.0, avg:55.0, median:56.5, std_dev:4.980
[1]: I776cabaeaf41ff4240f504fb1430d3e40892023d
1e5b10a217
[2]: I8da315936caebdc8b2c16cff4e24192c06743251
90120a8b5b
[3]: I7242e765426353672823fcc8277f20ac361930d7
c53d78e992
Bug: 111364446
Fix: 115893206
Test: atest ActivityManagerMultiDisplayTests
Test: atest CtsInputMethodTestCases CtsInputMethodServiceHostTestCases
Test: atest FrameworksCoreTests:android.view.inputmethod.InputMethodManagerTest
Test: No perf regression in LatencyTests#testExpandNotificationsLatency()
Change-Id: I78ad7cccb9586474c83f7e2f90c0bcabb221c47b
ContextImpl has an internal rule that when ContextImpl#mDisplay is
null the Context is associated with the default display. The problem
is that, as discussed in Bug 117709581, when ContextImpl#mDisplay is
null ContextImpl#getDisplay() tries to get some non-null Display
object by making an IPC to the system server, which is redundant when
the display ID is the only thing that the caller wants to know.
By having an @hide method Context.getDisplayId(), we can ensure that
display ID can be obtained without any IPC. This enables us to
re-submit my CL [1] that aimed to instantiate InputMethodManager (IMM)
for each display but then got reverted due to a performance regression
(Bug 117434607).
There should be no developer-observable behavior change.
[1]: I7242e765426353672823fcc8277f20ac361930d7
c53d78e992
Fix: 117712745
Test: atest FrameworksCoreTests:android.content.ContextTest
Test: prebuilts/checkstyle/checkstyle.py -f \
frameworks/base/core/tests/coretests/src/android/content/ContextTest.java
Change-Id: I2534530a5ce90e2620c5039d793a6454a0a1e154
The suspending app has more context about why a particular app was
suspended by the user, but we do not want to delegate the interception
of the suspended activity out of the system.
Hence allowing it further customizations to the dialog to make
it clearer.
Test: atest com.android.server.pm.SuspendDialogInfoTest \
com.android.server.pm.SuspendPackagesTest \
com.android.server.pm.PackageUserStateTest \
com.android.server.pm.PackageManagerSettingsTests \
com.android.server.am.ActivityStartInterceptorTest
atest GtsSuspendAppsPermissionTestCases GtsSuspendAppsTestCases
Bug: 112486945
Bug: 113150060
Change-Id: If9f4d14587a2b75bb572e7984a90e300a2c72d16
Test: UT and manual
atest .../LooperStatsTest.java
Verified that adb shell cmd looper_stats dump produces data
with dispatch delay
Bug: 113651685
Change-Id: I44550f8c5d71848932733bd02016aa65ce7b75b3
Background: BatteryStatsService tracks the phone scanning time metric. In Q,
we are migrating the dumpsys-based collection to the new infra. This CL is to
instrument the new logging mechanism.
Test: statsd test
FIX: b/116748990
Change-Id: I3cf5e0026bfc6f594c5f7b524f14b3a43b702afb
InputMethodManager has been a per-process singleton object. In order
to support behavior changes for multi-display support in Android Q,
however, InputMethodManager now needs to be per-display objects.
With this CL, context.getSystemService(InputMethodManager.class) will
start returning per-display InputMethodManager (IMM) instance.
Why?
There are two major reasons.
1. To support per-display focused window.
2. To support more simplified API for multi-session IME.
Currently per-process InputMethodManager instance directly receives
callback from ViewRootImpl upon windowFocusChanged, then it keeps
track of which Window is focused by storing its root view into
InputMethodManager#mCurRootView.
This design assumes that (within the same process) at most one Window
can have window focus, which is no longer true once we start
supporting per-display focused window (Bug 111361570).
Why we need to do this to support per-display focused window:
For traditional non multi-session IME cases (e.g. apps that use
Virtual Display APIs on phones), internal state of IMM can be easily
messed up once the system starts sending per-display
windowFocusChanged events to the same process, because IMM still
doesn't know that now each display has focused window. It is hard to
precisely predict what kind of issues we would see simply because such
a use case is most likely not expected in the original design.
Why we need to do this for multi-session IME:
For multi-session IME scenarios, in addition to the above concern in
InputMethodManager, the current design allows at most one IME session
per process. This means that if a process X is showing Activities to 3
different displays, only one Activity can interact with the
multi-session IME at the same time. If we do not change the current
design, the only way to work around is to ask app developers to
explicitly use different processes for each Activity, which may
require a lot of work (e.g. SharedPreference is not optimized for
multi-process use cases). This would also make multi-session IME
development complicated because the IME cannot know on which display
the IME is interacting until startInputOrWindowGainedFocus() is
actually called, and needs to do all the preparation and cleanup tasks
whenever startInputOrWindowGainedFocus() is called for a different
display than it's currently interacting with.
Alternative solutions considered:
Another possible approach is to update InputMethodManager singleton to
be able to maintain multiple mCurRootView and mServedView for each
display. This approach was abandoned because those fields and methods
are already marked as @UnsupportedAppUsage. I concluded that touching
@UnsupportedAppUsage things would have bigger compatibility risks than
per-display instance model.
Implementation note:
* Public APIs in IMM that take View instance as the first parameter
will verify whether the given View and IMM are associated with the
same display ID or not. If there is a display ID mismatch, such an
API call will be automatically forwarded to the correct IMM instance
IMM with a clear warning in logcat which tells that app developers
should use the correct IMM instance to avoid unnecessary performance
overhead.
* As a general rule, system server process cannot trust display ID
reported from applications. In order to enable IMMS to verify the
reported display ID, this CL also exposes display ID verification
logic from WMS to other system components via WindowManagerInternal.
* isInputMethodClientFocus() in WindowManagerService (WMS) is updated
to use top-focused-display to determine whether a given IME client
has IME focus or not. This is now necessary because with a recent
change [1] each display can have focused window. The previous logic
to check all the displays that belong to the given pid/uid [2] no
longer makes sense.
* Currently per-display InputMethodManager instances will not be
garbage collected because InputMethodManager#sInstanceMap keeps
holding strong references to them. Freeing those instances is
technically possible, but we need to be careful because multiple
processes (app, system, IME) are involved and at least system
process has a strict verification logic that lets the calling
process crash with SecurityException. We need to carefully
implement such a cleanup logic to avoid random process crash due to
race condition. Bug 116699479 will take care of this task.
[1]: I776cabaeaf41ff4240f504fb1430d3e40892023d
1e5b10a217
[2]: I8da315936caebdc8b2c16cff4e24192c06743251
90120a8b5b
Bug: 111364446
Fix: 115893206
Test: atest ActivityManagerMultiDisplayTests
Test: atest CtsInputMethodTestCases CtsInputMethodServiceHostTestCases
Test: atest FrameworksCoreTests:android.view.inputmethod.InputMethodManagerTest
Change-Id: I7242e765426353672823fcc8277f20ac361930d7
The extractNativeLibs property was ignored by the package installer
for environments with native bridge. This is not neccessary since
native bridge implementations are required to support
open-directly-from-apk feature and in this respect are not different
from environments without native bridge.
Bug: http://b/116854266
Test: cts-tradefed run singleCommand cts --skip-preconditions -m CtsJniTestCases
Change-Id: I9ea7397183d7ebe2c00e461b95d188b15b51eca2
For the intermediate period, MetricsLogger logs to both event buffer in
logd as well as stastd socket.
Bug: 110537511
Test: statsd, statsd_test
Change-Id: Ie349b1d202e07c585ab5b085141865f20d1f57cd
Adds diskio information to statsd. The puller queries the
proc/uid_io/stats file to get cumulative counts since boot.
Bug: b/116331466
Test: unit test
Test: manually verified that the puller and "cat /proc/uid_io/stats"
returned almost identical output when executed at the same time
Change-Id: Iac446f8dd879ab6bf859eed6e779cc16fdee6c5b