diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 8d480e5bc8f4519edd5a0ae20faf45aea691f623..de07fdde6267af63bedb7379d1dfd7aa29c98770 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -16834,6 +16834,10 @@ package android.telephony.satellite { field @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @NonNull public static final android.os.Parcelable.Creator<android.telephony.satellite.SatelliteCapabilities> CREATOR; } + @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public interface SatelliteCapabilitiesCallback { + method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public void onSatelliteCapabilitiesChanged(@NonNull android.telephony.satellite.SatelliteCapabilities); + } + @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public final class SatelliteDatagram implements android.os.Parcelable { method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public int describeContents(); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @NonNull public byte[] getSatelliteDatagram(); @@ -16852,6 +16856,7 @@ package android.telephony.satellite { method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void pollPendingSatelliteDatagrams(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void provisionSatelliteService(@NonNull String, @NonNull byte[], @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public int registerForNtnSignalStrengthChanged(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.NtnSignalStrengthCallback); + method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public int registerForSatelliteCapabilitiesChanged(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.SatelliteCapabilitiesCallback); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public int registerForSatelliteDatagram(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.SatelliteDatagramCallback); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public int registerForSatelliteModemStateChanged(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.SatelliteStateCallback); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public int registerForSatelliteProvisionStateChanged(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.SatelliteProvisionStateCallback); @@ -16872,6 +16877,7 @@ package android.telephony.satellite { method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void startSatelliteTransmissionUpdates(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>, @NonNull android.telephony.satellite.SatelliteTransmissionUpdateCallback); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void stopSatelliteTransmissionUpdates(@NonNull android.telephony.satellite.SatelliteTransmissionUpdateCallback, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void unregisterForNtnSignalStrengthChanged(@NonNull android.telephony.satellite.NtnSignalStrengthCallback); + method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void unregisterForSatelliteCapabilitiesChanged(@NonNull android.telephony.satellite.SatelliteCapabilitiesCallback); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void unregisterForSatelliteDatagram(@NonNull android.telephony.satellite.SatelliteDatagramCallback); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void unregisterForSatelliteModemStateChanged(@NonNull android.telephony.satellite.SatelliteStateCallback); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void unregisterForSatelliteProvisionStateChanged(@NonNull android.telephony.satellite.SatelliteProvisionStateCallback); diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 4c70c914ff211caa49636d389a727ac106e90089..3df11f6f5691f3e27468383eccfa50a2d85be351 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -81,6 +81,9 @@ import android.app.Activity; import android.app.IServiceConnection; import android.app.KeyguardManager; import android.app.admin.SecurityLog.SecurityEvent; +import android.app.compat.CompatChanges; +import android.compat.annotation.ChangeId; +import android.compat.annotation.EnabledSince; import android.compat.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Context; @@ -9117,6 +9120,19 @@ public class DevicePolicyManager { return false; } + /** + * For apps targeting {@link Build.VERSION_CODES#VANILLA_ICE_CREAM} and above, the + * {@link #isDeviceOwnerApp} method will use the user contained within the + * context. + * For apps targeting an SDK version <em>below</em> this, the user of the calling process will + * be used (Process.myUserHandle()). + * + * @hide + */ + @ChangeId + @EnabledSince(targetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) + public static final long IS_DEVICE_OWNER_USER_AWARE = 307233716L; + /** * Used to determine if a particular package has been registered as a Device Owner app. * A device owner app is a special device admin that cannot be deactivated by the user, once @@ -9130,8 +9146,13 @@ public class DevicePolicyManager { * app, if any. * @return whether or not the package is registered as the device owner app. */ + @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) public boolean isDeviceOwnerApp(String packageName) { throwIfParentInstance("isDeviceOwnerApp"); + if (android.permission.flags.Flags.roleControllerInSystemServer() + && CompatChanges.isChangeEnabled(IS_DEVICE_OWNER_USER_AWARE)) { + return isDeviceOwnerAppOnContextUser(packageName); + } return isDeviceOwnerAppOnCallingUser(packageName); } @@ -9192,6 +9213,24 @@ public class DevicePolicyManager { return packageName.equals(deviceOwner.getPackageName()); } + private boolean isDeviceOwnerAppOnContextUser(String packageName) { + if (packageName == null) { + return false; + } + ComponentName deviceOwner = null; + if (mService != null) { + try { + deviceOwner = mService.getDeviceOwnerComponentOnUser(myUserId()); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + if (deviceOwner == null) { + return false; + } + return packageName.equals(deviceOwner.getPackageName()); + } + private ComponentName getDeviceOwnerComponentInner(boolean callingUserOnly) { if (mService != null) { try { @@ -9608,6 +9647,7 @@ public class DevicePolicyManager { * @param packageName The package name of the app to compare with the registered profile owner. * @return Whether or not the package is registered as the profile owner. */ + @UserHandleAware public boolean isProfileOwnerApp(String packageName) { throwIfParentInstance("isProfileOwnerApp"); if (mService != null) { diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 6fe40be041cc3c54ffdaa087d78b431079bd2866..575fa4cac0b8d9f3fc088ec0ae1aa6739f2ea160 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -179,6 +179,7 @@ interface IDevicePolicyManager { boolean setDeviceOwner(in ComponentName who, int userId, boolean setProfileOwnerOnCurrentUserIfNecessary); ComponentName getDeviceOwnerComponent(boolean callingUserOnly); + ComponentName getDeviceOwnerComponentOnUser(int userId); boolean hasDeviceOwner(); String getDeviceOwnerName(); void clearDeviceOwner(String packageName); diff --git a/core/java/android/content/pm/SigningInfo.java b/core/java/android/content/pm/SigningInfo.java index 543703e734c2c34f7d049c7a7923bbf2bc3f02f0..a40770484ca560459ab4d6a583e216a12d85e606 100644 --- a/core/java/android/content/pm/SigningInfo.java +++ b/core/java/android/content/pm/SigningInfo.java @@ -190,9 +190,11 @@ public final class SigningInfo implements Parcelable { mSigningDetails.writeToParcel(dest, parcelableFlags); } - /* @hide */ + /** + * @hide + */ @NonNull - SigningDetails getSigningDetails() { + public SigningDetails getSigningDetails() { return mSigningDetails; } diff --git a/core/res/OWNERS b/core/res/OWNERS index 0df7c2047bc1045e653e910b2551bf1706f09aa2..f24c3f59155ac30e6cbb728d73dc05a39a410fd1 100644 --- a/core/res/OWNERS +++ b/core/res/OWNERS @@ -1,5 +1,6 @@ adamp@google.com asc@google.com +austindelgado@google.com cinek@google.com dsandler@android.com dsandler@google.com @@ -8,6 +9,7 @@ hackbod@android.com hackbod@google.com ilyamaty@google.com jaggies@google.com +jbolinger@google.com jsharkey@android.com jsharkey@google.com juliacr@google.com diff --git a/media/java/android/media/tv/ad/TvAdServiceInfo.aidl b/media/java/android/media/tv/ad/TvAdServiceInfo.aidl new file mode 100644 index 0000000000000000000000000000000000000000..a5e631fc8426e5fd59f262b3832005bcaccbcfc5 --- /dev/null +++ b/media/java/android/media/tv/ad/TvAdServiceInfo.aidl @@ -0,0 +1,19 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.ad; + +parcelable TvAdServiceInfo; diff --git a/media/java/android/media/tv/ad/TvAdServiceInfo.java b/media/java/android/media/tv/ad/TvAdServiceInfo.java new file mode 100644 index 0000000000000000000000000000000000000000..ed04f1f9058c98a7fd12da98fae875d43352ae22 --- /dev/null +++ b/media/java/android/media/tv/ad/TvAdServiceInfo.java @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.ad; + +import android.annotation.Nullable; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.content.res.Resources; +import android.content.res.XmlResourceParser; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.AttributeSet; +import android.util.Xml; + +import androidx.annotation.NonNull; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * This class is used to specify meta information of a TV AD service. + * @hide + */ +public final class TvAdServiceInfo implements Parcelable { + private static final boolean DEBUG = false; + private static final String TAG = "TvAdServiceInfo"; + + private static final String XML_START_TAG_NAME = "tv-ad-service"; + + private final ResolveInfo mService; + private final String mId; + private final List<String> mTypes = new ArrayList<>(); + + /** + * Constructs a TvAdServiceInfo object. + * + * @param context the application context + * @param component the component name of the TvAdService + */ + public TvAdServiceInfo(@NonNull Context context, @NonNull ComponentName component) { + if (context == null) { + throw new IllegalArgumentException("context cannot be null."); + } + // TODO: use a constant + Intent intent = new Intent("android.media.tv.ad.TvAdService").setComponent(component); + ResolveInfo resolveInfo = context.getPackageManager().resolveService( + intent, PackageManager.GET_SERVICES | PackageManager.GET_META_DATA); + if (resolveInfo == null) { + throw new IllegalArgumentException("Invalid component. Can't find the service."); + } + + ComponentName componentName = new ComponentName(resolveInfo.serviceInfo.packageName, + resolveInfo.serviceInfo.name); + String id; + id = generateAdServiceId(componentName); + List<String> types = new ArrayList<>(); + parseServiceMetadata(resolveInfo, context, types); + + mService = resolveInfo; + mId = id; + } + + private TvAdServiceInfo(ResolveInfo service, String id, List<String> types) { + mService = service; + mId = id; + mTypes.addAll(types); + } + + private TvAdServiceInfo(@NonNull Parcel in) { + mService = ResolveInfo.CREATOR.createFromParcel(in); + mId = in.readString(); + in.readStringList(mTypes); + } + + public static final Creator<TvAdServiceInfo> CREATOR = new Creator<TvAdServiceInfo>() { + @Override + public TvAdServiceInfo createFromParcel(Parcel in) { + return new TvAdServiceInfo(in); + } + + @Override + public TvAdServiceInfo[] newArray(int size) { + return new TvAdServiceInfo[size]; + } + }; + + /** + * Returns a unique ID for this TV AD service. The ID is generated from the package and class + * name implementing the TV AD service. + */ + @NonNull + public String getId() { + return mId; + } + + /** + * Returns the component of the TV AD service. + * @hide + */ + public ComponentName getComponent() { + return new ComponentName(mService.serviceInfo.packageName, mService.serviceInfo.name); + } + + /** + * Returns the information of the service that implements this AD service. + */ + @Nullable + public ServiceInfo getServiceInfo() { + return mService.serviceInfo; + } + + /** + * Gets supported TV AD types. + */ + @NonNull + public List<String> getSupportedTypes() { + return mTypes; + } + + private static String generateAdServiceId(ComponentName name) { + return name.flattenToShortString(); + } + + private static void parseServiceMetadata( + ResolveInfo resolveInfo, Context context, List<String> types) { + ServiceInfo serviceInfo = resolveInfo.serviceInfo; + PackageManager pm = context.getPackageManager(); + // TODO: use constant for the metadata + try (XmlResourceParser parser = + serviceInfo.loadXmlMetaData(pm, "android.media.tv.ad.service")) { + if (parser == null) { + throw new IllegalStateException( + "No " + "android.media.tv.ad.service" + + " meta-data found for " + serviceInfo.name); + } + + Resources resources = pm.getResourcesForApplication(serviceInfo.applicationInfo); + AttributeSet attrs = Xml.asAttributeSet(parser); + + int type; + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && type != XmlPullParser.START_TAG) { + // move to the START_TAG + } + + String nodeName = parser.getName(); + if (!XML_START_TAG_NAME.equals(nodeName)) { + throw new IllegalStateException("Meta-data does not start with " + + XML_START_TAG_NAME + " tag for " + serviceInfo.name); + } + + // TODO: parse attributes + } catch (IOException | XmlPullParserException e) { + throw new IllegalStateException( + "Failed reading meta-data for " + serviceInfo.packageName, e); + } catch (PackageManager.NameNotFoundException e) { + throw new IllegalStateException("No resources found for " + serviceInfo.packageName, e); + } + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + mService.writeToParcel(dest, flags); + dest.writeString(mId); + dest.writeStringList(mTypes); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt b/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt index 80be008dbd3a5905c09d2c6c77ad1b39fe05b7e7..e8b16db10da5ca3d1c74d5ebb0501c0b680b146c 100644 --- a/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt @@ -65,7 +65,7 @@ interface AuthenticationRepository { * Note that the length of the PIN is also important to take into consideration, please see * [hintedPinLength]. */ - val isAutoConfirmEnabled: StateFlow<Boolean> + val isAutoConfirmFeatureEnabled: StateFlow<Boolean> /** * The exact length a PIN should be for us to enable PIN length hinting. @@ -152,14 +152,14 @@ class AuthenticationRepositoryImpl @Inject constructor( @Application private val applicationScope: CoroutineScope, - private val getSecurityMode: Function<Int, KeyguardSecurityModel.SecurityMode>, @Background private val backgroundDispatcher: CoroutineDispatcher, + private val getSecurityMode: Function<Int, KeyguardSecurityModel.SecurityMode>, private val userRepository: UserRepository, private val lockPatternUtils: LockPatternUtils, broadcastDispatcher: BroadcastDispatcher, ) : AuthenticationRepository { - override val isAutoConfirmEnabled: StateFlow<Boolean> = + override val isAutoConfirmFeatureEnabled: StateFlow<Boolean> = refreshingFlow( initialValue = false, getFreshValue = lockPatternUtils::isAutoPinConfirmEnabled, diff --git a/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt b/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt index 345f15c5c6ad7668b9dd2869fe100d059896f75d..22b44d56fe9be270620cd5d23addbb91a02dadbf 100644 --- a/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt @@ -42,6 +42,7 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn @@ -103,9 +104,29 @@ constructor( initialValue = throttling.value.remainingMs > 0, ) + /** + * Whether the auto confirm feature is enabled for the currently-selected user. + * + * Note that the length of the PIN is also important to take into consideration, please see + * [hintedPinLength]. + * + * During throttling, this is always disabled (`false`). + */ + val isAutoConfirmEnabled: StateFlow<Boolean> = + combine(repository.isAutoConfirmFeatureEnabled, isThrottled) { featureEnabled, isThrottled + -> + // Disable auto-confirm during throttling. + featureEnabled && !isThrottled + } + .stateIn( + scope = applicationScope, + started = SharingStarted.WhileSubscribed(), + initialValue = false, + ) + /** The length of the hinted PIN, or `null` if pin length hint should not be shown. */ val hintedPinLength: StateFlow<Int?> = - repository.isAutoConfirmEnabled + isAutoConfirmEnabled .map { isAutoConfirmEnabled -> repository.getPinLength().takeIf { isAutoConfirmEnabled && it == repository.hintedPinLength @@ -119,9 +140,6 @@ constructor( initialValue = null, ) - /** Whether the auto confirm feature is enabled for the currently-selected user. */ - val isAutoConfirmEnabled: StateFlow<Boolean> = repository.isAutoConfirmEnabled - /** Whether the pattern should be visible for the currently-selected user. */ val isPatternVisible: StateFlow<Boolean> = repository.isPatternVisible diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepository.kt b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepository.kt index 6b27ce011e16c3b5c9c1beae4552b78f61288a6f..f7fee96c83c2256005c504bc88d3f50b7487afc4 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepository.kt @@ -18,13 +18,11 @@ package com.android.systemui.communal.data.repository import android.appwidget.AppWidgetHost import android.appwidget.AppWidgetManager -import android.appwidget.AppWidgetProviderInfo import android.content.BroadcastReceiver import android.content.ComponentName import android.content.Context import android.content.Intent import android.content.IntentFilter -import android.content.pm.PackageManager import android.os.UserManager import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging @@ -32,13 +30,10 @@ import com.android.systemui.communal.data.db.CommunalItemRank import com.android.systemui.communal.data.db.CommunalWidgetDao import com.android.systemui.communal.data.db.CommunalWidgetItem import com.android.systemui.communal.shared.CommunalWidgetHost -import com.android.systemui.communal.shared.model.CommunalAppWidgetInfo import com.android.systemui.communal.shared.model.CommunalWidgetContentModel import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background -import com.android.systemui.flags.FeatureFlagsClassic -import com.android.systemui.flags.Flags import com.android.systemui.log.LogBuffer import com.android.systemui.log.core.Logger import com.android.systemui.log.dagger.CommunalLog @@ -58,9 +53,6 @@ import kotlinx.coroutines.launch /** Encapsulates the state of widgets for communal mode. */ interface CommunalWidgetRepository { - /** A flow of provider info for the stopwatch widget, or null if widget is unavailable. */ - val stopwatchAppWidgetInfo: Flow<CommunalAppWidgetInfo?> - /** A flow of information about active communal widgets stored in database. */ val communalWidgets: Flow<List<CommunalWidgetContentModel>> @@ -84,15 +76,12 @@ constructor( communalRepository: CommunalRepository, private val communalWidgetHost: CommunalWidgetHost, private val communalWidgetDao: CommunalWidgetDao, - private val packageManager: PackageManager, private val userManager: UserManager, private val userTracker: UserTracker, @CommunalLog logBuffer: LogBuffer, - featureFlags: FeatureFlagsClassic, ) : CommunalWidgetRepository { companion object { const val TAG = "CommunalWidgetRepository" - const val WIDGET_LABEL = "Stopwatch" } private val logger = Logger(logBuffer, TAG) @@ -100,9 +89,6 @@ constructor( // Whether the [AppWidgetHost] is listening for updates. private var isHostListening = false - // Widgets that should be rendered in communal mode. - private val widgets: HashMap<Int, CommunalAppWidgetInfo> = hashMapOf() - private val isUserUnlocked: Flow<Boolean> = callbackFlow { if (!communalRepository.isCommunalEnabled) { @@ -149,25 +135,6 @@ constructor( } } - override val stopwatchAppWidgetInfo: Flow<CommunalAppWidgetInfo?> = - isHostActive.map { isHostActive -> - if (!isHostActive || !featureFlags.isEnabled(Flags.WIDGET_ON_KEYGUARD)) { - return@map null - } - - val providerInfo = - appWidgetManager.installedProviders.find { - it.loadLabel(packageManager).equals(WIDGET_LABEL) - } - - if (providerInfo == null) { - logger.w("Cannot find app widget: $WIDGET_LABEL") - return@map null - } - - return@map addStopWatchWidget(providerInfo) - } - override val communalWidgets: Flow<List<CommunalWidgetContentModel>> = isHostActive.flatMapLatest { isHostActive -> if (!isHostActive) { @@ -226,21 +193,4 @@ constructor( appWidgetHost.stopListening() isHostListening = false } - - // TODO(b/306471933): remove this prototype that shows a stopwatch in the communal blueprint - private fun addStopWatchWidget(providerInfo: AppWidgetProviderInfo): CommunalAppWidgetInfo { - val existing = widgets.values.firstOrNull { it.providerInfo == providerInfo } - if (existing != null) { - return existing - } - - val appWidgetId = appWidgetHost.allocateAppWidgetId() - val widget = - CommunalAppWidgetInfo( - providerInfo, - appWidgetId, - ) - widgets[appWidgetId] = widget - return widget - } } diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt index eb36b19972f98d0f2f717e8a169fe1c17a9ffc6c..508f52c849836788feea2c8668ef71af48dd42cb 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt @@ -23,7 +23,6 @@ import com.android.systemui.communal.data.repository.CommunalMediaRepository import com.android.systemui.communal.data.repository.CommunalRepository import com.android.systemui.communal.data.repository.CommunalWidgetRepository import com.android.systemui.communal.domain.model.CommunalContentModel -import com.android.systemui.communal.shared.model.CommunalAppWidgetInfo import com.android.systemui.communal.shared.model.CommunalContentSize import com.android.systemui.communal.shared.model.CommunalSceneKey import com.android.systemui.dagger.SysUISingleton @@ -55,9 +54,6 @@ constructor( val isCommunalEnabled: Boolean get() = communalRepository.isCommunalEnabled - /** A flow of info about the widget to be displayed, or null if widget is unavailable. */ - val appWidgetInfo: Flow<CommunalAppWidgetInfo?> = widgetRepository.stopwatchAppWidgetInfo - /** * Target scene as requested by the underlying [SceneTransitionLayout] or through * [onSceneChanged]. diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/binder/CommunalWidgetViewBinder.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/binder/CommunalWidgetViewBinder.kt deleted file mode 100644 index 65bf4b3e69cd9f64d63ccc8c9b9556e4f0ffd573..0000000000000000000000000000000000000000 --- a/packages/SystemUI/src/com/android/systemui/communal/ui/binder/CommunalWidgetViewBinder.kt +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2023 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.communal.ui.binder - -import androidx.lifecycle.Lifecycle -import androidx.lifecycle.repeatOnLifecycle -import com.android.systemui.res.R -import com.android.systemui.communal.ui.adapter.CommunalWidgetViewAdapter -import com.android.systemui.communal.ui.view.CommunalWidgetWrapper -import com.android.systemui.communal.ui.viewmodel.CommunalWidgetViewModel -import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor -import com.android.systemui.keyguard.ui.view.KeyguardRootView -import com.android.systemui.lifecycle.repeatWhenAttached -import kotlinx.coroutines.launch - -/** Binds [CommunalWidgetViewModel] to the keyguard root view. */ -object CommunalWidgetViewBinder { - - @JvmStatic - fun bind( - rootView: KeyguardRootView, - viewModel: CommunalWidgetViewModel, - adapter: CommunalWidgetViewAdapter, - keyguardBlueprintInteractor: KeyguardBlueprintInteractor, - ) { - rootView.repeatWhenAttached { - repeatOnLifecycle(Lifecycle.State.STARTED) { - launch { - adapter.adapt(viewModel.appWidgetInfo).collect { - val oldView = - rootView.findViewById<CommunalWidgetWrapper>( - R.id.communal_widget_wrapper - ) - var dirty = false - - if (oldView != null) { - rootView.removeView(oldView) - dirty = true - } - - if (it != null) { - rootView.addView(it) - dirty = true - } - - if (dirty) { - keyguardBlueprintInteractor.refreshBlueprint() - } - } - } - - launch { viewModel.alpha.collect { rootView.alpha = it } } - } - } - } -} diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprint.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprint.kt index 702554ab4943345a927d92bb0a7f1307ea2747b0..9198c7bd7009970b16cde1a1dac3cc5384e7aa11 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprint.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprint.kt @@ -17,7 +17,6 @@ package com.android.systemui.communal.ui.view.layout.blueprints import com.android.systemui.communal.ui.view.layout.sections.DefaultCommunalHubSection -import com.android.systemui.communal.ui.view.layout.sections.DefaultCommunalWidgetSection import com.android.systemui.dagger.SysUISingleton import com.android.systemui.keyguard.shared.model.KeyguardBlueprint import com.android.systemui.keyguard.shared.model.KeyguardSection @@ -30,13 +29,11 @@ class DefaultCommunalBlueprint @Inject constructor( defaultCommunalHubSection: DefaultCommunalHubSection, - defaultCommunalWidgetSection: DefaultCommunalWidgetSection, ) : KeyguardBlueprint { override val id: String = COMMUNAL override val sections: List<KeyguardSection> = listOf( defaultCommunalHubSection, - defaultCommunalWidgetSection, ) companion object { diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalWidgetSection.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalWidgetSection.kt deleted file mode 100644 index c3e8a96701ead940e461e52bc8f7d724238a3d84..0000000000000000000000000000000000000000 --- a/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalWidgetSection.kt +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2023 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.communal.ui.view.layout.sections - -import android.view.ViewGroup.LayoutParams.WRAP_CONTENT -import androidx.constraintlayout.widget.ConstraintLayout -import androidx.constraintlayout.widget.ConstraintSet -import androidx.constraintlayout.widget.ConstraintSet.BOTTOM -import androidx.constraintlayout.widget.ConstraintSet.END -import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID -import com.android.systemui.res.R -import com.android.systemui.communal.ui.adapter.CommunalWidgetViewAdapter -import com.android.systemui.communal.ui.binder.CommunalWidgetViewBinder -import com.android.systemui.communal.ui.viewmodel.CommunalWidgetViewModel -import com.android.systemui.flags.FeatureFlags -import com.android.systemui.flags.Flags -import com.android.systemui.keyguard.domain.interactor.KeyguardBlueprintInteractor -import com.android.systemui.keyguard.shared.model.KeyguardSection -import com.android.systemui.keyguard.ui.view.KeyguardRootView -import dagger.Lazy -import javax.inject.Inject - -class DefaultCommunalWidgetSection -@Inject -constructor( - private val featureFlags: FeatureFlags, - private val keyguardRootView: KeyguardRootView, - private val communalWidgetViewModel: CommunalWidgetViewModel, - private val communalWidgetViewAdapter: CommunalWidgetViewAdapter, - private val keyguardBlueprintInteractor: Lazy<KeyguardBlueprintInteractor>, -) : KeyguardSection() { - private val widgetAreaViewId = R.id.communal_widget_wrapper - - override fun addViews(constraintLayout: ConstraintLayout) {} - - override fun bindData(constraintLayout: ConstraintLayout) { - if (!featureFlags.isEnabled(Flags.WIDGET_ON_KEYGUARD)) { - return - } - - CommunalWidgetViewBinder.bind( - keyguardRootView, - communalWidgetViewModel, - communalWidgetViewAdapter, - keyguardBlueprintInteractor.get(), - ) - } - - override fun applyConstraints(constraintSet: ConstraintSet) { - constraintSet.apply { - constrainWidth(widgetAreaViewId, WRAP_CONTENT) - constrainHeight(widgetAreaViewId, WRAP_CONTENT) - connect(widgetAreaViewId, BOTTOM, PARENT_ID, BOTTOM) - connect(widgetAreaViewId, END, PARENT_ID, END) - } - } - - override fun removeViews(constraintLayout: ConstraintLayout) {} -} diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalWidgetViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalWidgetViewModel.kt deleted file mode 100644 index d7bbea64332e8c840445ba0771a19e6a327f7530..0000000000000000000000000000000000000000 --- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalWidgetViewModel.kt +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2023 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.communal.ui.viewmodel - -import com.android.systemui.communal.domain.interactor.CommunalInteractor -import com.android.systemui.communal.shared.model.CommunalAppWidgetInfo -import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.keyguard.ui.viewmodel.KeyguardBottomAreaViewModel -import javax.inject.Inject -import kotlinx.coroutines.flow.Flow - -@SysUISingleton -class CommunalWidgetViewModel -@Inject -constructor( - communalInteractor: CommunalInteractor, - keyguardBottomAreaViewModel: KeyguardBottomAreaViewModel, -) { - /** An observable for the alpha level for the communal widget area. */ - val alpha: Flow<Float> = keyguardBottomAreaViewModel.alpha - - /** A flow of info about the widget to be displayed, or null if widget is unavailable. */ - val appWidgetInfo: Flow<CommunalAppWidgetInfo?> = communalInteractor.appWidgetInfo -} diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt index b237b87987a4da201a9511b2cf7a719587c978b4..d64a1312ac66a22f1f9b3633adaac2a06b2b4f9b 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt @@ -239,8 +239,7 @@ object Flags { /** Provide new auth messages on the bouncer. */ // TODO(b/277961132): Tracking bug. - @JvmField val REVAMPED_BOUNCER_MESSAGES = unreleasedFlag("revamped_bouncer_messages", - teamfood = true) + @JvmField val REVAMPED_BOUNCER_MESSAGES = unreleasedFlag("revamped_bouncer_messages") /** Keyguard Migration */ @@ -255,9 +254,6 @@ object Flags { // TODO(b/287268101): Tracking bug. @JvmField val TRANSIT_CLOCK = releasedFlag("lockscreen_custom_transit_clock") - // TODO(b/288276738): Tracking bug. - @JvmField val WIDGET_ON_KEYGUARD = unreleasedFlag("widget_on_keyguard") - /** Migrate the NSSL to the a sibling to both the panel and keyguard root view. */ // TODO(b/288074305): Tracking bug. @JvmField val MIGRATE_NSSL = unreleasedFlag("migrate_nssl") @@ -776,9 +772,4 @@ object Flags { @JvmField val COMMUNAL_SERVICE_ENABLED = resourceBooleanFlag(R.bool.config_communalServiceEnabled, "communal_service_enabled") - - // TODO(b/303131306): Tracking Bug - /** Whether communal hub features are enabled. */ - @JvmField - val COMMUNAL_HUB = unreleasedFlag("communal_hub") } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileState.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileState.kt index 30b87cc9e662136da1717b372182af033417fa27..f9e0b160acd694d172478cfdbb4eb530eb61cf07 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileState.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileState.kt @@ -18,7 +18,10 @@ package com.android.systemui.qs.tiles.viewmodel import android.content.Context import android.service.quicksettings.Tile +import android.view.View +import android.widget.Switch import com.android.systemui.common.shared.model.Icon +import kotlin.reflect.KClass /** * Represents current a state of the tile to be displayed in on the view. Consider using @@ -111,7 +114,7 @@ data class QSTileState( var stateDescription: CharSequence? = null var sideViewIcon: SideViewIcon = SideViewIcon.None var enabledState: EnabledState = EnabledState.ENABLED - var expandedAccessibilityClassName: String? = null + var expandedAccessibilityClass: KClass<out View>? = Switch::class fun build(): QSTileState = QSTileState( @@ -124,7 +127,7 @@ data class QSTileState( stateDescription, sideViewIcon, enabledState, - expandedAccessibilityClassName, + expandedAccessibilityClass?.qualifiedName, ) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt index 6ac84bc503a2ae283ba1d0e6db028d7471f61e19..0c06808b10c9c897861b9f8feddd7ceae8d28e93 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt @@ -100,12 +100,12 @@ class AuthenticationRepositoryTest : SysuiTestCase() { } @Test - fun isAutoConfirmEnabled() = + fun isAutoConfirmFeatureEnabled() = testScope.runTest { whenever(lockPatternUtils.isAutoPinConfirmEnabled(USER_INFOS[0].id)).thenReturn(true) whenever(lockPatternUtils.isAutoPinConfirmEnabled(USER_INFOS[1].id)).thenReturn(false) - val values by collectValues(underTest.isAutoConfirmEnabled) + val values by collectValues(underTest.isAutoConfirmFeatureEnabled) assertThat(values.first()).isFalse() assertThat(values.last()).isTrue() diff --git a/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt index 2f5f4606c5f059c035499a932a86af823db5efcc..103f2b8ac3136de2414c6db57487e7004aee7bdc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt @@ -213,11 +213,14 @@ class AuthenticationInteractorTest : SysuiTestCase() { @Test fun tryAutoConfirm_withAutoConfirmPinAndShorterPin_returnsNullAndHasNoEffect() = testScope.runTest { + val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled) val isThrottled by collectLastValue(underTest.isThrottled) utils.authenticationRepository.apply { setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin) - setAutoConfirmEnabled(true) + setAutoConfirmFeatureEnabled(true) } + assertThat(isAutoConfirmEnabled).isTrue() + assertThat( underTest.authenticate( FakeAuthenticationRepository.DEFAULT_PIN.toMutableList().apply { @@ -233,10 +236,13 @@ class AuthenticationInteractorTest : SysuiTestCase() { @Test fun tryAutoConfirm_withAutoConfirmWrongPinCorrectLength_returnsFalseAndDoesNotUnlockDevice() = testScope.runTest { + val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled) utils.authenticationRepository.apply { setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin) - setAutoConfirmEnabled(true) + setAutoConfirmFeatureEnabled(true) } + assertThat(isAutoConfirmEnabled).isTrue() + assertThat( underTest.authenticate( FakeAuthenticationRepository.DEFAULT_PIN.map { it + 1 }, @@ -251,10 +257,13 @@ class AuthenticationInteractorTest : SysuiTestCase() { @Test fun tryAutoConfirm_withAutoConfirmLongerPin_returnsFalseAndDoesNotUnlockDevice() = testScope.runTest { + val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled) utils.authenticationRepository.apply { setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin) - setAutoConfirmEnabled(true) + setAutoConfirmFeatureEnabled(true) } + assertThat(isAutoConfirmEnabled).isTrue() + assertThat( underTest.authenticate( FakeAuthenticationRepository.DEFAULT_PIN + listOf(7), @@ -269,10 +278,13 @@ class AuthenticationInteractorTest : SysuiTestCase() { @Test fun tryAutoConfirm_withAutoConfirmCorrectPin_returnsTrueAndUnlocksDevice() = testScope.runTest { + val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled) utils.authenticationRepository.apply { setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin) - setAutoConfirmEnabled(true) + setAutoConfirmFeatureEnabled(true) } + assertThat(isAutoConfirmEnabled).isTrue() + assertThat( underTest.authenticate( FakeAuthenticationRepository.DEFAULT_PIN, @@ -284,12 +296,36 @@ class AuthenticationInteractorTest : SysuiTestCase() { assertThat(isUnlocked).isTrue() } + @Test + fun tryAutoConfirm_withAutoConfirmCorrectPinButDuringThrottling_returnsNullAndHasNoEffects() = + testScope.runTest { + val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled) + val isUnlocked by collectLastValue(utils.deviceEntryRepository.isUnlocked) + val hintedPinLength by collectLastValue(underTest.hintedPinLength) + utils.authenticationRepository.apply { + setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin) + setAutoConfirmFeatureEnabled(true) + setThrottleDuration(42) + } + + val authResult = + underTest.authenticate( + FakeAuthenticationRepository.DEFAULT_PIN, + tryAutoConfirm = true + ) + + assertThat(authResult).isEqualTo(AuthenticationResult.SKIPPED) + assertThat(isAutoConfirmEnabled).isFalse() + assertThat(isUnlocked).isFalse() + assertThat(hintedPinLength).isNull() + } + @Test fun tryAutoConfirm_withoutAutoConfirmButCorrectPin_returnsNullAndHasNoEffects() = testScope.runTest { utils.authenticationRepository.apply { setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin) - setAutoConfirmEnabled(false) + setAutoConfirmFeatureEnabled(false) } assertThat( underTest.authenticate( @@ -416,7 +452,7 @@ class AuthenticationInteractorTest : SysuiTestCase() { val hintedPinLength by collectLastValue(underTest.hintedPinLength) utils.authenticationRepository.apply { setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin) - setAutoConfirmEnabled(false) + setAutoConfirmFeatureEnabled(false) } assertThat(hintedPinLength).isNull() @@ -433,7 +469,7 @@ class AuthenticationInteractorTest : SysuiTestCase() { repeat(utils.authenticationRepository.hintedPinLength - 1) { add(it + 1) } } ) - setAutoConfirmEnabled(true) + setAutoConfirmFeatureEnabled(true) } assertThat(hintedPinLength).isNull() @@ -445,7 +481,7 @@ class AuthenticationInteractorTest : SysuiTestCase() { val hintedPinLength by collectLastValue(underTest.hintedPinLength) utils.authenticationRepository.apply { setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin) - setAutoConfirmEnabled(true) + setAutoConfirmFeatureEnabled(true) overrideCredential( buildList { repeat(utils.authenticationRepository.hintedPinLength) { add(it + 1) } @@ -467,7 +503,7 @@ class AuthenticationInteractorTest : SysuiTestCase() { repeat(utils.authenticationRepository.hintedPinLength + 1) { add(it + 1) } } ) - setAutoConfirmEnabled(true) + setAutoConfirmFeatureEnabled(true) } assertThat(hintedPinLength).isNull() diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt index 915661b8a77690e5f703405c577d7752b0031175..577539620ee3a3eb33c26b7b0d89dd19210a4cb5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt @@ -110,12 +110,14 @@ class BouncerInteractorTest : SysuiTestCase() { testScope.runTest { val currentScene by collectLastValue(sceneInteractor.desiredScene) val message by collectLastValue(underTest.message) + val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled) utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) runCurrent() - utils.authenticationRepository.setAutoConfirmEnabled(true) + utils.authenticationRepository.setAutoConfirmFeatureEnabled(true) utils.deviceEntryRepository.setUnlocked(false) underTest.showOrUnlockDevice() + assertThat(isAutoConfirmEnabled).isTrue() assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer)) assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PIN) underTest.clearMessage() diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt index 3ddac7e1ad1dfbc97edcb9ff187dbc7a1e1fbe0a..e07c0b87bc7959062b98a5f62e7e0a317874313a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt @@ -247,7 +247,7 @@ class PinBouncerViewModelTest : SysuiTestCase() { fun onAutoConfirm_whenCorrect() = testScope.runTest { val currentScene by collectLastValue(sceneInteractor.desiredScene) - utils.authenticationRepository.setAutoConfirmEnabled(true) + utils.authenticationRepository.setAutoConfirmFeatureEnabled(true) lockDeviceAndOpenPinBouncer() FakeAuthenticationRepository.DEFAULT_PIN.forEach { digit -> @@ -263,7 +263,7 @@ class PinBouncerViewModelTest : SysuiTestCase() { val currentScene by collectLastValue(sceneInteractor.desiredScene) val message by collectLastValue(bouncerViewModel.message) val pin by collectLastValue(underTest.pinInput.map { it.getPin() }) - utils.authenticationRepository.setAutoConfirmEnabled(true) + utils.authenticationRepository.setAutoConfirmFeatureEnabled(true) lockDeviceAndOpenPinBouncer() FakeAuthenticationRepository.DEFAULT_PIN.dropLast(1).forEach { digit -> @@ -323,7 +323,7 @@ class PinBouncerViewModelTest : SysuiTestCase() { testScope.runTest { val backspaceButtonAppearance by collectLastValue(underTest.backspaceButtonAppearance) utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) - utils.authenticationRepository.setAutoConfirmEnabled(true) + utils.authenticationRepository.setAutoConfirmFeatureEnabled(true) assertThat(backspaceButtonAppearance).isEqualTo(ActionButtonAppearance.Hidden) } @@ -333,7 +333,7 @@ class PinBouncerViewModelTest : SysuiTestCase() { testScope.runTest { val backspaceButtonAppearance by collectLastValue(underTest.backspaceButtonAppearance) utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) - utils.authenticationRepository.setAutoConfirmEnabled(true) + utils.authenticationRepository.setAutoConfirmFeatureEnabled(true) underTest.onPinButtonClicked(1) @@ -355,7 +355,7 @@ class PinBouncerViewModelTest : SysuiTestCase() { testScope.runTest { val confirmButtonAppearance by collectLastValue(underTest.confirmButtonAppearance) utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) - utils.authenticationRepository.setAutoConfirmEnabled(true) + utils.authenticationRepository.setAutoConfirmFeatureEnabled(true) assertThat(confirmButtonAppearance).isEqualTo(ActionButtonAppearance.Hidden) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt index ca8316dce10ec58824c303253af8d21021b71e15..28fae819de98fdfbaf91d88b834614aa4fb6b436 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt @@ -21,7 +21,6 @@ import android.appwidget.AppWidgetManager import android.appwidget.AppWidgetProviderInfo import android.content.BroadcastReceiver import android.content.ComponentName -import android.content.pm.PackageManager import android.os.UserHandle import android.os.UserManager import androidx.test.ext.junit.runners.AndroidJUnit4 @@ -34,8 +33,6 @@ import com.android.systemui.communal.data.db.CommunalWidgetItem import com.android.systemui.communal.shared.CommunalWidgetHost import com.android.systemui.communal.shared.model.CommunalWidgetContentModel import com.android.systemui.coroutines.collectLastValue -import com.android.systemui.flags.FeatureFlagsClassic -import com.android.systemui.flags.Flags import com.android.systemui.log.LogBuffer import com.android.systemui.log.core.FakeLogBuffer import com.android.systemui.res.R @@ -72,16 +69,12 @@ class CommunalWidgetRepositoryImplTest : SysuiTestCase() { @Mock private lateinit var broadcastDispatcher: BroadcastDispatcher - @Mock private lateinit var packageManager: PackageManager - @Mock private lateinit var userManager: UserManager @Mock private lateinit var userHandle: UserHandle @Mock private lateinit var userTracker: UserTracker - @Mock private lateinit var featureFlags: FeatureFlagsClassic - @Mock private lateinit var stopwatchProviderInfo: AppWidgetProviderInfo @Mock private lateinit var providerInfoA: AppWidgetProviderInfo @@ -113,13 +106,13 @@ class CommunalWidgetRepositoryImplTest : SysuiTestCase() { communalRepository = FakeCommunalRepository() communalEnabled(true) - widgetOnKeyguardEnabled(true) setAppWidgetIds(emptyList()) overrideResource(R.array.config_communalWidgetAllowlist, fakeAllowlist.toTypedArray()) whenever(stopwatchProviderInfo.loadLabel(any())).thenReturn("Stopwatch") whenever(userTracker.userHandle).thenReturn(userHandle) + whenever(communalWidgetDao.getWidgets()).thenReturn(flowOf(emptyMap())) } @Test @@ -213,7 +206,7 @@ class CommunalWidgetRepositoryImplTest : SysuiTestCase() { testScope.runTest { communalEnabled(false) val repository = initCommunalWidgetRepository() - collectLastValue(repository.stopwatchAppWidgetInfo)() + collectLastValue(repository.communalWidgets)() verifyBroadcastReceiverNeverRegistered() } @@ -222,7 +215,7 @@ class CommunalWidgetRepositoryImplTest : SysuiTestCase() { testScope.runTest { userUnlocked(true) val repository = initCommunalWidgetRepository() - collectLastValue(repository.stopwatchAppWidgetInfo)() + collectLastValue(repository.communalWidgets)() verifyBroadcastReceiverNeverRegistered() } @@ -231,7 +224,7 @@ class CommunalWidgetRepositoryImplTest : SysuiTestCase() { testScope.runTest { userUnlocked(false) val repository = initCommunalWidgetRepository() - collectLastValue(repository.stopwatchAppWidgetInfo)() + collectLastValue(repository.communalWidgets)() verifyBroadcastReceiverRegistered() } @@ -241,7 +234,7 @@ class CommunalWidgetRepositoryImplTest : SysuiTestCase() { userUnlocked(false) val repository = initCommunalWidgetRepository() - val job = launch { repository.stopwatchAppWidgetInfo.collect() } + val job = launch { repository.communalWidgets.collect() } runCurrent() val receiver = broadcastReceiverUpdate() @@ -251,54 +244,17 @@ class CommunalWidgetRepositoryImplTest : SysuiTestCase() { verify(broadcastDispatcher).unregisterReceiver(receiver) } - @Test - fun stopwatch_whenUserUnlocks_receiveProviderInfo() = - testScope.runTest { - userUnlocked(false) - val repository = initCommunalWidgetRepository() - val lastStopwatchProviderInfo = collectLastValue(repository.stopwatchAppWidgetInfo) - assertThat(lastStopwatchProviderInfo()).isNull() - - userUnlocked(true) - installedProviders(listOf(stopwatchProviderInfo)) - broadcastReceiverUpdate() - - assertThat(lastStopwatchProviderInfo()?.providerInfo).isEqualTo(stopwatchProviderInfo) - } - - @Test - fun stopwatch_userUnlockedButWidgetNotInstalled_noProviderInfo() = - testScope.runTest { - userUnlocked(true) - installedProviders(listOf()) - - val repository = initCommunalWidgetRepository() - - val lastStopwatchProviderInfo = collectLastValue(repository.stopwatchAppWidgetInfo) - assertThat(lastStopwatchProviderInfo()).isNull() - } - - @Test - fun appWidgetId_providerInfoAvailable_allocateAppWidgetId() = - testScope.runTest { - userUnlocked(true) - installedProviders(listOf(stopwatchProviderInfo)) - val repository = initCommunalWidgetRepository() - collectLastValue(repository.stopwatchAppWidgetInfo)() - verify(appWidgetHost).allocateAppWidgetId() - } - @Test fun appWidgetHost_userUnlocked_startListening() = testScope.runTest { userUnlocked(false) val repository = initCommunalWidgetRepository() - collectLastValue(repository.stopwatchAppWidgetInfo)() + collectLastValue(repository.communalWidgets)() verify(appWidgetHost, Mockito.never()).startListening() userUnlocked(true) broadcastReceiverUpdate() - collectLastValue(repository.stopwatchAppWidgetInfo)() + collectLastValue(repository.communalWidgets)() verify(appWidgetHost).startListening() } @@ -308,18 +264,18 @@ class CommunalWidgetRepositoryImplTest : SysuiTestCase() { testScope.runTest { userUnlocked(false) val repository = initCommunalWidgetRepository() - collectLastValue(repository.stopwatchAppWidgetInfo)() + collectLastValue(repository.communalWidgets)() userUnlocked(true) broadcastReceiverUpdate() - collectLastValue(repository.stopwatchAppWidgetInfo)() + collectLastValue(repository.communalWidgets)() verify(appWidgetHost).startListening() verify(appWidgetHost, Mockito.never()).stopListening() userUnlocked(false) broadcastReceiverUpdate() - collectLastValue(repository.stopwatchAppWidgetInfo)() + collectLastValue(repository.communalWidgets)() verify(appWidgetHost).stopListening() } @@ -334,11 +290,9 @@ class CommunalWidgetRepositoryImplTest : SysuiTestCase() { communalRepository, communalWidgetHost, communalWidgetDao, - packageManager, userManager, userTracker, logBuffer, - featureFlags, ) } @@ -385,10 +339,6 @@ class CommunalWidgetRepositoryImplTest : SysuiTestCase() { communalRepository.setIsCommunalEnabled(enabled) } - private fun widgetOnKeyguardEnabled(enabled: Boolean) { - whenever(featureFlags.isEnabled(Flags.WIDGET_ON_KEYGUARD)).thenReturn(enabled) - } - private fun userUnlocked(userUnlocked: Boolean) { whenever(userManager.isUserUnlockingOrUnlocked(userHandle)).thenReturn(userUnlocked) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt index 08d54c001d11e23b973299b7716e07421a56fa78..a6c4f1929333c394331345a508eb8546feaf5df2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt @@ -29,7 +29,6 @@ import com.android.systemui.communal.data.repository.FakeCommunalRepository import com.android.systemui.communal.data.repository.FakeCommunalTutorialRepository import com.android.systemui.communal.data.repository.FakeCommunalWidgetRepository import com.android.systemui.communal.domain.model.CommunalContentModel -import com.android.systemui.communal.shared.model.CommunalAppWidgetInfo import com.android.systemui.communal.shared.model.CommunalSceneKey import com.android.systemui.communal.shared.model.CommunalWidgetContentModel import com.android.systemui.coroutines.collectLastValue @@ -45,7 +44,6 @@ import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.mockito.Mock import org.mockito.Mockito.mock import org.mockito.MockitoAnnotations @@ -53,8 +51,6 @@ import org.mockito.MockitoAnnotations @OptIn(ExperimentalCoroutinesApi::class) @RunWith(AndroidJUnit4::class) class CommunalInteractorTest : SysuiTestCase() { - @Mock private lateinit var stopwatchAppWidgetInfo: CommunalAppWidgetInfo - private lateinit var testScope: TestScope private lateinit var tutorialRepository: FakeCommunalTutorialRepository @@ -84,18 +80,6 @@ class CommunalInteractorTest : SysuiTestCase() { underTest = withDeps.communalInteractor } - @Test - fun appWidgetInfoFlow() = - testScope.runTest { - val lastAppWidgetInfo = collectLastValue(underTest.appWidgetInfo) - runCurrent() - assertThat(lastAppWidgetInfo()).isNull() - - widgetRepository.setStopwatchAppWidgetInfo(stopwatchAppWidgetInfo) - runCurrent() - assertThat(lastAppWidgetInfo()).isEqualTo(stopwatchAppWidgetInfo) - } - @Test fun communalEnabled() = testScope.runTest { diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt b/packages/SystemUI/tests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt index 33a666700877ecf40585b15ff0d6b5312033c89e..a49629252520a5742cc3e90ff925cd43bf2ac83f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/communal/ui/view/layout/blueprints/DefaultCommunalBlueprintTest.kt @@ -7,7 +7,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.communal.ui.view.layout.sections.DefaultCommunalHubSection -import com.android.systemui.communal.ui.view.layout.sections.DefaultCommunalWidgetSection import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -20,14 +19,13 @@ import org.mockito.MockitoAnnotations @SmallTest class DefaultCommunalBlueprintTest : SysuiTestCase() { @Mock private lateinit var hubSection: DefaultCommunalHubSection - @Mock private lateinit var widgetSection: DefaultCommunalWidgetSection private lateinit var blueprint: DefaultCommunalBlueprint @Before fun setup() { MockitoAnnotations.initMocks(this) - blueprint = DefaultCommunalBlueprint(hubSection, widgetSection) + blueprint = DefaultCommunalBlueprint(hubSection) } @Test @@ -35,7 +33,6 @@ class DefaultCommunalBlueprintTest : SysuiTestCase() { val constraintLayout = ConstraintLayout(context, null) blueprint.replaceViews(null, constraintLayout) verify(hubSection).addViews(constraintLayout) - verify(widgetSection).addViews(constraintLayout) } @Test @@ -43,6 +40,5 @@ class DefaultCommunalBlueprintTest : SysuiTestCase() { val cs = ConstraintSet() blueprint.applyConstraints(cs) verify(hubSection).applyConstraints(cs) - verify(widgetSection).applyConstraints(cs) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/logging/QSTileLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/logging/QSTileLoggerTest.kt index b5e7e2c14211e4aa2da99228279a0923dab6a50e..92c2d743c26255039112962a7cb5dbf84fcb3f65 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/logging/QSTileLoggerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/base/logging/QSTileLoggerTest.kt @@ -130,7 +130,7 @@ class QSTileLoggerTest : SysuiTestCase() { "sd=null, " + "svi=None, " + "enabled=ENABLED, " + - "a11y=null" + + "a11y=android.widget.Switch" + "], " + "data=test_data" ) @@ -154,7 +154,7 @@ class QSTileLoggerTest : SysuiTestCase() { "sd=null, " + "svi=None, " + "enabled=ENABLED, " + - "a11y=null], " + + "a11y=android.widget.Switch], " + "data=test_data" ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt index ddfe79aedce647074c182d18eb7a19dd2a719961..81c5d9c248f3194ff9c86e5bb9649eaef02b2501 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt @@ -41,8 +41,9 @@ class FakeAuthenticationRepository( private val currentTime: () -> Long, ) : AuthenticationRepository { - private val _isAutoConfirmEnabled = MutableStateFlow(false) - override val isAutoConfirmEnabled: StateFlow<Boolean> = _isAutoConfirmEnabled.asStateFlow() + private val _isAutoConfirmFeatureEnabled = MutableStateFlow(false) + override val isAutoConfirmFeatureEnabled: StateFlow<Boolean> = + _isAutoConfirmFeatureEnabled.asStateFlow() override val hintedPinLength: Int = HINTING_PIN_LENGTH @@ -98,8 +99,8 @@ class FakeAuthenticationRepository( _throttling.value = throttlingModel } - fun setAutoConfirmEnabled(isEnabled: Boolean) { - _isAutoConfirmEnabled.value = isEnabled + fun setAutoConfirmFeatureEnabled(isEnabled: Boolean) { + _isAutoConfirmFeatureEnabled.value = isEnabled } override suspend fun setThrottleDuration(durationMs: Int) { diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalWidgetRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalWidgetRepository.kt index 8a2ff50d8a323b8bebed5106477849e263758c63..c6f12e2014b36ccd9264c89492ad1ba1552e18cc 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalWidgetRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalWidgetRepository.kt @@ -1,22 +1,14 @@ package com.android.systemui.communal.data.repository -import com.android.systemui.communal.shared.model.CommunalAppWidgetInfo import com.android.systemui.communal.shared.model.CommunalWidgetContentModel import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow /** Fake implementation of [CommunalWidgetRepository] */ class FakeCommunalWidgetRepository : CommunalWidgetRepository { - private val _stopwatchAppWidgetInfo = MutableStateFlow<CommunalAppWidgetInfo?>(null) - override val stopwatchAppWidgetInfo: Flow<CommunalAppWidgetInfo?> = _stopwatchAppWidgetInfo - private val _communalWidgets = MutableStateFlow<List<CommunalWidgetContentModel>>(emptyList()) override val communalWidgets: Flow<List<CommunalWidgetContentModel>> = _communalWidgets - fun setStopwatchAppWidgetInfo(appWidgetInfo: CommunalAppWidgetInfo) { - _stopwatchAppWidgetInfo.value = appWidgetInfo - } - fun setCommunalWidgets(inventory: List<CommunalWidgetContentModel>) { _communalWidgets.value = inventory } diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java index 052b0c2078d1c8d8050de6f4553f2410c3fc7f9d..e5f763722bf18ba9200e59b3272ad6d4e6d3cbe8 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -2391,7 +2391,8 @@ public class AppOpsService extends IAppOpsService.Stub { long token = Binder.clearCallingIdentity(); try { // Permissions are managed by UIDs, but unfortunately a package name is required in API. - String packageName = ArrayUtils.firstOrNull(packageManager.getPackagesForUid(uid)); + String packageName = ArrayUtils.firstOrNull(ArrayUtils.defeatNullable( + packageManager.getPackagesForUid(uid))); if (packageName == null) { return false; } diff --git a/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java b/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java index 86e417b183f8cff449a2ce5b0a3e7739edbb9b25..3b5ef4cadfdf75e6663d60c2d665d221c6dd42c8 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java @@ -77,13 +77,14 @@ final class InputMethodMenuController { void showInputMethodMenu(boolean showAuxSubtypes, int displayId) { if (DEBUG) Slog.v(TAG, "Show switching menu. showAuxSubtypes=" + showAuxSubtypes); - final boolean isScreenLocked = isScreenLocked(); - - final String lastInputMethodId = mSettings.getSelectedInputMethod(); - int lastInputMethodSubtypeId = mSettings.getSelectedInputMethodSubtypeId(lastInputMethodId); - if (DEBUG) Slog.v(TAG, "Current IME: " + lastInputMethodId); - synchronized (ImfLock.class) { + final boolean isScreenLocked = mWindowManagerInternal.isKeyguardLocked() + && mWindowManagerInternal.isKeyguardSecure(mSettings.getCurrentUserId()); + final String lastInputMethodId = mSettings.getSelectedInputMethod(); + int lastInputMethodSubtypeId = + mSettings.getSelectedInputMethodSubtypeId(lastInputMethodId); + if (DEBUG) Slog.v(TAG, "Current IME: " + lastInputMethodId); + final List<ImeSubtypeListItem> imList = mSwitchingController .getSortedInputMethodAndSubtypeListForImeMenuLocked( showAuxSubtypes, isScreenLocked); @@ -200,12 +201,8 @@ final class InputMethodMenuController { mService.updateSystemUiLocked(); mService.sendOnNavButtonFlagsChangedLocked(); mSwitchingDialog.show(); - } - } - private boolean isScreenLocked() { - return mWindowManagerInternal.isKeyguardLocked() - && mWindowManagerInternal.isKeyguardSecure(mSettings.getCurrentUserId()); + } } void updateKeyboardFromSettingsLocked() { diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java index cba605eac8f6db6f616b331220468754939edae1..26177037e1b45fb5c407bcc7319fa622bc5edbd8 100644 --- a/services/core/java/com/android/server/pm/ComputerEngine.java +++ b/services/core/java/com/android/server/pm/ComputerEngine.java @@ -60,6 +60,7 @@ import static com.android.server.pm.PackageManagerService.TAG; import static com.android.server.pm.PackageManagerServiceUtils.compareSignatureArrays; import static com.android.server.pm.PackageManagerServiceUtils.compareSignatures; import static com.android.server.pm.PackageManagerServiceUtils.isSystemOrRootOrShell; +import static com.android.server.pm.parsing.PackageInfoUtils.getDeprecatedSignatures; import static com.android.server.pm.resolution.ComponentResolver.RESOLVE_PRIORITY_SORTER; import android.Manifest; @@ -1531,6 +1532,7 @@ public class ComputerEngine implements Computer { pi.applicationInfo = PackageInfoUtils.generateDelegateApplicationInfo( ai, flags, state, userId); pi.signingInfo = ps.getSigningInfo(); + pi.signatures = getDeprecatedSignatures(pi.signingInfo.getSigningDetails(), flags); if (DEBUG_PACKAGE_INFO) { Log.v(TAG, "ps.pkg is n/a for [" diff --git a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java index c26cf1c9a113830b3e74d7a60c8e55bc615f9e19..38cde3e3f7d7aa21254b1e953392caed275e42f9 100644 --- a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java +++ b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java @@ -238,21 +238,7 @@ public class PackageInfoUtils { } final SigningDetails signingDetails = pkg.getSigningDetails(); - // deprecated method of getting signing certificates - if ((flags & PackageManager.GET_SIGNATURES) != 0) { - if (signingDetails.hasPastSigningCertificates()) { - // Package has included signing certificate rotation information. Return the oldest - // cert so that programmatic checks keep working even if unaware of key rotation. - info.signatures = new Signature[1]; - info.signatures[0] = signingDetails.getPastSigningCertificates()[0]; - } else if (signingDetails.hasSignatures()) { - // otherwise keep old behavior - int numberOfSigs = signingDetails.getSignatures().length; - info.signatures = new Signature[numberOfSigs]; - System.arraycopy(signingDetails.getSignatures(), 0, info.signatures, 0, - numberOfSigs); - } - } + info.signatures = getDeprecatedSignatures(signingDetails, flags); // replacement for GET_SIGNATURES if ((flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0) { @@ -358,6 +344,30 @@ public class PackageInfoUtils { return info; } + /** + * Retrieve the deprecated {@link PackageInfo.signatures} field of signing certificates + */ + public static Signature[] getDeprecatedSignatures(SigningDetails signingDetails, long flags) { + if ((flags & PackageManager.GET_SIGNATURES) == 0) { + return null; + } + if (signingDetails.hasPastSigningCertificates()) { + // Package has included signing certificate rotation information. Return the oldest + // cert so that programmatic checks keep working even if unaware of key rotation. + Signature[] signatures = new Signature[1]; + signatures[0] = signingDetails.getPastSigningCertificates()[0]; + return signatures; + } else if (signingDetails.hasSignatures()) { + // otherwise keep old behavior + int numberOfSigs = signingDetails.getSignatures().length; + Signature[] signatures = new Signature[numberOfSigs]; + System.arraycopy(signingDetails.getSignatures(), 0, signatures, 0, + numberOfSigs); + return signatures; + } + return null; + } + private static void updateApplicationInfo(ApplicationInfo ai, long flags, PackageUserState state) { if ((flags & PackageManager.GET_META_DATA) == 0) { diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java index 1b5631f59a3eb7101736952fc8e788b2d21f2831..a2f5a383caad1e3ac22726a76309d3ea62fddf87 100644 --- a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java +++ b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java @@ -256,13 +256,24 @@ public class BackgroundActivityStartController { mOriginatingPendingIntent = originatingPendingIntent; mIntent = intent; mRealCallingPackage = mService.getPackageNameIfUnique(realCallingUid, realCallingPid); + if (originatingPendingIntent == null) { + // grant creator BAL privileges unless explicitly opted out + mBalAllowedByPiCreator = + checkedOptions.getPendingIntentCreatorBackgroundActivityStartMode() + == ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED + ? BackgroundStartPrivileges.NONE + : BackgroundStartPrivileges.ALLOW_BAL; + } else { + // for PendingIntents we restrict creator BAL based on target_sdk + mBalAllowedByPiCreator = + checkedOptions.getPendingIntentCreatorBackgroundActivityStartMode() + == ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED + ? BackgroundStartPrivileges.NONE + : BackgroundStartPrivileges.ALLOW_BAL; + } mBalAllowedByPiSender = - PendingIntentRecord.getBackgroundStartPrivilegesAllowedByCaller(checkedOptions, - realCallingUid, mRealCallingPackage); - mBalAllowedByPiCreator = - checkedOptions.getPendingIntentCreatorBackgroundActivityStartMode() - == ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED - ? BackgroundStartPrivileges.NONE : BackgroundStartPrivileges.ALLOW_BAL; + PendingIntentRecord.getBackgroundStartPrivilegesAllowedByCaller( + checkedOptions, realCallingUid, mRealCallingPackage); mAppSwitchState = mService.getBalAppSwitchesState(); mCallingUidProcState = mService.mActiveUids.getUidState(callingUid); mIsCallingUidPersistentSystemProcess = @@ -306,10 +317,14 @@ public class BackgroundActivityStartController { return name + "[debugOnly]"; } - private boolean isPendingIntent() { + private boolean hasRealCaller() { return mRealCallingUid != NO_PROCESS_UID; } + private boolean isPendingIntent() { + return mOriginatingPendingIntent != null; + } + private String dump(BalVerdict resultIfPiCreatorAllowsBal) { Preconditions.checkState(!isPendingIntent()); return dump(resultIfPiCreatorAllowsBal, null); @@ -334,7 +349,9 @@ public class BackgroundActivityStartController { sb.append("; isCallingUidPersistentSystemProcess: ") .append(mIsCallingUidPersistentSystemProcess); sb.append("; balAllowedByPiCreator: ").append(mBalAllowedByPiCreator); - if (isPendingIntent()) { + sb.append("; hasRealCaller: ").append(hasRealCaller()); + sb.append("; isPendingIntent: ").append(isPendingIntent()); + if (hasRealCaller()) { sb.append("; balAllowedByPiSender: ").append(mBalAllowedByPiSender); sb.append("; realCallingPackage: ") .append(getDebugPackageName(mRealCallingPackage, mRealCallingUid)); @@ -351,13 +368,13 @@ public class BackgroundActivityStartController { sb.append("; mForcedBalByPiSender: ").append(mForcedBalByPiSender); sb.append("; intent: ").append(mIntent); sb.append("; callerApp: ").append(mCallerApp); - if (isPendingIntent()) { + if (hasRealCaller()) { sb.append("; realCallerApp: ").append(mRealCallerApp); } if (mCallerApp != null) { sb.append("; inVisibleTask: ").append(mCallerApp.hasActivityInVisibleTask()); } - if (isPendingIntent()) { + if (hasRealCaller()) { if (mRealCallerApp != null) { sb.append("; realInVisibleTask: ") .append(mRealCallerApp.hasActivityInVisibleTask()); @@ -484,7 +501,7 @@ public class BackgroundActivityStartController { BalVerdict resultForCaller = checkBackgroundActivityStartAllowedByCaller(state); - if (!state.isPendingIntent()) { + if (!state.hasRealCaller()) { if (resultForCaller.allows()) { if (DEBUG_ACTIVITY_STARTS) { Slog.d(TAG, "Background activity start allowed. " diff --git a/services/core/jni/tvinput/JTvInputHal.cpp b/services/core/jni/tvinput/JTvInputHal.cpp index 80427b346f1a4e26ae865d1276cbfa8063683b0a..505421e81d3d32d8db981b3f03593a73eed681b3 100644 --- a/services/core/jni/tvinput/JTvInputHal.cpp +++ b/services/core/jni/tvinput/JTvInputHal.cpp @@ -494,12 +494,21 @@ JTvInputHal::ITvInputWrapper::ITvInputWrapper(std::shared_ptr<AidlITvInput>& aid ::ndk::ScopedAStatus JTvInputHal::ITvInputWrapper::setCallback( const std::shared_ptr<TvInputCallbackWrapper>& in_callback) { if (mIsHidl) { - in_callback->aidlTvInputCallback = nullptr; - return hidlSetCallback(in_callback == nullptr ? nullptr : in_callback->hidlTvInputCallback); + if (in_callback == nullptr) { + return hidlSetCallback(nullptr); + } + else { + in_callback->aidlTvInputCallback = nullptr; + return hidlSetCallback(in_callback->hidlTvInputCallback); + } } else { - in_callback->hidlTvInputCallback = nullptr; - return mAidlTvInput->setCallback(in_callback == nullptr ? nullptr - : in_callback->aidlTvInputCallback); + if (in_callback == nullptr) { + return mAidlTvInput->setCallback(nullptr); + } + else { + in_callback->hidlTvInputCallback = nullptr; + return mAidlTvInput->setCallback(in_callback->aidlTvInputCallback); + } } } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 34d67551d49f4b954b689d4cf7f81ae028086bc5..9b62a2c416554b1f67b50142c87454fe37e313f8 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -9667,6 +9667,26 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } + @Override + public ComponentName getDeviceOwnerComponentOnUser(int userId) { + if (!mHasFeature) { + return null; + } + if (mInjector.userHandleGetCallingUserId() != userId) { + Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity()) + || hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS)); + } + synchronized (getLockObject()) { + // There is only ever one device owner on a device so if the passed userId is the same + // as the device owner userId we know that the componentName returned by + // getDeviceOwnerComponent will be the correct one. + if (mOwners.getDeviceOwnerUserId() == userId || userId == UserHandle.USER_ALL) { + return mOwners.getDeviceOwnerComponent(); + } + } + return null; + } + private int getDeviceOwnerUserIdUncheckedLocked() { return mOwners.hasDeviceOwner() ? mOwners.getDeviceOwnerUserId() : UserHandle.USER_NULL; } diff --git a/services/permission/java/com/android/server/permission/access/permission/DevicePermissionPolicy.kt b/services/permission/java/com/android/server/permission/access/permission/DevicePermissionPolicy.kt index 15a58593432e81ac3cc2fed9d68670dbb8d6cc50..7db09f9125de7d666b4c41bd45af92a160dd53fc 100644 --- a/services/permission/java/com/android/server/permission/access/permission/DevicePermissionPolicy.kt +++ b/services/permission/java/com/android/server/permission/access/permission/DevicePermissionPolicy.kt @@ -16,7 +16,9 @@ package com.android.server.permission.access.permission +import android.Manifest import android.permission.PermissionManager +import android.permission.flags.Flags import android.util.Slog import com.android.modules.utils.BinaryXmlPullParser import com.android.modules.utils.BinaryXmlSerializer @@ -273,7 +275,12 @@ class DevicePermissionPolicy : SchemePolicy() { /** These permissions are supported for virtual devices. */ // TODO: b/298661870 - Use new API to get the list of device aware permissions. - val DEVICE_AWARE_PERMISSIONS = emptySet<String>() + val DEVICE_AWARE_PERMISSIONS = + if (Flags.deviceAwarePermissionApis()) { + setOf(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO) + } else { + emptySet<String>() + } } /** diff --git a/telephony/java/android/telephony/satellite/ISatelliteCapabilitiesCallback.aidl b/telephony/java/android/telephony/satellite/ISatelliteCapabilitiesCallback.aidl new file mode 100644 index 0000000000000000000000000000000000000000..4c37a6dc383236c2231c5f8148b0cb2977f7df8a --- /dev/null +++ b/telephony/java/android/telephony/satellite/ISatelliteCapabilitiesCallback.aidl @@ -0,0 +1,33 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.satellite; + +import android.telephony.satellite.SatelliteCapabilities; + +/** + * Interface for satellite capabilities change callback. + * @hide + */ +oneway interface ISatelliteCapabilitiesCallback { + /** + * Called when satellite capability has changed. + * + * @param capabilities The new satellite capability. + */ + void onSatelliteCapabilitiesChanged(in SatelliteCapabilities capabilities); +} + diff --git a/telephony/java/android/telephony/satellite/SatelliteCapabilitiesCallback.java b/telephony/java/android/telephony/satellite/SatelliteCapabilitiesCallback.java new file mode 100644 index 0000000000000000000000000000000000000000..b68dd5a150ff5a9d44b0e4edcc78fa1739e98800 --- /dev/null +++ b/telephony/java/android/telephony/satellite/SatelliteCapabilitiesCallback.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.satellite; + +import android.annotation.FlaggedApi; +import android.annotation.NonNull; +import android.annotation.SystemApi; + +import com.android.internal.telephony.flags.Flags; + +/** + * A callback class for satellite capabilities change events. + * + * @hide + */ +@SystemApi +@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) +public interface SatelliteCapabilitiesCallback { + /** + * Called when satellite capability has changed. + * @param capabilities The new satellite capabilities. + */ + @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) + void onSatelliteCapabilitiesChanged(@NonNull SatelliteCapabilities capabilities); +} diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java index f18cbeafe752947e5eb008db7c8cb55b07a07821..71786b308937c8bb25887c36fad05af6f5bdab73 100644 --- a/telephony/java/android/telephony/satellite/SatelliteManager.java +++ b/telephony/java/android/telephony/satellite/SatelliteManager.java @@ -81,6 +81,9 @@ public final class SatelliteManager { new ConcurrentHashMap<>(); private static final ConcurrentHashMap<NtnSignalStrengthCallback, INtnSignalStrengthCallback> sNtnSignalStrengthCallbackMap = new ConcurrentHashMap<>(); + private static final ConcurrentHashMap<SatelliteCapabilitiesCallback, + ISatelliteCapabilitiesCallback> + sSatelliteCapabilitiesCallbackMap = new ConcurrentHashMap<>(); private final int mSubId; @@ -2018,7 +2021,7 @@ public final class SatelliteManager { * {@link TelephonyManager#unregisterTelephonyCallback(TelephonyCallback)}.. * </p> * - * @param callback The callback that was passed to + * @param callback The callback that was passed to. * {@link #registerForNtnSignalStrengthChanged(Executor, NtnSignalStrengthCallback)}. * * @throws SecurityException if the caller doesn't have required permission. @@ -2046,9 +2049,84 @@ public final class SatelliteManager { loge("unregisterForNtnSignalStrengthChanged() RemoteException: " + ex); ex.rethrowFromSystemServer(); } + } + /** + * Registers for satellite capabilities change event from the satellite service. + * + * @param executor The executor on which the callback will be called. + * @param callback The callback to handle the satellite capabilities changed event. + * + * @throws SecurityException if the caller doesn't have required permission. + * @throws IllegalStateException if the Telephony process is not currently available. + */ + @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) + @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) + @SatelliteResult public int registerForSatelliteCapabilitiesChanged( + @NonNull @CallbackExecutor Executor executor, + @NonNull SatelliteCapabilitiesCallback callback) { + Objects.requireNonNull(executor); + Objects.requireNonNull(callback); + + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + ISatelliteCapabilitiesCallback internalCallback = + new ISatelliteCapabilitiesCallback.Stub() { + @Override + public void onSatelliteCapabilitiesChanged( + SatelliteCapabilities capabilities) { + executor.execute(() -> Binder.withCleanCallingIdentity( + () -> callback.onSatelliteCapabilitiesChanged( + capabilities))); + } + }; + sSatelliteCapabilitiesCallbackMap.put(callback, internalCallback); + return telephony.registerForSatelliteCapabilitiesChanged(mSubId, internalCallback); + } else { + throw new IllegalStateException("Telephony service is null."); + } + } catch (RemoteException ex) { + loge("registerForSatelliteCapabilitiesChanged() RemoteException: " + ex); + ex.rethrowFromSystemServer(); + } + return SATELLITE_RESULT_REQUEST_FAILED; } + /** + * Unregisters for satellite capabilities change event from the satellite service. + * If callback was not registered before, the request will be ignored. + * + * @param callback The callback that was passed to. + * {@link #registerForSatelliteCapabilitiesChanged(Executor, SatelliteCapabilitiesCallback)}. + * + * @throws SecurityException if the caller doesn't have required permission. + * @throws IllegalStateException if the Telephony process is not currently available. + */ + @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) + @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG) + public void unregisterForSatelliteCapabilitiesChanged( + @NonNull SatelliteCapabilitiesCallback callback) { + Objects.requireNonNull(callback); + ISatelliteCapabilitiesCallback internalCallback = + sSatelliteCapabilitiesCallbackMap.remove(callback); + + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + if (internalCallback != null) { + telephony.unregisterForSatelliteCapabilitiesChanged(mSubId, internalCallback); + } else { + loge("unregisterForSatelliteCapabilitiesChanged: No internal callback."); + } + } else { + throw new IllegalStateException("Telephony service is null."); + } + } catch (RemoteException ex) { + loge("unregisterForSatelliteCapabilitiesChanged() RemoteException: " + ex); + ex.rethrowFromSystemServer(); + } + } private static ITelephony getITelephony() { ITelephony binder = ITelephony.Stub.asInterface(TelephonyFrameworkInitializer diff --git a/telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl b/telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl index d44ddfa1ee7f28cd5c7f79d8da15d84f7c880932..ccca5adba3676ad470648ebf770c6945de1cd5a0 100644 --- a/telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl +++ b/telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl @@ -19,6 +19,7 @@ package android.telephony.satellite.stub; import android.telephony.satellite.stub.NtnSignalStrength; import android.telephony.satellite.stub.NTRadioTechnology; import android.telephony.satellite.stub.PointingInfo; +import android.telephony.satellite.stub.SatelliteCapabilities; import android.telephony.satellite.stub.SatelliteDatagram; import android.telephony.satellite.stub.SatelliteModemState; @@ -62,7 +63,15 @@ oneway interface ISatelliteListener { /** * Called when NTN signal strength changes. + * * @param ntnSignalStrength The new NTN signal strength. */ void onNtnSignalStrengthChanged(in NtnSignalStrength ntnSignalStrength); + + /** + * Called when satellite capabilities of the satellite service have changed. + * + * @param SatelliteCapabilities The current satellite capabilities. + */ + void onSatelliteCapabilitiesChanged(in SatelliteCapabilities capabilities); } diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index c212e3575276a6556e5ab2dedc215e99c8fdcb04..15a20cb91d0490d9efcf8101103f93db79aec351 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -68,6 +68,7 @@ import android.telephony.ims.aidl.IImsRegistration; import android.telephony.ims.aidl.IImsRegistrationCallback; import android.telephony.ims.aidl.IRcsConfigCallback; import android.telephony.satellite.INtnSignalStrengthCallback; +import android.telephony.satellite.ISatelliteCapabilitiesCallback; import android.telephony.satellite.ISatelliteDatagramCallback; import android.telephony.satellite.ISatelliteTransmissionUpdateCallback; import android.telephony.satellite.ISatelliteProvisionStateCallback; @@ -3123,4 +3124,27 @@ interface ITelephony { + "android.Manifest.permission.SATELLITE_COMMUNICATION)") void unregisterForNtnSignalStrengthChanged(int subId, in INtnSignalStrengthCallback callback); + + /** + * Registers for satellite capabilities change event from the satellite service. + * + * @param executor The executor on which the callback will be called. + * @param callback The callback to handle the satellite capabilities changed event. + */ + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(" + + "android.Manifest.permission.SATELLITE_COMMUNICATION)") + int registerForSatelliteCapabilitiesChanged(int subId, + in ISatelliteCapabilitiesCallback callback); + + /** + * Unregisters for satellite capabilities change event from the satellite service. + * If callback was not registered before, the request will be ignored. + * + * @param callback The callback that was passed to. + * {@link #registerForSatelliteCapabilitiesChanged(Executor, SatelliteCapabilitiesCallback)}. + */ + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(" + + "android.Manifest.permission.SATELLITE_COMMUNICATION)") + void unregisterForSatelliteCapabilitiesChanged(int subId, + in ISatelliteCapabilitiesCallback callback); }