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

Commit eb5e807b authored by Caitlin Shkuratov's avatar Caitlin Shkuratov
Browse files

[SB][Sat] Update carrier text to display device-based satellite info.

Fixes: 333092296
Test: atest DeviceBasedSatelliteViewModelTest CarrierTextManagerTest
Test: manual: use satellite SOS, connect successfully -> see "Connected
to satellite" as the carrier text in shade and keyguard
Test: manual: use satellite SOS, have a connection failure -> see "Not
connected to satellite" as the carrier text in shade and keyguard
Flag: ACONFIG com.android.internal.telephony.flags.oem_enabled_satellite_flag NEXTFOOD

Change-Id: Id2025d65a17cdb2bcec3cd46acfbbbf6000d9dd5
parent 144bae3f
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -1716,6 +1716,11 @@
    <!-- Accessibility label for available satellite connection [CHAR LIMIT=NONE] -->
    <string name="accessibility_status_bar_satellite_available">Satellite, connection available</string>

    <!-- Text displayed indicating that the user is connected to a satellite signal. -->
    <string name="satellite_connected_carrier_text">Connected to satellite</string>
    <!-- Text displayed indicating that the user is not connected to a satellite signal. -->
    <string name="satellite_not_connected_carrier_text">Not connected to satellite</string>

    <!-- Accessibility label for managed profile icon (not shown on screen) [CHAR LIMIT=NONE] -->
    <string name="accessibility_managed_profile">Work profile</string>

+62 −3
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.keyguard;
import static com.android.keyguard.logging.CarrierTextManagerLogger.REASON_ACTIVE_DATA_SUB_CHANGED;
import static com.android.keyguard.logging.CarrierTextManagerLogger.REASON_ON_TELEPHONY_CAPABLE;
import static com.android.keyguard.logging.CarrierTextManagerLogger.REASON_REFRESH_CARRIER_INFO;
import static com.android.keyguard.logging.CarrierTextManagerLogger.REASON_SATELLITE_CHANGED;
import static com.android.keyguard.logging.CarrierTextManagerLogger.REASON_SIM_ERROR_STATE_CHANGED;

import android.content.Context;
@@ -43,17 +44,22 @@ import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.res.R;
import com.android.systemui.statusbar.pipeline.satellite.ui.viewmodel.DeviceBasedSatelliteViewModel;
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository;
import com.android.systemui.telephony.TelephonyListenerManager;
import com.android.systemui.util.kotlin.JavaAdapter;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CancellationException;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.inject.Inject;

import kotlinx.coroutines.Job;

/**
 * Controller that generates text including the carrier names and/or the status of all the SIM
 * interfaces in the device. Through a callback, the updates can be retrieved either as a list or
@@ -77,10 +83,17 @@ public class CarrierTextManager {
    protected KeyguardUpdateMonitor mKeyguardUpdateMonitor;
    private final CarrierTextManagerLogger mLogger;
    private final WifiRepository mWifiRepository;
    private final DeviceBasedSatelliteViewModel mDeviceBasedSatelliteViewModel;
    private final JavaAdapter mJavaAdapter;
    private final boolean[] mSimErrorState;
    private final int mSimSlotsNumber;
    @Nullable // Check for nullability before dispatching
    private CarrierTextCallback mCarrierTextCallback;
    @Nullable
    private Job mSatelliteConnectionJob;

    @Nullable private String mSatelliteCarrierText;

    private final Context mContext;
    private final TelephonyManager mTelephonyManager;
    private final CharSequence mSeparator;
@@ -178,6 +191,8 @@ public class CarrierTextManager {
            boolean showAirplaneMode,
            boolean showMissingSim,
            WifiRepository wifiRepository,
            DeviceBasedSatelliteViewModel deviceBasedSatelliteViewModel,
            JavaAdapter javaAdapter,
            TelephonyManager telephonyManager,
            TelephonyListenerManager telephonyListenerManager,
            WakefulnessLifecycle wakefulnessLifecycle,
@@ -192,6 +207,8 @@ public class CarrierTextManager {
        mShowAirplaneMode = showAirplaneMode;
        mShowMissingSim = showMissingSim;
        mWifiRepository = wifiRepository;
        mDeviceBasedSatelliteViewModel = deviceBasedSatelliteViewModel;
        mJavaAdapter = javaAdapter;
        mTelephonyManager = telephonyManager;
        mSeparator = separator;
        mTelephonyListenerManager = telephonyListenerManager;
@@ -282,6 +299,11 @@ public class CarrierTextManager {
                    mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
                });
                mTelephonyListenerManager.addActiveDataSubscriptionIdListener(mPhoneStateListener);
                cancelSatelliteCollectionJob(/* reason= */ "Starting new job");
                mSatelliteConnectionJob =
                    mJavaAdapter.alwaysCollectFlow(
                        mDeviceBasedSatelliteViewModel.getCarrierText(),
                        this::onSatelliteCarrierTextChanged);
            } else {
                // Don't listen and clear out the text when the device isn't a phone.
                mMainExecutor.execute(() -> callback.updateCarrierInfo(
@@ -294,6 +316,7 @@ public class CarrierTextManager {
                mWakefulnessLifecycle.removeObserver(mWakefulnessObserver);
            });
            mTelephonyListenerManager.removeActiveDataSubscriptionIdListener(mPhoneStateListener);
            cancelSatelliteCollectionJob(/* reason= */ "Stopping listening");
        }
    }

@@ -311,6 +334,12 @@ public class CarrierTextManager {
        return mKeyguardUpdateMonitor.getFilteredSubscriptionInfo();
    }

    private void onSatelliteCarrierTextChanged(@Nullable String text) {
        mLogger.logUpdateCarrierTextForReason(REASON_SATELLITE_CHANGED);
        mSatelliteCarrierText = text;
        updateCarrierText();
    }

    protected void updateCarrierText() {
        Trace.beginSection("CarrierTextManager#updateCarrierText");
        boolean allSimsMissing = true;
@@ -411,6 +440,12 @@ public class CarrierTextManager {
            airplaneMode = true;
        }

        String currentSatelliteText = mSatelliteCarrierText;
        if (currentSatelliteText != null) {
            mLogger.logUsingSatelliteText(currentSatelliteText);
            displayText = currentSatelliteText;
        }

        final CarrierTextCallbackInfo info = new CarrierTextCallbackInfo(
                displayText,
                carrierNames,
@@ -616,11 +651,20 @@ public class CarrierTextManager {
        return list;
    }

    private void cancelSatelliteCollectionJob(String reason) {
        Job job = mSatelliteConnectionJob;
        if (job != null) {
            job.cancel(new CancellationException(reason));
        }
    }

    /** Injectable Buildeer for {@#link CarrierTextManager}. */
    public static class Builder {
        private final Context mContext;
        private final String mSeparator;
        private final WifiRepository mWifiRepository;
        private final DeviceBasedSatelliteViewModel mDeviceBasedSatelliteViewModel;
        private final JavaAdapter mJavaAdapter;
        private final TelephonyManager mTelephonyManager;
        private final TelephonyListenerManager mTelephonyListenerManager;
        private final WakefulnessLifecycle mWakefulnessLifecycle;
@@ -637,6 +681,8 @@ public class CarrierTextManager {
                Context context,
                @Main Resources resources,
                @Nullable WifiRepository wifiRepository,
                DeviceBasedSatelliteViewModel deviceBasedSatelliteViewModel,
                JavaAdapter javaAdapter,
                TelephonyManager telephonyManager,
                TelephonyListenerManager telephonyListenerManager,
                WakefulnessLifecycle wakefulnessLifecycle,
@@ -648,6 +694,8 @@ public class CarrierTextManager {
            mSeparator = resources.getString(
                    com.android.internal.R.string.kg_text_message_separator);
            mWifiRepository = wifiRepository;
            mDeviceBasedSatelliteViewModel = deviceBasedSatelliteViewModel;
            mJavaAdapter = javaAdapter;
            mTelephonyManager = telephonyManager;
            mTelephonyListenerManager = telephonyListenerManager;
            mWakefulnessLifecycle = wakefulnessLifecycle;
@@ -682,9 +730,20 @@ public class CarrierTextManager {
        public CarrierTextManager build() {
            mLogger.setLocation(mDebugLocation);
            return new CarrierTextManager(
                    mContext, mSeparator, mShowAirplaneMode, mShowMissingSim, mWifiRepository,
                    mTelephonyManager, mTelephonyListenerManager, mWakefulnessLifecycle,
                    mMainExecutor, mBgExecutor, mKeyguardUpdateMonitor, mLogger);
                    mContext,
                    mSeparator,
                    mShowAirplaneMode,
                    mShowMissingSim,
                    mWifiRepository,
                    mDeviceBasedSatelliteViewModel,
                    mJavaAdapter,
                    mTelephonyManager,
                    mTelephonyListenerManager,
                    mWakefulnessLifecycle,
                    mMainExecutor,
                    mBgExecutor,
                    mKeyguardUpdateMonitor,
                    mLogger);
        }
    }

+12 −0
Original line number Diff line number Diff line
@@ -77,6 +77,15 @@ class CarrierTextManagerLogger @Inject constructor(@CarrierTextManagerLog val bu
        )
    }

    fun logUsingSatelliteText(satelliteText: String) {
        buffer.log(
            TAG,
            LogLevel.VERBOSE,
            { str1 = satelliteText },
            { "┣ updateCarrierText: using satellite text. text=$str1" },
        )
    }

    /** De-structures the info object so that we don't have to generate new strings */
    fun logCallbackSentFromUpdate(info: CarrierTextCallbackInfo) {
        buffer.log(
@@ -129,6 +138,7 @@ class CarrierTextManagerLogger @Inject constructor(@CarrierTextManagerLog val bu
        const val REASON_ON_TELEPHONY_CAPABLE = 2
        const val REASON_SIM_ERROR_STATE_CHANGED = 3
        const val REASON_ACTIVE_DATA_SUB_CHANGED = 4
        const val REASON_SATELLITE_CHANGED = 5

        @Retention(AnnotationRetention.SOURCE)
        @IntDef(
@@ -138,6 +148,7 @@ class CarrierTextManagerLogger @Inject constructor(@CarrierTextManagerLog val bu
                    REASON_ON_TELEPHONY_CAPABLE,
                    REASON_SIM_ERROR_STATE_CHANGED,
                    REASON_ACTIVE_DATA_SUB_CHANGED,
                    REASON_SATELLITE_CHANGED,
                ]
        )
        annotation class CarrierTextRefreshReason
@@ -148,6 +159,7 @@ class CarrierTextManagerLogger @Inject constructor(@CarrierTextManagerLog val bu
                REASON_ON_TELEPHONY_CAPABLE -> "ON_TELEPHONY_CAPABLE"
                REASON_SIM_ERROR_STATE_CHANGED -> "SIM_ERROR_STATE_CHANGED"
                REASON_ACTIVE_DATA_SUB_CHANGED -> "ACTIVE_DATA_SUB_CHANGED"
                REASON_SATELLITE_CHANGED -> "SATELLITE_CHANGED"
                else -> "unknown"
            }
    }
+7 −0
Original line number Diff line number Diff line
@@ -42,6 +42,8 @@ import com.android.systemui.statusbar.pipeline.mobile.util.SubscriptionManagerPr
import com.android.systemui.statusbar.pipeline.mobile.util.SubscriptionManagerProxyImpl
import com.android.systemui.statusbar.pipeline.satellite.data.DeviceBasedSatelliteRepository
import com.android.systemui.statusbar.pipeline.satellite.data.prod.DeviceBasedSatelliteRepositoryImpl
import com.android.systemui.statusbar.pipeline.satellite.ui.viewmodel.DeviceBasedSatelliteViewModel
import com.android.systemui.statusbar.pipeline.satellite.ui.viewmodel.DeviceBasedSatelliteViewModelImpl
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.shared.ui.binder.CollapsedStatusBarViewBinder
@@ -85,6 +87,11 @@ abstract class StatusBarPipelineModule {
        impl: DeviceBasedSatelliteRepositoryImpl
    ): DeviceBasedSatelliteRepository

    @Binds
    abstract fun deviceBasedSatelliteViewModel(
        impl: DeviceBasedSatelliteViewModelImpl
    ): DeviceBasedSatelliteViewModel

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

    @Binds abstract fun wifiInteractor(impl: WifiInteractorImpl): WifiInteractor
+41 −3
Original line number Diff line number Diff line
@@ -16,13 +16,16 @@

package com.android.systemui.statusbar.pipeline.satellite.ui.viewmodel

import android.content.Context
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.core.LogLevel
import com.android.systemui.res.R
import com.android.systemui.statusbar.pipeline.airplane.data.repository.AirplaneModeRepository
import com.android.systemui.statusbar.pipeline.dagger.OemSatelliteInputLog
import com.android.systemui.statusbar.pipeline.satellite.domain.interactor.DeviceBasedSatelliteInteractor
import com.android.systemui.statusbar.pipeline.satellite.shared.model.SatelliteConnectionState
import com.android.systemui.statusbar.pipeline.satellite.ui.model.SatelliteIconModel
import javax.inject.Inject
import kotlin.time.Duration.Companion.seconds
@@ -42,15 +45,30 @@ import kotlinx.coroutines.flow.stateIn
 * View-Model for the device-based satellite icon. This icon will only show in the status bar if
 * satellite is available AND all other service states are considered OOS.
 */
interface DeviceBasedSatelliteViewModel {
    /**
     * The satellite icon that should be displayed, or null if no satellite icon should be
     * displayed.
     */
    val icon: StateFlow<Icon?>

    /**
     * The satellite-related text that should be used as the carrier text string when satellite is
     * active, or null if the carrier text string shouldn't include any satellite information.
     */
    val carrierText: StateFlow<String?>
}

@OptIn(ExperimentalCoroutinesApi::class)
class DeviceBasedSatelliteViewModel
class DeviceBasedSatelliteViewModelImpl
@Inject
constructor(
    context: Context,
    interactor: DeviceBasedSatelliteInteractor,
    @Application scope: CoroutineScope,
    airplaneModeRepository: AirplaneModeRepository,
    @OemSatelliteInputLog logBuffer: LogBuffer,
) {
) : DeviceBasedSatelliteViewModel {
    private val shouldShowIcon: Flow<Boolean> =
        interactor.areAllConnectionsOutOfService.flatMapLatest { allOos ->
            if (!allOos) {
@@ -87,7 +105,7 @@ constructor(
            }
            .stateIn(scope, SharingStarted.WhileSubscribed(), false)

    val icon: StateFlow<Icon?> =
    override val icon: StateFlow<Icon?> =
        combine(
                shouldActuallyShowIcon,
                interactor.connectionState,
@@ -101,6 +119,26 @@ constructor(
            }
            .stateIn(scope, SharingStarted.WhileSubscribed(), null)

    override val carrierText: StateFlow<String?> =
        combine(
                shouldActuallyShowIcon,
                interactor.connectionState,
            ) { shouldShow, connectionState ->
                if (shouldShow) {
                    when (connectionState) {
                        SatelliteConnectionState.Connected ->
                            context.getString(R.string.satellite_connected_carrier_text)
                        SatelliteConnectionState.On ->
                            context.getString(R.string.satellite_not_connected_carrier_text)
                        SatelliteConnectionState.Off,
                        SatelliteConnectionState.Unknown -> null
                    }
                } else {
                    null
                }
            }
            .stateIn(scope, SharingStarted.WhileSubscribed(), null)

    companion object {
        private const val TAG = "DeviceBasedSatelliteViewModel"
        private val DELAY_DURATION = 10.seconds
Loading