summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Fabian Kozynski <kozynski@google.com> 2019-08-15 15:44:07 -0400
committer Fabian Kozynski <kozynski@google.com> 2019-09-05 12:26:13 -0400
commit3bf518dd98c14860cdae1cea73085d2187cbfdb9 (patch)
tree87fd04b0207e0363e0a32173033389bf976d3851
parentf7a1488e90c485b2b0cc7d002c2ad286782acb3c (diff)
Adding a Plugin to attach things under QQS
This plugin responds to expansion and changes in theme, ui, etc. Test: manual Change-Id: I5d866a4fff491aa6273edfb765e538864b270534
-rw-r--r--packages/SystemUI/docs/plugin_hooks.md5
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/NPVPlugin.java52
-rw-r--r--packages/SystemUI/res/layout/status_bar_expanded.xml2
-rw-r--r--packages/SystemUI/res/layout/status_bar_expanded_plugin_frame.xml29
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NPVPluginManager.kt92
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java69
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java3
7 files changed, 250 insertions, 2 deletions
diff --git a/packages/SystemUI/docs/plugin_hooks.md b/packages/SystemUI/docs/plugin_hooks.md
index 9fe2e181971a..2fb0c996111a 100644
--- a/packages/SystemUI/docs/plugin_hooks.md
+++ b/packages/SystemUI/docs/plugin_hooks.md
@@ -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.
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/NPVPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/NPVPlugin.java
new file mode 100644
index 000000000000..1426266a7048
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/NPVPlugin.java
@@ -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) {};
+}
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 7a9400887c75..e7c6b2574f5f 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -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>
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_plugin_frame.xml b/packages/SystemUI/res/layout/status_bar_expanded_plugin_frame.xml
new file mode 100644
index 000000000000..4849dfb777ed
--- /dev/null
+++ b/packages/SystemUI/res/layout/status_bar_expanded_plugin_frame.xml
@@ -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"/> \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NPVPluginManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NPVPluginManager.kt
new file mode 100644
index 000000000000..7dcc2fcfe2b2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NPVPluginManager.kt
@@ -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
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index a58ba858e518..f5835765bdea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -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
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
index a96efd7d2fc2..86ab3a70c3ac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -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;