Adding a Plugin to attach things under QQS
This plugin responds to expansion and changes in theme, ui, etc. Test: manual Change-Id: I5d866a4fff491aa6273edfb765e538864b270534
This commit is contained in:
@@ -56,6 +56,11 @@ Expected interface: [ClockPlugin](/packages/SystemUI/plugin/src/com/android/syst
|
||||
|
||||
Use: Allows replacement of the keyguard main clock.
|
||||
|
||||
### Action: com.android.systemui.action.PLUGIN_NPV
|
||||
Expected interface: [NPVPlugin](/packages/SystemUI/plugin/src/com/android/systemui/plugins/NPVPlugin.java)
|
||||
|
||||
Use: Attach a view under QQS for prototyping.
|
||||
|
||||
# Global plugin dependencies
|
||||
These classes can be accessed by any plugin using PluginDependency as long as they @Requires them.
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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.systemui.plugins;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.android.systemui.plugins.annotations.ProvidesInterface;
|
||||
|
||||
/**
|
||||
* Plugin to attach custom views under QQS.
|
||||
*
|
||||
* A parent view is provided to the plugin to which they can add Views.
|
||||
* <br>
|
||||
* The parent is a {@link FrameLayout} with same background as QS and 96dp height.
|
||||
*
|
||||
* {@see NPVPluginManager}
|
||||
* {@see status_bar_expanded_plugin_frame}
|
||||
*/
|
||||
@ProvidesInterface(action = NPVPlugin.ACTION, version = NPVPlugin.VERSION)
|
||||
public interface NPVPlugin extends Plugin {
|
||||
String ACTION = "com.android.systemui.action.PLUGIN_NPV";
|
||||
int VERSION = 1;
|
||||
|
||||
/**
|
||||
* Attach views to the parent.
|
||||
*
|
||||
* @param parent a {@link FrameLayout} to which to attach views. Preferably a root view.
|
||||
* @return a view attached to parent.
|
||||
*/
|
||||
View attachToRoot(FrameLayout parent);
|
||||
|
||||
/**
|
||||
* Indicate to the plugin when it is listening (QS expanded)
|
||||
* @param listening
|
||||
*/
|
||||
default void setListening(boolean listening) {};
|
||||
}
|
||||
@@ -111,4 +111,6 @@
|
||||
android:visibility="invisible"
|
||||
android:background="@drawable/qs_navbar_scrim" />
|
||||
|
||||
<include layout="@layout/status_bar_expanded_plugin_frame"/>
|
||||
|
||||
</com.android.systemui.statusbar.phone.NotificationPanelView>
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2019 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.
|
||||
-->
|
||||
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/plugin_frame"
|
||||
android:theme="@style/qs_theme"
|
||||
android:layout_width="@dimen/qs_panel_width"
|
||||
android:layout_height="96dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="@*android:dimen/quick_qs_total_height"
|
||||
android:layout_marginLeft="@dimen/notification_side_paddings"
|
||||
android:layout_marginRight="@dimen/notification_side_paddings"
|
||||
android:visibility="gone"
|
||||
android:background="@drawable/qs_background_primary"/>
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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.systemui.statusbar.phone
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import com.android.systemui.plugins.NPVPlugin
|
||||
import com.android.systemui.plugins.PluginListener
|
||||
import com.android.systemui.qs.TouchAnimator
|
||||
import com.android.systemui.shared.plugins.PluginManager
|
||||
|
||||
/**
|
||||
* Manages the NPVPlugin view and state
|
||||
*
|
||||
* Abstracts NPVPlugin from NPV and helps animate on expansion and respond to changes in Config.
|
||||
*/
|
||||
class NPVPluginManager(
|
||||
var parent: FrameLayout,
|
||||
val pluginManager: PluginManager
|
||||
) : PluginListener<NPVPlugin> {
|
||||
|
||||
private var plugin: NPVPlugin? = null
|
||||
private var animator = createAnimator()
|
||||
|
||||
private fun createAnimator() = TouchAnimator.Builder()
|
||||
.addFloat(parent, "alpha", 1f, 0f)
|
||||
.addFloat(parent, "scaleY", 1f, 0f)
|
||||
.build()
|
||||
|
||||
init {
|
||||
pluginManager.addPluginListener(NPVPlugin.ACTION, this, NPVPlugin::class.java, false)
|
||||
parent.pivotY = 0f
|
||||
}
|
||||
|
||||
override fun onPluginConnected(plugin: NPVPlugin, pluginContext: Context) {
|
||||
parent.removeAllViews()
|
||||
plugin.attachToRoot(parent)
|
||||
this.plugin = plugin
|
||||
parent.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
fun changeVisibility(visibility: Int) {
|
||||
parent.visibility = if (plugin != null) visibility else View.GONE
|
||||
}
|
||||
|
||||
fun destroy() {
|
||||
plugin?.onDestroy()
|
||||
pluginManager.removePluginListener(this)
|
||||
}
|
||||
|
||||
override fun onPluginDisconnected(plugin: NPVPlugin) {
|
||||
if (this.plugin == plugin) {
|
||||
this.plugin = null
|
||||
parent.removeAllViews()
|
||||
parent.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
fun setListening(listening: Boolean) {
|
||||
plugin?.setListening(listening)
|
||||
}
|
||||
|
||||
fun setExpansion(expansion: Float, headerTranslation: Float, heightDiff: Float) {
|
||||
parent.setTranslationY(expansion * heightDiff + headerTranslation)
|
||||
if (!expansion.isNaN()) animator.setPosition(expansion)
|
||||
}
|
||||
|
||||
fun replaceFrameLayout(newParent: FrameLayout) {
|
||||
newParent.visibility = parent.visibility
|
||||
parent.removeAllViews()
|
||||
plugin?.attachToRoot(newParent)
|
||||
parent = newParent
|
||||
animator = createAnimator()
|
||||
}
|
||||
|
||||
fun getHeight() = if (plugin != null) parent.height else 0
|
||||
}
|
||||
@@ -393,6 +393,10 @@ public class NotificationPanelView extends PanelView implements
|
||||
private boolean mAllowExpandForSmallExpansion;
|
||||
private Runnable mExpandAfterLayoutRunnable;
|
||||
|
||||
private PluginManager mPluginManager;
|
||||
private FrameLayout mPluginFrame;
|
||||
private NPVPluginManager mNPVPluginManager;
|
||||
|
||||
@Inject
|
||||
public NotificationPanelView(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
|
||||
InjectionInflationController injectionInflationController,
|
||||
@@ -400,7 +404,8 @@ public class NotificationPanelView extends PanelView implements
|
||||
PulseExpansionHandler pulseExpansionHandler,
|
||||
DynamicPrivacyController dynamicPrivacyController,
|
||||
KeyguardBypassController bypassController,
|
||||
FalsingManager falsingManager) {
|
||||
FalsingManager falsingManager,
|
||||
PluginManager pluginManager) {
|
||||
super(context, attrs);
|
||||
setWillNotDraw(!DEBUG);
|
||||
mInjectionInflationController = injectionInflationController;
|
||||
@@ -431,6 +436,7 @@ public class NotificationPanelView extends PanelView implements
|
||||
});
|
||||
mBottomAreaShadeAlphaAnimator.setDuration(160);
|
||||
mBottomAreaShadeAlphaAnimator.setInterpolator(Interpolators.ALPHA_OUT);
|
||||
mPluginManager = pluginManager;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -465,6 +471,9 @@ public class NotificationPanelView extends PanelView implements
|
||||
mKeyguardBottomArea = findViewById(R.id.keyguard_bottom_area);
|
||||
mQsNavbarScrim = findViewById(R.id.qs_navbar_scrim);
|
||||
mLastOrientation = getResources().getConfiguration().orientation;
|
||||
mPluginFrame = findViewById(R.id.plugin_frame);
|
||||
mNPVPluginManager = new NPVPluginManager(mPluginFrame, mPluginManager);
|
||||
|
||||
|
||||
initBottomArea();
|
||||
|
||||
@@ -584,6 +593,19 @@ public class NotificationPanelView extends PanelView implements
|
||||
lp.gravity = panelGravity;
|
||||
mNotificationStackScroller.setLayoutParams(lp);
|
||||
}
|
||||
int sideMargin = res.getDimensionPixelOffset(R.dimen.notification_side_paddings);
|
||||
int topMargin =
|
||||
res.getDimensionPixelOffset(com.android.internal.R.dimen.quick_qs_total_height);
|
||||
lp = (FrameLayout.LayoutParams) mPluginFrame.getLayoutParams();
|
||||
if (lp.width != qsWidth || lp.gravity != panelGravity || lp.leftMargin != sideMargin
|
||||
|| lp.rightMargin != sideMargin || lp.topMargin != topMargin) {
|
||||
lp.width = qsWidth;
|
||||
lp.gravity = panelGravity;
|
||||
lp.leftMargin = sideMargin;
|
||||
lp.rightMargin = sideMargin;
|
||||
lp.topMargin = topMargin;
|
||||
mPluginFrame.setLayoutParams(lp);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -650,6 +672,43 @@ public class NotificationPanelView extends PanelView implements
|
||||
if (mOnReinflationListener != null) {
|
||||
mOnReinflationListener.run();
|
||||
}
|
||||
reinflatePluginContainer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUiModeChanged() {
|
||||
reinflatePluginContainer();
|
||||
}
|
||||
|
||||
private void reinflatePluginContainer() {
|
||||
int index = indexOfChild(mPluginFrame);
|
||||
removeView(mPluginFrame);
|
||||
mPluginFrame = (FrameLayout) mInjectionInflationController
|
||||
.injectable(LayoutInflater.from(mContext)).inflate(
|
||||
R.layout.status_bar_expanded_plugin_frame,
|
||||
this,
|
||||
false);
|
||||
addView(mPluginFrame, index);
|
||||
|
||||
Resources res = getResources();
|
||||
int qsWidth = res.getDimensionPixelSize(R.dimen.qs_panel_width);
|
||||
int panelGravity = getResources().getInteger(R.integer.notification_panel_layout_gravity);
|
||||
FrameLayout.LayoutParams lp;
|
||||
int sideMargin = res.getDimensionPixelOffset(R.dimen.notification_side_paddings);
|
||||
int topMargin =
|
||||
res.getDimensionPixelOffset(com.android.internal.R.dimen.quick_qs_total_height);
|
||||
lp = (FrameLayout.LayoutParams) mPluginFrame.getLayoutParams();
|
||||
if (lp.width != qsWidth || lp.gravity != panelGravity || lp.leftMargin != sideMargin
|
||||
|| lp.rightMargin != sideMargin || lp.topMargin != topMargin) {
|
||||
lp.width = qsWidth;
|
||||
lp.gravity = panelGravity;
|
||||
lp.leftMargin = sideMargin;
|
||||
lp.rightMargin = sideMargin;
|
||||
lp.topMargin = topMargin;
|
||||
mPluginFrame.setLayoutParams(lp);
|
||||
}
|
||||
|
||||
mNPVPluginManager.replaceFrameLayout(mPluginFrame);
|
||||
}
|
||||
|
||||
private void initBottomArea() {
|
||||
@@ -679,6 +738,7 @@ public class NotificationPanelView extends PanelView implements
|
||||
int oldMaxHeight = mQsMaxExpansionHeight;
|
||||
if (mQs != null) {
|
||||
mQsMinExpansionHeight = mKeyguardShowing ? 0 : mQs.getQsMinExpansionHeight();
|
||||
mQsMinExpansionHeight += mNPVPluginManager.getHeight();
|
||||
mQsMaxExpansionHeight = mQs.getDesiredHeight();
|
||||
mNotificationStackScroller.setMaxTopPadding(
|
||||
mQsMaxExpansionHeight + mQsNotificationTopPadding);
|
||||
@@ -1784,6 +1844,9 @@ public class NotificationPanelView extends PanelView implements
|
||||
mBarState != StatusBarState.KEYGUARD && (!mQsExpanded
|
||||
|| mQsExpansionFromOverscroll));
|
||||
updateEmptyShadeView();
|
||||
mNPVPluginManager.changeVisibility((mBarState != StatusBarState.KEYGUARD)
|
||||
? View.VISIBLE
|
||||
: View.INVISIBLE);
|
||||
mQsNavbarScrim.setVisibility(mBarState == StatusBarState.SHADE && mQsExpanded
|
||||
&& !mStackScrollerOverscrolling && mQsScrimEnabled
|
||||
? View.VISIBLE
|
||||
@@ -1839,6 +1902,8 @@ public class NotificationPanelView extends PanelView implements
|
||||
if (mQs == null) return;
|
||||
float qsExpansionFraction = getQsExpansionFraction();
|
||||
mQs.setQsExpansion(qsExpansionFraction, getHeaderTranslation());
|
||||
int heightDiff = mQs.getDesiredHeight() - mQs.getQsMinExpansionHeight();
|
||||
mNPVPluginManager.setExpansion(qsExpansionFraction, getHeaderTranslation(), heightDiff);
|
||||
mNotificationStackScroller.setQsExpansionFraction(qsExpansionFraction);
|
||||
}
|
||||
|
||||
@@ -2259,6 +2324,7 @@ public class NotificationPanelView extends PanelView implements
|
||||
appearAmount = mNotificationStackScroller.calculateAppearFractionBypass();
|
||||
}
|
||||
startHeight = -mQs.getQsMinExpansionHeight();
|
||||
startHeight -= mNPVPluginManager.getHeight();
|
||||
}
|
||||
float translation = MathUtils.lerp(startHeight, 0,
|
||||
Math.min(1.0f, appearAmount))
|
||||
@@ -2399,6 +2465,7 @@ public class NotificationPanelView extends PanelView implements
|
||||
mKeyguardStatusBar.setListening(listening);
|
||||
if (mQs == null) return;
|
||||
mQs.setListening(listening);
|
||||
mNPVPluginManager.setListening(listening);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -38,6 +38,7 @@ import com.android.systemui.SystemUIFactory;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.plugins.FalsingManager;
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.shared.plugins.PluginManager;
|
||||
import com.android.systemui.statusbar.KeyguardAffordanceView;
|
||||
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
|
||||
import com.android.systemui.statusbar.NotificationShelf;
|
||||
@@ -195,7 +196,7 @@ public class NotificationPanelViewTest extends SysuiTestCase {
|
||||
SystemUIFactory.getInstance().getRootComponent()),
|
||||
coordinator, expansionHandler, mock(DynamicPrivacyController.class),
|
||||
bypassController,
|
||||
mFalsingManager);
|
||||
mFalsingManager, mock(PluginManager.class));
|
||||
mNotificationStackScroller = mNotificationStackScrollLayout;
|
||||
mKeyguardStatusView = NotificationPanelViewTest.this.mKeyguardStatusView;
|
||||
mKeyguardStatusBar = NotificationPanelViewTest.this.mKeyguardStatusBar;
|
||||
|
||||
Reference in New Issue
Block a user