Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a3cef0ce authored by Evan Laird's avatar Evan Laird
Browse files

[Sb refactor] Wifi demo mode

Test: WifiRepositorySwitcherTest
Bug: 238425913
Change-Id: Iea3d94f6543cd599f667b297edf9d5019e841067
parent 2775b3b3
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1302,7 +1302,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
            }
        }
        String wifi = args.getString("wifi");
        if (wifi != null) {
        if (wifi != null && !mStatusBarPipelineFlags.runNewWifiIconBackend()) {
            boolean show = wifi.equals("show");
            String level = args.getString("level");
            if (level != null) {
+43 −4
Original line number Diff line number Diff line
@@ -42,6 +42,8 @@ import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconStat
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernStatusBarMobileView;
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel;
import com.android.systemui.statusbar.pipeline.wifi.ui.view.ModernStatusBarWifiView;
import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.LocationBasedWifiViewModel;

import java.util.ArrayList;
import java.util.List;
@@ -56,6 +58,7 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
    private final int mIconSize;

    private StatusBarWifiView mWifiView;
    private ModernStatusBarWifiView mModernWifiView;
    private boolean mDemoMode;
    private int mColor;

@@ -236,14 +239,14 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da

    public void addDemoWifiView(WifiIconState state) {
        Log.d(TAG, "addDemoWifiView: ");
        // TODO(b/238425913): Migrate this view to {@code ModernStatusBarWifiView}.
        StatusBarWifiView view = StatusBarWifiView.fromContext(mContext, state.slot);

        int viewIndex = getChildCount();
        // If we have mobile views, put wifi before them
        for (int i = 0; i < getChildCount(); i++) {
            View child = getChildAt(i);
            if (child instanceof StatusBarMobileView) {
            if (child instanceof StatusBarMobileView
                    || child instanceof ModernStatusBarMobileView) {
                viewIndex = i;
                break;
            }
@@ -298,6 +301,30 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
        addView(view, getChildCount(), createLayoutParams());
    }

    /**
     * Add a {@link ModernStatusBarWifiView}
     */
    public void addModernWifiView(LocationBasedWifiViewModel viewModel) {
        Log.d(TAG, "addModernDemoWifiView: ");
        ModernStatusBarWifiView view = ModernStatusBarWifiView
                .constructAndBind(mContext, "wifi", viewModel);

        int viewIndex = getChildCount();
        // If we have mobile views, put wifi before them
        for (int i = 0; i < getChildCount(); i++) {
            View child = getChildAt(i);
            if (child instanceof StatusBarMobileView
                    || child instanceof ModernStatusBarMobileView) {
                viewIndex = i;
                break;
            }
        }

        mModernWifiView = view;
        mModernWifiView.setStaticDrawableColor(mColor);
        addView(view, viewIndex, createLayoutParams());
    }

    /**
     * Apply an update to a mobile icon view for the given {@link MobileIconState}. For
     * compatibility with {@link MobileContextProvider}, we have to recreate the view every time we
@@ -320,8 +347,14 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da

    public void onRemoveIcon(StatusIconDisplayable view) {
        if (view.getSlot().equals("wifi")) {
            if (view instanceof StatusBarWifiView) {
                removeView(mWifiView);
                mWifiView = null;
            } else if (view instanceof ModernStatusBarWifiView) {
                Log.d(TAG, "onRemoveIcon: removing modern wifi view");
                removeView(mModernWifiView);
                mModernWifiView = null;
            }
        } else if (view instanceof StatusBarMobileView) {
            StatusBarMobileView mobileView = matchingMobileView(view);
            if (mobileView != null) {
@@ -374,8 +407,14 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
        if (mWifiView != null) {
            mWifiView.onDarkChanged(areas, darkIntensity, tint);
        }
        if (mModernWifiView != null) {
            mModernWifiView.onDarkChanged(areas, darkIntensity, tint);
        }
        for (StatusBarMobileView view : mMobileViews) {
            view.onDarkChanged(areas, darkIntensity, tint);
        }
        for (ModernStatusBarMobileView view : mModernMobileViews) {
            view.onDarkChanged(areas, darkIntensity, tint);
        }
    }
}
+8 −0
Original line number Diff line number Diff line
@@ -497,6 +497,11 @@ public interface StatusBarIconController {

            ModernStatusBarWifiView view = onCreateModernStatusBarWifiView(slot);
            mGroup.addView(view, index, onCreateLayoutParams());

            if (mIsInDemoMode) {
                mDemoStatusIcons.addModernWifiView(mWifiViewModel);
            }

            return view;
        }

@@ -688,6 +693,9 @@ public interface StatusBarIconController {
            mIsInDemoMode = true;
            if (mDemoStatusIcons == null) {
                mDemoStatusIcons = createDemoStatusIcons();
                if (mStatusBarPipelineFlags.useNewWifiIcon()) {
                    mDemoStatusIcons.addModernWifiView(mWifiViewModel);
                }
            }
            mDemoStatusIcons.onDemoModeStarted();
        }
+2 −2
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@ import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxyIm
import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepository
import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepositoryImpl
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepositoryImpl
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepositorySwitcher
import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor
import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractorImpl
import dagger.Binds
@@ -56,7 +56,7 @@ abstract class StatusBarPipelineModule {
    @Binds
    abstract fun connectivityRepository(impl: ConnectivityRepositoryImpl): ConnectivityRepository

    @Binds abstract fun wifiRepository(impl: WifiRepositoryImpl): WifiRepository
    @Binds abstract fun wifiRepository(impl: WifiRepositorySwitcher): WifiRepository

    @Binds
    abstract fun wifiInteractor(impl: WifiInteractorImpl): WifiInteractor
+120 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.pipeline.wifi.data.repository

import android.os.Bundle
import androidx.annotation.VisibleForTesting
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.demomode.DemoMode
import com.android.systemui.demomode.DemoModeController
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel
import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoWifiRepository
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.stateIn

/**
 * Provides the [WifiRepository] interface either through the [DemoWifiRepository] implementation,
 * or the [WifiRepositoryImpl]'s prod implementation, based on the current demo mode value. In this
 * way, downstream clients can all consist of real implementations and not care about which
 * repository is responsible for the data. Graphically:
 *
 * ```
 * RealRepository
 *                 │
 *                 ├──►RepositorySwitcher──►RealInteractor──►RealViewModel
 *                 │
 * DemoRepository
 * ```
 *
 * When demo mode turns on, every flow will [flatMapLatest] to the current provider's version of
 * that flow.
 */
@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
@OptIn(ExperimentalCoroutinesApi::class)
class WifiRepositorySwitcher
@Inject
constructor(
    private val realImpl: WifiRepositoryImpl,
    private val demoImpl: DemoWifiRepository,
    private val demoModeController: DemoModeController,
    @Application scope: CoroutineScope,
) : WifiRepository {
    private val isDemoMode =
        conflatedCallbackFlow {
                val callback =
                    object : DemoMode {
                        override fun dispatchDemoCommand(command: String?, args: Bundle?) {
                            // Don't care
                        }

                        override fun onDemoModeStarted() {
                            demoImpl.startProcessingCommands()
                            trySend(true)
                        }

                        override fun onDemoModeFinished() {
                            demoImpl.stopProcessingCommands()
                            trySend(false)
                        }
                    }

                demoModeController.addCallback(callback)
                awaitClose { demoModeController.removeCallback(callback) }
            }
            .stateIn(scope, SharingStarted.WhileSubscribed(), demoModeController.isInDemoMode)

    @VisibleForTesting
    val activeRepo =
        isDemoMode
            .mapLatest { isDemoMode ->
                if (isDemoMode) {
                    demoImpl
                } else {
                    realImpl
                }
            }
            .stateIn(scope, SharingStarted.WhileSubscribed(), realImpl)

    override val isWifiEnabled: StateFlow<Boolean> =
        activeRepo
            .flatMapLatest { it.isWifiEnabled }
            .stateIn(scope, SharingStarted.WhileSubscribed(), realImpl.isWifiEnabled.value)

    override val isWifiDefault: StateFlow<Boolean> =
        activeRepo
            .flatMapLatest { it.isWifiDefault }
            .stateIn(scope, SharingStarted.WhileSubscribed(), realImpl.isWifiDefault.value)

    override val wifiNetwork: StateFlow<WifiNetworkModel> =
        activeRepo
            .flatMapLatest { it.wifiNetwork }
            .stateIn(scope, SharingStarted.WhileSubscribed(), realImpl.wifiNetwork.value)

    override val wifiActivity: StateFlow<DataActivityModel> =
        activeRepo
            .flatMapLatest { it.wifiActivity }
            .stateIn(scope, SharingStarted.WhileSubscribed(), realImpl.wifiActivity.value)
}
Loading