Snap for 11517367 from 12108acc07 to 24Q2-release
Change-Id: I09b5a93f800b059e4821d1634e44aa7e5a0bccbf
This commit is contained in:
75
res/layout/keyboard_layout_picker_one_pane_land.xml
Normal file
75
res/layout/keyboard_layout_picker_one_pane_land.xml
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
~ 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.
|
||||||
|
-->
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/keyboard_layout_picker_container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="@dimen/keyboard_picker_margin_one_pane"
|
||||||
|
android:layout_marginVertical="@dimen/keyboard_picker_margin_one_pane_large"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/keyboard_layout_preview_container"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginEnd="@dimen/keyboard_picker_margin_one_pane"
|
||||||
|
android:background="@drawable/keyboard_review_layout_background">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/keyboard_layout_preview"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="@dimen/keyboard_picker_margin_small"
|
||||||
|
android:layout_marginTop="@dimen/keyboard_picker_margin_small"
|
||||||
|
android:layout_marginBottom="@dimen/keyboard_picker_margin_large"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
android:scaleType="fitCenter" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/keyboard_layout_preview_name"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/keyboard_picker_margin_large"
|
||||||
|
android:layout_gravity="bottom"
|
||||||
|
android:gravity="center"
|
||||||
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
|
android:textSize="@dimen/keyboard_picker_text_size" />
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginStart="@dimen/keyboard_picker_margin_one_pane"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/keyboard_layout_title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?android:attr/colorBackground"
|
||||||
|
android:elevation="1dp"
|
||||||
|
android:outlineAmbientShadowColor="@android:color/transparent"
|
||||||
|
android:outlineSpotShadowColor="@android:color/transparent" />
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/keyboard_layouts"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/keyboard_picker_margin_small"
|
||||||
|
android:background="?android:attr/colorBackground" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -808,4 +808,8 @@
|
|||||||
<!-- Array of carrier id to allow the pSIM conversion-->
|
<!-- Array of carrier id to allow the pSIM conversion-->
|
||||||
<integer-array name="config_psim_conversion_menu_enabled_carrier" translatable="false">
|
<integer-array name="config_psim_conversion_menu_enabled_carrier" translatable="false">
|
||||||
</integer-array>
|
</integer-array>
|
||||||
|
|
||||||
|
<!-- Array of carrier id that uses reusable activation code-->
|
||||||
|
<integer-array name="config_carrier_use_rac" translatable="false">
|
||||||
|
</integer-array>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -168,6 +168,8 @@
|
|||||||
<!-- Keyboard -->
|
<!-- Keyboard -->
|
||||||
<dimen name="keyboard_picker_margin_large">68dp</dimen>
|
<dimen name="keyboard_picker_margin_large">68dp</dimen>
|
||||||
<dimen name="keyboard_picker_margin">24dp</dimen>
|
<dimen name="keyboard_picker_margin">24dp</dimen>
|
||||||
|
<dimen name="keyboard_picker_margin_one_pane_large">48dp</dimen>
|
||||||
|
<dimen name="keyboard_picker_margin_one_pane">24dp</dimen>
|
||||||
<dimen name="keyboard_picker_margin_small">16dp</dimen>
|
<dimen name="keyboard_picker_margin_small">16dp</dimen>
|
||||||
<dimen name="keyboard_picker_radius">28dp</dimen>
|
<dimen name="keyboard_picker_radius">28dp</dimen>
|
||||||
<dimen name="keyboard_picker_text_size">16sp</dimen>
|
<dimen name="keyboard_picker_text_size">16sp</dimen>
|
||||||
|
|||||||
@@ -2060,6 +2060,10 @@
|
|||||||
<string name="wifi_settings_wep_networks_button_allow">Allow WEP</string>
|
<string name="wifi_settings_wep_networks_button_allow">Allow WEP</string>
|
||||||
<!-- Wi-Fi settings dialog. Button text of dialog displayed when WEP network toggle is blocked. [CHAR LIMIT=NONE] -->
|
<!-- Wi-Fi settings dialog. Button text of dialog displayed when WEP network toggle is blocked. [CHAR LIMIT=NONE] -->
|
||||||
<string name="wifi_settings_ssid_block_button_close">Close</string>
|
<string name="wifi_settings_ssid_block_button_close">Close</string>
|
||||||
|
<!-- Wi-Fi settings dialog. Title of dialog displayed when the user turns off “Allow WEP networks” while connected to a WEP network. [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="wifi_settings_wep_networks_disconnect_title">Disconnect from <xliff:g id="name">%1$s</xliff:g>?</string>
|
||||||
|
<!-- Wi-Fi settings dialog. Summary text of dialog displayed when the user turns off “Allow WEP networks” while connected to a WEP network. [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="wifi_settings_wep_networks_disconnect_summary">You\u0027re connected to a WEP network. If you block these networks, you\u0027ll be disconnected.</string>
|
||||||
|
|
||||||
<!-- Dialog for Access Points --> <skip />
|
<!-- Dialog for Access Points --> <skip />
|
||||||
<!-- Label to show/hide advanced options [CHAR LIMIT=40] -->
|
<!-- Label to show/hide advanced options [CHAR LIMIT=40] -->
|
||||||
@@ -5154,14 +5158,14 @@
|
|||||||
<!-- Generic title for editing the shortcuts of multiple accessibility features. [CHAR LIMIT=NONE] -->
|
<!-- Generic title for editing the shortcuts of multiple accessibility features. [CHAR LIMIT=NONE] -->
|
||||||
<string name="accessibility_shortcut_edit_screen_title">Edit accessibility shortcuts</string>
|
<string name="accessibility_shortcut_edit_screen_title">Edit accessibility shortcuts</string>
|
||||||
<!-- Prompt for editing the shortcuts of multiple accessibility features. [CHAR LIMIT=NONE] -->
|
<!-- Prompt for editing the shortcuts of multiple accessibility features. [CHAR LIMIT=NONE] -->
|
||||||
<string name="accessibility_shortcut_edit_screen_prompt">Chose your shortcut for %1$s</string>
|
<string name="accessibility_shortcut_edit_screen_prompt">Choose your shortcut for %1$s</string>
|
||||||
|
|
||||||
<!-- Button text for the accessibility dialog continue to the next screen for hearing aid. [CHAR LIMIT=32] -->
|
<!-- Button text for the accessibility dialog continue to the next screen for hearing aid. [CHAR LIMIT=32] -->
|
||||||
<string name="accessibility_hearingaid_instruction_continue_button">Continue</string>
|
<string name="accessibility_hearingaid_instruction_continue_button">Continue</string>
|
||||||
<!-- Title for the accessibility preference for hearing devices. [CHAR LIMIT=35] -->
|
<!-- Title for the accessibility preference for hearing devices. [CHAR LIMIT=35] -->
|
||||||
<string name="accessibility_hearingaid_title">Hearing devices</string>
|
<string name="accessibility_hearingaid_title">Hearing devices</string>
|
||||||
<!-- Introduction for the Hearing devices page to introduce feature. [CHAR LIMIT=NONE] -->
|
<!-- Introduction for the Hearing devices page to introduce feature. [CHAR LIMIT=NONE BACKUP_MESSAGE_ID=5856992709195963850] -->
|
||||||
<string name="accessibility_hearingaid_intro">You can use hearing aids, cochlear implants, and other amplification devices with your phone</string>
|
<string name="accessibility_hearingaid_intro">Set up and manage ASHA and LE Audio hearing aids, cochlear implants, and other amplification devices</string>
|
||||||
<!-- Summary for the accessibility preference for hearing aid when not connected. [CHAR LIMIT=50] -->
|
<!-- Summary for the accessibility preference for hearing aid when not connected. [CHAR LIMIT=50] -->
|
||||||
<string name="accessibility_hearingaid_not_connected_summary">No hearing devices connected</string>
|
<string name="accessibility_hearingaid_not_connected_summary">No hearing devices connected</string>
|
||||||
<!-- Summary for the accessibility preference for hearing aid when adding new devices. [CHAR LIMIT=50] -->
|
<!-- Summary for the accessibility preference for hearing aid when adding new devices. [CHAR LIMIT=50] -->
|
||||||
@@ -5196,6 +5200,8 @@
|
|||||||
<string name="accessibility_hac_mode_summary">Improves compatibility with telecoils and reduces unwanted noise</string>
|
<string name="accessibility_hac_mode_summary">Improves compatibility with telecoils and reduces unwanted noise</string>
|
||||||
<!-- Title for accessibility hearing device page footer. [CHAR LIMIT=40] -->
|
<!-- Title for accessibility hearing device page footer. [CHAR LIMIT=40] -->
|
||||||
<string name="accessibility_hearing_device_about_title">About hearing devices</string>
|
<string name="accessibility_hearing_device_about_title">About hearing devices</string>
|
||||||
|
<!-- Description for text in accessibility hearing aids footer. [CHAR LIMIT=NONE BACKUP_MESSAGE_ID=7451899224828040581] -->
|
||||||
|
<string name="accessibility_hearing_device_footer_summary">To find other hearing devices that aren’t supported by ASHA or LE Audio, tap <b>Pair new device</b> > <b>See more devices</b></string>
|
||||||
<!-- Title for the pair hearing device page. [CHAR LIMIT=25] -->
|
<!-- Title for the pair hearing device page. [CHAR LIMIT=25] -->
|
||||||
<string name="accessibility_hearing_device_pairing_page_title">Pair hearing device</string>
|
<string name="accessibility_hearing_device_pairing_page_title">Pair hearing device</string>
|
||||||
<!-- Subtitle for the pair hearing device page. [CHAR LIMIT=NONE] -->
|
<!-- Subtitle for the pair hearing device page. [CHAR LIMIT=NONE] -->
|
||||||
@@ -12338,6 +12344,15 @@
|
|||||||
<!-- Summary for UWB preference when UWB is unavailable due to regulatory requirements. [CHAR_LIMIT=NONE]-->
|
<!-- Summary for UWB preference when UWB is unavailable due to regulatory requirements. [CHAR_LIMIT=NONE]-->
|
||||||
<string name="uwb_settings_summary_no_uwb_regulatory">UWB is unavailable in the current location</string>
|
<string name="uwb_settings_summary_no_uwb_regulatory">UWB is unavailable in the current location</string>
|
||||||
|
|
||||||
|
<!-- Title for Thread network preference [CHAR_LIMIT=60] -->
|
||||||
|
<string name="thread_network_settings_title">Thread</string>
|
||||||
|
|
||||||
|
<!-- Summary for Thread network preference. [CHAR_LIMIT=NONE]-->
|
||||||
|
<string name="thread_network_settings_summary">Connect to compatible devices using Thread for a seamless smart home experience</string>
|
||||||
|
|
||||||
|
<!-- Summary for Thread network preference when airplane mode is enabled. [CHAR_LIMIT=NONE]-->
|
||||||
|
<string name="thread_network_settings_summary_airplane_mode">Turn off airplane mode to use Thread</string>
|
||||||
|
|
||||||
<!-- Label for the camera use toggle [CHAR LIMIT=40] -->
|
<!-- Label for the camera use toggle [CHAR LIMIT=40] -->
|
||||||
<string name="camera_toggle_title">Camera access</string>
|
<string name="camera_toggle_title">Camera access</string>
|
||||||
<!-- Label for the camera use toggle [CHAR LIMIT=40] -->
|
<!-- Label for the camera use toggle [CHAR LIMIT=40] -->
|
||||||
|
|||||||
@@ -60,4 +60,11 @@
|
|||||||
settings:searchable="true"
|
settings:searchable="true"
|
||||||
settings:controller="com.android.settings.accessibility.HearingAidCompatibilityPreferenceController"/>
|
settings:controller="com.android.settings.accessibility.HearingAidCompatibilityPreferenceController"/>
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
<com.android.settings.accessibility.AccessibilityFooterPreference
|
||||||
|
android:key="hearing_device_footer"
|
||||||
|
android:title="@string/accessibility_hearing_device_footer_summary"
|
||||||
|
android:selectable="false"
|
||||||
|
settings:searchable="false"
|
||||||
|
settings:controller="com.android.settings.accessibility.HearingDeviceFooterPreferenceController"/>
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
@@ -63,6 +63,15 @@
|
|||||||
settings:useAdminDisabledSummary="true"
|
settings:useAdminDisabledSummary="true"
|
||||||
settings:userRestriction="no_ultra_wideband_radio" />
|
settings:userRestriction="no_ultra_wideband_radio" />
|
||||||
|
|
||||||
|
<com.android.settingslib.RestrictedSwitchPreference
|
||||||
|
android:key="thread_network_settings"
|
||||||
|
android:title="@string/thread_network_settings_title"
|
||||||
|
android:order="110"
|
||||||
|
android:summary="@string/summary_placeholder"
|
||||||
|
settings:controller="com.android.settings.connecteddevice.threadnetwork.ThreadNetworkPreferenceController"
|
||||||
|
settings:userRestriction="no_thread_network"
|
||||||
|
settings:useAdminDisabledSummary="true"/>
|
||||||
|
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
android:key="dashboard_tile_placeholder"
|
android:key="dashboard_tile_placeholder"
|
||||||
android:order="-8" />
|
android:order="-8" />
|
||||||
|
|||||||
@@ -38,5 +38,4 @@
|
|||||||
settings:useAdminDisabledSummary="true"
|
settings:useAdminDisabledSummary="true"
|
||||||
settings:controller="com.android.settings.accessibility.ViewAllBluetoothDevicesPreferenceController"/>
|
settings:controller="com.android.settings.accessibility.ViewAllBluetoothDevicesPreferenceController"/>
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package com.android.settings.accessibility;
|
package com.android.settings.accessibility;
|
||||||
|
|
||||||
|
import android.app.settings.SettingsEnums;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.dashboard.DashboardFragment;
|
import com.android.settings.dashboard.DashboardFragment;
|
||||||
import com.android.settings.search.BaseSearchIndexProvider;
|
import com.android.settings.search.BaseSearchIndexProvider;
|
||||||
@@ -40,8 +42,7 @@ public class ColorContrastFragment extends DashboardFragment {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMetricsCategory() {
|
public int getMetricsCategory() {
|
||||||
// TODO(b/326539398): Add metrics tracking for color contrast.
|
return SettingsEnums.ACCESSIBILITY_COLOR_CONTRAST;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||||
|
|||||||
@@ -563,7 +563,7 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
|
|||||||
@Override
|
@Override
|
||||||
@StringRes
|
@StringRes
|
||||||
protected int getAgreeButtonTextRes() {
|
protected int getAgreeButtonTextRes() {
|
||||||
return R.string.security_settings_fingerprint_enroll_introduction_agree;
|
return R.string.security_settings_face_enroll_introduction_agree;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
include platform/packages/modules/Connectivity:/thread/OWNERS
|
||||||
@@ -0,0 +1,236 @@
|
|||||||
|
/*
|
||||||
|
* 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.connecteddevice.threadnetwork
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.IntentFilter
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.net.thread.ThreadNetworkController
|
||||||
|
import android.net.thread.ThreadNetworkController.StateCallback
|
||||||
|
import android.net.thread.ThreadNetworkException
|
||||||
|
import android.net.thread.ThreadNetworkManager
|
||||||
|
import android.os.OutcomeReceiver
|
||||||
|
import android.provider.Settings
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.annotation.VisibleForTesting
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.LifecycleEventObserver
|
||||||
|
import androidx.lifecycle.LifecycleOwner
|
||||||
|
import androidx.preference.Preference
|
||||||
|
import androidx.preference.PreferenceScreen
|
||||||
|
import com.android.net.thread.platform.flags.Flags
|
||||||
|
import com.android.settings.R
|
||||||
|
import com.android.settings.core.TogglePreferenceController
|
||||||
|
import java.util.concurrent.Executor
|
||||||
|
|
||||||
|
/** Controller for the "Thread" toggle in "Connected devices > Connection preferences". */
|
||||||
|
class ThreadNetworkPreferenceController @VisibleForTesting constructor(
|
||||||
|
context: Context,
|
||||||
|
key: String,
|
||||||
|
private val executor: Executor,
|
||||||
|
private val threadController: BaseThreadNetworkController?
|
||||||
|
) : TogglePreferenceController(context, key), LifecycleEventObserver {
|
||||||
|
private val stateCallback: StateCallback
|
||||||
|
private val airplaneModeReceiver: BroadcastReceiver
|
||||||
|
private var threadEnabled = false
|
||||||
|
private var airplaneModeOn = false
|
||||||
|
private var preference: Preference? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A testable interface for [ThreadNetworkController] which is `final`.
|
||||||
|
*
|
||||||
|
* We are in a awkward situation that Android API guideline suggest `final` for API classes
|
||||||
|
* while Robolectric test is being deprecated for platform testing (See
|
||||||
|
* tests/robotests/new_tests_hook.sh). This force us to use "mockito-target-extended" but it's
|
||||||
|
* conflicting with the default "mockito-target" which is somehow indirectly depended by the
|
||||||
|
* `SettingsUnitTests` target.
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
interface BaseThreadNetworkController {
|
||||||
|
fun setEnabled(
|
||||||
|
enabled: Boolean,
|
||||||
|
executor: Executor,
|
||||||
|
receiver: OutcomeReceiver<Void?, ThreadNetworkException>
|
||||||
|
)
|
||||||
|
|
||||||
|
fun registerStateCallback(executor: Executor, callback: StateCallback)
|
||||||
|
|
||||||
|
fun unregisterStateCallback(callback: StateCallback)
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(context: Context, key: String) : this(
|
||||||
|
context,
|
||||||
|
key,
|
||||||
|
ContextCompat.getMainExecutor(context),
|
||||||
|
getThreadNetworkController(context)
|
||||||
|
)
|
||||||
|
|
||||||
|
init {
|
||||||
|
stateCallback = newStateCallback()
|
||||||
|
airplaneModeReceiver = newAirPlaneModeReceiver()
|
||||||
|
}
|
||||||
|
|
||||||
|
val isThreadSupportedOnDevice: Boolean
|
||||||
|
get() = threadController != null
|
||||||
|
|
||||||
|
private fun newStateCallback(): StateCallback {
|
||||||
|
return object : StateCallback {
|
||||||
|
override fun onThreadEnableStateChanged(enabledState: Int) {
|
||||||
|
threadEnabled = enabledState == ThreadNetworkController.STATE_ENABLED
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDeviceRoleChanged(role: Int) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun newAirPlaneModeReceiver(): BroadcastReceiver {
|
||||||
|
return object : BroadcastReceiver() {
|
||||||
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
|
airplaneModeOn = isAirplaneModeOn(context)
|
||||||
|
Log.i(TAG, "Airplane mode is " + if (airplaneModeOn) "ON" else "OFF")
|
||||||
|
preference?.let { preference -> updateState(preference) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getAvailabilityStatus(): Int {
|
||||||
|
return if (!Flags.threadEnabledPlatform()) {
|
||||||
|
CONDITIONALLY_UNAVAILABLE
|
||||||
|
} else if (!isThreadSupportedOnDevice) {
|
||||||
|
UNSUPPORTED_ON_DEVICE
|
||||||
|
} else if (airplaneModeOn) {
|
||||||
|
DISABLED_DEPENDENT_SETTING
|
||||||
|
} else {
|
||||||
|
AVAILABLE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun displayPreference(screen: PreferenceScreen) {
|
||||||
|
super.displayPreference(screen)
|
||||||
|
preference = screen.findPreference(preferenceKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isChecked(): Boolean {
|
||||||
|
// TODO (b/322742298):
|
||||||
|
// Check airplane mode here because it's planned to disable Thread state in airplane mode
|
||||||
|
// (code in the mainline module). But it's currently not implemented yet (b/322742298).
|
||||||
|
// By design, the toggle should be unchecked in airplane mode, so explicitly check the
|
||||||
|
// airplane mode here to acchieve the same UX.
|
||||||
|
return !airplaneModeOn && threadEnabled
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setChecked(isChecked: Boolean): Boolean {
|
||||||
|
if (threadController == null) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
val action = if (isChecked) "enable" else "disable"
|
||||||
|
threadController.setEnabled(
|
||||||
|
isChecked,
|
||||||
|
executor,
|
||||||
|
object : OutcomeReceiver<Void?, ThreadNetworkException> {
|
||||||
|
override fun onError(e: ThreadNetworkException) {
|
||||||
|
// TODO(b/327549838): gracefully handle the failure by resetting the UI state
|
||||||
|
Log.e(TAG, "Failed to $action Thread", e)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResult(unused: Void?) {
|
||||||
|
Log.d(TAG, "Successfully $action Thread")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStateChanged(lifecycleOwner: LifecycleOwner, event: Lifecycle.Event) {
|
||||||
|
if (threadController == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
when (event) {
|
||||||
|
Lifecycle.Event.ON_START -> {
|
||||||
|
threadController.registerStateCallback(executor, stateCallback)
|
||||||
|
airplaneModeOn = isAirplaneModeOn(mContext)
|
||||||
|
mContext.registerReceiver(
|
||||||
|
airplaneModeReceiver,
|
||||||
|
IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED)
|
||||||
|
)
|
||||||
|
preference?.let { preference -> updateState(preference) }
|
||||||
|
}
|
||||||
|
Lifecycle.Event.ON_STOP -> {
|
||||||
|
threadController.unregisterStateCallback(stateCallback)
|
||||||
|
mContext.unregisterReceiver(airplaneModeReceiver)
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateState(preference: Preference) {
|
||||||
|
super.updateState(preference)
|
||||||
|
preference.isEnabled = !airplaneModeOn
|
||||||
|
refreshSummary(preference)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getSummary(): CharSequence {
|
||||||
|
val resId: Int = if (airplaneModeOn) {
|
||||||
|
R.string.thread_network_settings_summary_airplane_mode
|
||||||
|
} else {
|
||||||
|
R.string.thread_network_settings_summary
|
||||||
|
}
|
||||||
|
return mContext.getResources().getString(resId)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getSliceHighlightMenuRes(): Int {
|
||||||
|
return R.string.menu_key_connected_devices
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "ThreadNetworkSettings"
|
||||||
|
private fun getThreadNetworkController(context: Context): BaseThreadNetworkController? {
|
||||||
|
if (!context.packageManager.hasSystemFeature(PackageManager.FEATURE_THREAD_NETWORK)) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
val manager = context.getSystemService(ThreadNetworkManager::class.java) ?: return null
|
||||||
|
val controller = manager.allThreadNetworkControllers[0]
|
||||||
|
return object : BaseThreadNetworkController {
|
||||||
|
override fun setEnabled(
|
||||||
|
enabled: Boolean,
|
||||||
|
executor: Executor,
|
||||||
|
receiver: OutcomeReceiver<Void?, ThreadNetworkException>
|
||||||
|
) {
|
||||||
|
controller.setEnabled(enabled, executor, receiver)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun registerStateCallback(executor: Executor, callback: StateCallback) {
|
||||||
|
controller.registerStateCallback(executor, callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun unregisterStateCallback(callback: StateCallback) {
|
||||||
|
controller.unregisterStateCallback(callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isAirplaneModeOn(context: Context): Boolean {
|
||||||
|
return Settings.Global.getInt(
|
||||||
|
context.contentResolver,
|
||||||
|
Settings.Global.AIRPLANE_MODE_ON,
|
||||||
|
0
|
||||||
|
) == 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -187,12 +187,6 @@ public class SettingsHomepageActivity extends FragmentActivity implements
|
|||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
if (!isTaskRoot() && !isSingleTask()) {
|
|
||||||
Log.i(TAG, "Not task root nor single task, finish");
|
|
||||||
finish();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mIsEmbeddingActivityEnabled = ActivityEmbeddingUtils.isEmbeddingActivityEnabled(this);
|
mIsEmbeddingActivityEnabled = ActivityEmbeddingUtils.isEmbeddingActivityEnabled(this);
|
||||||
if (mIsEmbeddingActivityEnabled) {
|
if (mIsEmbeddingActivityEnabled) {
|
||||||
final UserManager um = getSystemService(UserManager.class);
|
final UserManager um = getSystemService(UserManager.class);
|
||||||
@@ -319,12 +313,6 @@ public class SettingsHomepageActivity extends FragmentActivity implements
|
|||||||
updateHomepageUI();
|
updateHomepageUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSingleTask() {
|
|
||||||
ActivityInfo info = getIntent().resolveActivityInfo(getPackageManager(),
|
|
||||||
PackageManager.MATCH_DEFAULT_ONLY);
|
|
||||||
return info.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateSplitLayout() {
|
private void updateSplitLayout() {
|
||||||
if (!mIsEmbeddingActivityEnabled) {
|
if (!mIsEmbeddingActivityEnabled) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -16,9 +16,11 @@
|
|||||||
|
|
||||||
package com.android.settings.inputmethod;
|
package com.android.settings.inputmethod;
|
||||||
|
|
||||||
|
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
|
||||||
import static android.view.View.GONE;
|
import static android.view.View.GONE;
|
||||||
import static android.view.View.VISIBLE;
|
import static android.view.View.VISIBLE;
|
||||||
|
|
||||||
|
import android.content.res.Configuration;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.hardware.input.InputManager;
|
import android.hardware.input.InputManager;
|
||||||
import android.hardware.input.KeyboardLayout;
|
import android.hardware.input.KeyboardLayout;
|
||||||
@@ -35,6 +37,7 @@ import androidx.fragment.app.Fragment;
|
|||||||
|
|
||||||
import com.android.hardware.input.Flags;
|
import com.android.hardware.input.Flags;
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.activityembedding.ActivityEmbeddingUtils;
|
||||||
|
|
||||||
//TODO: b/316243168 - [Physical Keyboard Setting] Refactor NewKeyboardLayoutPickerFragment
|
//TODO: b/316243168 - [Physical Keyboard Setting] Refactor NewKeyboardLayoutPickerFragment
|
||||||
public class NewKeyboardLayoutPickerFragment extends Fragment {
|
public class NewKeyboardLayoutPickerFragment extends Fragment {
|
||||||
@@ -81,7 +84,7 @@ public class NewKeyboardLayoutPickerFragment extends Fragment {
|
|||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
mInputManager = requireContext().getSystemService(InputManager.class);
|
mInputManager = requireContext().getSystemService(InputManager.class);
|
||||||
ViewGroup fragmentView = (ViewGroup) inflater.inflate(
|
ViewGroup fragmentView = (ViewGroup) inflater.inflate(
|
||||||
R.layout.keyboard_layout_picker, container, false);
|
getPickerLayout(getResources().getConfiguration()), container, false);
|
||||||
mKeyboardLayoutPreview = fragmentView.findViewById(R.id.keyboard_layout_preview);
|
mKeyboardLayoutPreview = fragmentView.findViewById(R.id.keyboard_layout_preview);
|
||||||
mKeyboardLayoutPreviewText = fragmentView.findViewById(R.id.keyboard_layout_preview_name);
|
mKeyboardLayoutPreviewText = fragmentView.findViewById(R.id.keyboard_layout_preview_name);
|
||||||
if (!Flags.keyboardLayoutPreviewFlag()) {
|
if (!Flags.keyboardLayoutPreviewFlag()) {
|
||||||
@@ -102,6 +105,12 @@ public class NewKeyboardLayoutPickerFragment extends Fragment {
|
|||||||
return fragmentView;
|
return fragmentView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getPickerLayout(Configuration configuration) {
|
||||||
|
return !ActivityEmbeddingUtils.isAlreadyEmbedded(this.getActivity())
|
||||||
|
&& configuration.orientation == ORIENTATION_LANDSCAPE
|
||||||
|
? R.layout.keyboard_layout_picker_one_pane_land : R.layout.keyboard_layout_picker;
|
||||||
|
}
|
||||||
|
|
||||||
private void updateViewMarginForPreviewFlagOff(ViewGroup fragmentView) {
|
private void updateViewMarginForPreviewFlagOff(ViewGroup fragmentView) {
|
||||||
LinearLayout previewContainer = fragmentView.findViewById(
|
LinearLayout previewContainer = fragmentView.findViewById(
|
||||||
R.id.keyboard_layout_picker_container);
|
R.id.keyboard_layout_picker_container);
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package com.android.settings.network
|
package com.android.settings.network
|
||||||
|
|
||||||
import android.app.ProgressDialog
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
@@ -46,12 +45,12 @@ import androidx.compose.material3.rememberModalBottomSheetState
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.MutableState
|
import androidx.compose.runtime.MutableState
|
||||||
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.platform.LocalLifecycleOwner
|
import androidx.compose.ui.platform.LocalLifecycleOwner
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
@@ -59,12 +58,16 @@ import androidx.compose.ui.text.style.TextOverflow
|
|||||||
import com.android.settings.R
|
import com.android.settings.R
|
||||||
import com.android.settings.SidecarFragment
|
import com.android.settings.SidecarFragment
|
||||||
import com.android.settings.network.telephony.SubscriptionActionDialogActivity
|
import com.android.settings.network.telephony.SubscriptionActionDialogActivity
|
||||||
|
import com.android.settings.network.telephony.ToggleSubscriptionDialogActivity
|
||||||
import com.android.settings.spa.SpaActivity.Companion.startSpaActivity
|
import com.android.settings.spa.SpaActivity.Companion.startSpaActivity
|
||||||
import com.android.settings.spa.network.SimOnboardingPageProvider.getRoute
|
import com.android.settings.spa.network.SimOnboardingPageProvider.getRoute
|
||||||
import com.android.settingslib.spa.SpaBaseDialogActivity
|
import com.android.settingslib.spa.SpaBaseDialogActivity
|
||||||
import com.android.settingslib.spa.framework.theme.SettingsDimension
|
import com.android.settingslib.spa.framework.theme.SettingsDimension
|
||||||
import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
|
import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
|
||||||
|
import com.android.settingslib.spa.widget.dialog.AlertDialogButton
|
||||||
import com.android.settingslib.spa.widget.dialog.getDialogWidth
|
import com.android.settingslib.spa.widget.dialog.getDialogWidth
|
||||||
|
import com.android.settingslib.spa.widget.dialog.rememberAlertDialogPresenter
|
||||||
|
import com.android.settingslib.spa.widget.editor.SettingsOutlinedTextField
|
||||||
import com.android.settingslib.spa.widget.ui.SettingsTitle
|
import com.android.settingslib.spa.widget.ui.SettingsTitle
|
||||||
import com.android.settingslib.spaprivileged.framework.common.userManager
|
import com.android.settingslib.spaprivileged.framework.common.userManager
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
@@ -78,8 +81,8 @@ import kotlinx.coroutines.launch
|
|||||||
class SimOnboardingActivity : SpaBaseDialogActivity() {
|
class SimOnboardingActivity : SpaBaseDialogActivity() {
|
||||||
lateinit var scope: CoroutineScope
|
lateinit var scope: CoroutineScope
|
||||||
lateinit var showBottomSheet: MutableState<Boolean>
|
lateinit var showBottomSheet: MutableState<Boolean>
|
||||||
lateinit var showError: MutableState<Boolean>
|
lateinit var showError: MutableState<ErrorType>
|
||||||
lateinit var showDialog: MutableState<Boolean>
|
lateinit var showProgressDialog: MutableState<Boolean>
|
||||||
|
|
||||||
private var switchToEuiccSubscriptionSidecar: SwitchToEuiccSubscriptionSidecar? = null
|
private var switchToEuiccSubscriptionSidecar: SwitchToEuiccSubscriptionSidecar? = null
|
||||||
private var switchToRemovableSlotSidecar: SwitchToRemovableSlotSidecar? = null
|
private var switchToRemovableSlotSidecar: SwitchToRemovableSlotSidecar? = null
|
||||||
@@ -101,13 +104,19 @@ class SimOnboardingActivity : SpaBaseDialogActivity() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (onboardingService.activeSubInfoList.isEmpty()) {
|
||||||
|
// TODO: refactor and replace the ToggleSubscriptionDialogActivity
|
||||||
|
Log.d(TAG, "onboardingService.activeSubInfoList is empty" +
|
||||||
|
", start ToggleSubscriptionDialogActivity")
|
||||||
|
this.startActivity(ToggleSubscriptionDialogActivity
|
||||||
|
.getIntent(this.applicationContext, targetSubId, true))
|
||||||
|
finish()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
switchToEuiccSubscriptionSidecar = SwitchToEuiccSubscriptionSidecar.get(fragmentManager)
|
switchToEuiccSubscriptionSidecar = SwitchToEuiccSubscriptionSidecar.get(fragmentManager)
|
||||||
switchToRemovableSlotSidecar = SwitchToRemovableSlotSidecar.get(fragmentManager)
|
switchToRemovableSlotSidecar = SwitchToRemovableSlotSidecar.get(fragmentManager)
|
||||||
enableMultiSimSidecar = EnableMultiSimSidecar.get(fragmentManager)
|
enableMultiSimSidecar = EnableMultiSimSidecar.get(fragmentManager)
|
||||||
|
|
||||||
setContent {
|
|
||||||
Content()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun finish() {
|
override fun finish() {
|
||||||
@@ -116,15 +125,14 @@ class SimOnboardingActivity : SpaBaseDialogActivity() {
|
|||||||
super.finish()
|
super.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
var callbackListener: (Int) -> Unit = {
|
var callbackListener: (CallbackType) -> Unit = {
|
||||||
Log.d(TAG, "Receive the CALLBACK: $it")
|
Log.d(TAG, "Receive the CALLBACK: $it")
|
||||||
when (it) {
|
when (it) {
|
||||||
CALLBACK_ERROR -> {
|
CallbackType.CALLBACK_ERROR -> {
|
||||||
setProgressDialog(false)
|
setProgressDialog(false)
|
||||||
showError.value = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CALLBACK_ONBOARDING_COMPLETE -> {
|
CallbackType.CALLBACK_ONBOARDING_COMPLETE -> {
|
||||||
showBottomSheet.value = false
|
showBottomSheet.value = false
|
||||||
setProgressDialog(true)
|
setProgressDialog(true)
|
||||||
scope.launch {
|
scope.launch {
|
||||||
@@ -134,26 +142,29 @@ class SimOnboardingActivity : SpaBaseDialogActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CALLBACK_SETUP_NAME -> {
|
CallbackType.CALLBACK_SETUP_NAME -> {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
onboardingService.startSetupName()
|
onboardingService.startSetupName()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CALLBACK_SETUP_PRIMARY_SIM -> {
|
CallbackType.CALLBACK_SETUP_PRIMARY_SIM -> {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
onboardingService.startSetupPrimarySim(this@SimOnboardingActivity)
|
onboardingService.startSetupPrimarySim(this@SimOnboardingActivity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CALLBACK_FINISH -> {
|
CallbackType.CALLBACK_FINISH -> {
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setProgressDialog(enable: Boolean) {
|
fun setProgressDialog(enable: Boolean) {
|
||||||
showDialog.value = enable
|
if (!this::showProgressDialog.isInitialized) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
showProgressDialog.value = enable
|
||||||
val progressState = if (enable) {
|
val progressState = if (enable) {
|
||||||
SubscriptionActionDialogActivity.PROGRESS_IS_SHOWING
|
SubscriptionActionDialogActivity.PROGRESS_IS_SHOWING
|
||||||
} else {
|
} else {
|
||||||
@@ -165,16 +176,19 @@ class SimOnboardingActivity : SpaBaseDialogActivity() {
|
|||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
showBottomSheet = remember { mutableStateOf(true) }
|
showBottomSheet = remember { mutableStateOf(false) }
|
||||||
showError = remember { mutableStateOf(false) }
|
showError = remember { mutableStateOf(ErrorType.ERROR_NONE) }
|
||||||
showDialog = remember { mutableStateOf(false) }
|
showProgressDialog = remember { mutableStateOf(false) }
|
||||||
scope = rememberCoroutineScope()
|
scope = rememberCoroutineScope()
|
||||||
|
|
||||||
registerSidecarReceiverFlow()
|
registerSidecarReceiverFlow()
|
||||||
|
|
||||||
if(showError.value){
|
ErrorDialogImpl()
|
||||||
// show error
|
|
||||||
return
|
LaunchedEffect(Unit) {
|
||||||
|
if (onboardingService.activeSubInfoList.isNotEmpty()) {
|
||||||
|
showBottomSheet.value = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (showBottomSheet.value) {
|
if (showBottomSheet.value) {
|
||||||
@@ -195,7 +209,9 @@ class SimOnboardingActivity : SpaBaseDialogActivity() {
|
|||||||
},
|
},
|
||||||
cancelAction = { finish() },
|
cancelAction = { finish() },
|
||||||
)
|
)
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
if(showProgressDialog.value) {
|
||||||
ProgressDialogImpl()
|
ProgressDialogImpl()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -203,40 +219,88 @@ class SimOnboardingActivity : SpaBaseDialogActivity() {
|
|||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun ProgressDialogImpl() {
|
fun ProgressDialogImpl() {
|
||||||
if(showDialog.value) {
|
// TODO: Create the SPA's ProgressDialog and using SPA's widget
|
||||||
// TODO: Create the SPA's ProgressDialog and using SPA's widget
|
BasicAlertDialog(
|
||||||
BasicAlertDialog(
|
onDismissRequest = {},
|
||||||
onDismissRequest = {},
|
modifier = Modifier.width(
|
||||||
modifier = Modifier.width(
|
getDialogWidth()
|
||||||
getDialogWidth()
|
),
|
||||||
),
|
) {
|
||||||
|
Surface(
|
||||||
|
color = AlertDialogDefaults.containerColor,
|
||||||
|
shape = AlertDialogDefaults.shape
|
||||||
) {
|
) {
|
||||||
Surface(
|
Row(
|
||||||
color = AlertDialogDefaults.containerColor,
|
modifier = Modifier
|
||||||
shape = AlertDialogDefaults.shape
|
|
||||||
) {
|
|
||||||
Row(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(SettingsDimension.itemPaddingStart),
|
.padding(SettingsDimension.itemPaddingStart),
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
CircularProgressIndicator()
|
CircularProgressIndicator()
|
||||||
Column(modifier = Modifier
|
Column(modifier = Modifier
|
||||||
.padding(start = SettingsDimension.itemPaddingStart)) {
|
.padding(start = SettingsDimension.itemPaddingStart)) {
|
||||||
SettingsTitle(
|
SettingsTitle(
|
||||||
stringResource(
|
stringResource(
|
||||||
R.string.sim_onboarding_progressbar_turning_sim_on,
|
R.string.sim_onboarding_progressbar_turning_sim_on,
|
||||||
onboardingService.targetSubInfo?.displayName ?: ""
|
onboardingService.targetSubInfo?.displayName ?: ""
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ErrorDialogImpl(){
|
||||||
|
// EuiccSlotSidecar showErrorDialog
|
||||||
|
val errorDialogPresenterForEuiccSlotSidecar = rememberAlertDialogPresenter(
|
||||||
|
confirmButton = AlertDialogButton(
|
||||||
|
stringResource(android.R.string.ok)
|
||||||
|
) {
|
||||||
|
finish()
|
||||||
|
},
|
||||||
|
title = stringResource(R.string.privileged_action_disable_fail_title),
|
||||||
|
text = {
|
||||||
|
Text(stringResource(R.string.privileged_action_disable_fail_text))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
// RemovableSlotSidecar showErrorDialog
|
||||||
|
val errorDialogPresenterForRemovableSlotSidecar = rememberAlertDialogPresenter(
|
||||||
|
confirmButton = AlertDialogButton(
|
||||||
|
stringResource(android.R.string.ok)
|
||||||
|
) {
|
||||||
|
finish()
|
||||||
|
},
|
||||||
|
title = stringResource(R.string.sim_action_enable_sim_fail_title),
|
||||||
|
text = {
|
||||||
|
Text(stringResource(R.string.sim_action_enable_sim_fail_text))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
// enableDSDS showErrorDialog
|
||||||
|
val errorDialogPresenterForMultiSimSidecar = rememberAlertDialogPresenter(
|
||||||
|
confirmButton = AlertDialogButton(
|
||||||
|
stringResource(android.R.string.ok)
|
||||||
|
) {
|
||||||
|
finish()
|
||||||
|
},
|
||||||
|
title = stringResource(R.string.dsds_activation_failure_title),
|
||||||
|
text = {
|
||||||
|
Text(stringResource(R.string.dsds_activation_failure_body_msg2))
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
// show error
|
||||||
|
when (showError.value) {
|
||||||
|
ErrorType.ERROR_EUICC_SLOT -> errorDialogPresenterForEuiccSlotSidecar.open()
|
||||||
|
ErrorType.ERROR_REMOVABLE_SLOT -> errorDialogPresenterForRemovableSlotSidecar.open()
|
||||||
|
ErrorType.ERROR_ENABLE_DSDS -> errorDialogPresenterForMultiSimSidecar.open()
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun registerSidecarReceiverFlow(){
|
fun registerSidecarReceiverFlow(){
|
||||||
switchToEuiccSubscriptionSidecar?.sidecarReceiverFlow()
|
switchToEuiccSubscriptionSidecar?.sidecarReceiverFlow()
|
||||||
@@ -304,13 +368,14 @@ class SimOnboardingActivity : SpaBaseDialogActivity() {
|
|||||||
SidecarFragment.State.SUCCESS -> {
|
SidecarFragment.State.SUCCESS -> {
|
||||||
Log.i(TAG, "Successfully enable the eSIM profile.")
|
Log.i(TAG, "Successfully enable the eSIM profile.")
|
||||||
switchToEuiccSubscriptionSidecar!!.reset()
|
switchToEuiccSubscriptionSidecar!!.reset()
|
||||||
callbackListener(CALLBACK_SETUP_NAME)
|
callbackListener(CallbackType.CALLBACK_SETUP_NAME)
|
||||||
}
|
}
|
||||||
|
|
||||||
SidecarFragment.State.ERROR -> {
|
SidecarFragment.State.ERROR -> {
|
||||||
Log.i(TAG, "Failed to enable the eSIM profile.")
|
Log.i(TAG, "Failed to enable the eSIM profile.")
|
||||||
switchToEuiccSubscriptionSidecar!!.reset()
|
switchToEuiccSubscriptionSidecar!!.reset()
|
||||||
callbackListener(CALLBACK_ERROR)
|
showError.value = ErrorType.ERROR_EUICC_SLOT
|
||||||
|
callbackListener(CallbackType.CALLBACK_ERROR)
|
||||||
// TODO: showErrorDialog and using privileged_action_disable_fail_title and
|
// TODO: showErrorDialog and using privileged_action_disable_fail_title and
|
||||||
// privileged_action_disable_fail_text
|
// privileged_action_disable_fail_text
|
||||||
}
|
}
|
||||||
@@ -323,13 +388,14 @@ class SimOnboardingActivity : SpaBaseDialogActivity() {
|
|||||||
Log.i(TAG, "Successfully switched to removable slot.")
|
Log.i(TAG, "Successfully switched to removable slot.")
|
||||||
switchToRemovableSlotSidecar!!.reset()
|
switchToRemovableSlotSidecar!!.reset()
|
||||||
onboardingService.handleTogglePsimAction()
|
onboardingService.handleTogglePsimAction()
|
||||||
callbackListener(CALLBACK_SETUP_NAME)
|
callbackListener(CallbackType.CALLBACK_SETUP_NAME)
|
||||||
}
|
}
|
||||||
|
|
||||||
SidecarFragment.State.ERROR -> {
|
SidecarFragment.State.ERROR -> {
|
||||||
Log.e(TAG, "Failed switching to removable slot.")
|
Log.e(TAG, "Failed switching to removable slot.")
|
||||||
switchToRemovableSlotSidecar!!.reset()
|
switchToRemovableSlotSidecar!!.reset()
|
||||||
callbackListener(CALLBACK_ERROR)
|
showError.value = ErrorType.ERROR_REMOVABLE_SLOT
|
||||||
|
callbackListener(CallbackType.CALLBACK_ERROR)
|
||||||
// TODO: showErrorDialog and using sim_action_enable_sim_fail_title and
|
// TODO: showErrorDialog and using sim_action_enable_sim_fail_title and
|
||||||
// sim_action_enable_sim_fail_text
|
// sim_action_enable_sim_fail_text
|
||||||
}
|
}
|
||||||
@@ -347,7 +413,8 @@ class SimOnboardingActivity : SpaBaseDialogActivity() {
|
|||||||
SidecarFragment.State.ERROR -> {
|
SidecarFragment.State.ERROR -> {
|
||||||
enableMultiSimSidecar!!.reset()
|
enableMultiSimSidecar!!.reset()
|
||||||
Log.i(TAG, "Failed to switch to DSDS without rebooting.")
|
Log.i(TAG, "Failed to switch to DSDS without rebooting.")
|
||||||
callbackListener(CALLBACK_ERROR)
|
showError.value = ErrorType.ERROR_ENABLE_DSDS
|
||||||
|
callbackListener(CallbackType.CALLBACK_ERROR)
|
||||||
// TODO: showErrorDialog and using dsds_activation_failure_title and
|
// TODO: showErrorDialog and using dsds_activation_failure_title and
|
||||||
// dsds_activation_failure_body_msg2
|
// dsds_activation_failure_body_msg2
|
||||||
}
|
}
|
||||||
@@ -370,7 +437,7 @@ class SimOnboardingActivity : SpaBaseDialogActivity() {
|
|||||||
}
|
}
|
||||||
Log.i(TAG, "DSDS enabled, start to enable pSIM profile.")
|
Log.i(TAG, "DSDS enabled, start to enable pSIM profile.")
|
||||||
onboardingService.handleTogglePsimAction()
|
onboardingService.handleTogglePsimAction()
|
||||||
callbackListener(CALLBACK_FINISH)
|
callbackListener(CallbackType.CALLBACK_FINISH)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -426,7 +493,7 @@ class SimOnboardingActivity : SpaBaseDialogActivity() {
|
|||||||
Log.i(TAG, "setProgressState:$state")
|
Log.i(TAG, "setProgressState:$state")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun initServiceData(context: Context,targetSubId: Int, callback:(Int)->Unit) {
|
fun initServiceData(context: Context,targetSubId: Int, callback:(CallbackType)->Unit) {
|
||||||
onboardingService.initData(targetSubId, context,callback)
|
onboardingService.initData(targetSubId, context,callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -445,10 +512,20 @@ class SimOnboardingActivity : SpaBaseDialogActivity() {
|
|||||||
var onboardingService:SimOnboardingService = SimOnboardingService()
|
var onboardingService:SimOnboardingService = SimOnboardingService()
|
||||||
const val TAG = "SimOnboardingActivity"
|
const val TAG = "SimOnboardingActivity"
|
||||||
const val SUB_ID = "sub_id"
|
const val SUB_ID = "sub_id"
|
||||||
const val CALLBACK_ERROR = -1
|
|
||||||
const val CALLBACK_ONBOARDING_COMPLETE = 1
|
enum class ErrorType(val value:Int){
|
||||||
const val CALLBACK_SETUP_NAME = 2
|
ERROR_NONE(-1),
|
||||||
const val CALLBACK_SETUP_PRIMARY_SIM = 3
|
ERROR_EUICC_SLOT(1),
|
||||||
const val CALLBACK_FINISH = 4
|
ERROR_REMOVABLE_SLOT(2),
|
||||||
|
ERROR_ENABLE_DSDS(3)
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class CallbackType(val value:Int){
|
||||||
|
CALLBACK_ERROR(-1),
|
||||||
|
CALLBACK_ONBOARDING_COMPLETE(1),
|
||||||
|
CALLBACK_SETUP_NAME(2),
|
||||||
|
CALLBACK_SETUP_PRIMARY_SIM(3),
|
||||||
|
CALLBACK_FINISH(4)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -23,6 +23,7 @@ import android.telephony.TelephonyManager
|
|||||||
import android.telephony.UiccCardInfo
|
import android.telephony.UiccCardInfo
|
||||||
import android.telephony.UiccSlotInfo
|
import android.telephony.UiccSlotInfo
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import com.android.settings.network.SimOnboardingActivity.Companion.CallbackType
|
||||||
import com.android.settings.spa.network.setAutomaticData
|
import com.android.settings.spa.network.setAutomaticData
|
||||||
import com.android.settings.spa.network.setDefaultData
|
import com.android.settings.spa.network.setDefaultData
|
||||||
import com.android.settings.spa.network.setDefaultSms
|
import com.android.settings.spa.network.setDefaultSms
|
||||||
@@ -31,7 +32,6 @@ import com.android.settingslib.utils.ThreadUtils
|
|||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
|
||||||
private const val TAG = "SimOnboardingService"
|
private const val TAG = "SimOnboardingService"
|
||||||
private const val INVALID = SubscriptionManager.INVALID_SUBSCRIPTION_ID
|
private const val INVALID = SubscriptionManager.INVALID_SUBSCRIPTION_ID
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ class SimOnboardingService {
|
|||||||
.map { it.subscriptionId }
|
.map { it.subscriptionId }
|
||||||
.firstOrNull() ?: SubscriptionManager.INVALID_SUBSCRIPTION_ID
|
.firstOrNull() ?: SubscriptionManager.INVALID_SUBSCRIPTION_ID
|
||||||
}
|
}
|
||||||
var callback: (Int) -> Unit = {}
|
var callback: (CallbackType) -> Unit = {}
|
||||||
|
|
||||||
var isMultipleEnabledProfilesSupported: Boolean = false
|
var isMultipleEnabledProfilesSupported: Boolean = false
|
||||||
get() {
|
get() {
|
||||||
@@ -135,24 +135,24 @@ class SimOnboardingService {
|
|||||||
userSelectedSubInfoList.clear()
|
userSelectedSubInfoList.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun initData(inputTargetSubId:Int,context: Context, callback: (Int) -> Unit) {
|
fun initData(inputTargetSubId: Int,
|
||||||
|
context: Context,
|
||||||
|
callback: (CallbackType) -> Unit) {
|
||||||
this.callback = callback
|
this.callback = callback
|
||||||
targetSubId = inputTargetSubId
|
targetSubId = inputTargetSubId
|
||||||
subscriptionManager = context.getSystemService(SubscriptionManager::class.java)
|
subscriptionManager = context.getSystemService(SubscriptionManager::class.java)
|
||||||
telephonyManager = context.getSystemService(TelephonyManager::class.java)
|
telephonyManager = context.getSystemService(TelephonyManager::class.java)
|
||||||
Log.d(
|
Log.d(
|
||||||
TAG, "startInit: targetSubId:$targetSubId"
|
TAG, "startInit: targetSubId:$targetSubId, activeSubInfoList: $activeSubInfoList"
|
||||||
)
|
)
|
||||||
|
activeSubInfoList = SubscriptionUtil.getActiveSubscriptions(subscriptionManager)
|
||||||
|
|
||||||
ThreadUtils.postOnBackgroundThread {
|
ThreadUtils.postOnBackgroundThread {
|
||||||
activeSubInfoList = SubscriptionUtil.getActiveSubscriptions(subscriptionManager)
|
|
||||||
availableSubInfoList = SubscriptionUtil.getAvailableSubscriptions(context)
|
availableSubInfoList = SubscriptionUtil.getAvailableSubscriptions(context)
|
||||||
targetSubInfo =
|
targetSubInfo =
|
||||||
availableSubInfoList.find { subInfo -> subInfo.subscriptionId == targetSubId }
|
availableSubInfoList.find { subInfo -> subInfo.subscriptionId == targetSubId }
|
||||||
targetSubInfo?.let { userSelectedSubInfoList.add(it) }
|
targetSubInfo?.let { userSelectedSubInfoList.add(it) }
|
||||||
Log.d(
|
Log.d(TAG, "targetSubId: $targetSubId , targetSubInfo: $targetSubInfo")
|
||||||
TAG, "targetSubId: $targetSubId" + ", targetSubInfo: $targetSubInfo" +
|
|
||||||
". activeSubInfoList: $activeSubInfoList"
|
|
||||||
)
|
|
||||||
slotInfoList = telephonyManager?.uiccSlotsInfo?.toList() ?: listOf()
|
slotInfoList = telephonyManager?.uiccSlotsInfo?.toList() ?: listOf()
|
||||||
Log.d(TAG, "slotInfoList: $slotInfoList.")
|
Log.d(TAG, "slotInfoList: $slotInfoList.")
|
||||||
uiccCardInfoList = telephonyManager?.uiccCardsInfo!!
|
uiccCardInfoList = telephonyManager?.uiccCardsInfo!!
|
||||||
@@ -196,6 +196,16 @@ class SimOnboardingService {
|
|||||||
return userSelectedSubInfoList.toList()
|
return userSelectedSubInfoList.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getSelectedSubscriptionInfoListWithRenaming(): List<SubscriptionInfo> {
|
||||||
|
if (userSelectedSubInfoList.isEmpty()){
|
||||||
|
Log.d(TAG, "userSelectedSubInfoList is empty")
|
||||||
|
return activeSubInfoList
|
||||||
|
}
|
||||||
|
return userSelectedSubInfoList.map {
|
||||||
|
SubscriptionInfo.Builder(it).setDisplayName(getSubscriptionInfoDisplayName(it)).build()
|
||||||
|
}.toList()
|
||||||
|
}
|
||||||
|
|
||||||
fun addItemForRenaming(subInfo: SubscriptionInfo, newName: String) {
|
fun addItemForRenaming(subInfo: SubscriptionInfo, newName: String) {
|
||||||
if (subInfo.displayName == newName) {
|
if (subInfo.displayName == newName) {
|
||||||
return
|
return
|
||||||
@@ -211,8 +221,12 @@ class SimOnboardingService {
|
|||||||
return renameMutableMap[subInfo.subscriptionId] ?: subInfo.displayName.toString()
|
return renameMutableMap[subInfo.subscriptionId] ?: subInfo.displayName.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addCurrentItemForSelectedSim(){
|
fun addCurrentItemForSelectedSim() {
|
||||||
userSelectedSubInfoList.addAll(activeSubInfoList)
|
if (userSelectedSubInfoList.size < getActiveModemCount) {
|
||||||
|
userSelectedSubInfoList.addAll(activeSubInfoList)
|
||||||
|
Log.d(TAG, "addCurrentItemForSelectedSim: userSelectedSubInfoList:" +
|
||||||
|
", $userSelectedSubInfoList")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addItemForSelectedSim(selectedSubInfo: SubscriptionInfo) {
|
fun addItemForSelectedSim(selectedSubInfo: SubscriptionInfo) {
|
||||||
@@ -249,7 +263,7 @@ class SimOnboardingService {
|
|||||||
|
|
||||||
fun startActivatingSim(){
|
fun startActivatingSim(){
|
||||||
// TODO: start to activate sim
|
// TODO: start to activate sim
|
||||||
callback(SimOnboardingActivity.CALLBACK_FINISH)
|
callback(CallbackType.CALLBACK_FINISH)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun startSetupName() {
|
suspend fun startSetupName() {
|
||||||
@@ -261,7 +275,7 @@ class SimOnboardingService {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
// next action is SETUP_PRIMARY_SIM
|
// next action is SETUP_PRIMARY_SIM
|
||||||
callback(SimOnboardingActivity.CALLBACK_SETUP_PRIMARY_SIM)
|
callback(CallbackType.CALLBACK_SETUP_PRIMARY_SIM)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,7 +304,7 @@ class SimOnboardingService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// no next action, send finish
|
// no next action, send finish
|
||||||
callback(SimOnboardingActivity.CALLBACK_FINISH)
|
callback(CallbackType.CALLBACK_FINISH)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -49,9 +49,11 @@ import com.android.settings.flags.Flags;
|
|||||||
import com.android.settings.network.helper.SelectableSubscriptions;
|
import com.android.settings.network.helper.SelectableSubscriptions;
|
||||||
import com.android.settings.network.helper.SubscriptionAnnotation;
|
import com.android.settings.network.helper.SubscriptionAnnotation;
|
||||||
import com.android.settings.network.telephony.DeleteEuiccSubscriptionDialogActivity;
|
import com.android.settings.network.telephony.DeleteEuiccSubscriptionDialogActivity;
|
||||||
|
import com.android.settings.network.telephony.EuiccRacConnectivityDialogActivity;
|
||||||
import com.android.settings.network.telephony.ToggleSubscriptionDialogActivity;
|
import com.android.settings.network.telephony.ToggleSubscriptionDialogActivity;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@@ -557,13 +559,21 @@ public class SubscriptionUtil {
|
|||||||
* @param context {@code Context}
|
* @param context {@code Context}
|
||||||
* @param subId The id of subscription need to be deleted.
|
* @param subId The id of subscription need to be deleted.
|
||||||
*/
|
*/
|
||||||
public static void startDeleteEuiccSubscriptionDialogActivity(Context context, int subId) {
|
public static void startDeleteEuiccSubscriptionDialogActivity(Context context, int subId,
|
||||||
|
int carrierId) {
|
||||||
if (!SubscriptionManager.isUsableSubscriptionId(subId)) {
|
if (!SubscriptionManager.isUsableSubscriptionId(subId)) {
|
||||||
Log.i(TAG, "Unable to delete subscription due to invalid subscription ID.");
|
Log.i(TAG, "Unable to delete subscription due to invalid subscription ID.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// TODO(b/325693582): Add verification if carrier is RAC and logic for new dialog
|
final int[] carriersThatUseRAC = context.getResources().getIntArray(
|
||||||
context.startActivity(DeleteEuiccSubscriptionDialogActivity.getIntent(context, subId));
|
R.array.config_carrier_use_rac);
|
||||||
|
boolean isCarrierRac = Arrays.stream(carriersThatUseRAC).anyMatch(cid -> cid == carrierId);
|
||||||
|
|
||||||
|
if (isCarrierRac && !isConnectedToWifiOrDifferentSubId(context, subId)) {
|
||||||
|
context.startActivity(EuiccRacConnectivityDialogActivity.getIntent(context, subId));
|
||||||
|
} else {
|
||||||
|
context.startActivity(DeleteEuiccSubscriptionDialogActivity.getIntent(context, subId));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
|
|||||||
class DeleteSimProfilePreferenceController(context: Context, preferenceKey: String) :
|
class DeleteSimProfilePreferenceController(context: Context, preferenceKey: String) :
|
||||||
BasePreferenceController(context, preferenceKey) {
|
BasePreferenceController(context, preferenceKey) {
|
||||||
private var subscriptionId: Int = SubscriptionManager.INVALID_SUBSCRIPTION_ID
|
private var subscriptionId: Int = SubscriptionManager.INVALID_SUBSCRIPTION_ID
|
||||||
|
private var carrierId: Int = TelephonyManager.UNKNOWN_CARRIER_ID
|
||||||
private var subscriptionInfo: SubscriptionInfo? = null
|
private var subscriptionInfo: SubscriptionInfo? = null
|
||||||
private lateinit var preference: Preference
|
private lateinit var preference: Preference
|
||||||
|
|
||||||
@@ -40,6 +41,9 @@ class DeleteSimProfilePreferenceController(context: Context, preferenceKey: Stri
|
|||||||
this.subscriptionId = subscriptionId
|
this.subscriptionId = subscriptionId
|
||||||
subscriptionInfo = SubscriptionUtil.getAvailableSubscriptions(mContext)
|
subscriptionInfo = SubscriptionUtil.getAvailableSubscriptions(mContext)
|
||||||
.find { it.subscriptionId == subscriptionId && it.isEmbedded }
|
.find { it.subscriptionId == subscriptionId && it.isEmbedded }
|
||||||
|
subscriptionInfo?.let {
|
||||||
|
carrierId = it.carrierId
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getAvailabilityStatus() = when (subscriptionInfo) {
|
override fun getAvailabilityStatus() = when (subscriptionInfo) {
|
||||||
@@ -67,7 +71,8 @@ class DeleteSimProfilePreferenceController(context: Context, preferenceKey: Stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun deleteSim() {
|
private fun deleteSim() {
|
||||||
SubscriptionUtil.startDeleteEuiccSubscriptionDialogActivity(mContext, subscriptionId)
|
SubscriptionUtil.startDeleteEuiccSubscriptionDialogActivity(mContext, subscriptionId,
|
||||||
|
carrierId)
|
||||||
// result handled in MobileNetworkSettings
|
// result handled in MobileNetworkSettings
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import androidx.annotation.Nullable;
|
|||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
import androidx.preference.PreferenceScreen;
|
import androidx.preference.PreferenceScreen;
|
||||||
|
|
||||||
|
import com.android.internal.telephony.flags.Flags;
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.SettingsActivity;
|
import com.android.settings.SettingsActivity;
|
||||||
import com.android.settings.network.CarrierConfigCache;
|
import com.android.settings.network.CarrierConfigCache;
|
||||||
@@ -58,6 +59,11 @@ public class SatelliteSettingPreferenceController extends
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getAvailabilityStatus(int subId) {
|
public int getAvailabilityStatus(int subId) {
|
||||||
|
if (!Flags.carrierEnabledSatelliteFlag()) {
|
||||||
|
logd("getAvailabilityStatus() : carrierEnabledSatelliteFlag is disabled");
|
||||||
|
return UNSUPPORTED_ON_DEVICE;
|
||||||
|
}
|
||||||
|
|
||||||
final PersistableBundle carrierConfig = mCarrierConfigCache.getConfigForSubId(subId);
|
final PersistableBundle carrierConfig = mCarrierConfigCache.getConfigForSubId(subId);
|
||||||
final boolean isSatelliteAttachSupported = carrierConfig.getBoolean(
|
final boolean isSatelliteAttachSupported = carrierConfig.getBoolean(
|
||||||
CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL);
|
CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL);
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import com.android.settings.media.MediaOutputIndicatorWorker;
|
|||||||
import com.android.settings.slices.CustomSliceRegistry;
|
import com.android.settings.slices.CustomSliceRegistry;
|
||||||
import com.android.settings.slices.SliceBackgroundWorker;
|
import com.android.settings.slices.SliceBackgroundWorker;
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||||
|
import com.android.settingslib.flags.Flags;
|
||||||
import com.android.settingslib.media.BluetoothMediaDevice;
|
import com.android.settingslib.media.BluetoothMediaDevice;
|
||||||
import com.android.settingslib.media.MediaDevice;
|
import com.android.settingslib.media.MediaDevice;
|
||||||
import com.android.settingslib.media.MediaOutputConstants;
|
import com.android.settingslib.media.MediaOutputConstants;
|
||||||
@@ -94,7 +95,9 @@ public class MediaVolumePreferenceController extends VolumeSeekBarPreferenceCont
|
|||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
boolean isSupportEndItem() {
|
boolean isSupportEndItem() {
|
||||||
return getWorker() != null && getWorker().isBroadcastSupported()
|
return Flags.legacyLeAudioSharing()
|
||||||
|
&& getWorker() != null
|
||||||
|
&& getWorker().isBroadcastSupported()
|
||||||
&& (getWorker().isDeviceBroadcasting() || isConnectedBLEDevice());
|
&& (getWorker().isDeviceBroadcasting() || isConnectedBLEDevice());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,8 +117,9 @@ public class MediaVolumePreferenceController extends VolumeSeekBarPreferenceCont
|
|||||||
if (mPreference != null) {
|
if (mPreference != null) {
|
||||||
if (mPreference.isMuted()) {
|
if (mPreference.isMuted()) {
|
||||||
mPreference.updateContentDescription(
|
mPreference.updateContentDescription(
|
||||||
mContext.getString(R.string.volume_content_description_silent_mode,
|
mContext.getString(
|
||||||
mPreference.getTitle()));
|
R.string.volume_content_description_silent_mode,
|
||||||
|
mPreference.getTitle()));
|
||||||
} else {
|
} else {
|
||||||
mPreference.updateContentDescription(mPreference.getTitle());
|
mPreference.updateContentDescription(mPreference.getTitle());
|
||||||
}
|
}
|
||||||
@@ -134,11 +138,16 @@ public class MediaVolumePreferenceController extends VolumeSeekBarPreferenceCont
|
|||||||
if (getWorker().isDeviceBroadcasting()) {
|
if (getWorker().isDeviceBroadcasting()) {
|
||||||
intent.setPackage(MediaOutputConstants.SYSTEMUI_PACKAGE_NAME);
|
intent.setPackage(MediaOutputConstants.SYSTEMUI_PACKAGE_NAME);
|
||||||
intent.setAction(MediaOutputConstants.ACTION_LAUNCH_MEDIA_OUTPUT_BROADCAST_DIALOG);
|
intent.setAction(MediaOutputConstants.ACTION_LAUNCH_MEDIA_OUTPUT_BROADCAST_DIALOG);
|
||||||
intent.putExtra(MediaOutputConstants.EXTRA_PACKAGE_NAME,
|
intent.putExtra(
|
||||||
|
MediaOutputConstants.EXTRA_PACKAGE_NAME,
|
||||||
getWorker().getActiveLocalMediaController().getPackageName());
|
getWorker().getActiveLocalMediaController().getPackageName());
|
||||||
|
|
||||||
pi = PendingIntent.getBroadcast(context, 0 /* requestCode */, intent,
|
pi =
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
|
PendingIntent.getBroadcast(
|
||||||
|
context,
|
||||||
|
0 /* requestCode */,
|
||||||
|
intent,
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
|
||||||
} else {
|
} else {
|
||||||
final CachedBluetoothDevice bluetoothDevice =
|
final CachedBluetoothDevice bluetoothDevice =
|
||||||
((BluetoothMediaDevice) mMediaDevice).getCachedDevice();
|
((BluetoothMediaDevice) mMediaDevice).getCachedDevice();
|
||||||
@@ -147,15 +156,21 @@ public class MediaVolumePreferenceController extends VolumeSeekBarPreferenceCont
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
intent.setAction(ACTION_LAUNCH_BROADCAST_DIALOG);
|
intent.setAction(ACTION_LAUNCH_BROADCAST_DIALOG);
|
||||||
intent.putExtra(BluetoothBroadcastDialog.KEY_APP_LABEL,
|
intent.putExtra(
|
||||||
|
BluetoothBroadcastDialog.KEY_APP_LABEL,
|
||||||
Utils.getApplicationLabel(mContext, getWorker().getPackageName()));
|
Utils.getApplicationLabel(mContext, getWorker().getPackageName()));
|
||||||
intent.putExtra(BluetoothBroadcastDialog.KEY_DEVICE_ADDRESS,
|
intent.putExtra(
|
||||||
bluetoothDevice.getAddress());
|
BluetoothBroadcastDialog.KEY_DEVICE_ADDRESS, bluetoothDevice.getAddress());
|
||||||
intent.putExtra(BluetoothBroadcastDialog.KEY_MEDIA_STREAMING, getWorker() != null
|
intent.putExtra(
|
||||||
&& getWorker().getActiveLocalMediaController() != null);
|
BluetoothBroadcastDialog.KEY_MEDIA_STREAMING,
|
||||||
|
getWorker() != null && getWorker().getActiveLocalMediaController() != null);
|
||||||
|
|
||||||
pi = PendingIntent.getActivity(context, 0 /* requestCode */, intent,
|
pi =
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
|
PendingIntent.getActivity(
|
||||||
|
context,
|
||||||
|
0 /* requestCode */,
|
||||||
|
intent,
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
final IconCompat icon = getBroadcastIcon(context);
|
final IconCompat icon = getBroadcastIcon(context);
|
||||||
@@ -164,8 +179,8 @@ public class MediaVolumePreferenceController extends VolumeSeekBarPreferenceCont
|
|||||||
}
|
}
|
||||||
|
|
||||||
private IconCompat getBroadcastIcon(Context context) {
|
private IconCompat getBroadcastIcon(Context context) {
|
||||||
final Drawable drawable = context.getDrawable(
|
final Drawable drawable =
|
||||||
com.android.settingslib.R.drawable.settings_input_antenna);
|
context.getDrawable(com.android.settingslib.R.drawable.settings_input_antenna);
|
||||||
if (drawable != null) {
|
if (drawable != null) {
|
||||||
drawable.setTint(Utils.getColorAccentDefaultColor(context));
|
drawable.setTint(Utils.getColorAccentDefaultColor(context));
|
||||||
return Utils.createIconWithDrawable(drawable);
|
return Utils.createIconWithDrawable(drawable);
|
||||||
|
|||||||
@@ -136,9 +136,7 @@ public class SimDialogActivity extends FragmentActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Flags.isDualSimOnboardingEnabled()
|
if (Flags.isDualSimOnboardingEnabled()
|
||||||
&& getProgressState() == SubscriptionActionDialogActivity.PROGRESS_IS_SHOWING
|
&& (dialogType == DATA_PICK
|
||||||
&& (dialogType == PREFERRED_PICK
|
|
||||||
|| dialogType == DATA_PICK
|
|
||||||
|| dialogType == CALLS_PICK
|
|| dialogType == CALLS_PICK
|
||||||
|| dialogType == SMS_PICK)) {
|
|| dialogType == SMS_PICK)) {
|
||||||
Log.d(TAG, "Finish the sim dialog since the sim onboarding is shown");
|
Log.d(TAG, "Finish the sim dialog since the sim onboarding is shown");
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import android.os.Bundle
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.annotation.VisibleForTesting
|
import androidx.annotation.VisibleForTesting
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
import androidx.navigation.NavType
|
import androidx.navigation.NavType
|
||||||
@@ -33,6 +34,7 @@ import androidx.navigation.compose.rememberNavController
|
|||||||
import androidx.navigation.navArgument
|
import androidx.navigation.navArgument
|
||||||
import com.android.settings.R
|
import com.android.settings.R
|
||||||
import com.android.settings.network.SimOnboardingActivity
|
import com.android.settings.network.SimOnboardingActivity
|
||||||
|
import com.android.settings.network.SimOnboardingActivity.Companion.CallbackType
|
||||||
import com.android.settings.network.SimOnboardingService
|
import com.android.settings.network.SimOnboardingService
|
||||||
import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
|
import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
|
||||||
import com.android.settingslib.spa.framework.common.SettingsPageProvider
|
import com.android.settingslib.spa.framework.common.SettingsPageProvider
|
||||||
@@ -92,7 +94,7 @@ fun PageImpl(onboardingService:SimOnboardingService,navHostController: NavHostCo
|
|||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
var finishOnboarding: () -> Unit = {
|
var finishOnboarding: () -> Unit = {
|
||||||
context.getActivity()?.finish()
|
context.getActivity()?.finish()
|
||||||
onboardingService.callback(SimOnboardingActivity.CALLBACK_FINISH)
|
onboardingService.callback(CallbackType.CALLBACK_FINISH)
|
||||||
}
|
}
|
||||||
|
|
||||||
NavHost(
|
NavHost(
|
||||||
@@ -101,10 +103,13 @@ fun PageImpl(onboardingService:SimOnboardingService,navHostController: NavHostCo
|
|||||||
) {
|
) {
|
||||||
composable(route = SimOnboardingScreen.LabelSim.name) {
|
composable(route = SimOnboardingScreen.LabelSim.name) {
|
||||||
val nextPage =
|
val nextPage =
|
||||||
if (onboardingService.isMultipleEnabledProfilesSupported && onboardingService.isAllOfSlotAssigned) {
|
if (onboardingService.isMultipleEnabledProfilesSupported
|
||||||
|
&& onboardingService.isAllOfSlotAssigned) {
|
||||||
SimOnboardingScreen.SelectSim.name
|
SimOnboardingScreen.SelectSim.name
|
||||||
} else {
|
} else {
|
||||||
onboardingService.addCurrentItemForSelectedSim()
|
LaunchedEffect(Unit) {
|
||||||
|
onboardingService.addCurrentItemForSelectedSim()
|
||||||
|
}
|
||||||
SimOnboardingScreen.PrimarySim.name
|
SimOnboardingScreen.PrimarySim.name
|
||||||
}
|
}
|
||||||
SimOnboardingLabelSimImpl(
|
SimOnboardingLabelSimImpl(
|
||||||
@@ -116,7 +121,7 @@ fun PageImpl(onboardingService:SimOnboardingService,navHostController: NavHostCo
|
|||||||
composable(route = SimOnboardingScreen.PrimarySim.name) {
|
composable(route = SimOnboardingScreen.PrimarySim.name) {
|
||||||
SimOnboardingPrimarySimImpl(
|
SimOnboardingPrimarySimImpl(
|
||||||
nextAction = {
|
nextAction = {
|
||||||
onboardingService.callback(SimOnboardingActivity.CALLBACK_ONBOARDING_COMPLETE)
|
onboardingService.callback(CallbackType.CALLBACK_ONBOARDING_COMPLETE)
|
||||||
context.getActivity()?.finish()
|
context.getActivity()?.finish()
|
||||||
},
|
},
|
||||||
cancelAction = finishOnboarding,
|
cancelAction = finishOnboarding,
|
||||||
|
|||||||
@@ -77,7 +77,8 @@ fun SimOnboardingPrimarySimImpl(
|
|||||||
SettingsBody(stringResource(id = R.string.sim_onboarding_primary_sim_msg))
|
SettingsBody(stringResource(id = R.string.sim_onboarding_primary_sim_msg))
|
||||||
}
|
}
|
||||||
|
|
||||||
var selectedSubscriptionInfoList = onboardingService.getSelectedSubscriptionInfoList()
|
var selectedSubscriptionInfoList =
|
||||||
|
onboardingService.getSelectedSubscriptionInfoListWithRenaming()
|
||||||
callsSelectedId.intValue = onboardingService.targetPrimarySimCalls
|
callsSelectedId.intValue = onboardingService.targetPrimarySimCalls
|
||||||
textsSelectedId.intValue = onboardingService.targetPrimarySimTexts
|
textsSelectedId.intValue = onboardingService.targetPrimarySimTexts
|
||||||
mobileDataSelectedId.intValue = onboardingService.targetPrimarySimMobileData
|
mobileDataSelectedId.intValue = onboardingService.targetPrimarySimMobileData
|
||||||
|
|||||||
@@ -18,24 +18,33 @@ package com.android.settings.wifi
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.wifi.WifiManager
|
import android.net.wifi.WifiManager
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import androidx.preference.Preference
|
|
||||||
import androidx.preference.PreferenceScreen
|
|
||||||
import com.android.settings.R
|
import com.android.settings.R
|
||||||
import com.android.settings.spa.preference.ComposePreferenceController
|
import com.android.settings.spa.preference.ComposePreferenceController
|
||||||
import com.android.settingslib.spa.framework.compose.OverridableFlow
|
import com.android.settingslib.spa.framework.compose.OverridableFlow
|
||||||
|
import com.android.settingslib.spa.widget.dialog.AlertDialogButton
|
||||||
|
import com.android.settingslib.spa.widget.dialog.SettingsAlertDialogWithIcon
|
||||||
import com.android.settingslib.spa.widget.preference.SwitchPreference
|
import com.android.settingslib.spa.widget.preference.SwitchPreference
|
||||||
import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
|
import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
|
||||||
import com.android.wifi.flags.Flags
|
import com.android.wifi.flags.Flags
|
||||||
|
import com.android.wifitrackerlib.WifiEntry
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.asExecutor
|
import kotlinx.coroutines.asExecutor
|
||||||
import kotlinx.coroutines.channels.awaitClose
|
import kotlinx.coroutines.channels.awaitClose
|
||||||
import kotlinx.coroutines.flow.callbackFlow
|
import kotlinx.coroutines.flow.callbackFlow
|
||||||
|
|
||||||
/** Controller that controls whether the Wi-Fi Wakeup feature should be enabled. */
|
/** Controller that controls whether the WEP network can be connected. */
|
||||||
class WepNetworksPreferenceController(context: Context, preferenceKey: String) :
|
class WepNetworksPreferenceController(context: Context, preferenceKey: String) :
|
||||||
ComposePreferenceController(context, preferenceKey) {
|
ComposePreferenceController(context, preferenceKey) {
|
||||||
|
|
||||||
@@ -47,6 +56,8 @@ class WepNetworksPreferenceController(context: Context, preferenceKey: String) :
|
|||||||
@Composable
|
@Composable
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
val checked by wepAllowedFlow.flow.collectAsStateWithLifecycle(initialValue = null)
|
val checked by wepAllowedFlow.flow.collectAsStateWithLifecycle(initialValue = null)
|
||||||
|
var openDialog by rememberSaveable { mutableStateOf(false) }
|
||||||
|
val wifiInfo = wifiManager.connectionInfo
|
||||||
SwitchPreference(object : SwitchPreferenceModel {
|
SwitchPreference(object : SwitchPreferenceModel {
|
||||||
override val title = stringResource(R.string.wifi_allow_wep_networks)
|
override val title = stringResource(R.string.wifi_allow_wep_networks)
|
||||||
override val summary = { getSummary() }
|
override val summary = { getSummary() }
|
||||||
@@ -54,10 +65,40 @@ class WepNetworksPreferenceController(context: Context, preferenceKey: String) :
|
|||||||
override val changeable: () -> Boolean
|
override val changeable: () -> Boolean
|
||||||
get() = { carrierAllowed }
|
get() = { carrierAllowed }
|
||||||
override val onCheckedChange: (Boolean) -> Unit = { newChecked ->
|
override val onCheckedChange: (Boolean) -> Unit = { newChecked ->
|
||||||
wifiManager.setWepAllowed(newChecked)
|
if (!newChecked && wifiInfo.currentSecurityType == WifiEntry.SECURITY_WEP) {
|
||||||
wepAllowedFlow.override(newChecked)
|
openDialog = true
|
||||||
|
} else {
|
||||||
|
wifiManager.setWepAllowed(newChecked)
|
||||||
|
wepAllowedFlow.override(newChecked)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
if (openDialog) {
|
||||||
|
SettingsAlertDialogWithIcon(
|
||||||
|
onDismissRequest = { openDialog = false },
|
||||||
|
confirmButton = AlertDialogButton(
|
||||||
|
stringResource(R.string.wifi_disconnect_button_text)
|
||||||
|
) {
|
||||||
|
wifiManager.setWepAllowed(false)
|
||||||
|
wepAllowedFlow.override(false)
|
||||||
|
openDialog = false
|
||||||
|
},
|
||||||
|
dismissButton =
|
||||||
|
AlertDialogButton(
|
||||||
|
stringResource(R.string.wifi_cancel)
|
||||||
|
) { openDialog = false },
|
||||||
|
title = String.format(
|
||||||
|
stringResource(R.string.wifi_settings_wep_networks_disconnect_title),
|
||||||
|
wifiInfo.ssid.removeSurrounding("\"")
|
||||||
|
),
|
||||||
|
text = {
|
||||||
|
Text(
|
||||||
|
stringResource(R.string.wifi_settings_wep_networks_disconnect_summary),
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getSummary(): String = mContext.getString(
|
override fun getSummary(): String = mContext.getString(
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import static org.mockito.Mockito.spy;
|
|||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.app.UiModeManager;
|
import android.app.UiModeManager;
|
||||||
|
import android.app.settings.SettingsEnums;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
@@ -59,7 +60,8 @@ public class ColorContrastFragmentTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getMetricsCategory_returnsCorrectCategory() {
|
public void getMetricsCategory_returnsCorrectCategory() {
|
||||||
assertThat(mFragment.getMetricsCategory()).isEqualTo(0);
|
assertThat(mFragment.getMetricsCategory()).isEqualTo(
|
||||||
|
SettingsEnums.ACCESSIBILITY_COLOR_CONTRAST);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.android.settings.applications.appinfo;
|
|||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.doReturn;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
@@ -25,10 +26,12 @@ import static org.mockito.Mockito.when;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.os.UserManager;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
|
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
import androidx.preference.PreferenceScreen;
|
import androidx.preference.PreferenceScreen;
|
||||||
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
|
||||||
import com.android.settings.SettingsActivity;
|
import com.android.settings.SettingsActivity;
|
||||||
import com.android.settings.applications.ProcStatsData;
|
import com.android.settings.applications.ProcStatsData;
|
||||||
@@ -37,14 +40,14 @@ import com.android.settings.core.BasePreferenceController;
|
|||||||
import com.android.settings.testutils.shadow.ShadowUserManager;
|
import com.android.settings.testutils.shadow.ShadowUserManager;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Ignore;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.junit.MockitoJUnit;
|
||||||
|
import org.mockito.junit.MockitoRule;
|
||||||
import org.robolectric.RobolectricTestRunner;
|
import org.robolectric.RobolectricTestRunner;
|
||||||
import org.robolectric.RuntimeEnvironment;
|
|
||||||
import org.robolectric.annotation.Config;
|
import org.robolectric.annotation.Config;
|
||||||
import org.robolectric.util.ReflectionHelpers;
|
import org.robolectric.util.ReflectionHelpers;
|
||||||
|
|
||||||
@@ -54,6 +57,8 @@ import org.robolectric.util.ReflectionHelpers;
|
|||||||
com.android.settings.testutils.shadow.ShadowFragment.class,
|
com.android.settings.testutils.shadow.ShadowFragment.class,
|
||||||
})
|
})
|
||||||
public class AppMemoryPreferenceControllerTest {
|
public class AppMemoryPreferenceControllerTest {
|
||||||
|
@Rule
|
||||||
|
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private SettingsActivity mActivity;
|
private SettingsActivity mActivity;
|
||||||
@@ -69,9 +74,11 @@ public class AppMemoryPreferenceControllerTest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
MockitoAnnotations.initMocks(this);
|
mContext = spy(ApplicationProvider.getApplicationContext());
|
||||||
mContext = RuntimeEnvironment.application;
|
UserManager userManager = mock(UserManager.class);
|
||||||
ShadowUserManager.getShadow().setIsAdminUser(true);
|
when(userManager.isAdminUser()).thenReturn(true);
|
||||||
|
doReturn(userManager).when(mContext).getSystemService(Context.USER_SERVICE);
|
||||||
|
|
||||||
mController =
|
mController =
|
||||||
spy(new AppMemoryPreferenceController(mContext, mFragment, null /* lifecycle */));
|
spy(new AppMemoryPreferenceController(mContext, mFragment, null /* lifecycle */));
|
||||||
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
|
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
|
||||||
@@ -80,7 +87,6 @@ public class AppMemoryPreferenceControllerTest {
|
|||||||
when(mFragment.getActivity()).thenReturn(mActivity);
|
when(mFragment.getActivity()).thenReturn(mActivity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Ignore("b/313582035")
|
|
||||||
@Test
|
@Test
|
||||||
@Config(qualifiers = "mcc999")
|
@Config(qualifiers = "mcc999")
|
||||||
public void getAvailabilityStatus_developmentSettingsEnabled_shouldReturnAvailable() {
|
public void getAvailabilityStatus_developmentSettingsEnabled_shouldReturnAvailable() {
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import static org.mockito.ArgumentMatchers.anyString;
|
|||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.doReturn;
|
import static org.mockito.Mockito.doReturn;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.never;
|
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
@@ -223,28 +222,6 @@ public class SettingsHomepageActivityTest {
|
|||||||
& SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS).isEqualTo(0);
|
& SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS).isEqualTo(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void onCreate_notTaskRoot_shouldFinishActivity() {
|
|
||||||
SettingsHomepageActivity activity =
|
|
||||||
spy(Robolectric.buildActivity(SettingsHomepageActivity.class).get());
|
|
||||||
doReturn(false).when(activity).isTaskRoot();
|
|
||||||
|
|
||||||
activity.onCreate(/* savedInstanceState */ null);
|
|
||||||
|
|
||||||
verify(activity).finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void onCreate_singleTaskActivity_shouldNotFinishActivity() {
|
|
||||||
SettingsHomepageActivity activity =
|
|
||||||
spy(Robolectric.buildActivity(DeepLinkHomepageActivity.class).get());
|
|
||||||
doReturn(false).when(activity).isTaskRoot();
|
|
||||||
|
|
||||||
activity.onCreate(/* savedInstanceState */ null);
|
|
||||||
|
|
||||||
verify(activity, never()).finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** This test is for large screen devices Activity embedding. */
|
/** This test is for large screen devices Activity embedding. */
|
||||||
@Test
|
@Test
|
||||||
@Config(shadows = ShadowActivityEmbeddingUtils.class)
|
@Config(shadows = ShadowActivityEmbeddingUtils.class)
|
||||||
|
|||||||
@@ -31,17 +31,23 @@ import android.content.Intent;
|
|||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
import android.media.session.MediaController;
|
import android.media.session.MediaController;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.platform.test.annotations.RequiresFlagsDisabled;
|
||||||
|
import android.platform.test.annotations.RequiresFlagsEnabled;
|
||||||
|
import android.platform.test.flag.junit.CheckFlagsRule;
|
||||||
|
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
|
||||||
|
|
||||||
import androidx.slice.builders.SliceAction;
|
import androidx.slice.builders.SliceAction;
|
||||||
|
|
||||||
import com.android.settings.media.MediaOutputIndicatorWorker;
|
import com.android.settings.media.MediaOutputIndicatorWorker;
|
||||||
import com.android.settings.slices.SliceBackgroundWorker;
|
import com.android.settings.slices.SliceBackgroundWorker;
|
||||||
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
|
||||||
|
import com.android.settingslib.flags.Flags;
|
||||||
import com.android.settingslib.media.BluetoothMediaDevice;
|
import com.android.settingslib.media.BluetoothMediaDevice;
|
||||||
import com.android.settingslib.media.MediaDevice;
|
import com.android.settingslib.media.MediaDevice;
|
||||||
import com.android.settingslib.media.MediaOutputConstants;
|
import com.android.settingslib.media.MediaOutputConstants;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
@@ -60,16 +66,16 @@ public class MediaVolumePreferenceControllerTest {
|
|||||||
"android.settings.MEDIA_BROADCAST_DIALOG";
|
"android.settings.MEDIA_BROADCAST_DIALOG";
|
||||||
private static MediaOutputIndicatorWorker sMediaOutputIndicatorWorker;
|
private static MediaOutputIndicatorWorker sMediaOutputIndicatorWorker;
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
|
||||||
|
|
||||||
private MediaVolumePreferenceController mController;
|
private MediaVolumePreferenceController mController;
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
|
|
||||||
@Mock
|
@Mock private MediaController mMediaController;
|
||||||
private MediaController mMediaController;
|
@Mock private MediaDevice mDevice1;
|
||||||
@Mock
|
@Mock private MediaDevice mDevice2;
|
||||||
private MediaDevice mDevice1;
|
|
||||||
@Mock
|
|
||||||
private MediaDevice mDevice2;
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
@@ -77,8 +83,8 @@ public class MediaVolumePreferenceControllerTest {
|
|||||||
|
|
||||||
mContext = RuntimeEnvironment.application;
|
mContext = RuntimeEnvironment.application;
|
||||||
mController = new MediaVolumePreferenceController(mContext);
|
mController = new MediaVolumePreferenceController(mContext);
|
||||||
sMediaOutputIndicatorWorker = spy(
|
sMediaOutputIndicatorWorker =
|
||||||
new MediaOutputIndicatorWorker(mContext, VOLUME_MEDIA_URI));
|
spy(new MediaOutputIndicatorWorker(mContext, VOLUME_MEDIA_URI));
|
||||||
when(mDevice1.isBLEDevice()).thenReturn(true);
|
when(mDevice1.isBLEDevice()).thenReturn(true);
|
||||||
when(mDevice2.isBLEDevice()).thenReturn(false);
|
when(mDevice2.isBLEDevice()).thenReturn(false);
|
||||||
}
|
}
|
||||||
@@ -101,8 +107,8 @@ public class MediaVolumePreferenceControllerTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isSliceableCorrectKey_returnsTrue() {
|
public void isSliceableCorrectKey_returnsTrue() {
|
||||||
final MediaVolumePreferenceController controller = new MediaVolumePreferenceController(
|
final MediaVolumePreferenceController controller =
|
||||||
mContext);
|
new MediaVolumePreferenceController(mContext);
|
||||||
assertThat(controller.isSliceable()).isTrue();
|
assertThat(controller.isSliceable()).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,6 +118,17 @@ public class MediaVolumePreferenceControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@RequiresFlagsDisabled(Flags.FLAG_LEGACY_LE_AUDIO_SHARING)
|
||||||
|
public void isSupportEndItem_flagOff_returnsFalse() {
|
||||||
|
doReturn(true).when(sMediaOutputIndicatorWorker).isBroadcastSupported();
|
||||||
|
doReturn(false).when(sMediaOutputIndicatorWorker).isDeviceBroadcasting();
|
||||||
|
doReturn(mDevice1).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice();
|
||||||
|
|
||||||
|
assertThat(mController.isSupportEndItem()).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@RequiresFlagsEnabled(Flags.FLAG_LEGACY_LE_AUDIO_SHARING)
|
||||||
public void isSupportEndItem_withBleDevice_returnsTrue() {
|
public void isSupportEndItem_withBleDevice_returnsTrue() {
|
||||||
doReturn(true).when(sMediaOutputIndicatorWorker).isBroadcastSupported();
|
doReturn(true).when(sMediaOutputIndicatorWorker).isBroadcastSupported();
|
||||||
doReturn(false).when(sMediaOutputIndicatorWorker).isDeviceBroadcasting();
|
doReturn(false).when(sMediaOutputIndicatorWorker).isDeviceBroadcasting();
|
||||||
@@ -121,6 +138,7 @@ public class MediaVolumePreferenceControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@RequiresFlagsEnabled(Flags.FLAG_LEGACY_LE_AUDIO_SHARING)
|
||||||
public void isSupportEndItem_notSupportedBroadcast_returnsFalse() {
|
public void isSupportEndItem_notSupportedBroadcast_returnsFalse() {
|
||||||
doReturn(false).when(sMediaOutputIndicatorWorker).isBroadcastSupported();
|
doReturn(false).when(sMediaOutputIndicatorWorker).isBroadcastSupported();
|
||||||
doReturn(mDevice1).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice();
|
doReturn(mDevice1).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice();
|
||||||
@@ -129,6 +147,7 @@ public class MediaVolumePreferenceControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@RequiresFlagsEnabled(Flags.FLAG_LEGACY_LE_AUDIO_SHARING)
|
||||||
public void isSupportEndItem_withNonBleDevice_returnsFalse() {
|
public void isSupportEndItem_withNonBleDevice_returnsFalse() {
|
||||||
doReturn(true).when(sMediaOutputIndicatorWorker).isBroadcastSupported();
|
doReturn(true).when(sMediaOutputIndicatorWorker).isBroadcastSupported();
|
||||||
doReturn(false).when(sMediaOutputIndicatorWorker).isDeviceBroadcasting();
|
doReturn(false).when(sMediaOutputIndicatorWorker).isDeviceBroadcasting();
|
||||||
@@ -138,6 +157,7 @@ public class MediaVolumePreferenceControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@RequiresFlagsEnabled(Flags.FLAG_LEGACY_LE_AUDIO_SHARING)
|
||||||
public void isSupportEndItem_deviceIsBroadcastingAndConnectedToNonBleDevice_returnsTrue() {
|
public void isSupportEndItem_deviceIsBroadcastingAndConnectedToNonBleDevice_returnsTrue() {
|
||||||
doReturn(true).when(sMediaOutputIndicatorWorker).isBroadcastSupported();
|
doReturn(true).when(sMediaOutputIndicatorWorker).isBroadcastSupported();
|
||||||
doReturn(true).when(sMediaOutputIndicatorWorker).isDeviceBroadcasting();
|
doReturn(true).when(sMediaOutputIndicatorWorker).isDeviceBroadcasting();
|
||||||
@@ -147,6 +167,7 @@ public class MediaVolumePreferenceControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@RequiresFlagsEnabled(Flags.FLAG_LEGACY_LE_AUDIO_SHARING)
|
||||||
public void isSupportEndItem_deviceIsNotBroadcastingAndConnectedToNonBleDevice_returnsFalse() {
|
public void isSupportEndItem_deviceIsNotBroadcastingAndConnectedToNonBleDevice_returnsFalse() {
|
||||||
doReturn(true).when(sMediaOutputIndicatorWorker).isBroadcastSupported();
|
doReturn(true).when(sMediaOutputIndicatorWorker).isBroadcastSupported();
|
||||||
doReturn(false).when(sMediaOutputIndicatorWorker).isDeviceBroadcasting();
|
doReturn(false).when(sMediaOutputIndicatorWorker).isDeviceBroadcasting();
|
||||||
@@ -155,8 +176,20 @@ public class MediaVolumePreferenceControllerTest {
|
|||||||
assertThat(mController.isSupportEndItem()).isFalse();
|
assertThat(mController.isSupportEndItem()).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@RequiresFlagsDisabled(Flags.FLAG_LEGACY_LE_AUDIO_SHARING)
|
||||||
|
public void getSliceEndItem_flagOff_getsNullSliceAction() {
|
||||||
|
doReturn(true).when(sMediaOutputIndicatorWorker).isBroadcastSupported();
|
||||||
|
doReturn(true).when(sMediaOutputIndicatorWorker).isDeviceBroadcasting();
|
||||||
|
doReturn(mDevice2).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice();
|
||||||
|
|
||||||
|
final SliceAction sliceAction = mController.getSliceEndItem(mContext);
|
||||||
|
|
||||||
|
assertThat(sliceAction).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@RequiresFlagsEnabled(Flags.FLAG_LEGACY_LE_AUDIO_SHARING)
|
||||||
public void getSliceEndItem_NotSupportEndItem_getsNullSliceAction() {
|
public void getSliceEndItem_NotSupportEndItem_getsNullSliceAction() {
|
||||||
doReturn(true).when(sMediaOutputIndicatorWorker).isBroadcastSupported();
|
doReturn(true).when(sMediaOutputIndicatorWorker).isBroadcastSupported();
|
||||||
doReturn(false).when(sMediaOutputIndicatorWorker).isDeviceBroadcasting();
|
doReturn(false).when(sMediaOutputIndicatorWorker).isDeviceBroadcasting();
|
||||||
@@ -168,22 +201,26 @@ public class MediaVolumePreferenceControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@RequiresFlagsEnabled(Flags.FLAG_LEGACY_LE_AUDIO_SHARING)
|
||||||
public void getSliceEndItem_deviceIsBroadcasting_getsBroadcastIntent() {
|
public void getSliceEndItem_deviceIsBroadcasting_getsBroadcastIntent() {
|
||||||
doReturn(true).when(sMediaOutputIndicatorWorker).isBroadcastSupported();
|
doReturn(true).when(sMediaOutputIndicatorWorker).isBroadcastSupported();
|
||||||
doReturn(mDevice1).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice();
|
doReturn(mDevice1).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice();
|
||||||
doReturn(true).when(sMediaOutputIndicatorWorker).isDeviceBroadcasting();
|
doReturn(true).when(sMediaOutputIndicatorWorker).isDeviceBroadcasting();
|
||||||
doReturn(mMediaController).when(sMediaOutputIndicatorWorker)
|
doReturn(mMediaController)
|
||||||
|
.when(sMediaOutputIndicatorWorker)
|
||||||
.getActiveLocalMediaController();
|
.getActiveLocalMediaController();
|
||||||
|
|
||||||
final SliceAction sliceAction = mController.getSliceEndItem(mContext);
|
final SliceAction sliceAction = mController.getSliceEndItem(mContext);
|
||||||
|
|
||||||
final PendingIntent endItemPendingIntent = sliceAction.getAction();
|
final PendingIntent endItemPendingIntent = sliceAction.getAction();
|
||||||
final PendingIntent expectedToggleIntent = getBroadcastIntent(
|
final PendingIntent expectedToggleIntent =
|
||||||
MediaOutputConstants.ACTION_LAUNCH_MEDIA_OUTPUT_BROADCAST_DIALOG);
|
getBroadcastIntent(
|
||||||
|
MediaOutputConstants.ACTION_LAUNCH_MEDIA_OUTPUT_BROADCAST_DIALOG);
|
||||||
assertThat(endItemPendingIntent).isEqualTo(expectedToggleIntent);
|
assertThat(endItemPendingIntent).isEqualTo(expectedToggleIntent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@RequiresFlagsEnabled(Flags.FLAG_LEGACY_LE_AUDIO_SHARING)
|
||||||
public void getSliceEndItem_deviceIsNotBroadcasting_getsActivityIntent() {
|
public void getSliceEndItem_deviceIsNotBroadcasting_getsActivityIntent() {
|
||||||
final MediaDevice device = mock(BluetoothMediaDevice.class);
|
final MediaDevice device = mock(BluetoothMediaDevice.class);
|
||||||
final CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class);
|
final CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class);
|
||||||
@@ -192,7 +229,8 @@ public class MediaVolumePreferenceControllerTest {
|
|||||||
doReturn(true).when(sMediaOutputIndicatorWorker).isBroadcastSupported();
|
doReturn(true).when(sMediaOutputIndicatorWorker).isBroadcastSupported();
|
||||||
doReturn(device).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice();
|
doReturn(device).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice();
|
||||||
doReturn(false).when(sMediaOutputIndicatorWorker).isDeviceBroadcasting();
|
doReturn(false).when(sMediaOutputIndicatorWorker).isDeviceBroadcasting();
|
||||||
doReturn(mMediaController).when(sMediaOutputIndicatorWorker)
|
doReturn(mMediaController)
|
||||||
|
.when(sMediaOutputIndicatorWorker)
|
||||||
.getActiveLocalMediaController();
|
.getActiveLocalMediaController();
|
||||||
|
|
||||||
final SliceAction sliceAction = mController.getSliceEndItem(mContext);
|
final SliceAction sliceAction = mController.getSliceEndItem(mContext);
|
||||||
@@ -215,13 +253,19 @@ public class MediaVolumePreferenceControllerTest {
|
|||||||
private PendingIntent getBroadcastIntent(String action) {
|
private PendingIntent getBroadcastIntent(String action) {
|
||||||
final Intent intent = new Intent(action);
|
final Intent intent = new Intent(action);
|
||||||
intent.setPackage(MediaOutputConstants.SYSTEMUI_PACKAGE_NAME);
|
intent.setPackage(MediaOutputConstants.SYSTEMUI_PACKAGE_NAME);
|
||||||
return PendingIntent.getBroadcast(mContext, 0 /* requestCode */, intent,
|
return PendingIntent.getBroadcast(
|
||||||
|
mContext,
|
||||||
|
0 /* requestCode */,
|
||||||
|
intent,
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
|
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private PendingIntent getActivityIntent(String action) {
|
private PendingIntent getActivityIntent(String action) {
|
||||||
final Intent intent = new Intent(action);
|
final Intent intent = new Intent(action);
|
||||||
return PendingIntent.getActivity(mContext, 0 /* requestCode */, intent,
|
return PendingIntent.getActivity(
|
||||||
|
mContext,
|
||||||
|
0 /* requestCode */,
|
||||||
|
intent,
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
|
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ import com.android.settings.testutils.shadow.ShadowDevicePolicyManager;
|
|||||||
import com.android.settings.testutils.shadow.ShadowUserManager;
|
import com.android.settings.testutils.shadow.ShadowUserManager;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.robolectric.Robolectric;
|
import org.robolectric.Robolectric;
|
||||||
@@ -44,7 +43,6 @@ import org.robolectric.annotation.Config;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Ignore("b/315133235")
|
|
||||||
@RunWith(RobolectricTestRunner.class)
|
@RunWith(RobolectricTestRunner.class)
|
||||||
@Config(shadows = {ShadowUserManager.class, ShadowDevicePolicyManager.class})
|
@Config(shadows = {ShadowUserManager.class, ShadowDevicePolicyManager.class})
|
||||||
public class RestrictedButtonTest {
|
public class RestrictedButtonTest {
|
||||||
|
|||||||
@@ -35,18 +35,19 @@ import android.widget.ImageView;
|
|||||||
|
|
||||||
import androidx.preference.PreferenceFragmentCompat;
|
import androidx.preference.PreferenceFragmentCompat;
|
||||||
import androidx.preference.PreferenceViewHolder;
|
import androidx.preference.PreferenceViewHolder;
|
||||||
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.testutils.shadow.ShadowSettingsMediaPlayer;
|
import com.android.settings.testutils.shadow.ShadowSettingsMediaPlayer;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Ignore;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.junit.MockitoJUnit;
|
||||||
|
import org.mockito.junit.MockitoRule;
|
||||||
import org.robolectric.RobolectricTestRunner;
|
import org.robolectric.RobolectricTestRunner;
|
||||||
import org.robolectric.RuntimeEnvironment;
|
|
||||||
import org.robolectric.annotation.Config;
|
import org.robolectric.annotation.Config;
|
||||||
import org.robolectric.shadows.androidx.fragment.FragmentController;
|
import org.robolectric.shadows.androidx.fragment.FragmentController;
|
||||||
|
|
||||||
@@ -55,7 +56,8 @@ import org.robolectric.shadows.androidx.fragment.FragmentController;
|
|||||||
public class VideoPreferenceTest {
|
public class VideoPreferenceTest {
|
||||||
private static final int VIDEO_WIDTH = 100;
|
private static final int VIDEO_WIDTH = 100;
|
||||||
private static final int VIDEO_HEIGHT = 150;
|
private static final int VIDEO_HEIGHT = 150;
|
||||||
|
@Rule
|
||||||
|
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||||
private VideoPreference.AnimationController mAnimationController;
|
private VideoPreference.AnimationController mAnimationController;
|
||||||
@Mock
|
@Mock
|
||||||
private ImageView fakePreview;
|
private ImageView fakePreview;
|
||||||
@@ -68,9 +70,7 @@ public class VideoPreferenceTest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
MockitoAnnotations.initMocks(this);
|
mContext = ApplicationProvider.getApplicationContext();
|
||||||
|
|
||||||
mContext = RuntimeEnvironment.application;
|
|
||||||
mAnimationController = spy(
|
mAnimationController = spy(
|
||||||
new MediaAnimationController(mContext, R.raw.sample_video));
|
new MediaAnimationController(mContext, R.raw.sample_video));
|
||||||
mVideoPreference = new VideoPreference(mContext, null /* attrs */);
|
mVideoPreference = new VideoPreference(mContext, null /* attrs */);
|
||||||
@@ -141,7 +141,6 @@ public class VideoPreferenceTest {
|
|||||||
assertThat(mAnimationController.isPlaying()).isTrue();
|
assertThat(mAnimationController.isPlaying()).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Ignore("b/315133235")
|
|
||||||
@Test
|
@Test
|
||||||
@Config(qualifiers = "mcc999")
|
@Config(qualifiers = "mcc999")
|
||||||
public void onViewVisible_createAnimationController() {
|
public void onViewVisible_createAnimationController() {
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ import android.content.Context
|
|||||||
import android.net.wifi.WifiManager
|
import android.net.wifi.WifiManager
|
||||||
import androidx.compose.ui.test.assertIsOff
|
import androidx.compose.ui.test.assertIsOff
|
||||||
import androidx.compose.ui.test.assertIsOn
|
import androidx.compose.ui.test.assertIsOn
|
||||||
|
import androidx.compose.ui.test.isDisplayed
|
||||||
|
import androidx.compose.ui.test.isNotDisplayed
|
||||||
import androidx.compose.ui.test.junit4.createComposeRule
|
import androidx.compose.ui.test.junit4.createComposeRule
|
||||||
import androidx.compose.ui.test.onNodeWithText
|
import androidx.compose.ui.test.onNodeWithText
|
||||||
import androidx.compose.ui.test.onRoot
|
import androidx.compose.ui.test.onRoot
|
||||||
@@ -28,12 +30,16 @@ import androidx.preference.PreferenceManager
|
|||||||
import androidx.test.core.app.ApplicationProvider
|
import androidx.test.core.app.ApplicationProvider
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import com.android.settings.R
|
import com.android.settings.R
|
||||||
|
import com.android.settings.dashboard.DashboardFragment
|
||||||
import com.android.settings.spa.preference.ComposePreference
|
import com.android.settings.spa.preference.ComposePreference
|
||||||
|
import com.android.settingslib.spa.testutils.onDialogText
|
||||||
|
import com.android.wifitrackerlib.WifiEntry
|
||||||
import java.util.function.Consumer
|
import java.util.function.Consumer
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
import org.mockito.Mockito
|
||||||
import org.mockito.kotlin.any
|
import org.mockito.kotlin.any
|
||||||
import org.mockito.kotlin.doAnswer
|
import org.mockito.kotlin.doAnswer
|
||||||
import org.mockito.kotlin.doReturn
|
import org.mockito.kotlin.doReturn
|
||||||
@@ -48,25 +54,30 @@ class WepNetworksPreferenceControllerTest {
|
|||||||
|
|
||||||
private var wepAllowed = true
|
private var wepAllowed = true
|
||||||
|
|
||||||
private val mockWifiManager = mock<WifiManager> {
|
private var mockWifiInfo = mock<android.net.wifi.WifiInfo> {
|
||||||
|
on { it.currentSecurityType } doReturn WifiEntry.SECURITY_EAP
|
||||||
|
on { it.ssid } doReturn SSID
|
||||||
|
}
|
||||||
|
|
||||||
|
private var mockWifiManager = mock<WifiManager> {
|
||||||
on { queryWepAllowed(any(), any()) } doAnswer {
|
on { queryWepAllowed(any(), any()) } doAnswer {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
val consumer = it.arguments[1] as Consumer<Boolean>
|
val consumer = it.arguments[1] as Consumer<Boolean>
|
||||||
consumer.accept(wepAllowed)
|
consumer.accept(wepAllowed)
|
||||||
}
|
}
|
||||||
on { it.isWepSupported } doReturn true
|
on { it.isWepSupported } doReturn true
|
||||||
|
on { it.connectionInfo } doReturn mockWifiInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
private var context: Context =
|
private var context: Context =
|
||||||
spy(ApplicationProvider.getApplicationContext()) {
|
spy(ApplicationProvider.getApplicationContext()) {
|
||||||
on { getSystemService(WifiManager::class.java) } doReturn mockWifiManager
|
on { getSystemService(WifiManager::class.java) } doReturn mockWifiManager
|
||||||
}
|
}
|
||||||
private var controller = WepNetworksPreferenceController(context, TEST_KEY)
|
|
||||||
|
|
||||||
|
private var controller = WepNetworksPreferenceController(context, TEST_KEY)
|
||||||
private val preference = ComposePreference(context).apply { key = TEST_KEY }
|
private val preference = ComposePreference(context).apply { key = TEST_KEY }
|
||||||
private val preferenceScreen = PreferenceManager(context).createPreferenceScreen(context)
|
private val preferenceScreen = PreferenceManager(context).createPreferenceScreen(context)
|
||||||
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
preferenceScreen.addPreference(preference)
|
preferenceScreen.addPreference(preference)
|
||||||
@@ -79,6 +90,7 @@ class WepNetworksPreferenceControllerTest {
|
|||||||
composeTestRule.setContent {
|
composeTestRule.setContent {
|
||||||
controller.Content()
|
controller.Content()
|
||||||
}
|
}
|
||||||
|
|
||||||
composeTestRule.onNodeWithText(context.getString(R.string.wifi_allow_wep_networks))
|
composeTestRule.onNodeWithText(context.getString(R.string.wifi_allow_wep_networks))
|
||||||
.assertIsOn()
|
.assertIsOn()
|
||||||
}
|
}
|
||||||
@@ -89,6 +101,7 @@ class WepNetworksPreferenceControllerTest {
|
|||||||
composeTestRule.setContent {
|
composeTestRule.setContent {
|
||||||
controller.Content()
|
controller.Content()
|
||||||
}
|
}
|
||||||
|
|
||||||
composeTestRule.onNodeWithText(context.getString(R.string.wifi_allow_wep_networks))
|
composeTestRule.onNodeWithText(context.getString(R.string.wifi_allow_wep_networks))
|
||||||
.assertIsOff()
|
.assertIsOff()
|
||||||
}
|
}
|
||||||
@@ -101,7 +114,6 @@ class WepNetworksPreferenceControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
composeTestRule.onRoot().performClick()
|
composeTestRule.onRoot().performClick()
|
||||||
|
|
||||||
composeTestRule.onNodeWithText(context.getString(R.string.wifi_allow_wep_networks))
|
composeTestRule.onNodeWithText(context.getString(R.string.wifi_allow_wep_networks))
|
||||||
.assertIsOn()
|
.assertIsOn()
|
||||||
}
|
}
|
||||||
@@ -114,12 +126,38 @@ class WepNetworksPreferenceControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
composeTestRule.onRoot().performClick()
|
composeTestRule.onRoot().performClick()
|
||||||
|
|
||||||
composeTestRule.onNodeWithText(context.getString(R.string.wifi_allow_wep_networks))
|
composeTestRule.onNodeWithText(context.getString(R.string.wifi_allow_wep_networks))
|
||||||
.assertIsOff()
|
.assertIsOff()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun whenClick_wepAllowed_openDialog() {
|
||||||
|
wepAllowed = true
|
||||||
|
Mockito.`when`(mockWifiInfo.currentSecurityType).thenReturn(WifiEntry.SECURITY_WEP)
|
||||||
|
composeTestRule.setContent {
|
||||||
|
controller.Content()
|
||||||
|
}
|
||||||
|
|
||||||
|
composeTestRule.onRoot().performClick()
|
||||||
|
composeTestRule.onDialogText(context.getString(R.string.wifi_disconnect_button_text))
|
||||||
|
.isDisplayed()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun whenClick_wepDisallowed_openDialog() {
|
||||||
|
wepAllowed = false
|
||||||
|
Mockito.`when`(mockWifiInfo.currentSecurityType).thenReturn(WifiEntry.SECURITY_WEP)
|
||||||
|
composeTestRule.setContent {
|
||||||
|
controller.Content()
|
||||||
|
}
|
||||||
|
|
||||||
|
composeTestRule.onRoot().performClick()
|
||||||
|
composeTestRule.onDialogText(context.getString(R.string.wifi_disconnect_button_text))
|
||||||
|
.isNotDisplayed()
|
||||||
|
}
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
const val TEST_KEY = "test_key"
|
const val TEST_KEY = "test_key"
|
||||||
|
const val SSID = "ssid"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -26,6 +26,7 @@ android_test {
|
|||||||
"androidx.test.rules",
|
"androidx.test.rules",
|
||||||
"androidx.test.ext.junit",
|
"androidx.test.ext.junit",
|
||||||
"androidx.preference_preference",
|
"androidx.preference_preference",
|
||||||
|
"flag-junit",
|
||||||
"mockito-target-minus-junit4",
|
"mockito-target-minus-junit4",
|
||||||
"platform-test-annotations",
|
"platform-test-annotations",
|
||||||
"platform-test-rules",
|
"platform-test-rules",
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
include platform/packages/modules/Connectivity:/thread/OWNERS
|
||||||
@@ -0,0 +1,255 @@
|
|||||||
|
/*
|
||||||
|
* 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.connecteddevice.threadnetwork
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.thread.ThreadNetworkController.STATE_DISABLED
|
||||||
|
import android.net.thread.ThreadNetworkController.STATE_DISABLING
|
||||||
|
import android.net.thread.ThreadNetworkController.STATE_ENABLED
|
||||||
|
import android.net.thread.ThreadNetworkController.StateCallback
|
||||||
|
import android.net.thread.ThreadNetworkException
|
||||||
|
import android.os.OutcomeReceiver
|
||||||
|
import android.platform.test.flag.junit.SetFlagsRule
|
||||||
|
import android.provider.Settings
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.LifecycleOwner
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
|
import androidx.preference.SwitchPreference
|
||||||
|
import androidx.test.core.app.ApplicationProvider
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
import com.android.net.thread.platform.flags.Flags
|
||||||
|
import com.android.settings.R
|
||||||
|
import com.android.settings.core.BasePreferenceController.AVAILABLE
|
||||||
|
import com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE
|
||||||
|
import com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING
|
||||||
|
import com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE
|
||||||
|
import com.android.settings.connecteddevice.threadnetwork.ThreadNetworkPreferenceController.BaseThreadNetworkController
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mockito.ArgumentCaptor
|
||||||
|
import org.mockito.ArgumentMatchers.any
|
||||||
|
import org.mockito.Mockito.mock
|
||||||
|
import org.mockito.Mockito.spy
|
||||||
|
import org.mockito.Mockito.verify
|
||||||
|
import java.util.concurrent.Executor
|
||||||
|
|
||||||
|
/** Unit tests for [ThreadNetworkPreferenceController]. */
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
class ThreadNetworkPreferenceControllerTest {
|
||||||
|
@get:Rule
|
||||||
|
val mSetFlagsRule = SetFlagsRule()
|
||||||
|
private lateinit var context: Context
|
||||||
|
private lateinit var executor: Executor
|
||||||
|
private lateinit var controller: ThreadNetworkPreferenceController
|
||||||
|
private lateinit var fakeThreadNetworkController: FakeThreadNetworkController
|
||||||
|
private lateinit var preference: SwitchPreference
|
||||||
|
private val broadcastReceiverArgumentCaptor = ArgumentCaptor.forClass(
|
||||||
|
BroadcastReceiver::class.java
|
||||||
|
)
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setUp() {
|
||||||
|
mSetFlagsRule.enableFlags(Flags.FLAG_THREAD_ENABLED_PLATFORM)
|
||||||
|
context = spy(ApplicationProvider.getApplicationContext<Context>())
|
||||||
|
executor = ContextCompat.getMainExecutor(context)
|
||||||
|
fakeThreadNetworkController = FakeThreadNetworkController(executor)
|
||||||
|
controller = newControllerWithThreadFeatureSupported(true)
|
||||||
|
val preferenceManager = PreferenceManager(context)
|
||||||
|
val preferenceScreen = preferenceManager.createPreferenceScreen(context)
|
||||||
|
preference = SwitchPreference(context)
|
||||||
|
preference.key = "thread_network_settings"
|
||||||
|
preferenceScreen.addPreference(preference)
|
||||||
|
controller.displayPreference(preferenceScreen)
|
||||||
|
|
||||||
|
Settings.Global.putInt(context.contentResolver, Settings.Global.AIRPLANE_MODE_ON, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun newControllerWithThreadFeatureSupported(
|
||||||
|
present: Boolean
|
||||||
|
): ThreadNetworkPreferenceController {
|
||||||
|
return ThreadNetworkPreferenceController(
|
||||||
|
context,
|
||||||
|
"thread_network_settings" /* key */,
|
||||||
|
executor,
|
||||||
|
if (present) fakeThreadNetworkController else null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun availabilityStatus_flagDisabled_returnsConditionallyUnavailable() {
|
||||||
|
mSetFlagsRule.disableFlags(Flags.FLAG_THREAD_ENABLED_PLATFORM)
|
||||||
|
assertThat(controller.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun availabilityStatus_airPlaneModeOn_returnsDisabledDependentSetting() {
|
||||||
|
Settings.Global.putInt(context.contentResolver, Settings.Global.AIRPLANE_MODE_ON, 1)
|
||||||
|
controller.onStateChanged(mock(LifecycleOwner::class.java), Lifecycle.Event.ON_START)
|
||||||
|
|
||||||
|
assertThat(controller.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun availabilityStatus_airPlaneModeOff_returnsAvailable() {
|
||||||
|
Settings.Global.putInt(context.contentResolver, Settings.Global.AIRPLANE_MODE_ON, 0)
|
||||||
|
controller.onStateChanged(mock(LifecycleOwner::class.java), Lifecycle.Event.ON_START)
|
||||||
|
|
||||||
|
assertThat(controller.getAvailabilityStatus()).isEqualTo(AVAILABLE)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun availabilityStatus_threadFeatureNotSupported_returnsUnsupported() {
|
||||||
|
controller = newControllerWithThreadFeatureSupported(false)
|
||||||
|
controller.onStateChanged(mock(LifecycleOwner::class.java), Lifecycle.Event.ON_START)
|
||||||
|
|
||||||
|
assertThat(fakeThreadNetworkController.registeredStateCallback).isNull()
|
||||||
|
assertThat(controller.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isChecked_threadSetEnabled_returnsTrue() {
|
||||||
|
fakeThreadNetworkController.setEnabled(true, executor) { }
|
||||||
|
controller.onStateChanged(mock(LifecycleOwner::class.java), Lifecycle.Event.ON_START)
|
||||||
|
|
||||||
|
assertThat(controller.isChecked).isTrue()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isChecked_threadSetDisabled_returnsFalse() {
|
||||||
|
fakeThreadNetworkController.setEnabled(false, executor) { }
|
||||||
|
controller.onStateChanged(mock(LifecycleOwner::class.java), Lifecycle.Event.ON_START)
|
||||||
|
|
||||||
|
assertThat(controller.isChecked).isFalse()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun setChecked_setChecked_threadIsEnabled() {
|
||||||
|
controller.onStateChanged(mock(LifecycleOwner::class.java), Lifecycle.Event.ON_START)
|
||||||
|
|
||||||
|
controller.setChecked(true)
|
||||||
|
|
||||||
|
assertThat(fakeThreadNetworkController.isEnabled).isTrue()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun setChecked_setUnchecked_threadIsDisabled() {
|
||||||
|
controller.onStateChanged(mock(LifecycleOwner::class.java), Lifecycle.Event.ON_START)
|
||||||
|
|
||||||
|
controller.setChecked(false)
|
||||||
|
|
||||||
|
assertThat(fakeThreadNetworkController.isEnabled).isFalse()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun updatePreference_airPlaneModeOff_preferenceEnabled() {
|
||||||
|
Settings.Global.putInt(context.contentResolver, Settings.Global.AIRPLANE_MODE_ON, 0)
|
||||||
|
controller.onStateChanged(mock(LifecycleOwner::class.java), Lifecycle.Event.ON_START)
|
||||||
|
|
||||||
|
assertThat(preference.isEnabled).isTrue()
|
||||||
|
assertThat(preference.summary).isEqualTo(
|
||||||
|
context.resources.getString(R.string.thread_network_settings_summary)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun updatePreference_airPlaneModeOn_preferenceDisabled() {
|
||||||
|
Settings.Global.putInt(context.contentResolver, Settings.Global.AIRPLANE_MODE_ON, 1)
|
||||||
|
controller.onStateChanged(mock(LifecycleOwner::class.java), Lifecycle.Event.ON_START)
|
||||||
|
|
||||||
|
assertThat(preference.isEnabled).isFalse()
|
||||||
|
assertThat(preference.summary).isEqualTo(
|
||||||
|
context.resources.getString(R.string.thread_network_settings_summary_airplane_mode)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun updatePreference_airPlaneModeTurnedOn_preferenceDisabled() {
|
||||||
|
Settings.Global.putInt(context.contentResolver, Settings.Global.AIRPLANE_MODE_ON, 0)
|
||||||
|
startControllerAndCaptureCallbacks()
|
||||||
|
|
||||||
|
Settings.Global.putInt(context.contentResolver, Settings.Global.AIRPLANE_MODE_ON, 1)
|
||||||
|
broadcastReceiverArgumentCaptor.value.onReceive(context, Intent())
|
||||||
|
|
||||||
|
assertThat(preference.isEnabled).isFalse()
|
||||||
|
assertThat(preference.summary).isEqualTo(
|
||||||
|
context.resources.getString(R.string.thread_network_settings_summary_airplane_mode)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startControllerAndCaptureCallbacks() {
|
||||||
|
controller.onStateChanged(mock(LifecycleOwner::class.java), Lifecycle.Event.ON_START)
|
||||||
|
verify(context)!!.registerReceiver(broadcastReceiverArgumentCaptor.capture(), any())
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FakeThreadNetworkController(private val executor: Executor) :
|
||||||
|
BaseThreadNetworkController {
|
||||||
|
var isEnabled = true
|
||||||
|
private set
|
||||||
|
var registeredStateCallback: StateCallback? = null
|
||||||
|
private set
|
||||||
|
|
||||||
|
override fun setEnabled(
|
||||||
|
enabled: Boolean,
|
||||||
|
executor: Executor,
|
||||||
|
receiver: OutcomeReceiver<Void?, ThreadNetworkException>
|
||||||
|
) {
|
||||||
|
isEnabled = enabled
|
||||||
|
if (registeredStateCallback != null) {
|
||||||
|
if (!isEnabled) {
|
||||||
|
executor.execute {
|
||||||
|
registeredStateCallback!!.onThreadEnableStateChanged(
|
||||||
|
STATE_DISABLING
|
||||||
|
)
|
||||||
|
}
|
||||||
|
executor.execute {
|
||||||
|
registeredStateCallback!!.onThreadEnableStateChanged(
|
||||||
|
STATE_DISABLED
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
executor.execute {
|
||||||
|
registeredStateCallback!!.onThreadEnableStateChanged(
|
||||||
|
STATE_ENABLED
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
executor.execute { receiver.onResult(null) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun registerStateCallback(
|
||||||
|
executor: Executor,
|
||||||
|
callback: StateCallback
|
||||||
|
) {
|
||||||
|
require(callback !== registeredStateCallback) { "callback is already registered" }
|
||||||
|
registeredStateCallback = callback
|
||||||
|
val enabledState =
|
||||||
|
if (isEnabled) STATE_ENABLED else STATE_DISABLED
|
||||||
|
executor.execute { registeredStateCallback!!.onThreadEnableStateChanged(enabledState) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun unregisterStateCallback(callback: StateCallback) {
|
||||||
|
requireNotNull(registeredStateCallback) { "callback is already unregistered" }
|
||||||
|
registeredStateCallback = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user