Merge "Remove overload ImeVisibilityApplier#applyImeVisibility" into main
diff --git a/core/api/current.txt b/core/api/current.txt
index 44a6c6b..5456c15 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -43901,6 +43901,7 @@
field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT = "satellite_connection_hysteresis_sec_int";
field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String KEY_SATELLITE_ENTITLEMENT_STATUS_REFRESH_DAYS_INT = "satellite_entitlement_status_refresh_days_int";
field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL = "satellite_entitlement_supported_bool";
+ field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_SATELLITE_ESOS_SUPPORTED_BOOL = "satellite_esos_supported_bool";
field public static final String KEY_SHOW_4G_FOR_3G_DATA_ICON_BOOL = "show_4g_for_3g_data_icon_bool";
field public static final String KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL = "show_4g_for_lte_data_icon_bool";
field public static final String KEY_SHOW_APN_SETTING_CDMA_BOOL = "show_apn_setting_cdma_bool";
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 2313fa2..5214d2c 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -2981,9 +2981,7 @@
new AppOpInfo.Builder(OP_ESTABLISH_VPN_MANAGER, OPSTR_ESTABLISH_VPN_MANAGER,
"ESTABLISH_VPN_MANAGER").setDefaultMode(AppOpsManager.MODE_ALLOWED).build(),
new AppOpInfo.Builder(OP_ACCESS_RESTRICTED_SETTINGS, OPSTR_ACCESS_RESTRICTED_SETTINGS,
- "ACCESS_RESTRICTED_SETTINGS").setDefaultMode(
- android.permission.flags.Flags.enhancedConfirmationModeApisEnabled()
- ? MODE_DEFAULT : MODE_ALLOWED)
+ "ACCESS_RESTRICTED_SETTINGS").setDefaultMode(AppOpsManager.MODE_ALLOWED)
.setDisableReset(true).setRestrictRead(true).build(),
new AppOpInfo.Builder(OP_RECEIVE_AMBIENT_TRIGGER_AUDIO, OPSTR_RECEIVE_AMBIENT_TRIGGER_AUDIO,
"RECEIVE_SOUNDTRIGGER_AUDIO").setDefaultMode(AppOpsManager.MODE_ALLOWED)
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 88bd87e..d019bad 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -4940,7 +4940,7 @@
*
* @hide
*/
- public static final String COLUMN_IS_NTN = "is_ntn";
+ public static final String COLUMN_IS_ONLY_NTN = "is_only_ntn";
/**
* TelephonyProvider column name for transferred status
@@ -4976,6 +4976,15 @@
public static final String COLUMN_SATELLITE_ENTITLEMENT_PLMNS =
"satellite_entitlement_plmns";
+ /**
+ * TelephonyProvider column name to indicate the satellite ESOS supported. The value of this
+ * column is set based on {@link CarrierConfigManager#KEY_SATELLITE_ESOS_SUPPORTED_BOOL}.
+ * By default, it's disabled.
+ *
+ * @hide
+ */
+ public static final String COLUMN_SATELLITE_ESOS_SUPPORTED = "satellite_esos_supported";
+
/** All columns in {@link SimInfo} table. */
private static final List<String> ALL_COLUMNS = List.of(
COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID,
@@ -5047,11 +5056,12 @@
COLUMN_USER_HANDLE,
COLUMN_SATELLITE_ENABLED,
COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER,
- COLUMN_IS_NTN,
+ COLUMN_IS_ONLY_NTN,
COLUMN_SERVICE_CAPABILITIES,
COLUMN_TRANSFER_STATUS,
COLUMN_SATELLITE_ENTITLEMENT_STATUS,
- COLUMN_SATELLITE_ENTITLEMENT_PLMNS
+ COLUMN_SATELLITE_ENTITLEMENT_PLMNS,
+ COLUMN_SATELLITE_ESOS_SUPPORTED
);
/**
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 212dae2..177ba598 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -233,7 +233,6 @@
<item type="id" name="smart_space_barrier_bottom" />
<item type="id" name="small_clock_guideline_top" />
<item type="id" name="weather_clock_date_and_icons_barrier_bottom" />
- <item type="id" name="weather_clock_bc_smartspace_bottom" />
<item type="id" name="accessibility_actions_view" />
<!-- Privacy dialog -->
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinder.kt
index e063380..f2821a0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardClockViewBinder.kt
@@ -37,10 +37,6 @@
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.plugins.clocks.AodClockBurnInModel
import com.android.systemui.plugins.clocks.ClockController
-import com.android.systemui.util.ui.value
-import kotlinx.coroutines.flow.combine
-import kotlinx.coroutines.flow.distinctUntilChanged
-import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
object KeyguardClockViewBinder {
@@ -103,20 +99,15 @@
launch {
if (!MigrateClocksToBlueprint.isEnabled) return@launch
- combine(
- viewModel.hasAodIcons,
- rootViewModel.isNotifIconContainerVisible.map { it.value }
- ) { hasIcon, isVisible ->
- hasIcon && isVisible
- }
- .distinctUntilChanged()
- .collect { _ ->
- viewModel.currentClock.value?.let {
- if (it.config.useCustomClockScene) {
- blueprintInteractor.refreshBlueprint(Type.DefaultTransition)
- }
+ viewModel.isAodIconsVisible.collect {
+ viewModel.currentClock.value?.let {
+ if (
+ viewModel.isLargeClockVisible.value && it.config.useCustomClockScene
+ ) {
+ blueprintInteractor.refreshBlueprint(Type.DefaultTransition)
}
}
+ }
}
launch {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt
index 0637bba..34a1da5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSection.kt
@@ -45,7 +45,6 @@
import com.android.systemui.plugins.clocks.ClockFaceLayout
import com.android.systemui.res.R
import com.android.systemui.shared.R as sharedR
-import com.android.systemui.util.ui.value
import dagger.Lazy
import javax.inject.Inject
@@ -71,7 +70,6 @@
private val rootViewModel: KeyguardRootViewModel,
) : KeyguardSection() {
override fun addViews(constraintLayout: ConstraintLayout) {}
-
override fun bindData(constraintLayout: ConstraintLayout) {
if (!MigrateClocksToBlueprint.isEnabled) {
return
@@ -123,39 +121,35 @@
private fun getTargetClockFace(clock: ClockController): ClockFaceLayout =
if (keyguardClockViewModel.isLargeClockVisible.value) clock.largeClock.layout
else clock.smallClock.layout
-
private fun getNonTargetClockFace(clock: ClockController): ClockFaceLayout =
if (keyguardClockViewModel.isLargeClockVisible.value) clock.smallClock.layout
else clock.largeClock.layout
fun constrainWeatherClockDateIconsBarrier(constraints: ConstraintSet) {
constraints.apply {
- createBarrier(
- R.id.weather_clock_bc_smartspace_bottom,
- Barrier.BOTTOM,
- getDimen(ENHANCED_SMARTSPACE_HEIGHT),
- (custR.id.weather_clock_time)
- )
- if (
- rootViewModel.isNotifIconContainerVisible.value.value &&
- keyguardClockViewModel.hasAodIcons.value
- ) {
+ if (keyguardClockViewModel.isAodIconsVisible.value) {
createBarrier(
R.id.weather_clock_date_and_icons_barrier_bottom,
Barrier.BOTTOM,
0,
- *intArrayOf(
- R.id.aod_notification_icon_container,
- R.id.weather_clock_bc_smartspace_bottom
- )
+ *intArrayOf(sharedR.id.bc_smartspace_view, R.id.aod_notification_icon_container)
)
} else {
- createBarrier(
- R.id.weather_clock_date_and_icons_barrier_bottom,
- Barrier.BOTTOM,
- 0,
- *intArrayOf(R.id.weather_clock_bc_smartspace_bottom)
- )
+ if (smartspaceViewModel.bcSmartspaceVisibility.value == VISIBLE) {
+ createBarrier(
+ R.id.weather_clock_date_and_icons_barrier_bottom,
+ Barrier.BOTTOM,
+ 0,
+ (sharedR.id.bc_smartspace_view)
+ )
+ } else {
+ createBarrier(
+ R.id.weather_clock_date_and_icons_barrier_bottom,
+ Barrier.BOTTOM,
+ getDimen(ENHANCED_SMARTSPACE_HEIGHT),
+ (R.id.lockscreen_clock_view)
+ )
+ }
}
}
}
@@ -204,7 +198,6 @@
companion object {
private const val DATE_WEATHER_VIEW_HEIGHT = "date_weather_view_height"
private const val ENHANCED_SMARTSPACE_HEIGHT = "enhanced_smartspace_height"
-
fun getDimen(context: Context, name: String): Int {
val res = context.packageManager.getResourcesForApplication(context.packageName)
val id = res.getIdentifier(name, "dimen", context.packageName)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt
index 573b75e..f5c521a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt
@@ -31,6 +31,7 @@
import com.android.systemui.res.R
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.shade.shared.model.ShadeMode
+import com.android.systemui.statusbar.notification.domain.interactor.NotificationsKeyguardInteractor
import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerAlwaysOnDisplayViewModel
import com.android.systemui.statusbar.ui.SystemBarUtilsProxy
import javax.inject.Inject
@@ -49,6 +50,7 @@
keyguardClockInteractor: KeyguardClockInteractor,
@Application private val applicationScope: CoroutineScope,
aodNotificationIconViewModel: NotificationIconContainerAlwaysOnDisplayViewModel,
+ notifsKeyguardInteractor: NotificationsKeyguardInteractor,
@get:VisibleForTesting val shadeInteractor: ShadeInteractor,
private val systemBarUtils: SystemBarUtilsProxy,
configurationInteractor: ConfigurationInteractor,
@@ -88,13 +90,14 @@
currentClock?.let { clock ->
val face = if (isLargeClock) clock.largeClock else clock.smallClock
face.config.hasCustomWeatherDataDisplay
- } ?: false
+ }
+ ?: false
}
.stateIn(
scope = applicationScope,
started = SharingStarted.WhileSubscribed(),
- initialValue =
- currentClock.value?.largeClock?.config?.hasCustomWeatherDataDisplay ?: false
+ initialValue = currentClock.value?.largeClock?.config?.hasCustomWeatherDataDisplay
+ ?: false
)
val clockShouldBeCentered: StateFlow<Boolean> =
@@ -106,14 +109,15 @@
// To translate elements below smartspace in weather clock to avoid overlapping between date
// element in weather clock and aod icons
- val hasAodIcons: StateFlow<Boolean> =
- aodNotificationIconViewModel.icons
- .map { it.visibleIcons.isNotEmpty() }
- .stateIn(
- scope = applicationScope,
- started = SharingStarted.WhileSubscribed(),
- initialValue = false
- )
+ val isAodIconsVisible: StateFlow<Boolean> = combine(aodNotificationIconViewModel.icons.map {
+ it.visibleIcons.isNotEmpty()
+ }, notifsKeyguardInteractor.areNotificationsFullyHidden) { hasIcons, visible ->
+ hasIcons && visible
+ }.stateIn(
+ scope = applicationScope,
+ started = SharingStarted.WhileSubscribed(),
+ initialValue = false
+ )
val currentClockLayout: StateFlow<ClockLayout> =
combine(
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
index 25a9e9e..ef01194 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
@@ -167,6 +167,10 @@
initialValue = isVisibleInternal()
)
+ /** Whether there's an ongoing remotely-initiated user interaction. */
+ val isRemoteUserInteractionOngoing: StateFlow<Boolean> =
+ repository.isRemoteUserInteractionOngoing
+
/**
* The amount of transition into or out of the given [scene].
*
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 2f3fc729..c1eb8bc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -1276,7 +1276,7 @@
mPowerPluggedInWired = status.isPluggedInWired() && isChargingOrFull;
mPowerPluggedInWireless = status.isPluggedInWireless() && isChargingOrFull;
mPowerPluggedInDock = status.isPluggedInDock() && isChargingOrFull;
- mPowerPluggedIn = status.isPluggedIn() && isChargingOrFull;
+ mPowerPluggedIn = isPowerPluggedIn(status, isChargingOrFull);
mPowerCharged = status.isCharged();
mChargingWattage = status.maxChargingWattage;
mChargingSpeed = status.getChargingSpeed(mContext);
@@ -1562,6 +1562,11 @@
return status.isBatteryDefender();
}
+ /** Return true if the device has power plugged in. */
+ protected boolean isPowerPluggedIn(BatteryStatus status, boolean isChargingOrFull) {
+ return status.isPluggedIn() && isChargingOrFull;
+ }
+
private boolean isCurrentUser(int userId) {
return getCurrentUser() == userId;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
index 0218784..45aee5b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
@@ -29,6 +29,7 @@
import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
import android.view.WindowInsets;
+import androidx.annotation.VisibleForTesting;
import com.android.compose.animation.scene.ObservableTransitionState;
import com.android.internal.policy.SystemBarUtils;
import com.android.systemui.Dumpable;
@@ -69,6 +70,7 @@
private boolean mIsStatusBarExpanded = false;
private boolean mIsIdleOnGone = true;
+ private boolean mIsRemoteUserInteractionOngoing = false;
private boolean mShouldAdjustInsets = false;
private View mNotificationShadeWindowView;
private View mNotificationPanelView;
@@ -133,6 +135,9 @@
javaAdapter.alwaysCollectFlow(
sceneInteractor.get().getTransitionState(),
this::onSceneChanged);
+ javaAdapter.alwaysCollectFlow(
+ sceneInteractor.get().isRemoteUserInteractionOngoing(),
+ this::onRemoteUserInteractionOngoingChanged);
} else {
javaAdapter.alwaysCollectFlow(
shadeInteractor.isAnyExpanded(),
@@ -179,6 +184,13 @@
}
}
+ private void onRemoteUserInteractionOngoingChanged(Boolean ongoing) {
+ if (ongoing != mIsRemoteUserInteractionOngoing) {
+ mIsRemoteUserInteractionOngoing = ongoing;
+ updateTouchableRegion();
+ }
+ }
+
/**
* Calculates the touch region needed for heads up notifications, taking into consideration
* any existing display cutouts (notch)
@@ -276,13 +288,15 @@
* Helper to let us know when calculating the region is not needed because we know the entire
* screen needs to be touchable.
*/
- private boolean shouldMakeEntireScreenTouchable() {
+ @VisibleForTesting
+ boolean shouldMakeEntireScreenTouchable() {
// The touchable region is always the full area when expanded, whether we're showing the
// shade or the bouncer. It's also fully touchable when the screen off animation is playing
// since we don't want stray touches to go through the light reveal scrim to whatever is
// underneath.
return mIsStatusBarExpanded
- || (SceneContainerFlag.isEnabled() && !mIsIdleOnGone)
+ || (SceneContainerFlag.isEnabled()
+ && (!mIsIdleOnGone || mIsRemoteUserInteractionOngoing))
|| mPrimaryBouncerInteractor.isShowing().getValue()
|| mAlternateBouncerInteractor.isVisibleState()
|| mUnlockedScreenOffAnimationController.isAnimationPlaying();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManagerTest.kt
new file mode 100644
index 0000000..230ddf9
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManagerTest.kt
@@ -0,0 +1,116 @@
+/*
+ * 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.systemui.statusbar.phone
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.compose.animation.scene.ObservableTransitionState
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.flags.DisableSceneContainer
+import com.android.systemui.flags.EnableSceneContainer
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.data.repository.sceneContainerRepository
+import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.testKosmos
+import com.android.systemui.util.kotlin.getValue
+import com.google.common.truth.Truth.assertThat
+import dagger.Lazy
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@OptIn(ExperimentalCoroutinesApi::class)
+class StatusBarTouchableRegionManagerTest : SysuiTestCase() {
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
+ private val sceneRepository = kosmos.sceneContainerRepository
+
+ private val underTest by Lazy { kosmos.statusBarTouchableRegionManager }
+
+ @Test
+ @EnableSceneContainer
+ fun entireScreenTouchable_sceneContainerEnabled_isRemoteUserInteractionOngoing() =
+ testScope.runTest {
+ sceneRepository.setTransitionState(
+ flowOf(ObservableTransitionState.Idle(currentScene = Scenes.Gone))
+ )
+ runCurrent()
+ assertThat(underTest.shouldMakeEntireScreenTouchable()).isFalse()
+
+ sceneRepository.isRemoteUserInteractionOngoing.value = true
+ runCurrent()
+ assertThat(underTest.shouldMakeEntireScreenTouchable()).isTrue()
+
+ sceneRepository.isRemoteUserInteractionOngoing.value = false
+ runCurrent()
+ assertThat(underTest.shouldMakeEntireScreenTouchable()).isFalse()
+ }
+
+ @Test
+ @DisableSceneContainer
+ fun entireScreenTouchable_sceneContainerDisabled_isRemoteUserInteractionOngoing() =
+ testScope.runTest {
+ assertThat(underTest.shouldMakeEntireScreenTouchable()).isFalse()
+
+ sceneRepository.isRemoteUserInteractionOngoing.value = true
+ runCurrent()
+
+ assertThat(underTest.shouldMakeEntireScreenTouchable()).isFalse()
+ }
+
+ @Test
+ @EnableSceneContainer
+ fun entireScreenTouchable_sceneContainerEnabled_isIdleOnGone() =
+ testScope.runTest {
+ sceneRepository.setTransitionState(
+ flowOf(ObservableTransitionState.Idle(currentScene = Scenes.Gone))
+ )
+ runCurrent()
+ assertThat(underTest.shouldMakeEntireScreenTouchable()).isFalse()
+
+ sceneRepository.setTransitionState(
+ flowOf(ObservableTransitionState.Idle(currentScene = Scenes.Shade))
+ )
+ runCurrent()
+ assertThat(underTest.shouldMakeEntireScreenTouchable()).isTrue()
+
+ sceneRepository.setTransitionState(
+ flowOf(ObservableTransitionState.Idle(currentScene = Scenes.Gone))
+ )
+ runCurrent()
+ assertThat(underTest.shouldMakeEntireScreenTouchable()).isFalse()
+ }
+
+ @Test
+ @DisableSceneContainer
+ fun entireScreenTouchable_sceneContainerDisabled_isIdleOnGone() =
+ testScope.runTest {
+ assertThat(underTest.shouldMakeEntireScreenTouchable()).isFalse()
+
+ sceneRepository.setTransitionState(
+ flowOf(ObservableTransitionState.Idle(currentScene = Scenes.Shade))
+ )
+ runCurrent()
+
+ assertThat(underTest.shouldMakeEntireScreenTouchable()).isFalse()
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelKosmos.kt
index b5e6f75..3c62b44 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelKosmos.kt
@@ -23,6 +23,7 @@
import com.android.systemui.kosmos.applicationCoroutineScope
import com.android.systemui.shade.domain.interactor.shadeInteractor
import com.android.systemui.statusbar.notification.icon.ui.viewmodel.notificationIconContainerAlwaysOnDisplayViewModel
+import com.android.systemui.statusbar.notification.stack.domain.interactor.notificationsKeyguardInteractor
import com.android.systemui.statusbar.ui.systemBarUtilsProxy
val Kosmos.keyguardClockViewModel by
@@ -31,6 +32,7 @@
keyguardClockInteractor = keyguardClockInteractor,
applicationScope = applicationCoroutineScope,
aodNotificationIconViewModel = notificationIconContainerAlwaysOnDisplayViewModel,
+ notifsKeyguardInteractor = notificationsKeyguardInteractor,
shadeInteractor = shadeInteractor,
systemBarUtils = systemBarUtilsProxy,
configurationInteractor = configurationInteractor,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManagerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManagerKosmos.kt
new file mode 100644
index 0000000..8785256
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManagerKosmos.kt
@@ -0,0 +1,47 @@
+/*
+ * 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.systemui.statusbar.phone
+
+import android.content.applicationContext
+import com.android.systemui.bouncer.domain.interactor.alternateBouncerInteractor
+import com.android.systemui.bouncer.domain.interactor.primaryBouncerInteractor
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.shade.domain.interactor.shadeInteractor
+import com.android.systemui.statusbar.notificationShadeWindowController
+import com.android.systemui.statusbar.policy.configurationController
+import com.android.systemui.statusbar.policy.headsUpManager
+import com.android.systemui.util.kotlin.JavaAdapter
+import com.android.systemui.util.mockito.mock
+import org.mockito.Mockito.mock
+
+var Kosmos.statusBarTouchableRegionManager by
+ Kosmos.Fixture {
+ StatusBarTouchableRegionManager(
+ applicationContext,
+ notificationShadeWindowController,
+ configurationController,
+ headsUpManager,
+ shadeInteractor,
+ { sceneInteractor },
+ JavaAdapter(testScope.backgroundScope),
+ mock<UnlockedScreenOffAnimationController>(),
+ primaryBouncerInteractor,
+ alternateBouncerInteractor,
+ )
+ }
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 6ff4a61..2986340 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -2528,7 +2528,7 @@
mDeviceBroker.setBluetoothA2dpOnInt(true, false /*fromA2dp*/, eventSource);
AudioDeviceAttributes ada = new AudioDeviceAttributes(device, address, name);
- final int res = AudioSystem.setDeviceConnectionState(ada,
+ final int res = mAudioSystem.setDeviceConnectionState(ada,
AudioSystem.DEVICE_STATE_AVAILABLE, codec);
if (res != AudioSystem.AUDIO_STATUS_OK) {
AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent(
@@ -2575,7 +2575,7 @@
AudioDeviceAttributes ada = null;
if (device != AudioSystem.DEVICE_NONE) {
ada = new AudioDeviceAttributes(device, address);
- final int res = AudioSystem.setDeviceConnectionState(ada,
+ final int res = mAudioSystem.setDeviceConnectionState(ada,
AudioSystem.DEVICE_STATE_UNAVAILABLE,
codec);
diff --git a/services/core/java/com/android/server/inputmethod/AutofillSuggestionsController.java b/services/core/java/com/android/server/inputmethod/AutofillSuggestionsController.java
index 0749edc..aeace7a 100644
--- a/services/core/java/com/android/server/inputmethod/AutofillSuggestionsController.java
+++ b/services/core/java/com/android/server/inputmethod/AutofillSuggestionsController.java
@@ -103,8 +103,8 @@
// Note that current user ID is guaranteed to be userId.
final var imeId = mBindingController.getSelectedMethodId();
- final InputMethodInfo imi = InputMethodSettingsRepository.get(mBindingController.mUserId)
- .getMethodMap().get(imeId);
+ final InputMethodInfo imi = InputMethodSettingsRepository.get(
+ mBindingController.getUserId()).getMethodMap().get(imeId);
if (imi == null || !isInlineSuggestionsEnabled(imi, touchExplorationEnabled)) {
callback.onInlineSuggestionsUnsupported();
return;
diff --git a/services/core/java/com/android/server/inputmethod/ImeTrackerService.java b/services/core/java/com/android/server/inputmethod/ImeTrackerService.java
index 56fa8c9..14551a1 100644
--- a/services/core/java/com/android/server/inputmethod/ImeTrackerService.java
+++ b/services/core/java/com/android/server/inputmethod/ImeTrackerService.java
@@ -23,7 +23,6 @@
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
-import android.os.Looper;
import android.util.Log;
import android.view.inputmethod.ImeTracker;
@@ -70,8 +69,8 @@
private final Object mLock = new Object();
- ImeTrackerService(@NonNull Looper looper) {
- mHandler = new Handler(looper, null /* callback */, true /* async */);
+ ImeTrackerService(@NonNull Handler handler) {
+ mHandler = handler;
}
@NonNull
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java
index afc1029..e1aa3a2 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java
@@ -70,7 +70,7 @@
/** Time in milliseconds that the IME service has to bind before it is reconnected. */
static final long TIME_TO_RECONNECT = 3 * 1000;
- @UserIdInt final int mUserId;
+ @UserIdInt private final int mUserId;
@NonNull private final InputMethodManagerService mService;
@NonNull private final Context mContext;
@NonNull private final AutofillSuggestionsController mAutofillController;
@@ -657,4 +657,9 @@
int getDeviceIdToShowIme() {
return mDeviceIdToShowIme;
}
+
+ @UserIdInt
+ int getUserId() {
+ return mUserId;
+ }
}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 2242d4f..56ac760 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -90,7 +90,6 @@
import android.os.Handler;
import android.os.IBinder;
import android.os.LocaleList;
-import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
@@ -511,16 +510,6 @@
private final WeakHashMap<IBinder, Boolean> mFocusedWindowPerceptible = new WeakHashMap<>();
/**
- * The token we have made for the currently active input method, to
- * identify it in the future.
- */
- @GuardedBy("ImfLock.class")
- @Nullable
- IBinder getCurTokenLocked() {
- return getInputMethodBindingController(mCurrentUserId).getCurToken();
- }
-
- /**
* The displayId of current active input method.
*/
@GuardedBy("ImfLock.class")
@@ -1169,8 +1158,7 @@
mIoHandler = Handler.createAsync(ioThread.getLooper());
}
SystemLocaleWrapper.onStart(context, this::onActionLocaleChanged, mHandler);
- mImeTrackerService = new ImeTrackerService(serviceThreadForTesting != null
- ? serviceThreadForTesting.getLooper() : Looper.getMainLooper());
+ mImeTrackerService = new ImeTrackerService(mHandler);
// Note: SettingsObserver doesn't register observers in its constructor.
mSettingsObserver = new SettingsObserver(mHandler);
mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
@@ -1493,14 +1481,16 @@
* Returns true iff the caller is identified to be the current input method with the token.
*
* @param token the window token given to the input method when it was started
+ * @param userId userId of the calling IME process
* @return true if and only if non-null valid token is specified
*/
@GuardedBy("ImfLock.class")
- private boolean calledWithValidTokenLocked(@NonNull IBinder token) {
+ private boolean calledWithValidTokenLocked(@NonNull IBinder token, @UserIdInt int userId) {
if (token == null) {
throw new InvalidParameterException("token must not be null.");
}
- if (token != getCurTokenLocked()) {
+ final var bindingController = getInputMethodBindingController(userId);
+ if (token != bindingController.getCurToken()) {
Slog.e(TAG, "Ignoring " + Debug.getCaller() + " due to an invalid token."
+ " uid:" + Binder.getCallingUid() + " token:" + token);
return false;
@@ -2052,7 +2042,7 @@
@NonNull ImeOnBackInvokedDispatcher imeDispatcher,
@NonNull InputMethodBindingController bindingController) {
- final int userId = bindingController.mUserId;
+ final int userId = bindingController.getUserId();
final var userData = getUserData(userId);
// Compute the final shown display ID with validated cs.selfReportedDisplayId for this
@@ -2069,8 +2059,8 @@
// Potentially override the selected input method if the new display belongs to a virtual
// device with a custom IME.
String selectedMethodId = bindingController.getSelectedMethodId();
- final String deviceMethodId = computeCurrentDeviceMethodIdLocked(bindingController.mUserId,
- selectedMethodId);
+ final String deviceMethodId = computeCurrentDeviceMethodIdLocked(
+ bindingController.getUserId(), selectedMethodId);
if (deviceMethodId == null) {
mVisibilityStateComputer.getImePolicy().setImeHiddenByDisplayPolicy(true);
} else if (!Objects.equals(deviceMethodId, selectedMethodId)) {
@@ -2568,7 +2558,7 @@
@GuardedBy("ImfLock.class")
void clearClientSessionsLocked(@NonNull InputMethodBindingController bindingController) {
- final int userId = bindingController.mUserId;
+ final int userId = bindingController.getUserId();
final var userData = getUserData(userId);
if (bindingController.getCurMethod() != null) {
// TODO(b/324907325): Remove the suppress warnings once b/324907325 is fixed.
@@ -2600,9 +2590,9 @@
@BinderThread
private void updateStatusIcon(@NonNull IBinder token, String packageName,
- @DrawableRes int iconId) {
+ @DrawableRes int iconId, @UserIdInt int userId) {
synchronized (ImfLock.class) {
- if (!calledWithValidTokenLocked(token)) {
+ if (!calledWithValidTokenLocked(token, userId)) {
return;
}
final long ident = Binder.clearCallingIdentity();
@@ -2744,24 +2734,26 @@
@BinderThread
@SuppressWarnings("deprecation")
- private void setImeWindowStatus(@NonNull IBinder token, int vis, int backDisposition) {
+ private void setImeWindowStatus(@NonNull IBinder token, int vis, int backDisposition,
+ @UserIdInt int userId) {
final int topFocusedDisplayId = mWindowManagerInternal.getTopFocusedDisplayId();
synchronized (ImfLock.class) {
- if (!calledWithValidTokenLocked(token)) {
+ if (!calledWithValidTokenLocked(token, userId)) {
return;
}
+ final var bindingController = getInputMethodBindingController(userId);
// Skip update IME status when current token display is not same as focused display.
// Note that we still need to update IME status when focusing external display
// that does not support system decoration and fallback to show IME on default
// display since it is intentional behavior.
- final int tokenDisplayId = getCurTokenDisplayIdLocked();
+ final int tokenDisplayId = bindingController.getCurTokenDisplayId();
if (tokenDisplayId != topFocusedDisplayId && tokenDisplayId != FALLBACK_DISPLAY_ID) {
return;
}
mImeWindowVis = vis;
mBackDisposition = backDisposition;
- updateSystemUiLocked(vis, backDisposition);
+ updateSystemUiLocked(vis, backDisposition, userId);
}
final boolean dismissImeOnBackKeyPressed;
@@ -2781,9 +2773,10 @@
}
@BinderThread
- private void reportStartInput(@NonNull IBinder token, IBinder startInputToken) {
+ private void reportStartInput(@NonNull IBinder token, IBinder startInputToken,
+ @UserIdInt int userId) {
synchronized (ImfLock.class) {
- if (!calledWithValidTokenLocked(token)) {
+ if (!calledWithValidTokenLocked(token, userId)) {
return;
}
final IBinder targetWindow = mImeTargetWindowMap.get(startInputToken);
@@ -3857,7 +3850,7 @@
+ " cs=" + cs);
}
- final int userId = bindingController.mUserId;
+ final int userId = bindingController.getUserId();
final var userData = getUserData(userId);
final boolean sameWindowFocused = userData.mImeBindingState.mFocusedWindow == windowToken;
final boolean isTextEditor = (startInputFlags & StartInputFlags.IS_TEXT_EDITOR) != 0;
@@ -3891,7 +3884,7 @@
null, null, null, null, -1, false);
}
- userData.mImeBindingState = new ImeBindingState(bindingController.mUserId, windowToken,
+ userData.mImeBindingState = new ImeBindingState(bindingController.getUserId(), windowToken,
softInputMode, cs, editorInfo);
mFocusedWindowPerceptible.put(windowToken, true);
@@ -4049,7 +4042,7 @@
private void setInputMethod(@NonNull IBinder token, String id, @UserIdInt int userId) {
final int callingUid = Binder.getCallingUid();
synchronized (ImfLock.class) {
- if (!calledWithValidTokenLocked(token)) {
+ if (!calledWithValidTokenLocked(token, userId)) {
return;
}
final InputMethodSettings settings = InputMethodSettingsRepository.get(mCurrentUserId);
@@ -4067,7 +4060,7 @@
InputMethodSubtype subtype, @UserIdInt int userId) {
final int callingUid = Binder.getCallingUid();
synchronized (ImfLock.class) {
- if (!calledWithValidTokenLocked(token)) {
+ if (!calledWithValidTokenLocked(token, userId)) {
return;
}
final InputMethodSettings settings = InputMethodSettingsRepository.get(mCurrentUserId);
@@ -4088,7 +4081,7 @@
@BinderThread
private boolean switchToPreviousInputMethod(@NonNull IBinder token, @UserIdInt int userId) {
synchronized (ImfLock.class) {
- if (!calledWithValidTokenLocked(token)) {
+ if (!calledWithValidTokenLocked(token, userId)) {
return false;
}
final var bindingController = getInputMethodBindingController(userId);
@@ -4170,7 +4163,7 @@
private boolean switchToNextInputMethod(@NonNull IBinder token, boolean onlyCurrentIme,
@UserIdInt int userId) {
synchronized (ImfLock.class) {
- if (!calledWithValidTokenLocked(token)) {
+ if (!calledWithValidTokenLocked(token, userId)) {
return false;
}
return switchToNextInputMethodLocked(token, onlyCurrentIme, userId);
@@ -4197,7 +4190,7 @@
private boolean shouldOfferSwitchingToNextInputMethod(@NonNull IBinder token,
@UserIdInt int userId) {
synchronized (ImfLock.class) {
- if (!calledWithValidTokenLocked(token)) {
+ if (!calledWithValidTokenLocked(token, userId)) {
return false;
}
final var bindingController = getInputMethodBindingController(userId);
@@ -4659,7 +4652,7 @@
try {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.applyImeVisibility");
synchronized (ImfLock.class) {
- if (!calledWithValidTokenLocked(token)) {
+ if (!calledWithValidTokenLocked(token, userId)) {
ImeTracker.forLogging().onFailed(statsToken,
ImeTracker.PHASE_SERVER_CURRENT_ACTIVE_IME);
return;
@@ -4759,7 +4752,7 @@
try {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.hideMySoftInput");
synchronized (ImfLock.class) {
- if (!calledWithValidTokenLocked(token)) {
+ if (!calledWithValidTokenLocked(token, userId)) {
ImeTracker.forLogging().onFailed(statsToken,
ImeTracker.PHASE_SERVER_CURRENT_ACTIVE_IME);
return;
@@ -4798,7 +4791,7 @@
try {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.showMySoftInput");
synchronized (ImfLock.class) {
- if (!calledWithValidTokenLocked(token)) {
+ if (!calledWithValidTokenLocked(token, userId)) {
ImeTracker.forLogging().onFailed(statsToken,
ImeTracker.PHASE_SERVER_CURRENT_ACTIVE_IME);
return;
@@ -6014,7 +6007,7 @@
private void reportFullscreenMode(@NonNull IBinder token, boolean fullscreen,
@UserIdInt int userId) {
synchronized (ImfLock.class) {
- if (!calledWithValidTokenLocked(token)) {
+ if (!calledWithValidTokenLocked(token, userId)) {
return;
}
final var userData = getUserData(userId);
@@ -6844,13 +6837,13 @@
@BinderThread
@Override
public void setImeWindowStatusAsync(int vis, int backDisposition) {
- mImms.setImeWindowStatus(mToken, vis, backDisposition);
+ mImms.setImeWindowStatus(mToken, vis, backDisposition, mUserId);
}
@BinderThread
@Override
public void reportStartInputAsync(IBinder startInputToken) {
- mImms.reportStartInput(mToken, startInputToken);
+ mImms.reportStartInput(mToken, startInputToken, mUserId);
}
@BinderThread
@@ -6934,7 +6927,7 @@
@BinderThread
@Override
public void updateStatusIconAsync(String packageName, @DrawableRes int iconId) {
- mImms.updateStatusIcon(mToken, packageName, iconId);
+ mImms.updateStatusIcon(mToken, packageName, iconId, mUserId);
}
@BinderThread
@@ -7001,7 +6994,7 @@
@Override
public void switchKeyboardLayoutAsync(int direction) {
synchronized (ImfLock.class) {
- if (!mImms.calledWithValidTokenLocked(mToken)) {
+ if (!mImms.calledWithValidTokenLocked(mToken, mUserId)) {
return;
}
final long ident = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 6eac72d..173fc5c 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -2504,13 +2504,13 @@
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
- private void enableRestrictedSettings(String pkgName, int appId, int userId) {
+ private void setAccessRestrictedSettingsMode(String pkgName, int appId, int userId, int mode) {
final AppOpsManager appOpsManager = mPm.mContext.getSystemService(AppOpsManager.class);
final int uid = UserHandle.getUid(userId, appId);
appOpsManager.setMode(AppOpsManager.OP_ACCESS_RESTRICTED_SETTINGS,
uid,
pkgName,
- AppOpsManager.MODE_ERRORED);
+ mode);
}
/**
@@ -2888,8 +2888,21 @@
mPm.notifyPackageChanged(packageName, request.getAppId());
}
- if (!android.permission.flags.Flags.enhancedConfirmationModeApisEnabled()
- || !android.security.Flags.extendEcmToAllSettings()) {
+ // Set the OP_ACCESS_RESTRICTED_SETTINGS op, which is used by ECM (see {@link
+ // EnhancedConfirmationManager}) as a persistent state denoting whether an app is
+ // currently guarded by ECM, not guarded by ECM, or (in Android V+) that this should
+ // be decided later.
+ if (android.permission.flags.Flags.enhancedConfirmationModeApisEnabled()
+ && android.security.Flags.extendEcmToAllSettings()) {
+ final int appId = request.getAppId();
+ mPm.mHandler.post(() -> {
+ for (int userId : firstUserIds) {
+ // MODE_DEFAULT means that the app's guardedness will be decided lazily
+ setAccessRestrictedSettingsMode(packageName, appId, userId,
+ AppOpsManager.MODE_DEFAULT);
+ }
+ });
+ } else {
// Apply restricted settings on potentially dangerous packages. Needs to happen
// after appOpsManager is notified of the new package
if (request.getPackageSource() == PackageInstaller.PACKAGE_SOURCE_LOCAL_FILE
@@ -2898,7 +2911,9 @@
final int appId = request.getAppId();
mPm.mHandler.post(() -> {
for (int userId : firstUserIds) {
- enableRestrictedSettings(packageName, appId, userId);
+ // MODE_ERRORED means that the app is explicitly guarded
+ setAccessRestrictedSettingsMode(packageName, appId, userId,
+ AppOpsManager.MODE_ERRORED);
}
});
}
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
index 42bd75a..80eab11 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java
@@ -189,6 +189,7 @@
// Injecting and mocked InputMethodBindingController and InputMethod.
mMockInputMethodInvoker = IInputMethodInvoker.create(mMockInputMethod);
mInputManagerGlobalSession = InputManagerGlobal.createTestSession(mMockIInputManager);
+ when(mMockInputMethodBindingController.getUserId()).thenReturn(mCallingUserId);
synchronized (ImfLock.class) {
when(mMockInputMethodBindingController.getCurMethod())
.thenReturn(mMockInputMethodInvoker);
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/UserDataRepositoryTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/UserDataRepositoryTest.java
index f9f45057..e2f3eec 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/UserDataRepositoryTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/UserDataRepositoryTest.java
@@ -106,7 +106,7 @@
// Assert UserDataRepository called the InputMethodBindingController creator function.
verify(bindingControllerFactorySpy).apply(ANY_USER_ID);
- assertThat(allUserData.get(0).mBindingController.mUserId).isEqualTo(ANY_USER_ID);
+ assertThat(allUserData.get(0).mBindingController.getUserId()).isEqualTo(ANY_USER_ID);
}
@Test
@@ -149,7 +149,7 @@
assertThat(allUserData.get(0).mUserId).isEqualTo(ANY_USER_ID);
// Assert UserDataRepository called the InputMethodBindingController creator function.
- assertThat(allUserData.get(0).mBindingController.mUserId).isEqualTo(ANY_USER_ID);
+ assertThat(allUserData.get(0).mBindingController.getUserId()).isEqualTo(ANY_USER_ID);
}
private List<UserDataRepository.UserData> collectUserData(UserDataRepository repository) {
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 09cb464..61698db 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -9981,6 +9981,18 @@
"carrier_roaming_satellite_default_services_int_array";
/**
+ * Indicate whether carrier roaming to satellite is using ESOS (Emergency SOS) which connects
+ * to an emergency provider instead of PSAP (Public Safety Answering Point) for emergency
+ * messaging.
+ *
+ * This will need agreement with carriers before enabling this flag.
+ *
+ * The default value is false.
+ */
+ @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
+ public static final String KEY_SATELLITE_ESOS_SUPPORTED_BOOL = "satellite_esos_supported_bool";
+
+ /**
* Indicating whether DUN APN should be disabled when the device is roaming. In that case,
* the default APN (i.e. internet) will be used for tethering.
*
@@ -11137,6 +11149,7 @@
sDefaults.putBoolean(KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL, false);
sDefaults.putInt(KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT,
(int) TimeUnit.SECONDS.toMillis(30));
+ sDefaults.putBoolean(KEY_SATELLITE_ESOS_SUPPORTED_BOOL, false);
sDefaults.putString(KEY_DEFAULT_PREFERRED_APN_NAME_STRING, "");
sDefaults.putBoolean(KEY_SUPPORTS_CALL_COMPOSER_BOOL, false);
sDefaults.putBoolean(KEY_SUPPORTS_BUSINESS_CALL_COMPOSER_BOOL, false);
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index 58488d1..1089602 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -274,6 +274,11 @@
private final int mServiceCapabilities;
/**
+ * Whether the carrier roaming to satellite is using ESOS for emergency messaging.
+ */
+ private final boolean mIsSatelliteESOSSupported;
+
+ /**
* @hide
*
* @deprecated Use {@link SubscriptionInfo.Builder}.
@@ -400,6 +405,7 @@
this.mIsOnlyNonTerrestrialNetwork = false;
this.mServiceCapabilities = 0;
this.mTransferStatus = 0;
+ this.mIsSatelliteESOSSupported = false;
}
/**
@@ -441,6 +447,7 @@
this.mIsOnlyNonTerrestrialNetwork = builder.mIsOnlyNonTerrestrialNetwork;
this.mServiceCapabilities = builder.mServiceCapabilities;
this.mTransferStatus = builder.mTransferStatus;
+ this.mIsSatelliteESOSSupported = builder.mIsSatelliteESOSSupported;
}
/**
@@ -898,6 +905,19 @@
return mIsOnlyNonTerrestrialNetwork;
}
+
+ /**
+ * Checks if the subscription is supported ESOS over Carrier Roaming NB-IOT Satellite.
+ *
+ * @return {@code true} if the subscription supports ESOS over Carrier Roaming NB-IOT Satellite,
+ * {@code false} otherwise.
+ * @hide
+ */
+ @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
+ public boolean isSatelliteESOSSupported() {
+ return mIsSatelliteESOSSupported;
+ }
+
// TODO(b/316183370): replace @code with @link in javadoc after feature is released
/**
* Retrieves the service capabilities for the current subscription.
@@ -989,6 +1009,7 @@
.setServiceCapabilities(
SubscriptionManager.getServiceCapabilitiesSet(source.readInt()))
.setTransferStatus(source.readInt())
+ .setSatelliteESOSSupported(source.readBoolean())
.build();
}
@@ -1033,6 +1054,7 @@
dest.writeBoolean(mIsOnlyNonTerrestrialNetwork);
dest.writeInt(mServiceCapabilities);
dest.writeInt(mTransferStatus);
+ dest.writeBoolean(mIsSatelliteESOSSupported);
}
@Override
@@ -1099,6 +1121,7 @@
+ " serviceCapabilities=" + SubscriptionManager.getServiceCapabilitiesSet(
mServiceCapabilities).toString()
+ " transferStatus=" + mTransferStatus
+ + " isSatelliteESOSSupported=" + mIsSatelliteESOSSupported
+ "]";
}
@@ -1126,7 +1149,8 @@
&& mCountryIso.equals(that.mCountryIso) && mGroupOwner.equals(that.mGroupOwner)
&& mIsOnlyNonTerrestrialNetwork == that.mIsOnlyNonTerrestrialNetwork
&& mServiceCapabilities == that.mServiceCapabilities
- && mTransferStatus == that.mTransferStatus;
+ && mTransferStatus == that.mTransferStatus
+ && mIsSatelliteESOSSupported == that.mIsSatelliteESOSSupported;
}
@Override
@@ -1136,7 +1160,7 @@
mCardString, mIsOpportunistic, mGroupUuid, mCountryIso, mCarrierId, mProfileClass,
mType, mGroupOwner, mAreUiccApplicationsEnabled, mPortIndex, mUsageSetting, mCardId,
mIsGroupDisabled, mIsOnlyNonTerrestrialNetwork, mServiceCapabilities,
- mTransferStatus);
+ mTransferStatus, mIsSatelliteESOSSupported);
result = 31 * result + Arrays.hashCode(mEhplmns);
result = 31 * result + Arrays.hashCode(mHplmns);
result = 31 * result + Arrays.hashCode(mNativeAccessRules);
@@ -1346,6 +1370,11 @@
* Service capabilities bitmasks the subscription supports.
*/
private int mServiceCapabilities = 0;
+ /**
+ * {@code true} if the subscription supports ESOS over Carrier Roaming NB-IOT Satellite.
+ * {@code false} otherwise.
+ */
+ private boolean mIsSatelliteESOSSupported = false;
/**
* Default constructor.
@@ -1392,6 +1421,7 @@
mIsOnlyNonTerrestrialNetwork = info.mIsOnlyNonTerrestrialNetwork;
mServiceCapabilities = info.mServiceCapabilities;
mTransferStatus = info.mTransferStatus;
+ mIsSatelliteESOSSupported = info.mIsSatelliteESOSSupported;
}
/**
@@ -1828,6 +1858,21 @@
}
/**
+ * Set whether the subscription is supported ESOS over Carrier Roaming NB-IOT Satellite or
+ * not.
+ *
+ * @param isSatelliteESOSSupported {@code true} if the subscription supports ESOS over
+ * Carrier Roaming NB-IOT Satellite, {@code false} otherwise.
+ * @return The builder.
+ */
+ @FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
+ @NonNull
+ public Builder setSatelliteESOSSupported(boolean isSatelliteESOSSupported) {
+ mIsSatelliteESOSSupported = isSatelliteESOSSupported;
+ return this;
+ }
+
+ /**
* Build the {@link SubscriptionInfo}.
*
* @return The {@link SubscriptionInfo} instance.
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index b208ee3..dea10b70 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -1127,7 +1127,7 @@
* <P>Type: INTEGER (int)</P>
* @hide
*/
- public static final String IS_NTN = SimInfo.COLUMN_IS_NTN;
+ public static final String IS_ONLY_NTN = SimInfo.COLUMN_IS_ONLY_NTN;
/**
* TelephonyProvider column name to identify service capabilities.
@@ -1167,6 +1167,16 @@
public static final String SATELLITE_ENTITLEMENT_PLMNS =
SimInfo.COLUMN_SATELLITE_ENTITLEMENT_PLMNS;
+ /**
+ * TelephonyProvider column name to indicate the satellite ESOS supported. The value of this
+ * column is set based on {@link CarrierConfigManager#KEY_SATELLITE_ESOS_SUPPORTED_BOOL}.
+ * By default, it's disabled.
+ * <P>Type: INTEGER (int)</P>
+ *
+ * @hide
+ */
+ public static final String SATELLITE_ESOS_SUPPORTED = SimInfo.COLUMN_SATELLITE_ESOS_SUPPORTED;
+
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"USAGE_SETTING_"},
diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java
index 2a359cd..6caed14 100644
--- a/telephony/java/android/telephony/satellite/SatelliteManager.java
+++ b/telephony/java/android/telephony/satellite/SatelliteManager.java
@@ -371,6 +371,24 @@
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_RESULT_MODEM_TIMEOUT = 24;
+ /**
+ * Telephony framework needs to access the current location of the device to perform the
+ * request. However, location in the settings is disabled by users.
+ *
+ * @hide
+ */
+ @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
+ public static final int SATELLITE_RESULT_LOCATION_DISABLED = 25;
+
+ /**
+ * Telephony framework needs to access the current location of the device to perform the
+ * request. However, Telephony fails to fetch the current location from location service.
+ *
+ * @hide
+ */
+ @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
+ public static final int SATELLITE_RESULT_LOCATION_NOT_AVAILABLE = 26;
+
/** @hide */
@IntDef(prefix = {"SATELLITE_RESULT_"}, value = {
SATELLITE_RESULT_SUCCESS,
@@ -397,7 +415,9 @@
SATELLITE_RESULT_REQUEST_IN_PROGRESS,
SATELLITE_RESULT_MODEM_BUSY,
SATELLITE_RESULT_ILLEGAL_STATE,
- SATELLITE_RESULT_MODEM_TIMEOUT
+ SATELLITE_RESULT_MODEM_TIMEOUT,
+ SATELLITE_RESULT_LOCATION_DISABLED,
+ SATELLITE_RESULT_LOCATION_NOT_AVAILABLE
})
@Retention(RetentionPolicy.SOURCE)
public @interface SatelliteResult {}