Add a status bar to dream overlay.
This change adds a status bar (with battery and wifi icons) to dream overlays. Test: atest DreamOverlayStatusBarViewControllerTest, atest DreamOverlayServiceTest Bug: 207681288 Change-Id: I32b1fc452364fb7d072bb2d84fd205e31909b642
This commit is contained in:
24
packages/SystemUI/res/drawable/ic_signal_wifi_off.xml
Normal file
24
packages/SystemUI/res/drawable/ic_signal_wifi_off.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<!--
|
||||
~ 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.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M18.575,15.2L7.55,4.175q1.1,-0.325 2.212,-0.462 1.113,-0.138 2.238,-0.138 3.45,0 6.55,1.45Q21.65,6.475 24,9zM20.225,23.575l-4.75,-4.75 -3.475,4.1L0,9q0.675,-0.725 1.438,-1.4 0.762,-0.675 1.612,-1.225l-2.625,-2.6L2.1,2.1l19.8,19.8z"/>
|
||||
</vector>
|
||||
61
packages/SystemUI/res/layout/dream_overlay_container.xml
Normal file
61
packages/SystemUI/res/layout/dream_overlay_container.xml
Normal file
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ 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.
|
||||
-->
|
||||
<com.android.systemui.dreams.DreamOverlayContainerView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/dream_overlay_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/dream_overlay_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
<com.android.systemui.dreams.DreamOverlayStatusBarView
|
||||
android:id="@+id/dream_overlay_status_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/dream_overlay_status_bar_height"
|
||||
android:layout_marginEnd="@dimen/dream_overlay_status_bar_margin"
|
||||
android:layout_marginStart="@dimen/dream_overlay_status_bar_margin"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/dream_overlay_system_status"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_constraintEnd_toEndOf="parent">
|
||||
|
||||
<com.android.systemui.statusbar.AlphaOptimizedImageView
|
||||
android:id="@+id/dream_overlay_wifi_status"
|
||||
android:layout_width="@dimen/status_bar_wifi_signal_size"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginEnd="@dimen/dream_overlay_status_icon_margin"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toStartOf="@id/dream_overlay_battery" />
|
||||
|
||||
<com.android.systemui.battery.BatteryMeterView
|
||||
android:id="@+id/dream_overlay_battery"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</com.android.systemui.dreams.DreamOverlayStatusBarView>
|
||||
</com.android.systemui.dreams.DreamOverlayContainerView>
|
||||
@@ -1303,4 +1303,9 @@
|
||||
<dimen name="keyguard_unfold_translation_x">16dp</dimen>
|
||||
|
||||
<dimen name="fgs_manager_min_width_minor">100%</dimen>
|
||||
|
||||
<!-- Dream overlay related dimensions -->
|
||||
<dimen name="dream_overlay_status_bar_height">80dp</dimen>
|
||||
<dimen name="dream_overlay_status_bar_margin">40dp</dimen>
|
||||
<dimen name="dream_overlay_status_icon_margin">8dp</dimen>
|
||||
</resources>
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.dreams;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
|
||||
/**
|
||||
* {@link DreamOverlayContainerView} contains a dream overlay and its status bar.
|
||||
*/
|
||||
public class DreamOverlayContainerView extends ConstraintLayout {
|
||||
public DreamOverlayContainerView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public DreamOverlayContainerView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public DreamOverlayContainerView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
this(context, attrs, defStyleAttr, 0);
|
||||
}
|
||||
|
||||
public DreamOverlayContainerView(
|
||||
Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
}
|
||||
@@ -29,11 +29,11 @@ import android.view.WindowInsets;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.policy.PhoneWindow;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.dreams.dagger.DreamOverlayComponent;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
@@ -54,10 +54,12 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
|
||||
private final Executor mExecutor;
|
||||
// The state controller informs the service of updates to the overlays present.
|
||||
private final DreamOverlayStateController mStateController;
|
||||
// The component used to resolve dream overlay dependencies.
|
||||
private final DreamOverlayComponent mDreamOverlayComponent;
|
||||
|
||||
// The window is populated once the dream informs the service it has begun dreaming.
|
||||
private Window mWindow;
|
||||
private ConstraintLayout mLayout;
|
||||
// The dream overlay's content view, which is located below the status bar (in z-order) and is
|
||||
// the space into which widgets are placed.
|
||||
private ViewGroup mDreamOverlayContentView;
|
||||
|
||||
private final DreamOverlayStateController.Callback mOverlayStateCallback =
|
||||
new DreamOverlayStateController.Callback() {
|
||||
@@ -90,12 +92,12 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
|
||||
new ViewTreeObserver.OnComputeInternalInsetsListener() {
|
||||
@Override
|
||||
public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo inoutInfo) {
|
||||
if (mLayout != null) {
|
||||
if (mDreamOverlayContentView != null) {
|
||||
inoutInfo.setTouchableInsets(
|
||||
ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
|
||||
final Region region = new Region();
|
||||
for (int i = 0; i < mLayout.getChildCount(); i++) {
|
||||
View child = mLayout.getChildAt(i);
|
||||
for (int i = 0; i < mDreamOverlayContentView.getChildCount(); i++) {
|
||||
View child = mDreamOverlayContentView.getChildAt(i);
|
||||
final Rect rect = new Rect();
|
||||
child.getGlobalVisibleRect(rect);
|
||||
region.op(rect, Region.Op.UNION);
|
||||
@@ -106,16 +108,30 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
|
||||
}
|
||||
};
|
||||
|
||||
@Inject
|
||||
public DreamOverlayService(
|
||||
Context context,
|
||||
@Main Executor executor,
|
||||
DreamOverlayStateController overlayStateController,
|
||||
DreamOverlayComponent.Factory dreamOverlayComponentFactory) {
|
||||
mContext = context;
|
||||
mExecutor = executor;
|
||||
mStateController = overlayStateController;
|
||||
mDreamOverlayComponent = dreamOverlayComponentFactory.create();
|
||||
|
||||
mStateController.addCallback(mOverlayStateCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartDream(@NonNull WindowManager.LayoutParams layoutParams) {
|
||||
mExecutor.execute(() -> addOverlayWindowLocked(layoutParams));
|
||||
}
|
||||
|
||||
private void reloadOverlaysLocked() {
|
||||
if (mLayout == null) {
|
||||
if (mDreamOverlayContentView == null) {
|
||||
return;
|
||||
}
|
||||
mLayout.removeAllViews();
|
||||
mDreamOverlayContentView.removeAllViews();
|
||||
for (OverlayProvider overlayProvider : mStateController.getOverlays()) {
|
||||
addOverlay(overlayProvider);
|
||||
}
|
||||
@@ -129,31 +145,30 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
|
||||
* into the dream window.
|
||||
*/
|
||||
private void addOverlayWindowLocked(WindowManager.LayoutParams layoutParams) {
|
||||
mWindow = new PhoneWindow(mContext);
|
||||
mWindow.setAttributes(layoutParams);
|
||||
mWindow.setWindowManager(null, layoutParams.token, "DreamOverlay", true);
|
||||
final PhoneWindow window = new PhoneWindow(mContext);
|
||||
window.setAttributes(layoutParams);
|
||||
window.setWindowManager(null, layoutParams.token, "DreamOverlay", true);
|
||||
|
||||
mWindow.setBackgroundDrawable(new ColorDrawable(0));
|
||||
window.setBackgroundDrawable(new ColorDrawable(0));
|
||||
|
||||
mWindow.clearFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
|
||||
mWindow.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
|
||||
mWindow.requestFeature(Window.FEATURE_NO_TITLE);
|
||||
window.clearFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
|
||||
window.requestFeature(Window.FEATURE_NO_TITLE);
|
||||
// Hide all insets when the dream is showing
|
||||
mWindow.getDecorView().getWindowInsetsController().hide(WindowInsets.Type.systemBars());
|
||||
mWindow.setDecorFitsSystemWindows(false);
|
||||
window.getDecorView().getWindowInsetsController().hide(WindowInsets.Type.systemBars());
|
||||
window.setDecorFitsSystemWindows(false);
|
||||
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "adding overlay window to dream");
|
||||
}
|
||||
|
||||
mLayout = new ConstraintLayout(mContext);
|
||||
mLayout.setLayoutParams(new ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
mLayout.addOnAttachStateChangeListener(mRootViewAttachListener);
|
||||
mWindow.setContentView(mLayout);
|
||||
window.setContentView(mDreamOverlayComponent.getDreamOverlayContainerView());
|
||||
mDreamOverlayContentView = mDreamOverlayComponent.getDreamOverlayContentView();
|
||||
|
||||
mDreamOverlayComponent.getDreamOverlayStatusBarViewController().init();
|
||||
|
||||
final WindowManager windowManager = mContext.getSystemService(WindowManager.class);
|
||||
windowManager.addView(mWindow.getDecorView(), mWindow.getAttributes());
|
||||
windowManager.addView(window.getDecorView(), window.getAttributes());
|
||||
mExecutor.execute(this::reloadOverlaysLocked);
|
||||
}
|
||||
|
||||
@@ -163,11 +178,11 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
|
||||
(view, layoutParams) -> {
|
||||
// Always move UI related work to the main thread.
|
||||
mExecutor.execute(() -> {
|
||||
if (mLayout == null) {
|
||||
if (mDreamOverlayContentView == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
mLayout.addView(view, layoutParams);
|
||||
mDreamOverlayContentView.addView(view, layoutParams);
|
||||
});
|
||||
},
|
||||
() -> {
|
||||
@@ -178,15 +193,6 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
|
||||
});
|
||||
}
|
||||
|
||||
@Inject
|
||||
public DreamOverlayService(Context context, @Main Executor executor,
|
||||
DreamOverlayStateController overlayStateController) {
|
||||
mContext = context;
|
||||
mExecutor = executor;
|
||||
mStateController = overlayStateController;
|
||||
mStateController.addCallback(mOverlayStateCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
mStateController.removeCallback(mOverlayStateCallback);
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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.dreams;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.battery.BatteryMeterView;
|
||||
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
|
||||
|
||||
/**
|
||||
* {@link DreamOverlayStatusBarView} is the view responsible for displaying the status bar in a
|
||||
* dream. The status bar includes status icons such as battery and wifi.
|
||||
*/
|
||||
public class DreamOverlayStatusBarView extends ConstraintLayout implements
|
||||
BatteryStateChangeCallback {
|
||||
|
||||
private BatteryMeterView mBatteryView;
|
||||
private ImageView mWifiStatusView;
|
||||
|
||||
public DreamOverlayStatusBarView(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public DreamOverlayStatusBarView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public DreamOverlayStatusBarView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
this(context, attrs, defStyleAttr, 0);
|
||||
}
|
||||
|
||||
public DreamOverlayStatusBarView(
|
||||
Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
|
||||
mBatteryView = Preconditions.checkNotNull(findViewById(R.id.dream_overlay_battery),
|
||||
"R.id.dream_overlay_battery must not be null");
|
||||
mWifiStatusView = Preconditions.checkNotNull(findViewById(R.id.dream_overlay_wifi_status),
|
||||
"R.id.dream_overlay_wifi_status must not be null");
|
||||
|
||||
mWifiStatusView.setImageDrawable(getContext().getDrawable(R.drawable.ic_signal_wifi_off));
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to show the battery percent text next to the battery status icons.
|
||||
* @param show True if the battery percent text should be shown.
|
||||
*/
|
||||
void showBatteryPercentText(boolean show) {
|
||||
mBatteryView.setForceShowPercent(show);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to show the wifi status icon.
|
||||
* @param show True if the wifi status icon should be shown.
|
||||
*/
|
||||
void showWifiStatus(boolean show) {
|
||||
// Only show the wifi status icon when wifi isn't available.
|
||||
mWifiStatusView.setVisibility(show ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* 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.dreams;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.ConnectivityManager.NetworkCallback;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.net.NetworkRequest;
|
||||
|
||||
import com.android.systemui.battery.BatteryMeterViewController;
|
||||
import com.android.systemui.dreams.dagger.DreamOverlayComponent;
|
||||
import com.android.systemui.dreams.dagger.DreamOverlayModule;
|
||||
import com.android.systemui.statusbar.policy.BatteryController;
|
||||
import com.android.systemui.util.ViewController;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
/**
|
||||
* View controller for {@link DreamOverlayStatusBarView}.
|
||||
*/
|
||||
@DreamOverlayComponent.DreamOverlayScope
|
||||
public class DreamOverlayStatusBarViewController extends ViewController<DreamOverlayStatusBarView> {
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef(prefix = { "WIFI_STATUS_" }, value = {
|
||||
WIFI_STATUS_UNKNOWN,
|
||||
WIFI_STATUS_UNAVAILABLE,
|
||||
WIFI_STATUS_AVAILABLE
|
||||
})
|
||||
private @interface WifiStatus {}
|
||||
private static final int WIFI_STATUS_UNKNOWN = 0;
|
||||
private static final int WIFI_STATUS_UNAVAILABLE = 1;
|
||||
private static final int WIFI_STATUS_AVAILABLE = 2;
|
||||
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef(prefix = { "BATTERY_STATUS_" }, value = {
|
||||
BATTERY_STATUS_UNKNOWN,
|
||||
BATTERY_STATUS_NOT_CHARGING,
|
||||
BATTERY_STATUS_CHARGING
|
||||
})
|
||||
private @interface BatteryStatus {}
|
||||
private static final int BATTERY_STATUS_UNKNOWN = 0;
|
||||
private static final int BATTERY_STATUS_NOT_CHARGING = 1;
|
||||
private static final int BATTERY_STATUS_CHARGING = 2;
|
||||
|
||||
private final BatteryController mBatteryController;
|
||||
private final BatteryMeterViewController mBatteryMeterViewController;
|
||||
private final ConnectivityManager mConnectivityManager;
|
||||
private final boolean mShowPercentAvailable;
|
||||
|
||||
private final NetworkRequest mNetworkRequest = new NetworkRequest.Builder()
|
||||
.clearCapabilities()
|
||||
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI).build();
|
||||
|
||||
private final NetworkCallback mNetworkCallback = new NetworkCallback() {
|
||||
@Override
|
||||
public void onCapabilitiesChanged(
|
||||
Network network, NetworkCapabilities networkCapabilities) {
|
||||
onWifiAvailabilityChanged(
|
||||
networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAvailable(Network network) {
|
||||
onWifiAvailabilityChanged(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLost(Network network) {
|
||||
onWifiAvailabilityChanged(false);
|
||||
}
|
||||
};
|
||||
|
||||
private final BatteryController.BatteryStateChangeCallback mBatteryStateChangeCallback =
|
||||
new BatteryController.BatteryStateChangeCallback() {
|
||||
@Override
|
||||
public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
|
||||
DreamOverlayStatusBarViewController.this.onBatteryLevelChanged(charging);
|
||||
}
|
||||
};
|
||||
|
||||
private @WifiStatus int mWifiStatus = WIFI_STATUS_UNKNOWN;
|
||||
private @BatteryStatus int mBatteryStatus = BATTERY_STATUS_UNKNOWN;
|
||||
|
||||
@Inject
|
||||
public DreamOverlayStatusBarViewController(
|
||||
Context context,
|
||||
DreamOverlayStatusBarView view,
|
||||
BatteryController batteryController,
|
||||
@Named(DreamOverlayModule.DREAM_OVERLAY_BATTERY_CONTROLLER)
|
||||
BatteryMeterViewController batteryMeterViewController,
|
||||
ConnectivityManager connectivityManager) {
|
||||
super(view);
|
||||
mBatteryController = batteryController;
|
||||
mBatteryMeterViewController = batteryMeterViewController;
|
||||
mConnectivityManager = connectivityManager;
|
||||
|
||||
mShowPercentAvailable = context.getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_battery_percentage_setting_available);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInit() {
|
||||
super.onInit();
|
||||
mBatteryMeterViewController.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onViewAttached() {
|
||||
mBatteryController.addCallback(mBatteryStateChangeCallback);
|
||||
mConnectivityManager.registerNetworkCallback(mNetworkRequest, mNetworkCallback);
|
||||
|
||||
NetworkCapabilities capabilities =
|
||||
mConnectivityManager.getNetworkCapabilities(
|
||||
mConnectivityManager.getActiveNetwork());
|
||||
onWifiAvailabilityChanged(
|
||||
capabilities != null
|
||||
&& capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onViewDetached() {
|
||||
mBatteryController.removeCallback(mBatteryStateChangeCallback);
|
||||
mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wifi availability has changed. Update the wifi status icon as appropriate.
|
||||
* @param available Whether wifi is available.
|
||||
*/
|
||||
private void onWifiAvailabilityChanged(boolean available) {
|
||||
final int newWifiStatus = available ? WIFI_STATUS_AVAILABLE : WIFI_STATUS_UNAVAILABLE;
|
||||
if (mWifiStatus != newWifiStatus) {
|
||||
mWifiStatus = newWifiStatus;
|
||||
mView.showWifiStatus(mWifiStatus == WIFI_STATUS_UNAVAILABLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The battery level has changed. Update the battery status icon as appropriate.
|
||||
* @param charging Whether the battery is currently charging.
|
||||
*/
|
||||
private void onBatteryLevelChanged(boolean charging) {
|
||||
final int newBatteryStatus =
|
||||
charging ? BATTERY_STATUS_CHARGING : BATTERY_STATUS_NOT_CHARGING;
|
||||
if (mBatteryStatus != newBatteryStatus) {
|
||||
mBatteryStatus = newBatteryStatus;
|
||||
mView.showBatteryPercentText(
|
||||
mBatteryStatus == BATTERY_STATUS_CHARGING && mShowPercentAvailable);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,8 +21,6 @@ import dagger.Module;
|
||||
/**
|
||||
* Dagger Module providing Communal-related functionality.
|
||||
*/
|
||||
@Module(subcomponents = {
|
||||
AppWidgetOverlayComponent.class,
|
||||
})
|
||||
@Module(subcomponents = {AppWidgetOverlayComponent.class, DreamOverlayComponent.class})
|
||||
public interface DreamModule {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.dreams.dagger;
|
||||
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.android.systemui.dreams.DreamOverlayContainerView;
|
||||
import com.android.systemui.dreams.DreamOverlayStatusBarViewController;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
|
||||
import javax.inject.Scope;
|
||||
|
||||
import dagger.Subcomponent;
|
||||
|
||||
/**
|
||||
* Dagger subcomponent for {@link DreamOverlayModule}.
|
||||
*/
|
||||
@Subcomponent(modules = {DreamOverlayModule.class})
|
||||
@DreamOverlayComponent.DreamOverlayScope
|
||||
public interface DreamOverlayComponent {
|
||||
/** Simple factory for {@link DreamOverlayComponent}. */
|
||||
@Subcomponent.Factory
|
||||
interface Factory {
|
||||
DreamOverlayComponent create();
|
||||
}
|
||||
|
||||
/** Scope annotation for singleton items within the {@link DreamOverlayComponent}. */
|
||||
@Documented
|
||||
@Retention(RUNTIME)
|
||||
@Scope
|
||||
@interface DreamOverlayScope {}
|
||||
|
||||
/** Builds a {@link DreamOverlayContainerView} */
|
||||
@DreamOverlayScope
|
||||
DreamOverlayContainerView getDreamOverlayContainerView();
|
||||
|
||||
/** Builds a content view for dream overlays */
|
||||
@DreamOverlayScope
|
||||
ViewGroup getDreamOverlayContentView();
|
||||
|
||||
/** Builds a {@link DreamOverlayStatusBarViewController}. */
|
||||
@DreamOverlayScope
|
||||
DreamOverlayStatusBarViewController getDreamOverlayStatusBarViewController();
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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.dreams.dagger;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.os.Handler;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.battery.BatteryMeterView;
|
||||
import com.android.systemui.battery.BatteryMeterViewController;
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.dreams.DreamOverlayContainerView;
|
||||
import com.android.systemui.dreams.DreamOverlayStatusBarView;
|
||||
import com.android.systemui.statusbar.policy.BatteryController;
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||
import com.android.systemui.tuner.TunerService;
|
||||
|
||||
import javax.inject.Named;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
||||
/** Dagger module for {@link DreamOverlayComponent}. */
|
||||
@Module
|
||||
public abstract class DreamOverlayModule {
|
||||
private static final String DREAM_OVERLAY_BATTERY_VIEW = "dream_overlay_battery_view";
|
||||
public static final String DREAM_OVERLAY_BATTERY_CONTROLLER =
|
||||
"dream_overlay_battery_controller";
|
||||
|
||||
/** */
|
||||
@Provides
|
||||
@DreamOverlayComponent.DreamOverlayScope
|
||||
public static DreamOverlayContainerView providesDreamOverlayContainerView(
|
||||
LayoutInflater layoutInflater) {
|
||||
return Preconditions.checkNotNull((DreamOverlayContainerView)
|
||||
layoutInflater.inflate(R.layout.dream_overlay_container, null),
|
||||
"R.layout.dream_layout_container could not be properly inflated");
|
||||
}
|
||||
|
||||
/** */
|
||||
@Provides
|
||||
@DreamOverlayComponent.DreamOverlayScope
|
||||
public static ViewGroup providesDreamOverlayContentView(DreamOverlayContainerView view) {
|
||||
return Preconditions.checkNotNull(view.findViewById(R.id.dream_overlay_content),
|
||||
"R.id.dream_overlay_content must not be null");
|
||||
}
|
||||
|
||||
/** */
|
||||
@Provides
|
||||
@DreamOverlayComponent.DreamOverlayScope
|
||||
public static DreamOverlayStatusBarView providesDreamOverlayStatusBarView(
|
||||
DreamOverlayContainerView view) {
|
||||
return Preconditions.checkNotNull(view.findViewById(R.id.dream_overlay_status_bar),
|
||||
"R.id.status_bar must not be null");
|
||||
}
|
||||
|
||||
/** */
|
||||
@Provides
|
||||
@DreamOverlayComponent.DreamOverlayScope
|
||||
@Named(DREAM_OVERLAY_BATTERY_VIEW)
|
||||
static BatteryMeterView providesBatteryMeterView(DreamOverlayContainerView view) {
|
||||
return Preconditions.checkNotNull(view.findViewById(R.id.dream_overlay_battery),
|
||||
"R.id.battery must not be null");
|
||||
}
|
||||
|
||||
/** */
|
||||
@Provides
|
||||
@DreamOverlayComponent.DreamOverlayScope
|
||||
@Named(DREAM_OVERLAY_BATTERY_CONTROLLER)
|
||||
static BatteryMeterViewController providesBatteryMeterViewController(
|
||||
@Named(DREAM_OVERLAY_BATTERY_VIEW) BatteryMeterView batteryMeterView,
|
||||
ConfigurationController configurationController,
|
||||
TunerService tunerService,
|
||||
BroadcastDispatcher broadcastDispatcher,
|
||||
@Main Handler mainHandler,
|
||||
ContentResolver contentResolver,
|
||||
BatteryController batteryController) {
|
||||
return new BatteryMeterViewController(
|
||||
batteryMeterView,
|
||||
configurationController,
|
||||
tunerService,
|
||||
broadcastDispatcher,
|
||||
mainHandler,
|
||||
contentResolver,
|
||||
batteryController);
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,7 @@ import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.SysuiTestableContext;
|
||||
import com.android.systemui.dreams.dagger.DreamOverlayComponent;
|
||||
import com.android.systemui.util.concurrency.FakeExecutor;
|
||||
import com.android.systemui.util.time.FakeSystemClock;
|
||||
import com.android.systemui.utils.leaks.LeakCheckedTest;
|
||||
@@ -78,16 +79,41 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
|
||||
@Mock
|
||||
DreamOverlayStateController mDreamOverlayStateController;
|
||||
|
||||
@Mock
|
||||
DreamOverlayComponent.Factory mDreamOverlayStatusBarViewComponentFactory;
|
||||
|
||||
@Mock
|
||||
DreamOverlayComponent mDreamOverlayComponent;
|
||||
|
||||
@Mock
|
||||
DreamOverlayStatusBarViewController mDreamOverlayStatusBarViewController;
|
||||
|
||||
@Mock
|
||||
DreamOverlayContainerView mDreamOverlayContainerView;
|
||||
|
||||
@Mock
|
||||
ViewGroup mDreamOverlayContentView;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext.addMockSystemService(WindowManager.class, mWindowManager);
|
||||
|
||||
when(mDreamOverlayComponent.getDreamOverlayContentView())
|
||||
.thenReturn(mDreamOverlayContentView);
|
||||
when(mDreamOverlayComponent.getDreamOverlayContainerView())
|
||||
.thenReturn(mDreamOverlayContainerView);
|
||||
when(mDreamOverlayComponent.getDreamOverlayStatusBarViewController())
|
||||
.thenReturn(mDreamOverlayStatusBarViewController);
|
||||
when(mDreamOverlayStatusBarViewComponentFactory.create())
|
||||
.thenReturn(mDreamOverlayComponent);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInteraction() throws Exception {
|
||||
final DreamOverlayService service = new DreamOverlayService(mContext, mMainExecutor,
|
||||
mDreamOverlayStateController);
|
||||
mDreamOverlayStateController, mDreamOverlayStatusBarViewComponentFactory);
|
||||
final IBinder proxy = service.onBind(new Intent());
|
||||
final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
|
||||
clearInvocations(mWindowManager);
|
||||
@@ -128,7 +154,7 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
|
||||
@Test
|
||||
public void testListening() throws Exception {
|
||||
final DreamOverlayService service = new DreamOverlayService(mContext, mMainExecutor,
|
||||
mDreamOverlayStateController);
|
||||
mDreamOverlayStateController, mDreamOverlayStatusBarViewComponentFactory);
|
||||
|
||||
final IBinder proxy = service.onBind(new Intent());
|
||||
final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
|
||||
@@ -150,4 +176,19 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
|
||||
// Verify provider is asked to create overlay.
|
||||
verify(mProvider).onCreateOverlay(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDreamOverlayStatusBarViewControllerInitialized() throws Exception {
|
||||
final DreamOverlayService service = new DreamOverlayService(mContext, mMainExecutor,
|
||||
mDreamOverlayStateController, mDreamOverlayStatusBarViewComponentFactory);
|
||||
|
||||
final IBinder proxy = service.onBind(new Intent());
|
||||
final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
|
||||
|
||||
// Inform the overlay service of dream starting.
|
||||
overlay.startDream(mWindowParams, mDreamOverlayCallback);
|
||||
mMainExecutor.runAllReady();
|
||||
|
||||
verify(mDreamOverlayStatusBarViewController).init();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* 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.dreams;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.net.NetworkRequest;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.battery.BatteryMeterViewController;
|
||||
import com.android.systemui.statusbar.policy.BatteryController;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase {
|
||||
|
||||
@Mock
|
||||
DreamOverlayStatusBarView mView;
|
||||
@Mock
|
||||
BatteryController mBatteryController;
|
||||
@Mock
|
||||
BatteryMeterViewController mBatteryMeterViewController;
|
||||
@Mock
|
||||
ConnectivityManager mConnectivityManager;
|
||||
@Mock
|
||||
NetworkCapabilities mNetworkCapabilities;
|
||||
@Mock
|
||||
Network mNetwork;
|
||||
|
||||
DreamOverlayStatusBarViewController mController;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mController = new DreamOverlayStatusBarViewController(
|
||||
mContext, mView, mBatteryController, mBatteryMeterViewController,
|
||||
mConnectivityManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnInitInitializesControllers() {
|
||||
mController.onInit();
|
||||
verify(mBatteryMeterViewController).init();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnViewAttachedAddsBatteryControllerCallback() {
|
||||
mController.onViewAttached();
|
||||
verify(mBatteryController)
|
||||
.addCallback(any(BatteryController.BatteryStateChangeCallback.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnViewAttachedRegistersNetworkCallback() {
|
||||
mController.onViewAttached();
|
||||
verify(mConnectivityManager)
|
||||
.registerNetworkCallback(any(NetworkRequest.class), any(
|
||||
ConnectivityManager.NetworkCallback.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnViewAttachedShowsWifiStatusWhenWifiUnavailable() {
|
||||
when(mNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
|
||||
.thenReturn(false);
|
||||
when(mConnectivityManager.getNetworkCapabilities(any())).thenReturn(mNetworkCapabilities);
|
||||
mController.onViewAttached();
|
||||
verify(mView).showWifiStatus(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnViewAttachedHidesWifiStatusWhenWifiAvailable() {
|
||||
when(mNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
|
||||
.thenReturn(true);
|
||||
when(mConnectivityManager.getNetworkCapabilities(any())).thenReturn(mNetworkCapabilities);
|
||||
mController.onViewAttached();
|
||||
verify(mView).showWifiStatus(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnViewAttachedShowsWifiStatusWhenNetworkCapabilitiesUnavailable() {
|
||||
when(mConnectivityManager.getNetworkCapabilities(any())).thenReturn(null);
|
||||
mController.onViewAttached();
|
||||
verify(mView).showWifiStatus(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnViewDetachedRemovesBatteryControllerCallback() {
|
||||
mController.onViewDetached();
|
||||
verify(mBatteryController)
|
||||
.removeCallback(any(BatteryController.BatteryStateChangeCallback.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnViewDetachedUnregistersNetworkCallback() {
|
||||
mController.onViewDetached();
|
||||
verify(mConnectivityManager)
|
||||
.unregisterNetworkCallback(any(ConnectivityManager.NetworkCallback.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBatteryPercentTextShownWhenBatteryLevelChangesWhileCharging() {
|
||||
final ArgumentCaptor<BatteryController.BatteryStateChangeCallback> callbackCapture =
|
||||
ArgumentCaptor.forClass(BatteryController.BatteryStateChangeCallback.class);
|
||||
mController.onViewAttached();
|
||||
verify(mBatteryController).addCallback(callbackCapture.capture());
|
||||
callbackCapture.getValue().onBatteryLevelChanged(1, true, true);
|
||||
verify(mView).showBatteryPercentText(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBatteryPercentTextHiddenWhenBatteryLevelChangesWhileNotCharging() {
|
||||
final ArgumentCaptor<BatteryController.BatteryStateChangeCallback> callbackCapture =
|
||||
ArgumentCaptor.forClass(BatteryController.BatteryStateChangeCallback.class);
|
||||
mController.onViewAttached();
|
||||
verify(mBatteryController).addCallback(callbackCapture.capture());
|
||||
callbackCapture.getValue().onBatteryLevelChanged(1, true, false);
|
||||
verify(mView).showBatteryPercentText(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWifiStatusHiddenWhenWifiBecomesAvailable() {
|
||||
// Make sure wifi starts out unavailable when onViewAttached is called.
|
||||
when(mNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
|
||||
.thenReturn(false);
|
||||
when(mConnectivityManager.getNetworkCapabilities(any())).thenReturn(mNetworkCapabilities);
|
||||
mController.onViewAttached();
|
||||
|
||||
final ArgumentCaptor<ConnectivityManager.NetworkCallback> callbackCapture =
|
||||
ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
|
||||
verify(mConnectivityManager).registerNetworkCallback(any(), callbackCapture.capture());
|
||||
callbackCapture.getValue().onAvailable(mNetwork);
|
||||
verify(mView).showWifiStatus(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWifiStatusShownWhenWifiBecomesUnavailable() {
|
||||
// Make sure wifi starts out available when onViewAttached is called.
|
||||
when(mNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
|
||||
.thenReturn(true);
|
||||
when(mConnectivityManager.getNetworkCapabilities(any())).thenReturn(mNetworkCapabilities);
|
||||
mController.onViewAttached();
|
||||
|
||||
final ArgumentCaptor<ConnectivityManager.NetworkCallback> callbackCapture =
|
||||
ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
|
||||
verify(mConnectivityManager).registerNetworkCallback(any(), callbackCapture.capture());
|
||||
callbackCapture.getValue().onLost(mNetwork);
|
||||
verify(mView).showWifiStatus(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWifiStatusHiddenWhenCapabilitiesChange() {
|
||||
// Make sure wifi starts out unavailable when onViewAttached is called.
|
||||
when(mNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
|
||||
.thenReturn(false);
|
||||
when(mConnectivityManager.getNetworkCapabilities(any())).thenReturn(mNetworkCapabilities);
|
||||
mController.onViewAttached();
|
||||
|
||||
final ArgumentCaptor<ConnectivityManager.NetworkCallback> callbackCapture =
|
||||
ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
|
||||
verify(mConnectivityManager).registerNetworkCallback(any(), callbackCapture.capture());
|
||||
when(mNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
|
||||
.thenReturn(true);
|
||||
callbackCapture.getValue().onCapabilitiesChanged(mNetwork, mNetworkCapabilities);
|
||||
verify(mView).showWifiStatus(false);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user