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

Commit 4601261f authored by SongFerng Wang's avatar SongFerng Wang Committed by Android (Google) Code Review
Browse files

Merge "Add the UI of dual sim onboarding" into main

parents e5aff321 4713fd6b
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -11538,7 +11538,7 @@
    <!-- Button on the dual sim onboarding to go to next page. [CHAR LIMIT=30] -->
    <string name="sim_onboarding_next">Next</string>
    <!-- Text on the progressbar of dual sim onboarding for turning sim on. [CHAR LIMIT=30] -->
    <string name="sim_onboarding_profressbar_turning_sim_on">Turning on <xliff:g id="carrier_name" example="Google Fi">%1$s</xliff:g>&#8230;</string>
    <string name="sim_onboarding_progressbar_turning_sim_on">Turning on <xliff:g id="carrier_name" example="Google Fi">%1$s</xliff:g>&#8230;</string>
    <!-- Title of service provider name(SPN) at mobile network settings page. [CHAR LIMIT=30] -->
    <string name="mobile_network_spn_title">Mobile network</string>
    <!-- Title of phone number at mobile network settings page. [CHAR LIMIT=30] -->
+126 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.settings.network

import android.content.Context
import android.telephony.SubscriptionInfo
import android.telephony.SubscriptionManager
import android.telephony.TelephonyManager
import android.telephony.UiccCardInfo
import android.telephony.UiccSlotInfo
import android.util.Log
import com.android.settingslib.utils.ThreadUtils


private const val TAG = "SimOnboardingService"
private const val INVALID = -1

class SimOnboardingService {
    var subscriptionManager:SubscriptionManager? = null
    var telephonyManager:TelephonyManager? = null

    var targetSubId: Int = INVALID
    var targetSubInfo: SubscriptionInfo? = null
    var availableSubInfoList: List<SubscriptionInfo> = listOf()
    var activeSubInfoList: List<SubscriptionInfo> = listOf()
    var slotInfoList: List<UiccSlotInfo> = listOf()
    var uiccCardInfoList: List<UiccCardInfo> = listOf()
    var selectedSubInfoList: MutableList<SubscriptionInfo> = mutableListOf()
    var targetPrimarySimCalls: Int = -1
    var targetPrimarySimTexts: Int = -1
    var targetPrimarySimMobileData: Int = -1
    var isMultipleEnabledProfilesSupported: Boolean = false
        get() {
            if (uiccCardInfoList.isEmpty()) {
                Log.w(TAG, "UICC cards info list is empty.")
                return false
            }
            return uiccCardInfoList.stream()
                .anyMatch { cardInfo: UiccCardInfo -> cardInfo.isMultipleEnabledProfilesSupported }
        }
    var renameMutableMap : MutableMap<Int, String> = mutableMapOf()

    fun isValid(): Boolean {
        return targetSubId != INVALID
            && targetSubInfo != null
            && activeSubInfoList.isNotEmpty()
            && slotInfoList.isNotEmpty()
            && selectedSubInfoList.isNotEmpty()
    }

    fun clear() {
        targetSubId = -1
        targetSubInfo = null
        availableSubInfoList = listOf()
        activeSubInfoList = listOf()
        slotInfoList = listOf()
        uiccCardInfoList = listOf()
        selectedSubInfoList = mutableListOf()
        targetPrimarySimCalls = -1
        targetPrimarySimTexts = -1
        targetPrimarySimMobileData = -1
        renameMutableMap.clear()
    }

    fun initData(inputTargetSubId:Int,context: Context) {
        targetSubId = inputTargetSubId
        subscriptionManager = context.getSystemService(SubscriptionManager::class.java)
        telephonyManager = context.getSystemService(TelephonyManager::class.java)

        ThreadUtils.postOnBackgroundThread {
            activeSubInfoList = SubscriptionUtil.getActiveSubscriptions(subscriptionManager)
            availableSubInfoList = SubscriptionUtil.getAvailableSubscriptions(context)
            targetSubInfo = availableSubInfoList.find { subInfo -> subInfo.subscriptionId == targetSubId }
            Log.d(
                TAG, "targetSubId: $targetSubId" + ", targetSubInfo: $targetSubInfo" +
                    ". activeSubInfoList: $activeSubInfoList"
            )
            slotInfoList = telephonyManager?.uiccSlotsInfo?.toList() ?: listOf()
            Log.d(TAG, "slotInfoList: $slotInfoList.")
            uiccCardInfoList = telephonyManager?.uiccCardsInfo!!
            Log.d(TAG, "uiccCardInfoList: $uiccCardInfoList")

            Log.d(TAG, "isMultipleEnabledProfilesSupported: $isMultipleEnabledProfilesSupported")
        }
    }

    fun getSelectableSubscriptionInfo(): List<SubscriptionInfo> {
        var list: MutableList<SubscriptionInfo> = mutableListOf()
        list.addAll(activeSubInfoList)
        if (!list.contains(targetSubInfo)) {
            targetSubInfo?.let { list.add(it) }
        }

        Log.d(TAG, "list: $list")
        return list.toList()
    }

    fun addItemForRenaming(subInfo: SubscriptionInfo, newName: String) {
        if (subInfo.displayName == newName) {
            return
        }
        renameMutableMap[subInfo.subscriptionId] = newName
    }

    fun getSubscriptionInfoDisplayName(subInfo: SubscriptionInfo): String {
        return renameMutableMap[subInfo.subscriptionId] ?: subInfo.displayName.toString()
    }

    fun startActivatingSim(callback:() -> Unit){
        // TODO: start to activate sim
    }
}
 No newline at end of file
+9 −2
Original line number Diff line number Diff line
@@ -42,12 +42,14 @@ import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;

import com.android.internal.telephony.MccTable;
import com.android.internal.telephony.flags.Flags;
import com.android.settings.R;
import com.android.settings.flags.Flags;
import com.android.settings.network.helper.SelectableSubscriptions;
import com.android.settings.network.helper.SubscriptionAnnotation;
import com.android.settings.network.telephony.DeleteEuiccSubscriptionDialogActivity;
import com.android.settings.network.telephony.ToggleSubscriptionDialogActivity;
import com.android.settings.spa.SpaActivity;
import com.android.settings.spa.network.SimOnboardingPageProvider;

import java.util.ArrayList;
import java.util.Collections;
@@ -543,6 +545,11 @@ public class SubscriptionUtil {
            Log.i(TAG, "Unable to toggle subscription due to invalid subscription ID.");
            return;
        }
        if (enable && Flags.isDualSimOnboardingEnabled()) {
            String route = SimOnboardingPageProvider.INSTANCE.getRoute(subId);
            SpaActivity.startSpaActivity(context, route);
            return;
        }
        context.startActivity(ToggleSubscriptionDialogActivity.getIntent(context, subId, enable));
    }

@@ -822,7 +829,7 @@ public class SubscriptionUtil {
    private static boolean isEmbeddedSubscriptionVisible(@NonNull SubscriptionInfo subInfo) {
        if (subInfo.isEmbedded()
                && (subInfo.getProfileClass() == PROFILE_CLASS_PROVISIONING
                || (Flags.oemEnabledSatelliteFlag()
                || (com.android.internal.telephony.flags.Flags.oemEnabledSatelliteFlag()
                && subInfo.isOnlyNonTerrestrialNetwork()))) {
            return false;
        }
+2 −0
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ import com.android.settings.spa.development.UsageStatsPageProvider
import com.android.settings.spa.development.compat.PlatformCompatAppListPageProvider
import com.android.settings.spa.home.HomePageProvider
import com.android.settings.spa.network.NetworkAndInternetPageProvider
import com.android.settings.spa.network.SimOnboardingPageProvider
import com.android.settings.spa.notification.AppListNotificationsPageProvider
import com.android.settings.spa.notification.NotificationMainPageProvider
import com.android.settings.spa.system.AppLanguagesPageProvider
@@ -114,6 +115,7 @@ open class SettingsSpaEnvironment(context: Context) : SpaEnvironment(context) {
        StorageAppListPageProvider.Apps,
        StorageAppListPageProvider.Games,
        ApnEditPageProvider,
        SimOnboardingPageProvider,
    )

    override val logger = if (FeatureFlagUtils.isEnabled(
+113 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.settings.spa.network

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.SignalCellularAlt
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import com.android.settings.R
import com.android.settings.network.SimOnboardingService
import com.android.settings.network.SubscriptionUtil
import com.android.settingslib.spa.framework.theme.SettingsDimension
import com.android.settingslib.spa.widget.dialog.AlertDialogButton
import com.android.settingslib.spa.widget.dialog.rememberAlertDialogPresenter
import com.android.settingslib.spa.widget.editor.SettingsOutlinedTextField

import com.android.settingslib.spa.widget.preference.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel
import com.android.settingslib.spa.widget.scaffold.BottomAppBarButton
import com.android.settingslib.spa.widget.scaffold.SuwScaffold
import com.android.settingslib.spa.widget.ui.SettingsBody

/**
 * the sim onboarding label compose
 */
@Composable
fun SimOnboardingLabelSimImpl(
    nextAction: () -> Unit,
    cancelAction: () -> Unit,
    onboardingService: SimOnboardingService
) {
    SuwScaffold(
        imageVector = Icons.Outlined.SignalCellularAlt,
        title = stringResource(R.string.sim_onboarding_label_sim_title),
        actionButton = BottomAppBarButton(
            stringResource(R.string.sim_onboarding_next),
            nextAction
        ),
        dismissButton = BottomAppBarButton(
            stringResource(R.string.cancel),
            cancelAction
        ),
    ) {
        labelSimBody(onboardingService)
    }
}

@Composable
private fun labelSimBody(onboardingService: SimOnboardingService) {
    Column(Modifier.padding(SettingsDimension.itemPadding)) {
        SettingsBody(stringResource(R.string.sim_onboarding_label_sim_msg))
    }

    for (subInfo in onboardingService.getSelectableSubscriptionInfo()) {
        var titleSimName by remember {
            mutableStateOf(
                onboardingService.getSubscriptionInfoDisplayName(subInfo)
            )
        }
        var summaryNumber = subInfo.number
            // TODO using the SubscriptionUtil.getFormattedPhoneNumber
        val alertDialogPresenter = rememberAlertDialogPresenter(
            confirmButton = AlertDialogButton(
                stringResource(R.string.mobile_network_sim_name_rename)
            ) {
                onboardingService.addItemForRenaming(subInfo, titleSimName)
            },
            dismissButton = AlertDialogButton(stringResource(R.string.cancel)) {
                titleSimName = onboardingService.getSubscriptionInfoDisplayName(subInfo)
            },
            title = stringResource(R.string.sim_onboarding_label_sim_dialog_title),
            text = {
                Text(summaryNumber)
                SettingsOutlinedTextField(
                    value = titleSimName,
                    label = stringResource(R.string.sim_onboarding_label_sim_dialog_label),
                    enabled = true
                ) {
                    titleSimName = it
                }
            },
        )
        Preference(object : PreferenceModel {
            override val title = titleSimName
            override val summary: () -> String
                get() = { summaryNumber }
            override val onClick = alertDialogPresenter::open
        })
    }
}
 No newline at end of file
Loading