Lots of things detect overlays these days (installing apps) and the
only way to avoid the problems associated with this is to live in
the status bar window. So allow plugins to hold the window open
when they want to so they can have overlays be in that.
Move StatusBarWindowManager to Dependency to make things easier
as well.
Test: Install the example plugin, test can access QS and interact
with apps
Change-Id: Ib2288bf56704960847217bad01a480ab407e0ffe
Add support for testing for PluginManager and TunerService leaks
and add tests for the known leaks and fix them. Also port PluginManager
and TunerService to Dependency to make them easier to handle in
tests.
Test: runtest systemui
Change-Id: I5642539ee24dd72f802905106decd0c87b41b4eb
Fixes: 34846972
It is a relic of a more complex time, but has passed out of all
knowledge for too long.
Test: manual testing on phones and TV
Change-Id: I62a15d9413ea4bda3ac82bf6f7d22c096e2c1cdc
There are five channels at present:
ALERTS - low battery etc.
SCREENSHOTS - progress & result
SECURITY - notifications hidden due to policy
STORAGE - disk low
STATUS - basically everything else
The importance for each channel should match the legacy
priority of the notifications it carries.
Bug: 34250937
Test: runtest systemui
Change-Id: I5915ca453258caea63b0d9bd756893db05e8d600
NotificationGuts is now given a view to display, the notification
management controls have been moved into their own view.
NotificationGuts is provided a view to show via a MenuItem.
This allows configuration via the NotificationMenuRowProvider Plugin.
Test: manual
Change-Id: I68cb23ea2cada30cc6e930fa8c03e0aa4014dfe2
This will allow plugins to supply additional menu options to the
menu "behind" a notification.
This CL does not include behavior for when one of these new menu
items is tapped, this will be added in a separate CL.
Test: manual
Change-Id: I322f9f39d33b043bd23dcbede5dd15e6afa73fc1
Use a new system for constructing fragments so they can be swapped
out in place maintaining state. This will allow easier integration
with plugin lifecycle as parents who have child plugin fragments
can depend on the class existing and won't have to listen to
the lifecycle.
Test: runtest systemui
Change-Id: I517f4ce3d114abd49b1b5baca388d19e929b8f90
One of the many problems with PhoneStatusBar is that it holds
dependencies for many other parts of SysUI. Fix this by creating
a static method of grabbing dependencies that are global to sysui
this cleans up a lot of chains of interdependence.
Also add easy way to inject mocks of these dependencies for the
purpose of testing.
Test: runtest systemui
Change-Id: Ia0e947faea62d15b665facada47ac9916c99f895
This will hopefully avoid blaming sysui for ANRs when the system
is hosed.
Test: Manual, build, push, wait for time to change
Change-Id: I1661ac1a997ad8917b449dd175229d8b77f583c9
Port all system UI notifications to use the registry. Retain stable
integer IDs where they exist. Assign new stable IDs where resource IDs
were previously used.
Using "message" rather than "notification" since we may eventually
want to include dialogs and toasts.
Bug: 32584866
Bug: 30995038
Test: runtest systemui
Change-Id: Iec4d7cebbd88683e339ada29a279315222699942
Before navbar assumes rotation 0 means portrait and rotation 90
means landscape. This is not necessarily true, in certain devices
the natural orientation (0) is landscape. Here we removed that
assumption and make sure we use the right inflater at all times.
Bug: 32516898
Test: Locally on test device
Change-Id: I3db44dcb35d8511fb9d42b147b2bd137ff0750f7
Allows fragments to be easily switched over to plugins and a provides
a convenient base class for plugins to use that makes sure the layout
inflater and context point at the plugin's and not sysui's.
Bug: 32609190
Test: runtest systemui
Change-Id: I6503947e980f66ddcd826f6ca9a92b591ce0eb1e
There is now a bit too much of the view/layout logic touching the
fragment, but sort out that later and get something over to fragments
for now.
Bug: 32609190
Test: Manual
Change-Id: Icf677f4a70e6b92892a0fc27a0e673940ebc7a73
The heart of this change are two things:
1) Instead of using the force hide mechanism to hide windows behind
Keyguard, we actually make the activities invisible in activity manager.
2) When Keyguard is going away, we change the visibilities in activity
manager and run an app transition.
At the very core we move the responsibility of hiding activities to
ActivityStack, which checks whether Keyguard is showing, and then
hides all non-show-when-locked activities. For that, we need to check
whether any window of an activity has SHOW_WHEN_LOCKED set. We
introduce a callback from WM -> AM in case these Keyguard flags have
changed.
Furthermore, we decide whether to occlude Keyguard in KeyguardController,
which just checks whether the top activity has SHOW_WHEN_LOCKED set. When
this state changes, we prepare an occlude/unocclude app transition, and
in PWM we just inform the Keyguard about the animation so SysUI can play
along this animations in a mostly synchronized manner.
Since we now use an app transition when unlocking the phone, we get
lockscreen launch animations for free - window manager automatically
waits until the activity is drawn, or directly executes the transition
if there is nothing to animate. Thus, we can remove all the infrastructure
around "waitingForActivityDrawn".
The logic to show/hide non-app windows is moved to policy, and we add the
ability to run animations on non-app windows when executing an app
transition.
Test:
1) runtest frameworks-services -c com.android.server.wm.AppTransitionTests
2) Manually test unlocking Keyguard:
2a) Without security
2b) With security
2c) With security but trusted
2d) Portrait while activity behind is in landscape
3) Test launching things from Keyguard
3a) Without security
3b) With security
3c) Launch camera without security
3d) Launch camera with security
3e) Launch camera with securtiy and trusted
3f) Launch voice affordance
4) Set no notifications on lockscreen, drag down, make sure you get
the correct animation
5) Test clicking "emergency" on bouncer
5b) Test "Emergency info" on emergency dialer
5c) Test clicking edit button on emergency info, should show pattern on
Keyguard
Bug: 32057734
Change-Id: Icada03cca74d6a612c1f988845f4d4f601087558
Should be used only during dev to avoid having to turn crashing
plugins back on constantly.
Test: Manual
Change-Id: I2f2a461bf7aef017781ed3b61fcb216d7e1cbae9
Send a broadcast back and forth to speed up the rate at which plugins
are enabled or disabled.
Also update make files to handle exclude tests better.
Test: Manual
Change-Id: Ic8f45c663c3a5e5fd4b3e9e2f79480e155845c14
For some reason it makes android studio angry when embedding the
plugin lib in it.
Test: runtest systemui
Change-Id: I8c7202846903a75ffcbad86cb31862098e8d939a
Cache ClassLoader by pkg so that Plugins can talk to each other.
Also add some filtering so that only classes from the plugins package
and sub-packages are included in plugin classloaders.
Test: Manual
Change-Id: I42aabb418168d5a5d0581b8133aa93f07cb7e977
Create an interface so a plugin can replace the intent and icon of
the camera trigger on the lock screen.
Test: Manual
Change-Id: I867ffb10e3b3906ca3903f96309a3ee5ef9e19d9
This allows plugins to create their own or override nav buttons
based on the button spec.
Test: Manual
Change-Id: I11e9a953710ed14bb9c6d9f96027852a737b58ba
Allow plugins to be manually turned off from within the tuner. This
screen only shows itself if at some point in time a plugin has been
active on this device. Plugins can also serface settings there by
receiving the com.android.systemui.action.PLUGIN_SETTINGS action.
Test: Manual
Change-Id: Ifb043c85e383fc072c6445ae322293a6401a6f2c
Users must implement the QSContainer interface to be returned by
a ViewProvider plugin. The QSContainer must contain a
BaseStatusBarHeader and have the id of quick_settings_container.
Test: Manual
Change-Id: Ibfaa835cad20855a530e4ae142d8a2aeba4a277b
PluginInflateContainer extends AutoReinflateContainer, except that
it also uses the plugin interface to allow the view to be swapped
out with something else.
Define an interface or abstract class as follows that includes the
version and action.
public interface MyInterface {
public static final String ACTION =
"com.android.systemui.action.PLUGIN_MYINTERFACE";
public static final int VERSION = 1;
void myImportantInterface();
}
Then put in a PluginInflateContainer to use and specify the interface
or class that will be implemented as viewType. The layout specified
will be used by default and whenever a plugin is not present.
<com.android.systemui.PluginInflateContainer
android:id="@+id/some_id"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout="@layout/my_default_component"
systemui:viewType="com.android.systemui.plugins.MyInterface" />
Test: Manual
Change-Id: I2ef3fa8dbe344c4635df20056182c1c0b3846fdf
Why this is safe:
- To never ever be used in production code, simply for rapid
prototyping (multiple checks in place)
- Guarded by signature level permission checks, so only matching
signed code will be used
- Any crashing plugins are auto-disabled and sysui is allowed
to continue in peace
Now on to what it actually does. Plugins are separate APKs that
are expected to implement interfaces provided by SystemUI. Their
code is dynamically loaded into the SysUI process which can allow
for multiple prototypes to be created and run on a single android
build.
-------
PluginLifecycle:
plugin.onCreate(Context sysuiContext, Context pluginContext);
--- This is always called before any other calls
pluginListener.onPluginConnected(Plugin p);
--- This lets the plugin hook know that a plugin is now connected.
** Any other calls back and forth between sysui/plugin **
pluginListener.onPluginDisconnected(Plugin p);
--- Lets the plugin hook know that it should stop interacting with
this plugin and drop all references to it.
plugin.onDestroy();
--- Finally the plugin can perform any cleanup to ensure that its not
leaking into the SysUI process.
Any time a plugin APK is updated the plugin is destroyed and recreated
to load the new code/resources.
-------
Creating plugin hooks:
To create a plugin hook, first create an interface in
frameworks/base/packages/SystemUI/plugin that extends Plugin.
Include in it any hooks you want to be able to call into from
sysui and create callback interfaces for anything you need to
pass through into the plugin.
Then to attach to any plugins simply add a plugin listener and
onPluginConnected will get called whenever new plugins are installed,
updated, or enabled. Like this example from SystemUIApplication:
PluginManager.getInstance(this).addPluginListener(OverlayPlugin.COMPONENT,
new PluginListener<OverlayPlugin>() {
@Override
public void onPluginConnected(OverlayPlugin plugin) {
PhoneStatusBar phoneStatusBar = getComponent(PhoneStatusBar.class);
if (phoneStatusBar != null) {
plugin.setup(phoneStatusBar.getStatusBarWindow(),
phoneStatusBar.getNavigationBarView());
}
}
}, OverlayPlugin.VERSION, true /* Allow multiple plugins */);
Note the VERSION included here. Any time incompatible changes in the
interface are made, this version should be changed to ensure old plugins
aren't accidentally loaded. Since the plugin library is provided by
SystemUI, default implementations can be added for new methods to avoid
version changes when possible.
-------
Implementing a Plugin:
See the ExamplePlugin for an example Android.mk on how to compile
a plugin. Note that SystemUILib is not static for plugins, its classes
are provided by SystemUI.
Plugin security is based around a signature permission, so plugins must
hold the following permission in their manifest.
<uses-permission android:name="com.android.systemui.permission.PLUGIN" />
A plugin is found through a querying for services, so to let SysUI know
about it, create a service with a name that points at your implementation
of the plugin interface with the action accompanying it:
<service android:name=".TestOverlayPlugin">
<intent-filter>
<action android:name="com.android.systemui.action.PLUGIN_COMPONENT" />
</intent-filter>
</service>
Change-Id: I42c573a94907ca7a2eaacbb0a44614d49b8fc26f