diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 4e140a8d3f45d..26805fab69b21 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -9150,9 +9150,12 @@ public class Notification implements Parcelable
*
*/
public static class CallStyle extends Style {
- private static final int CALL_TYPE_INCOMING = 1;
- private static final int CALL_TYPE_ONGOING = 2;
- private static final int CALL_TYPE_SCREENING = 3;
+ /** @hide */
+ public static final int CALL_TYPE_INCOMING = 1;
+ /** @hide */
+ public static final int CALL_TYPE_ONGOING = 2;
+ /** @hide */
+ public static final int CALL_TYPE_SCREENING = 3;
/**
* This is a key used privately on the action.extras to give spacing priority
diff --git a/packages/SystemUI/res/values/flags.xml b/packages/SystemUI/res/values/flags.xml
index 2f3fbe74d5fa6..6af982ddad728 100644
--- a/packages/SystemUI/res/values/flags.xml
+++ b/packages/SystemUI/res/values/flags.xml
@@ -50,4 +50,6 @@
false
false
+
+ false
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
index 0673879758ad5..37b8a2c953fe3 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
@@ -23,6 +23,7 @@ import android.view.View;
import com.android.systemui.Dumpable;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.qs.QSFragment;
+import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
import com.android.systemui.statusbar.policy.ConfigurationController;
import java.io.FileDescriptor;
@@ -128,6 +129,9 @@ public class FragmentService implements Dumpable {
* Inject a QSFragment.
*/
QSFragment createQSFragment();
+
+ /** Inject a CollapsedStatusBarFragment. */
+ CollapsedStatusBarFragment createCollapsedStatusBarFragment();
}
private class FragmentHostState {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java b/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
index 90c3dfcee5bf0..b937dad269e94 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/FeatureFlags.java
@@ -98,4 +98,8 @@ public class FeatureFlags {
public boolean isChargingRippleEnabled() {
return mFlagReader.isEnabled(R.bool.flag_charging_ripple);
}
+
+ public boolean isOngoingCallStatusBarChipEnabled() {
+ return mFlagReader.isEnabled(R.bool.flag_ongoing_call_status_bar_chip);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java
index efd0519d6608d..14c73b5cbb4c9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java
@@ -49,6 +49,7 @@ import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.inflation.LowPriorityInflationHelper;
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
import com.android.systemui.statusbar.notification.stack.ForegroundServiceSectionController;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.ManagedProfileController;
@@ -57,6 +58,7 @@ import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarIconControllerImpl;
import com.android.systemui.statusbar.phone.StatusBarRemoteInputCallback;
+import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
import com.android.systemui.statusbar.policy.RemoteInputUriController;
import com.android.systemui.tracing.ProtoTracer;
import com.android.systemui.util.DeviceConfigProxy;
@@ -226,4 +228,16 @@ public interface StatusBarDependenciesModule {
@Binds
StatusBarIconController provideStatusBarIconController(
StatusBarIconControllerImpl controllerImpl);
+
+ /**
+ */
+ @Provides
+ @SysUISingleton
+ static OngoingCallController provideOngoingCallController(
+ CommonNotifCollection notifCollection, FeatureFlags featureFlags) {
+ OngoingCallController ongoingCallController =
+ new OngoingCallController(notifCollection, featureFlags);
+ ongoingCallController.init();
+ return ongoingCallController;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionListener.java
index 75d772e8a1c51..db0c1745f5657 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionListener.java
@@ -57,7 +57,7 @@ public interface NotifCollectionListener {
* Called whenever a notification with the same key as an existing notification is posted. By
* the time this listener is called, the entry's SBN and Ranking will already have been updated.
*/
- default void onEntryUpdated(NotificationEntry entry) {
+ default void onEntryUpdated(@NonNull NotificationEntry entry) {
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
index 268f3484354a6..f64a0e03698a9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
@@ -37,6 +37,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.StatusBarIconController.DarkIconManager;
+import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
import com.android.systemui.statusbar.policy.EncryptionHelper;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.NetworkController;
@@ -45,6 +46,8 @@ import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
import java.util.ArrayList;
import java.util.List;
+import javax.inject.Inject;
+
/**
* Contains the collapsed status bar and handles hiding/showing based on disable flags
* and keyguard state. Also manages lifecycle to make sure the views it contains are being
@@ -72,6 +75,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
private DarkIconManager mDarkIconManager;
private View mOperatorNameFrame;
private CommandQueue mCommandQueue;
+ private OngoingCallController mOngoingCallController;
private List mBlockedIcons = new ArrayList<>();
@@ -82,6 +86,11 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
}
};
+ @Inject
+ public CollapsedStatusBarFragment(OngoingCallController ongoingCallController) {
+ mOngoingCallController = ongoingCallController;
+ }
+
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 012439e448c34..d4df126c55b97 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -225,6 +225,7 @@ import com.android.systemui.statusbar.notification.stack.NotificationStackScroll
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
import com.android.systemui.statusbar.phone.dagger.StatusBarPhoneModule;
+import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -424,6 +425,7 @@ public class StatusBar extends SystemUI implements DemoMode,
private final DismissCallbackRegistry mDismissCallbackRegistry;
private final DemoModeController mDemoModeController;
private NotificationsController mNotificationsController;
+ private final OngoingCallController mOngoingCallController;
// expanded notifications
// the sliding/resizing panel within the notification window
@@ -788,6 +790,7 @@ public class StatusBar extends SystemUI implements DemoMode,
NotificationIconAreaController notificationIconAreaController,
BrightnessSlider.Factory brightnessSliderFactory,
WiredChargingRippleController chargingRippleAnimationController,
+ OngoingCallController ongoingCallController,
FeatureFlags featureFlags) {
super(context);
mNotificationsController = notificationsController;
@@ -867,6 +870,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mNotificationIconAreaController = notificationIconAreaController;
mBrightnessSliderFactory = brightnessSliderFactory;
mChargingRippleAnimationController = chargingRippleAnimationController;
+ mOngoingCallController = ongoingCallController;
mFeatureFlags = featureFlags;
mExpansionChangedListeners = new ArrayList<>();
@@ -1153,7 +1157,8 @@ public class StatusBar extends SystemUI implements DemoMode,
checkBarModes();
}).getFragmentManager()
.beginTransaction()
- .replace(R.id.status_bar_container, new CollapsedStatusBarFragment(),
+ .replace(R.id.status_bar_container,
+ new CollapsedStatusBarFragment(mOngoingCallController),
CollapsedStatusBarFragment.TAG)
.commit();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
index 4f32712e81fa2..785d98ccd8dc9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
@@ -90,6 +90,7 @@ import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.StatusBarNotificationActivityStarter;
import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager;
+import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -206,6 +207,7 @@ public interface StatusBarPhoneModule {
NotificationIconAreaController notificationIconAreaController,
BrightnessSlider.Factory brightnessSliderFactory,
WiredChargingRippleController chargingRippleAnimationController,
+ OngoingCallController ongoingCallController,
FeatureFlags featureFlags) {
return new StatusBar(
context,
@@ -288,6 +290,7 @@ public interface StatusBarPhoneModule {
notificationIconAreaController,
brightnessSliderFactory,
chargingRippleAnimationController,
+ ongoingCallController,
featureFlags);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
new file mode 100644
index 0000000000000..60d3ea3a70937
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2021 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.ongoingcall
+
+import android.app.Notification
+import android.app.Notification.CallStyle.CALL_TYPE_ONGOING
+import android.util.Log
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.FeatureFlags
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
+import javax.inject.Inject
+
+/**
+ * A controller to handle the ongoing call chip in the collapsed status bar.
+ */
+@SysUISingleton
+class OngoingCallController @Inject constructor(
+ private val notifCollection: CommonNotifCollection,
+ private val featureFlags: FeatureFlags
+) {
+
+ private val notifListener = object : NotifCollectionListener {
+ override fun onEntryUpdated(entry: NotificationEntry) {
+ if (isOngoingCallNotification(entry) && DEBUG) {
+ Log.d(TAG, "Ongoing call notification updated")
+ }
+ }
+
+ override fun onEntryRemoved(entry: NotificationEntry, reason: Int) {
+ if (isOngoingCallNotification(entry) && DEBUG) {
+ Log.d(TAG, "Ongoing call notification removed")
+ }
+ }
+ }
+
+ fun init() {
+ if (featureFlags.isOngoingCallStatusBarChipEnabled) {
+ notifCollection.addCollectionListener(notifListener)
+ }
+ }
+}
+
+private fun isOngoingCallNotification(entry: NotificationEntry): Boolean {
+ val extras = entry.sbn.notification.extras
+ val callStyleTemplateName = Notification.CallStyle::class.java.name
+ return extras.getString(Notification.EXTRA_TEMPLATE) == callStyleTemplateName &&
+ extras.getInt(Notification.EXTRA_CALL_TYPE, -1) == CALL_TYPE_ONGOING
+}
+
+private const val TAG = "OngoingCallController"
+private val DEBUG = Log.isLoggable(TAG, Log.DEBUG)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
index 781f875fd8682..96cdaf98d964b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
@@ -23,7 +23,10 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.when;
+import android.app.Fragment;
import android.app.StatusBarManager;
+import android.content.Context;
+import android.os.Bundle;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
import android.view.View;
@@ -34,6 +37,7 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.R;
import com.android.systemui.SysuiBaseFragmentTest;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
import org.junit.Before;
import org.junit.Test;
@@ -157,4 +161,9 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
Mockito.verify(mStatusBarStateController).isDozing();
Mockito.verify(mNotificationAreaInner, atLeast(1)).setVisibility(eq(View.VISIBLE));
}
+
+ @Override
+ protected Fragment instantiate(Context context, String className, Bundle arguments) {
+ return new CollapsedStatusBarFragment(mock(OngoingCallController.class));
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 781cde6c48b5a..2576d958b5fc3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -132,6 +132,7 @@ import com.android.systemui.statusbar.notification.stack.NotificationListContain
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
+import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -263,6 +264,7 @@ public class StatusBarTest extends SysuiTestCase {
@Mock private Lazy mNotificationShadeDepthControllerLazy;
@Mock private BrightnessSlider.Factory mBrightnessSliderFactory;
@Mock private WiredChargingRippleController mWiredChargingRippleController;
+ @Mock private OngoingCallController mOngoingCallController;
@Mock private FeatureFlags mFeatureFlags;
private ShadeController mShadeController;
private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
@@ -427,6 +429,7 @@ public class StatusBarTest extends SysuiTestCase {
mNotificationIconAreaController,
mBrightnessSliderFactory,
mWiredChargingRippleController,
+ mOngoingCallController,
mFeatureFlags);
when(mNotificationShadeWindowView.findViewById(R.id.lock_icon_container)).thenReturn(