diff options
540 files changed, 27944 insertions, 14043 deletions
diff --git a/AconfigFlags.bp b/AconfigFlags.bp index 8547ec164084..69892f9ba103 100644 --- a/AconfigFlags.bp +++ b/AconfigFlags.bp @@ -277,6 +277,7 @@ java_aconfig_library { java_aconfig_library { name: "com.android.input.flags-aconfig-java", aconfig_declarations: "com.android.input.flags-aconfig", + host_supported: true, defaults: ["framework-minus-apex-aconfig-java-defaults"], } diff --git a/core/api/current.txt b/core/api/current.txt index d0b3a51f998e..59eb31ad9a24 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -27202,7 +27202,7 @@ package android.media.quality { field public static final int AMBIENT_BACKLIGHT_EVENT_DISABLED = 2; // 0x2 field public static final int AMBIENT_BACKLIGHT_EVENT_ENABLED = 1; // 0x1 field public static final int AMBIENT_BACKLIGHT_EVENT_INTERRUPTED = 4; // 0x4 - field public static final int AMBIENT_BACKLIGHT_EVENT_METADATA = 3; // 0x3 + field public static final int AMBIENT_BACKLIGHT_EVENT_METADATA_AVAILABLE = 3; // 0x3 field @NonNull public static final android.os.Parcelable.Creator<android.media.quality.AmbientBacklightEvent> CREATOR; } @@ -27210,13 +27210,15 @@ package android.media.quality { ctor public AmbientBacklightMetadata(@NonNull String, int, int, int, int, int, @NonNull int[]); method public int describeContents(); method public int getColorFormat(); - method public int getCompressAlgorithm(); - method @IntRange(from=0, to=128) public int getHorizontalZonesNumber(); + method public int getCompressionAlgorithm(); + method @IntRange(from=0, to=128) public int getHorizontalZonesCount(); method @NonNull public String getPackageName(); method public int getSource(); - method @IntRange(from=0, to=80) public int getVerticalZonesNumber(); - method @NonNull public int[] getZonesColors(); + method @IntRange(from=0, to=80) public int getVerticalZonesCount(); + method @NonNull public int[] getZoneColors(); method public void writeToParcel(@NonNull android.os.Parcel, int); + field public static final int ALGORITHM_NONE = 0; // 0x0 + field public static final int ALGORITHM_RLE = 1; // 0x1 field @NonNull public static final android.os.Parcelable.Creator<android.media.quality.AmbientBacklightMetadata> CREATOR; } @@ -27224,15 +27226,13 @@ package android.media.quality { ctor public AmbientBacklightSettings(int, int, int, int, int, boolean, int); method public int describeContents(); method public int getColorFormat(); - method @IntRange(from=0) public int getHorizontalZonesNumber(); + method @IntRange(from=0) public int getHorizontalZonesCount(); method @IntRange(from=1) public int getMaxFps(); method public int getSource(); method public int getThreshold(); - method @IntRange(from=0) public int getVerticalZonesNumber(); + method @IntRange(from=0) public int getVerticalZonesCount(); method public boolean isLetterboxOmitted(); method public void writeToParcel(@NonNull android.os.Parcel, int); - field public static final int ALGORITHM_NONE = 0; // 0x0 - field public static final int ALGORITHM_RLE = 1; // 0x1 field @NonNull public static final android.os.Parcelable.Creator<android.media.quality.AmbientBacklightSettings> CREATOR; field public static final int SOURCE_AUDIO = 1; // 0x1 field public static final int SOURCE_AUDIO_VIDEO = 3; // 0x3 @@ -27241,6 +27241,10 @@ package android.media.quality { } @FlaggedApi("android.media.tv.flags.media_quality_fw") public class MediaQualityContract { + field public static final String LEVEL_HIGH = "level_high"; + field public static final String LEVEL_LOW = "level_low"; + field public static final String LEVEL_MEDIUM = "level_medium"; + field public static final String LEVEL_OFF = "level_off"; } public static final class MediaQualityContract.PictureQuality { @@ -27273,20 +27277,41 @@ package android.media.quality { } public static final class MediaQualityContract.SoundQuality { + field public static final String PARAMETER_AUTO_VOLUME_CONTROL = "auto_volume_control"; field public static final String PARAMETER_BALANCE = "balance"; field public static final String PARAMETER_BASS = "bass"; + field public static final String PARAMETER_DIALOGUE_ENHANCER = "dialogue_enhancer"; + field public static final String PARAMETER_DIGITAL_OUTPUT_DELAY_MILLIS = "digital_output_delay_millis"; + field public static final String PARAMETER_DIGITAL_OUTPUT_MODE = "digital_output_mode"; + field public static final String PARAMETER_DOLBY_AUDIO_PROCESSING_DOLBY_ATMOS = "dolby_audio_processing_dolby_atmos"; + field public static final String PARAMETER_DOLBY_AUDIO_PROCESSING_SOUND_MODE = "dolby_audio_processing_sound_mode"; + field public static final String PARAMETER_DOLBY_AUDIO_PROCESSING_SURROUND_VIRTUALIZER = "dolby_audio_processing_surround_virtualizer"; + field public static final String PARAMETER_DOLBY_AUDIO_PROCESSING_VOLUME_LEVELER = "dolby_audio_processing_volume_leveler"; + field public static final String PARAMETER_DOWN_MIX_MODE = "down_mix_mode"; + field public static final String PARAMETER_DTS_DRC = "dts_drc"; + field public static final String PARAMETER_DTS_VIRTUAL_X_DEFINITION = "dts_virtual_x_definition"; + field public static final String PARAMETER_DTS_VIRTUAL_X_DIALOG_CLARITY = "dts_virtual_x_dialog_clarity"; + field public static final String PARAMETER_DTS_VIRTUAL_X_HEIGHT = "dts_virtual_x_height"; + field public static final String PARAMETER_DTS_VIRTUAL_X_LIMITER = "dts_virtual_x_limiter"; + field public static final String PARAMETER_DTS_VIRTUAL_X_TBHDX = "dts_virtual_x_tbhdx"; + field public static final String PARAMETER_DTS_VIRTUAL_X_TRU_SURROUND_X = "dts_virtual_x_tru_surround_x"; + field public static final String PARAMETER_DTS_VIRTUAL_X_TRU_VOLUME_HD = "dts_virtual_x_tru_volume_hd"; + field public static final String PARAMETER_EARC = "earc"; + field public static final String PARAMETER_SPEAKERS = "speakers"; + field public static final String PARAMETER_SPEAKERS_DELAY_MILLIS = "speakers_delay_millis"; + field public static final String PARAMETER_SURROUND_SOUND = "surround_sound"; field public static final String PARAMETER_TREBLE = "treble"; } @FlaggedApi("android.media.tv.flags.media_quality_fw") public final class MediaQualityManager { - method public void addActiveProcessingPictureListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.quality.MediaQualityManager.ActiveProcessingPictureListener); + method public void addActiveProcessingPictureListener(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.util.List<android.media.quality.ActiveProcessingPicture>>); method public void createPictureProfile(@NonNull android.media.quality.PictureProfile); method public void createSoundProfile(@NonNull android.media.quality.SoundProfile); - method @NonNull public java.util.List<android.media.quality.PictureProfile> getAvailablePictureProfiles(boolean); - method @NonNull public java.util.List<android.media.quality.SoundProfile> getAvailableSoundProfiles(boolean); - method @NonNull public java.util.List<android.media.quality.ParamCapability> getParamCapabilities(@NonNull java.util.List<java.lang.String>); - method @Nullable public android.media.quality.PictureProfile getPictureProfile(int, @NonNull String, boolean); - method @Nullable public android.media.quality.SoundProfile getSoundProfile(int, @NonNull String, boolean); + method @NonNull public java.util.List<android.media.quality.PictureProfile> getAvailablePictureProfiles(@Nullable android.media.quality.MediaQualityManager.ProfileQueryParams); + method @NonNull public java.util.List<android.media.quality.SoundProfile> getAvailableSoundProfiles(@Nullable android.media.quality.MediaQualityManager.ProfileQueryParams); + method @NonNull public java.util.List<android.media.quality.ParameterCapability> getParameterCapabilities(@NonNull java.util.List<java.lang.String>); + method @Nullable public android.media.quality.PictureProfile getPictureProfile(int, @NonNull String, @Nullable android.media.quality.MediaQualityManager.ProfileQueryParams); + method @Nullable public android.media.quality.SoundProfile getSoundProfile(int, @NonNull String, @Nullable android.media.quality.MediaQualityManager.ProfileQueryParams); method public boolean isAmbientBacklightEnabled(); method public boolean isAutoPictureQualityEnabled(); method public boolean isAutoSoundQualityEnabled(); @@ -27294,7 +27319,7 @@ package android.media.quality { method public void registerAmbientBacklightCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.quality.MediaQualityManager.AmbientBacklightCallback); method public void registerPictureProfileCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.quality.MediaQualityManager.PictureProfileCallback); method public void registerSoundProfileCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.quality.MediaQualityManager.SoundProfileCallback); - method public void removeActiveProcessingPictureListener(@NonNull android.media.quality.MediaQualityManager.ActiveProcessingPictureListener); + method public void removeActiveProcessingPictureListener(@NonNull java.util.function.Consumer<java.util.List<android.media.quality.ActiveProcessingPicture>>); method public void removePictureProfile(@NonNull String); method public void removeSoundProfile(@NonNull String); method public void setAmbientBacklightEnabled(boolean); @@ -27306,48 +27331,57 @@ package android.media.quality { method public void updateSoundProfile(@NonNull String, @NonNull android.media.quality.SoundProfile); } - public static interface MediaQualityManager.ActiveProcessingPictureListener { - method public void onActiveProcessingPicturesChanged(@NonNull java.util.List<android.media.quality.ActiveProcessingPicture>); - } - - public abstract static class MediaQualityManager.AmbientBacklightCallback { - ctor public MediaQualityManager.AmbientBacklightCallback(); + public static interface MediaQualityManager.AmbientBacklightCallback { method public void onAmbientBacklightEvent(@NonNull android.media.quality.AmbientBacklightEvent); } public abstract static class MediaQualityManager.PictureProfileCallback { ctor public MediaQualityManager.PictureProfileCallback(); method public void onError(@Nullable String, int); - method public void onParamCapabilitiesChanged(@Nullable String, @NonNull java.util.List<android.media.quality.ParamCapability>); + method public void onParameterCapabilitiesChanged(@Nullable String, @NonNull java.util.List<android.media.quality.ParameterCapability>); method public void onPictureProfileAdded(@NonNull String, @NonNull android.media.quality.PictureProfile); method public void onPictureProfileRemoved(@NonNull String, @NonNull android.media.quality.PictureProfile); method public void onPictureProfileUpdated(@NonNull String, @NonNull android.media.quality.PictureProfile); } + public static final class MediaQualityManager.ProfileQueryParams implements android.os.Parcelable { + method public boolean areParametersIncluded(); + method public int describeContents(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.media.quality.MediaQualityManager.ProfileQueryParams> CREATOR; + } + + public static final class MediaQualityManager.ProfileQueryParams.Builder { + ctor public MediaQualityManager.ProfileQueryParams.Builder(); + method @NonNull public android.media.quality.MediaQualityManager.ProfileQueryParams build(); + method @NonNull public android.media.quality.MediaQualityManager.ProfileQueryParams.Builder setParametersIncluded(boolean); + } + public abstract static class MediaQualityManager.SoundProfileCallback { ctor public MediaQualityManager.SoundProfileCallback(); method public void onError(@Nullable String, int); - method public void onParamCapabilitiesChanged(@Nullable String, @NonNull java.util.List<android.media.quality.ParamCapability>); + method public void onParameterCapabilitiesChanged(@Nullable String, @NonNull java.util.List<android.media.quality.ParameterCapability>); method public void onSoundProfileAdded(@NonNull String, @NonNull android.media.quality.SoundProfile); method public void onSoundProfileRemoved(@NonNull String, @NonNull android.media.quality.SoundProfile); method public void onSoundProfileUpdated(@NonNull String, @NonNull android.media.quality.SoundProfile); } - @FlaggedApi("android.media.tv.flags.media_quality_fw") public final class ParamCapability implements android.os.Parcelable { + @FlaggedApi("android.media.tv.flags.media_quality_fw") public final class ParameterCapability implements android.os.Parcelable { method public int describeContents(); method @NonNull public android.os.Bundle getCapabilities(); - method @NonNull public String getParamName(); - method public int getParamType(); + method @NonNull public String getParameterName(); + method public int getParameterType(); method public boolean isSupported(); method public void writeToParcel(@NonNull android.os.Parcel, int); field public static final String CAPABILITY_DEFAULT = "default"; field public static final String CAPABILITY_ENUM = "enum"; field public static final String CAPABILITY_MAX = "max"; field public static final String CAPABILITY_MIN = "min"; - field @NonNull public static final android.os.Parcelable.Creator<android.media.quality.ParamCapability> CREATOR; + field @NonNull public static final android.os.Parcelable.Creator<android.media.quality.ParameterCapability> CREATOR; field public static final int TYPE_DOUBLE = 3; // 0x3 field public static final int TYPE_INT = 1; // 0x1 field public static final int TYPE_LONG = 2; // 0x2 + field public static final int TYPE_NONE = 0; // 0x0 field public static final int TYPE_STRING = 4; // 0x4 } diff --git a/core/api/system-current.txt b/core/api/system-current.txt index e724ab885c39..f82aecbd6d44 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -7992,13 +7992,13 @@ package android.media.musicrecognition { package android.media.quality { @FlaggedApi("android.media.tv.flags.media_quality_fw") public final class MediaQualityManager { - method public void addGlobalActiveProcessingPictureListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.quality.MediaQualityManager.ActiveProcessingPictureListener); + method public void addGlobalActiveProcessingPictureListener(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.util.List<android.media.quality.ActiveProcessingPicture>>); method @NonNull public java.util.List<java.lang.String> getPictureProfileAllowList(); method @NonNull public java.util.List<java.lang.String> getPictureProfilePackageNames(); - method @NonNull public java.util.List<android.media.quality.PictureProfile> getPictureProfilesByPackage(@NonNull String, boolean); + method @NonNull public java.util.List<android.media.quality.PictureProfile> getPictureProfilesByPackage(@NonNull String, @Nullable android.media.quality.MediaQualityManager.ProfileQueryParams); method @NonNull public java.util.List<java.lang.String> getSoundProfileAllowList(); method @NonNull public java.util.List<java.lang.String> getSoundProfilePackageNames(); - method @NonNull public java.util.List<android.media.quality.SoundProfile> getSoundProfilesByPackage(@NonNull String, boolean); + method @NonNull public java.util.List<android.media.quality.SoundProfile> getSoundProfilesByPackage(@NonNull String, @Nullable android.media.quality.MediaQualityManager.ProfileQueryParams); method public void setAutoPictureQualityEnabled(boolean); method public void setAutoSoundQualityEnabled(boolean); method public boolean setDefaultPictureProfile(@Nullable String); @@ -8320,104 +8320,6 @@ package android.media.tv { method public void onSetMain(boolean); } - @FlaggedApi("android.media.tv.flags.tif_extension_standardization") public final class TvInputServiceExtensionManager { - method @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE) public int registerExtensionIBinder(@NonNull String, @NonNull android.os.IBinder); - field public static final String IANALOG_ATTRIBUTE_INTERFACE = "android.media.tv.extension.analog.IAnalogAttributeInterface"; - field public static final String IANALOG_AUDIO_INFO = "android.media.tv.extension.signal.IAnalogAudioInfo"; - field public static final String IAUDIO_SIGNAL_INFO = "android.media.tv.extension.signal.IAudioSignalInfo"; - field public static final String IAUDIO_SIGNAL_INFO_LISTENER = "android.media.tv.extension.signal.IAudioSignalInfoListener"; - field public static final String IBROADCAST_TIME = "android.media.tv.extension.time.IBroadcastTime"; - field public static final String ICAM_APP_INFO_LISTENER = "android.media.tv.extension.cam.ICamAppInfoListener"; - field public static final String ICAM_APP_INFO_SERVICE = "android.media.tv.extension.cam.ICamAppInfoService"; - field public static final String ICAM_DRM_INFO_LISTENER = "android.media.tv.extension.cam.ICamDrmInfoListener"; - field public static final String ICAM_HOST_CONTROL_ASK_RELEASE_REPLY_CALLBACK = "android.media.tv.extension.cam.ICamHostControlAskReleaseReplyCallback"; - field public static final String ICAM_HOST_CONTROL_INFO_LISTENER = "android.media.tv.extension.cam.ICamHostControlInfoListener"; - field public static final String ICAM_HOST_CONTROL_SERVICE = "android.media.tv.extension.cam.ICamHostControlService"; - field public static final String ICAM_HOST_CONTROL_TUNE_QUIETLY_FLAG = "android.media.tv.extension.cam.ICamHostControlTuneQuietlyFlag"; - field public static final String ICAM_HOST_CONTROL_TUNE_QUIETLY_FLAG_LISTENER = "android.media.tv.extension.cam.ICamHostControlTuneQuietlyFlagListener"; - field public static final String ICAM_INFO_LISTENER = "android.media.tv.extension.cam.ICamInfoListener"; - field public static final String ICAM_MONITORING_SERVICE = "android.media.tv.extension.cam.ICamMonitoringService"; - field public static final String ICAM_PIN_CAPABILITY_LISTENER = "android.media.tv.extension.cam.ICamPinCapabilityListener"; - field public static final String ICAM_PIN_SERVICE = "android.media.tv.extension.cam.ICamPinService"; - field public static final String ICAM_PIN_STATUS_LISTENER = "android.media.tv.extension.cam.ICamPinStatusListener"; - field public static final String ICAM_PROFILE_INTERFACE = "android.media.tv.extension.cam.ICamProfileInterface"; - field public static final String ICHANNEL_LIST_TRANSFER = "android.media.tv.extension.servicedb.IChannelListTransfer"; - field public static final String ICHANNEL_TUNED_INTERFACE = "android.media.tv.extension.tune.IChannelTunedInterface"; - field public static final String ICHANNEL_TUNED_LISTENER = "android.media.tv.extension.tune.IChannelTunedListener"; - field public static final String ICI_OPERATOR_INTERFACE = "android.media.tv.extension.cam.ICiOperatorInterface"; - field public static final String ICI_OPERATOR_LISTENER = "android.media.tv.extension.cam.ICiOperatorListener"; - field public static final String ICLIENT_TOKEN = "android.media.tv.extension.clienttoken.IClientToken"; - field public static final String ICONTENT_CONTROL_SERVICE = "android.media.tv.extension.cam.IContentControlService"; - field public static final String IDATA_SERVICE_SIGNAL_INFO = "android.media.tv.extension.teletext.IDataServiceSignalInfo"; - field public static final String IDATA_SERVICE_SIGNAL_INFO_LISTENER = "android.media.tv.extension.teletext.IDataServiceSignalInfoListener"; - field public static final String IDELETE_RECORDED_CONTENTS_CALLBACK = "android.media.tv.extension.pvr.IDeleteRecordedContentsCallback"; - field public static final String IDOWNLOADABLE_RATING_TABLE_MONITOR = "android.media.tv.extension.rating.IDownloadableRatingTableMonitor"; - field public static final String IENTER_MENU_ERROR_CALLBACK = "android.media.tv.extension.cam.IEnterMenuErrorCallback"; - field public static final String IEVENT_DOWNLOAD = "android.media.tv.extension.event.IEventDownload"; - field public static final String IEVENT_DOWNLOAD_LISTENER = "android.media.tv.extension.event.IEventDownloadListener"; - field public static final String IEVENT_DOWNLOAD_SESSION = "android.media.tv.extension.event.IEventDownloadSession"; - field public static final String IEVENT_MONITOR = "android.media.tv.extension.event.IEventMonitor"; - field public static final String IEVENT_MONITOR_LISTENER = "android.media.tv.extension.event.IEventMonitorListener"; - field public static final String IFAVORITE_NETWORK = "android.media.tv.extension.scan.IFavoriteNetwork"; - field public static final String IFAVORITE_NETWORK_LISTENER = "android.media.tv.extension.scan.IFavoriteNetworkListener"; - field public static final String IGET_INFO_RECORDED_CONTENTS_CALLBACK = "android.media.tv.extension.pvr.IGetInfoRecordedContentsCallback"; - field public static final String IHDMI_SIGNAL_INFO_LISTENER = "android.media.tv.extension.signal.IHdmiSignalInfoListener"; - field public static final String IHDMI_SIGNAL_INTERFACE = "android.media.tv.extension.signal.IHdmiSignalInterface"; - field public static final String IHDPLUS_INFO = "android.media.tv.extension.scan.IHDPlusInfo"; - field public static final String ILCNV2_CHANNEL_LIST = "android.media.tv.extension.scan.ILcnV2ChannelList"; - field public static final String ILCNV2_CHANNEL_LIST_LISTENER = "android.media.tv.extension.scan.ILcnV2ChannelListListener"; - field public static final String ILCN_CONFLICT = "android.media.tv.extension.scan.ILcnConflict"; - field public static final String ILCN_CONFLICT_LISTENER = "android.media.tv.extension.scan.ILcnConflictListener"; - field public static final String IMMI_INTERFACE = "android.media.tv.extension.cam.IMmiInterface"; - field public static final String IMMI_SESSION = "android.media.tv.extension.cam.IMmiSession"; - field public static final String IMMI_STATUS_CALLBACK = "android.media.tv.extension.cam.IMmiStatusCallback"; - field public static final String IMUX_TUNE = "android.media.tv.extension.tune.IMuxTune"; - field public static final String IMUX_TUNE_SESSION = "android.media.tv.extension.tune.IMuxTuneSession"; - field public static final String IOAD_UPDATE_INTERFACE = "android.media.tv.extension.oad.IOadUpdateInterface"; - field public static final String IOPERATOR_DETECTION = "android.media.tv.extension.scan.IOperatorDetection"; - field public static final String IOPERATOR_DETECTION_LISTENER = "android.media.tv.extension.scan.IOperatorDetectionListener"; - field public static final String IPMT_RATING_INTERFACE = "android.media.tv.extension.rating.IPmtRatingInterface"; - field public static final String IPMT_RATING_LISTENER = "android.media.tv.extension.rating.IPmtRatingListener"; - field public static final String IPROGRAM_INFO = "android.media.tv.extension.rating.IProgramInfo"; - field public static final String IPROGRAM_INFO_LISTENER = "android.media.tv.extension.rating.IProgramInfoListener"; - field public static final String IRATING_INTERFACE = "android.media.tv.extension.rating.IRatingInterface"; - field public static final String IRECORDED_CONTENTS = "android.media.tv.extension.pvr.IRecordedContents"; - field public static final String IREGION_CHANNEL_LIST = "android.media.tv.extension.scan.IRegionChannelList"; - field public static final String IREGION_CHANNEL_LIST_LISTENER = "android.media.tv.extension.scan.IRegionChannelListListener"; - field public static final String ISCAN_BACKGROUND_SERVICE_UPDATE = "android.media.tv.extension.scanbsu.IScanBackgroundServiceUpdate"; - field public static final String ISCAN_BACKGROUND_SERVICE_UPDATE_LISTENER = "android.media.tv.extension.scanbsu.IScanBackgroundServiceUpdateListener"; - field public static final String ISCAN_INTERFACE = "android.media.tv.extension.scan.IScanInterface"; - field public static final String ISCAN_LISTENER = "android.media.tv.extension.scan.IScanListener"; - field public static final String ISCAN_SAT_SEARCH = "android.media.tv.extension.scan.IScanSatSearch"; - field public static final String ISCAN_SESSION = "android.media.tv.extension.scan.IScanSession"; - field public static final String ISCREEN_MODE_SETTINGS = "android.media.tv.extension.screenmode.IScreenModeSettings"; - field public static final String ISERVICE_LIST = "android.media.tv.extension.servicedb.IServiceList"; - field public static final String ISERVICE_LIST_EDIT = "android.media.tv.extension.servicedb.IServiceListEdit"; - field public static final String ISERVICE_LIST_EDIT_LISTENER = "android.media.tv.extension.servicedb.IServiceListEditListener"; - field public static final String ISERVICE_LIST_EXPORT_LISTENER = "android.media.tv.extension.servicedb.IServiceListExportListener"; - field public static final String ISERVICE_LIST_EXPORT_SESSION = "android.media.tv.extension.servicedb.IServiceListExportSession"; - field public static final String ISERVICE_LIST_IMPORT_LISTENER = "android.media.tv.extension.servicedb.IServiceListImportListener"; - field public static final String ISERVICE_LIST_IMPORT_SESSION = "android.media.tv.extension.servicedb.IServiceListImportSession"; - field public static final String ISERVICE_LIST_SET_CHANNEL_LIST_LISTENER = "android.media.tv.extension.servicedb.IServiceListSetChannelListListener"; - field public static final String ISERVICE_LIST_SET_CHANNEL_LIST_SESSION = "android.media.tv.extension.servicedb.IServiceListSetChannelListSession"; - field public static final String ISERVICE_LIST_TRANSFER_INTERFACE = "android.media.tv.extension.servicedb.IServiceListTransferInterface"; - field public static final String ITARGET_REGION = "android.media.tv.extension.scan.ITargetRegion"; - field public static final String ITARGET_REGION_LISTENER = "android.media.tv.extension.scan.ITargetRegionListener"; - field public static final String ITELETEXT_PAGE_SUB_CODE = "android.media.tv.extension.teletext.ITeletextPageSubCode"; - field public static final String ITKGS_INFO = "android.media.tv.extension.scan.ITkgsInfo"; - field public static final String ITKGS_INFO_LISTENER = "android.media.tv.extension.scan.ITkgsInfoListener"; - field public static final String ITUNER_FRONTEND_SIGNAL_INFO_INTERFACE = "android.media.tv.extension.signal.ITunerFrontendSignalInfoInterface"; - field public static final String ITUNER_FRONTEND_SIGNAL_INFO_LISTENER = "android.media.tv.extension.signal.ITunerFrontendSignalInfoListener"; - field public static final String IVBI_RATING_INTERFACE = "android.media.tv.extension.rating.IVbiRatingInterface"; - field public static final String IVBI_RATING_LISTENER = "android.media.tv.extension.rating.IVbiRatingListener"; - field public static final String IVIDEO_SIGNAL_INFO = "android.media.tv.extension.signal.IVideoSignalInfo"; - field public static final String IVIDEO_SIGNAL_INFO_LISTENER = "android.media.tv.extension.signal.IVideoSignalInfoListener"; - field public static final int REGISTER_FAIL_IMPLEMENTATION_NOT_STANDARDIZED = 2; // 0x2 - field public static final int REGISTER_FAIL_NAME_NOT_STANDARDIZED = 1; // 0x1 - field public static final int REGISTER_FAIL_REMOTE_EXCEPTION = 3; // 0x3 - field public static final int REGISTER_SUCCESS = 0; // 0x0 - } - public abstract static class TvRecordingClient.RecordingCallback { method public void onEvent(String, String, android.os.Bundle); } @@ -12676,27 +12578,21 @@ package android.security { package android.security.advancedprotection { @FlaggedApi("android.security.aapm_api") public final class AdvancedProtectionFeature implements android.os.Parcelable { - ctor public AdvancedProtectionFeature(@NonNull String); + ctor public AdvancedProtectionFeature(int); method public int describeContents(); - method @NonNull public String getId(); + method public int getId(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.security.advancedprotection.AdvancedProtectionFeature> CREATOR; } @FlaggedApi("android.security.aapm_api") public final class AdvancedProtectionManager { - method @NonNull public android.content.Intent createSupportIntent(@NonNull String, @Nullable String); method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_ADVANCED_PROTECTION_MODE) public java.util.List<android.security.advancedprotection.AdvancedProtectionFeature> getAdvancedProtectionFeatures(); method @RequiresPermission(android.Manifest.permission.MANAGE_ADVANCED_PROTECTION_MODE) public void setAdvancedProtectionEnabled(boolean); - field @FlaggedApi("android.security.aapm_api") public static final String ACTION_SHOW_ADVANCED_PROTECTION_SUPPORT_DIALOG = "android.security.advancedprotection.action.SHOW_ADVANCED_PROTECTION_SUPPORT_DIALOG"; - field public static final String EXTRA_SUPPORT_DIALOG_FEATURE = "android.security.advancedprotection.extra.SUPPORT_DIALOG_FEATURE"; - field public static final String EXTRA_SUPPORT_DIALOG_TYPE = "android.security.advancedprotection.extra.SUPPORT_DIALOG_TYPE"; - field public static final String FEATURE_ID_DISALLOW_CELLULAR_2G = "android.security.advancedprotection.feature_disallow_2g"; - field public static final String FEATURE_ID_DISALLOW_INSTALL_UNKNOWN_SOURCES = "android.security.advancedprotection.feature_disallow_install_unknown_sources"; - field public static final String FEATURE_ID_DISALLOW_USB = "android.security.advancedprotection.feature_disallow_usb"; - field public static final String FEATURE_ID_DISALLOW_WEP = "android.security.advancedprotection.feature_disallow_wep"; - field public static final String FEATURE_ID_ENABLE_MTE = "android.security.advancedprotection.feature_enable_mte"; - field public static final String SUPPORT_DIALOG_TYPE_BLOCKED_INTERACTION = "android.security.advancedprotection.type_blocked_interaction"; - field public static final String SUPPORT_DIALOG_TYPE_DISABLED_SETTING = "android.security.advancedprotection.type_disabled_setting"; + field public static final int FEATURE_ID_DISALLOW_CELLULAR_2G = 0; // 0x0 + field public static final int FEATURE_ID_DISALLOW_INSTALL_UNKNOWN_SOURCES = 1; // 0x1 + field public static final int FEATURE_ID_DISALLOW_USB = 2; // 0x2 + field public static final int FEATURE_ID_DISALLOW_WEP = 3; // 0x3 + field public static final int FEATURE_ID_ENABLE_MTE = 4; // 0x4 } } @@ -15962,7 +15858,7 @@ package android.telephony { method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public default void onCallStatesChanged(@NonNull java.util.List<android.telephony.CallState>); } - @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static interface TelephonyCallback.CarrierRoamingNtnModeListener { + @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public static interface TelephonyCallback.CarrierRoamingNtnListener { method public default void onCarrierRoamingNtnAvailableServicesChanged(@NonNull int[]); method public default void onCarrierRoamingNtnEligibleStateChanged(boolean); method public void onCarrierRoamingNtnModeChanged(boolean); @@ -18640,9 +18536,9 @@ package android.telephony.satellite { 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.satellite_system_apis") public interface SatelliteCommunicationAllowedStateCallback { - method public default void onSatelliteAccessConfigurationChanged(@Nullable android.telephony.satellite.SatelliteAccessConfiguration); - method public void onSatelliteCommunicationAllowedStateChanged(boolean); + @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public interface SatelliteCommunicationAccessStateCallback { + method public void onAccessAllowedStateChanged(boolean); + method public default void onAccessConfigurationChanged(@Nullable android.telephony.satellite.SatelliteAccessConfiguration); } @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") public final class SatelliteDatagram implements android.os.Parcelable { @@ -18681,7 +18577,7 @@ package android.telephony.satellite { method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void provisionSatellite(@NonNull java.util.List<android.telephony.satellite.SatelliteSubscriberInfo>, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Boolean,android.telephony.satellite.SatelliteManager.SatelliteException>); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void provisionService(@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 registerForCapabilitiesChanged(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.SatelliteCapabilitiesCallback); - method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public int registerForCommunicationAllowedStateChanged(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.SatelliteCommunicationAllowedStateCallback); + method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public int registerForCommunicationAccessStateChanged(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.SatelliteCommunicationAccessStateCallback); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public int registerForIncomingDatagram(@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 registerForModemStateChanged(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.SatelliteModemStateCallback); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void registerForNtnSignalStrengthChanged(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.satellite.NtnSignalStrengthCallback); @@ -18710,7 +18606,7 @@ package android.telephony.satellite { method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void startTransmissionUpdates(@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 stopTransmissionUpdates(@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 unregisterForCapabilitiesChanged(@NonNull android.telephony.satellite.SatelliteCapabilitiesCallback); - method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void unregisterForCommunicationAllowedStateChanged(@NonNull android.telephony.satellite.SatelliteCommunicationAllowedStateCallback); + method @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void unregisterForCommunicationAccessStateChanged(@NonNull android.telephony.satellite.SatelliteCommunicationAccessStateCallback); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void unregisterForIncomingDatagram(@NonNull android.telephony.satellite.SatelliteDatagramCallback); method @FlaggedApi("com.android.internal.telephony.flags.oem_enabled_satellite_flag") @RequiresPermission(android.Manifest.permission.SATELLITE_COMMUNICATION) public void unregisterForModemStateChanged(@NonNull android.telephony.satellite.SatelliteModemStateCallback); 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); @@ -18839,9 +18735,9 @@ package android.telephony.satellite { method public int describeContents(); method public int getCarrierId(); method @NonNull public String getNiddApn(); - method public int getSubId(); method @NonNull public String getSubscriberId(); method public int getSubscriberIdType(); + method public int getSubscriptionId(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.telephony.satellite.SatelliteSubscriberInfo> CREATOR; field public static final int SUBSCRIBER_ID_TYPE_ICCID = 0; // 0x0 @@ -18853,9 +18749,9 @@ package android.telephony.satellite { method @NonNull public android.telephony.satellite.SatelliteSubscriberInfo build(); method @NonNull public android.telephony.satellite.SatelliteSubscriberInfo.Builder setCarrierId(int); method @NonNull public android.telephony.satellite.SatelliteSubscriberInfo.Builder setNiddApn(@NonNull String); - method @NonNull public android.telephony.satellite.SatelliteSubscriberInfo.Builder setSubId(int); method @NonNull public android.telephony.satellite.SatelliteSubscriberInfo.Builder setSubscriberId(@NonNull String); method @NonNull public android.telephony.satellite.SatelliteSubscriberInfo.Builder setSubscriberIdType(int); + method @NonNull public android.telephony.satellite.SatelliteSubscriberInfo.Builder setSubscriptionId(int); } @FlaggedApi("com.android.internal.telephony.flags.satellite_system_apis") public final class SatelliteSubscriberProvisionStatus implements android.os.Parcelable { diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index c3ef104075f2..8614bde775ad 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -5770,6 +5770,11 @@ public class Activity extends ContextThemeWrapper @FlaggedApi(Flags.FLAG_DEVICE_AWARE_PERMISSION_APIS_ENABLED) public final void requestPermissions(@NonNull String[] permissions, int requestCode, int deviceId) { + // Pre M apps shouldn't request permissions, as permissions are granted at install time. + if (getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.M) { + onRequestPermissionsResult(requestCode, new String[0], new int[0], deviceId); + } + if (requestCode < 0) { throw new IllegalArgumentException("requestCode should be >= 0"); } diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 84d67415a4b4..a2fddb045179 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -4443,7 +4443,8 @@ public class DevicePolicyManager { * disabled through this Config. */ private static final IpcDataCache.Config sDpmCaches = - new IpcDataCache.Config(8, IpcDataCache.MODULE_SYSTEM, "DevicePolicyManagerCaches"); + new IpcDataCache.Config(8, IpcDataCache.MODULE_SYSTEM, "DevicePolicyManagerCaches") + .cacheNulls(true); /** @hide */ public static void invalidateBinderCaches() { diff --git a/core/java/android/app/appfunctions/AppFunctionService.java b/core/java/android/app/appfunctions/AppFunctionService.java index 85b6ab2b4e61..d86f1d841d33 100644 --- a/core/java/android/app/appfunctions/AppFunctionService.java +++ b/core/java/android/app/appfunctions/AppFunctionService.java @@ -24,6 +24,7 @@ import android.annotation.FlaggedApi; import android.annotation.MainThread; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SdkConstant; import android.app.Service; import android.content.Context; import android.content.Intent; @@ -59,6 +60,7 @@ public abstract class AppFunctionService extends Service { * service must also require the {@link BIND_APP_FUNCTION_SERVICE} permission so that other * applications can not abuse it. */ + @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION) @NonNull public static final String SERVICE_INTERFACE = "android.app.appfunctions.AppFunctionService"; diff --git a/core/java/android/content/pm/multiuser.aconfig b/core/java/android/content/pm/multiuser.aconfig index 2ad9660534a6..4a579a4c0e85 100644 --- a/core/java/android/content/pm/multiuser.aconfig +++ b/core/java/android/content/pm/multiuser.aconfig @@ -214,7 +214,7 @@ flag { name: "place_add_user_dialog_within_activity" namespace: "multiuser" description: "Display dialog within activity to make it traversable by Accessibility" - bug: "383034393" + bug: "376815882" metadata { purpose: PURPOSE_BUGFIX } diff --git a/core/java/android/hardware/contexthub/HubEndpoint.java b/core/java/android/hardware/contexthub/HubEndpoint.java index 6c669a3d7032..71702d996883 100644 --- a/core/java/android/hardware/contexthub/HubEndpoint.java +++ b/core/java/android/hardware/contexthub/HubEndpoint.java @@ -358,6 +358,7 @@ public class HubEndpoint { service.registerEndpoint( mPendingHubEndpointInfo, mServiceCallback, + mPendingHubEndpointInfo.getName(), mPendingHubEndpointInfo.getTag()); mAssignedHubEndpointInfo = serviceToken.getAssignedHubEndpointInfo(); mServiceToken = serviceToken; @@ -514,6 +515,7 @@ public class HubEndpoint { /** Create a builder for {@link HubEndpoint} */ public Builder(@NonNull Context context) { mPackageName = context.getPackageName(); + mTag = context.getAttributionTag(); mVersion = (int) context.getApplicationInfo().longVersionCode; mMainExecutor = context.getMainExecutor(); } @@ -532,6 +534,7 @@ public class HubEndpoint { /** * Set a tag string. The tag can be used to further identify the creator of the endpoint. * Endpoints created by the same package share the same name but should have different tags. + * The default value of the tag is retrieved from {@link Context#getAttributionTag()}. */ @NonNull public Builder setTag(@NonNull String tag) { diff --git a/core/java/android/hardware/input/input_framework.aconfig b/core/java/android/hardware/input/input_framework.aconfig index c4d11cd8aff7..7887c15a72ff 100644 --- a/core/java/android/hardware/input/input_framework.aconfig +++ b/core/java/android/hardware/input/input_framework.aconfig @@ -67,17 +67,17 @@ flag { } flag { - name: "modifier_shortcut_dump" - namespace: "input" - description: "Dump keyboard shortcuts in dumpsys window" - bug: "351963350" + name: "modifier_shortcut_dump" + namespace: "input" + description: "Dump keyboard shortcuts in dumpsys window" + bug: "351963350" } flag { - name: "modifier_shortcut_manager_refactor" - namespace: "input" - description: "Refactor ModifierShortcutManager internal representation of shortcuts." - bug: "358603902" + name: "modifier_shortcut_manager_refactor" + namespace: "input" + description: "Refactor ModifierShortcutManager internal representation of shortcuts." + bug: "358603902" } flag { @@ -114,31 +114,31 @@ flag { } flag { - name: "keyboard_repeat_keys" - namespace: "input_native" - description: "Allow configurable timeout before key repeat and repeat delay rate for key repeats" - bug: "336585002" + name: "keyboard_repeat_keys" + namespace: "input_native" + description: "Allow configurable timeout before key repeat and repeat delay rate for key repeats" + bug: "336585002" } flag { - name: "mouse_reverse_vertical_scrolling" - namespace: "input" - description: "Controls whether external mouse vertical scrolling can be reversed" - bug: "352598211" + name: "mouse_reverse_vertical_scrolling" + namespace: "input" + description: "Controls whether external mouse vertical scrolling can be reversed" + bug: "352598211" } flag { - name: "mouse_swap_primary_button" - namespace: "input" - description: "Controls whether the connected mice's primary buttons, left and right, can be swapped." - bug: "352598211" + name: "mouse_swap_primary_button" + namespace: "input" + description: "Controls whether the connected mice's primary buttons, left and right, can be swapped." + bug: "352598211" } flag { - name: "keyboard_a11y_shortcut_control" - namespace: "input" - description: "Adds shortcuts to toggle and control a11y keyboard features" - bug: "373458181" + name: "keyboard_a11y_shortcut_control" + namespace: "input" + description: "Adds shortcuts to toggle and control a11y keyboard features" + bug: "373458181" } flag { @@ -164,32 +164,39 @@ flag { } flag { - name: "override_power_key_behavior_in_focused_window" - namespace: "wallet_integration" - description: "Allows privileged focused windows to override the power key double tap behavior." - bug: "357144512" + name: "override_power_key_behavior_in_focused_window" + namespace: "wallet_integration" + description: "Allows privileged focused windows to override the power key double tap behavior." + bug: "357144512" +} + +flag { + name: "touchpad_three_finger_tap_shortcut" + namespace: "input" + description: "Turns three-finger touchpad taps into a customizable shortcut." + bug: "365063048" } flag { - name: "touchpad_three_finger_tap_shortcut" - namespace: "input" - description: "Turns three-finger touchpad taps into a customizable shortcut." - bug: "365063048" + name: "enable_talkback_and_magnifier_key_gestures" + namespace: "input" + description: "Adds key gestures for talkback and magnifier" + bug: "375277034" } flag { - name: "enable_talkback_and_magnifier_key_gestures" - namespace: "input" - description: "Adds key gestures for talkback and magnifier" - bug: "375277034" + name: "enable_voice_access_key_gestures" + namespace: "input" + description: "Adds key gestures for voice access" + bug: "383734125" } flag { - name: "can_window_override_power_gesture_api" - namespace: "wallet_integration" - description: "Adds new API in WindowManager class to check if the window can override the power key double tap behavior." - bug: "378736024" - } + name: "can_window_override_power_gesture_api" + namespace: "wallet_integration" + description: "Adds new API in WindowManager class to check if the window can override the power key double tap behavior." + bug: "378736024" +} flag { name: "pointer_acceleration" @@ -206,8 +213,8 @@ flag { } flag { - name: "remove_fallback_modifiers" - namespace: "input" - description: "Removes modifiers from the original key event that activated the fallback, ensuring that only the intended fallback event is sent." - bug: "382545048" + name: "remove_fallback_modifiers" + namespace: "input" + description: "Removes modifiers from the original key event that activated the fallback, ensuring that only the intended fallback event is sent." + bug: "382545048" } diff --git a/core/java/android/hardware/location/IContextHubService.aidl b/core/java/android/hardware/location/IContextHubService.aidl index 2a472375a00f..d5b3fa251e82 100644 --- a/core/java/android/hardware/location/IContextHubService.aidl +++ b/core/java/android/hardware/location/IContextHubService.aidl @@ -137,7 +137,7 @@ interface IContextHubService { // Register an endpoint with the context hub @EnforcePermission("ACCESS_CONTEXT_HUB") - IContextHubEndpoint registerEndpoint(in HubEndpointInfo pendingEndpointInfo, in IContextHubEndpointCallback callback, String packageName); + IContextHubEndpoint registerEndpoint(in HubEndpointInfo pendingEndpointInfo, in IContextHubEndpointCallback callback, String packageName, String attributionTag); // Register an endpoint discovery callback (id) @EnforcePermission("ACCESS_CONTEXT_HUB") diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 298cec1674b2..71d79bb32807 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -6895,7 +6895,9 @@ public abstract class BatteryStats { || wakelockTag.poolIdx == HistoryTag.HISTORY_TAG_POOL_OVERFLOW) { UserHandle.formatUid(sb, wakelockTag.uid); sb.append(":\""); - sb.append(wakelockTag.string.replace("\"", "\"\"")); + if (wakelockTag.string != null) { + sb.append(wakelockTag.string.replace("\"", "\"\"")); + } sb.append("\""); } else { sb.append(wakelockTag.poolIdx); diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 6e58780ac7a7..df12a68a8f22 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -1256,12 +1256,12 @@ public final class Settings { /** * Activity Action: Show numbering system configuration settings. * <p> - * In some cases, a matching Activity may not exist, so ensure you - * safeguard against this. - * <p> * Input: Nothing. * <p> - * Output: Nothing. + * Output: After calling {@link android.app.Activity#startActivityForResult}, the callback + * {@code onActivityResult} will have resultCode {@link android.app.Activity#RESULT_OK} if + * the numbering system settings page is suitable to show on the UI. Otherwise, the result is + * set to {@link android.app.Activity#RESULT_CANCELED}. */ @FlaggedApi(Flags.FLAG_SYSTEM_REGIONAL_PREFERENCES_API_ENABLED) @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) diff --git a/core/java/android/security/advancedprotection/AdvancedProtectionFeature.java b/core/java/android/security/advancedprotection/AdvancedProtectionFeature.java index a086bf7f8b08..d476d960890b 100644 --- a/core/java/android/security/advancedprotection/AdvancedProtectionFeature.java +++ b/core/java/android/security/advancedprotection/AdvancedProtectionFeature.java @@ -30,26 +30,25 @@ import android.security.Flags; @FlaggedApi(Flags.FLAG_AAPM_API) @SystemApi public final class AdvancedProtectionFeature implements Parcelable { - private final String mId; + private final int mId; /** * Create an object identifying an Advanced Protection feature for AdvancedProtectionManager - * @param id A unique ID to identify this feature. It is used by Settings screens to display - * information about this feature. + * @param id Feature identifier. It is used by Settings screens to display information about + * this feature. */ - public AdvancedProtectionFeature(@NonNull String id) { + public AdvancedProtectionFeature(@AdvancedProtectionManager.FeatureId int id) { mId = id; } private AdvancedProtectionFeature(Parcel in) { - mId = in.readString8(); + mId = in.readInt(); } /** * @return the unique ID representing this feature */ - @NonNull - public String getId() { + public int getId() { return mId; } @@ -60,7 +59,7 @@ public final class AdvancedProtectionFeature implements Parcelable { @Override public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeString8(mId); + dest.writeInt(mId); } @NonNull diff --git a/core/java/android/security/advancedprotection/AdvancedProtectionManager.java b/core/java/android/security/advancedprotection/AdvancedProtectionManager.java index 59628e8e69d7..ea01fc98eda0 100644 --- a/core/java/android/security/advancedprotection/AdvancedProtectionManager.java +++ b/core/java/android/security/advancedprotection/AdvancedProtectionManager.java @@ -24,17 +24,18 @@ import static android.os.UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY; import android.Manifest; import android.annotation.CallbackExecutor; import android.annotation.FlaggedApi; +import android.annotation.IntDef; import android.annotation.NonNull; -import android.annotation.Nullable; import android.annotation.RequiresPermission; -import android.annotation.SdkConstant; -import android.annotation.StringDef; import android.annotation.SystemApi; import android.annotation.SystemService; +import android.app.admin.DevicePolicyManager; import android.content.Context; import android.content.Intent; +import android.net.wifi.WifiManager; import android.os.Binder; import android.os.RemoteException; +import android.os.UserManager; import android.security.Flags; import android.util.Log; @@ -59,54 +60,57 @@ public final class AdvancedProtectionManager { private static final String TAG = "AdvancedProtectionMgr"; /** - * Advanced Protection's identifier for setting policies or restrictions in DevicePolicyManager. + * Advanced Protection's identifier for setting policies or restrictions in + * {@link DevicePolicyManager}. * * @hide */ public static final String ADVANCED_PROTECTION_SYSTEM_ENTITY = "android.security.advancedprotection"; /** - * Feature identifier for disallowing 2G. + * Feature identifier for disallowing connections to 2G networks. * + * @see UserManager#DISALLOW_CELLULAR_2G * @hide */ @SystemApi - public static final String FEATURE_ID_DISALLOW_CELLULAR_2G = - "android.security.advancedprotection.feature_disallow_2g"; + public static final int FEATURE_ID_DISALLOW_CELLULAR_2G = 0; /** - * Feature identifier for disallowing install of unknown sources. + * Feature identifier for disallowing installs of apps from unknown sources. * + * @see UserManager#DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY * @hide */ @SystemApi - public static final String FEATURE_ID_DISALLOW_INSTALL_UNKNOWN_SOURCES = - "android.security.advancedprotection.feature_disallow_install_unknown_sources"; + public static final int FEATURE_ID_DISALLOW_INSTALL_UNKNOWN_SOURCES = 1; /** - * Feature identifier for disallowing USB. + * Feature identifier for disallowing USB connections. * * @hide */ @SystemApi - public static final String FEATURE_ID_DISALLOW_USB = - "android.security.advancedprotection.feature_disallow_usb"; + public static final int FEATURE_ID_DISALLOW_USB = 2; /** - * Feature identifier for disallowing WEP. + * Feature identifier for disallowing connections to Wi-Fi Wired Equivalent Privacy (WEP) + * networks. * + * @see WifiManager#isWepSupported() * @hide */ @SystemApi - public static final String FEATURE_ID_DISALLOW_WEP = - "android.security.advancedprotection.feature_disallow_wep"; + public static final int FEATURE_ID_DISALLOW_WEP = 3; /** - * Feature identifier for enabling MTE. + * Feature identifier for enabling the Memory Tagging Extension (MTE). MTE is a CPU extension + * that allows to protect against certain classes of security problems at a small runtime + * performance cost overhead. * + * @see DevicePolicyManager#setMtePolicy(int) * @hide */ @SystemApi - public static final String FEATURE_ID_ENABLE_MTE = - "android.security.advancedprotection.feature_enable_mte"; + public static final int FEATURE_ID_ENABLE_MTE = 4; /** @hide */ - @StringDef(prefix = { "FEATURE_ID_" }, value = { + @IntDef(prefix = { "FEATURE_ID_" }, value = { FEATURE_ID_DISALLOW_CELLULAR_2G, FEATURE_ID_DISALLOW_INSTALL_UNKNOWN_SOURCES, FEATURE_ID_DISALLOW_USB, @@ -116,7 +120,7 @@ public final class AdvancedProtectionManager { @Retention(RetentionPolicy.SOURCE) public @interface FeatureId {} - private static final Set<String> ALL_FEATURE_IDS = Set.of( + private static final Set<Integer> ALL_FEATURE_IDS = Set.of( FEATURE_ID_DISALLOW_CELLULAR_2G, FEATURE_ID_DISALLOW_INSTALL_UNKNOWN_SOURCES, FEATURE_ID_DISALLOW_USB, @@ -135,9 +139,6 @@ public final class AdvancedProtectionManager { * Output: Nothing. * * @hide */ - @SystemApi - @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION) - @FlaggedApi(android.security.Flags.FLAG_AAPM_API) public static final String ACTION_SHOW_ADVANCED_PROTECTION_SUPPORT_DIALOG = "android.security.advancedprotection.action.SHOW_ADVANCED_PROTECTION_SUPPORT_DIALOG"; @@ -147,7 +148,6 @@ public final class AdvancedProtectionManager { * * @hide */ @FeatureId - @SystemApi public static final String EXTRA_SUPPORT_DIALOG_FEATURE = "android.security.advancedprotection.extra.SUPPORT_DIALOG_FEATURE"; @@ -157,37 +157,41 @@ public final class AdvancedProtectionManager { * * @hide */ @SupportDialogType - @SystemApi public static final String EXTRA_SUPPORT_DIALOG_TYPE = "android.security.advancedprotection.extra.SUPPORT_DIALOG_TYPE"; /** + * Type for {@link #EXTRA_SUPPORT_DIALOG_TYPE} indicating an unknown action was blocked by + * advanced protection, hence the support dialog should display a default explanation. + * + * @hide */ + public static final int SUPPORT_DIALOG_TYPE_UNKNOWN = 0; + + /** * Type for {@link #EXTRA_SUPPORT_DIALOG_TYPE} indicating a user performed an action that was * blocked by advanced protection. * * @hide */ - @SystemApi - public static final String SUPPORT_DIALOG_TYPE_BLOCKED_INTERACTION = - "android.security.advancedprotection.type_blocked_interaction"; + public static final int SUPPORT_DIALOG_TYPE_BLOCKED_INTERACTION = 1; /** * Type for {@link #EXTRA_SUPPORT_DIALOG_TYPE} indicating a user pressed on a setting toggle * that was disabled by advanced protection. * * @hide */ - @SystemApi - public static final String SUPPORT_DIALOG_TYPE_DISABLED_SETTING = - "android.security.advancedprotection.type_disabled_setting"; + public static final int SUPPORT_DIALOG_TYPE_DISABLED_SETTING = 2; /** @hide */ - @StringDef(prefix = { "SUPPORT_DIALOG_TYPE_" }, value = { + @IntDef(prefix = { "SUPPORT_DIALOG_TYPE_" }, value = { + SUPPORT_DIALOG_TYPE_UNKNOWN, SUPPORT_DIALOG_TYPE_BLOCKED_INTERACTION, SUPPORT_DIALOG_TYPE_DISABLED_SETTING, }) @Retention(RetentionPolicy.SOURCE) public @interface SupportDialogType {} - private static final Set<String> ALL_SUPPORT_DIALOG_TYPES = Set.of( + private static final Set<Integer> ALL_SUPPORT_DIALOG_TYPES = Set.of( + SUPPORT_DIALOG_TYPE_UNKNOWN, SUPPORT_DIALOG_TYPE_BLOCKED_INTERACTION, SUPPORT_DIALOG_TYPE_DISABLED_SETTING); @@ -324,15 +328,13 @@ public final class AdvancedProtectionManager { * disabled by advanced protection. * @hide */ - @SystemApi - public @NonNull Intent createSupportIntent(@NonNull @FeatureId String featureId, - @Nullable @SupportDialogType String type) { - Objects.requireNonNull(featureId); + public static @NonNull Intent createSupportIntent(@FeatureId int featureId, + @SupportDialogType int type) { if (!ALL_FEATURE_IDS.contains(featureId)) { throw new IllegalArgumentException(featureId + " is not a valid feature ID. See" + " FEATURE_ID_* APIs."); } - if (type != null && !ALL_SUPPORT_DIALOG_TYPES.contains(type)) { + if (!ALL_SUPPORT_DIALOG_TYPES.contains(type)) { throw new IllegalArgumentException(type + " is not a valid type. See" + " SUPPORT_DIALOG_TYPE_* APIs."); } @@ -340,21 +342,19 @@ public final class AdvancedProtectionManager { Intent intent = new Intent(ACTION_SHOW_ADVANCED_PROTECTION_SUPPORT_DIALOG); intent.setFlags(FLAG_ACTIVITY_NEW_TASK); intent.putExtra(EXTRA_SUPPORT_DIALOG_FEATURE, featureId); - if (type != null) { - intent.putExtra(EXTRA_SUPPORT_DIALOG_TYPE, type); - } + intent.putExtra(EXTRA_SUPPORT_DIALOG_TYPE, type); return intent; } /** @hide */ - public @NonNull Intent createSupportIntentForPolicyIdentifierOrRestriction( - @NonNull String identifier, @Nullable @SupportDialogType String type) { + public static @NonNull Intent createSupportIntentForPolicyIdentifierOrRestriction( + @NonNull String identifier, @SupportDialogType int type) { Objects.requireNonNull(identifier); - if (type != null && !ALL_SUPPORT_DIALOG_TYPES.contains(type)) { + if (!ALL_SUPPORT_DIALOG_TYPES.contains(type)) { throw new IllegalArgumentException(type + " is not a valid type. See" + " SUPPORT_DIALOG_TYPE_* APIs."); } - final String featureId; + final int featureId; if (DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY.equals(identifier)) { featureId = FEATURE_ID_DISALLOW_INSTALL_UNKNOWN_SOURCES; } else if (DISALLOW_CELLULAR_2G.equals(identifier)) { diff --git a/core/java/android/service/quickaccesswallet/flags.aconfig b/core/java/android/service/quickaccesswallet/flags.aconfig index 9736345ae3a9..2b40f340f3b8 100644 --- a/core/java/android/service/quickaccesswallet/flags.aconfig +++ b/core/java/android/service/quickaccesswallet/flags.aconfig @@ -14,4 +14,14 @@ flag { namespace: "wallet_integration" description: "When the wallet QS tile is tapped, launch the selected card pending intent instead of the home screen pending intent." bug: "378469025" +} + +flag { + name: "launch_wallet_via_sysui_callbacks" + namespace: "wallet_integration" + description: "Refactor Wallet double press power launch to be handled by SysUI instead of core. This allows handling dismissing the keyguard before launch." + bug: "384938619" + metadata { + purpose: PURPOSE_BUGFIX + } }
\ No newline at end of file diff --git a/core/java/android/telephony/TelephonyCallback.java b/core/java/android/telephony/TelephonyCallback.java index cc19e7cab537..d05fa9e43cd4 100644 --- a/core/java/android/telephony/TelephonyCallback.java +++ b/core/java/android/telephony/TelephonyCallback.java @@ -1819,7 +1819,7 @@ public class TelephonyCallback { */ @SystemApi @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) - public interface CarrierRoamingNtnModeListener { + public interface CarrierRoamingNtnListener { /** * Callback invoked when carrier roaming non-terrestrial network mode changes. * @@ -2332,8 +2332,8 @@ public class TelephonyCallback { public void onCarrierRoamingNtnModeChanged(boolean active) { if (!Flags.carrierEnabledSatelliteFlag()) return; - CarrierRoamingNtnModeListener listener = - (CarrierRoamingNtnModeListener) mTelephonyCallbackWeakRef.get(); + CarrierRoamingNtnListener listener = + (CarrierRoamingNtnListener) mTelephonyCallbackWeakRef.get(); if (listener == null) return; Binder.withCleanCallingIdentity( @@ -2343,8 +2343,8 @@ public class TelephonyCallback { public void onCarrierRoamingNtnEligibleStateChanged(boolean eligible) { if (!Flags.carrierRoamingNbIotNtn()) return; - CarrierRoamingNtnModeListener listener = - (CarrierRoamingNtnModeListener) mTelephonyCallbackWeakRef.get(); + CarrierRoamingNtnListener listener = + (CarrierRoamingNtnListener) mTelephonyCallbackWeakRef.get(); if (listener == null) return; Binder.withCleanCallingIdentity(() -> mExecutor.execute( @@ -2355,8 +2355,8 @@ public class TelephonyCallback { @NetworkRegistrationInfo.ServiceType int[] availableServices) { if (!Flags.carrierRoamingNbIotNtn()) return; - CarrierRoamingNtnModeListener listener = - (CarrierRoamingNtnModeListener) mTelephonyCallbackWeakRef.get(); + CarrierRoamingNtnListener listener = + (CarrierRoamingNtnListener) mTelephonyCallbackWeakRef.get(); if (listener == null) return; Binder.withCleanCallingIdentity(() -> mExecutor.execute( @@ -2367,8 +2367,8 @@ public class TelephonyCallback { @NonNull NtnSignalStrength ntnSignalStrength) { if (!Flags.carrierRoamingNbIotNtn()) return; - CarrierRoamingNtnModeListener listener = - (CarrierRoamingNtnModeListener) mTelephonyCallbackWeakRef.get(); + CarrierRoamingNtnListener listener = + (CarrierRoamingNtnListener) mTelephonyCallbackWeakRef.get(); if (listener == null) return; Binder.withCleanCallingIdentity(() -> mExecutor.execute( diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java index 4ec429d0c4ad..fa44fcf0dffa 100644 --- a/core/java/android/telephony/TelephonyRegistryManager.java +++ b/core/java/android/telephony/TelephonyRegistryManager.java @@ -1341,7 +1341,7 @@ public class TelephonyRegistryManager { TelephonyCallback.EVENT_SIMULTANEOUS_CELLULAR_CALLING_SUBSCRIPTIONS_CHANGED); } - if (telephonyCallback instanceof TelephonyCallback.CarrierRoamingNtnModeListener) { + if (telephonyCallback instanceof TelephonyCallback.CarrierRoamingNtnListener) { eventList.add(TelephonyCallback.EVENT_CARRIER_ROAMING_NTN_MODE_CHANGED); eventList.add(TelephonyCallback.EVENT_CARRIER_ROAMING_NTN_ELIGIBLE_STATE_CHANGED); eventList.add(TelephonyCallback.EVENT_CARRIER_ROAMING_NTN_AVAILABLE_SERVICES_CHANGED); diff --git a/core/java/android/window/flags/windowing_frontend.aconfig b/core/java/android/window/flags/windowing_frontend.aconfig index 74a3819e03f9..091f86ec9234 100644 --- a/core/java/android/window/flags/windowing_frontend.aconfig +++ b/core/java/android/window/flags/windowing_frontend.aconfig @@ -303,17 +303,6 @@ flag { } flag { - name: "remove_starting_window_wait_for_multi_transitions" - namespace: "windowing_frontend" - description: "Avoid remove starting window too early when playing multiple transitions" - bug: "362347290" - is_fixed_read_only: true - metadata { - purpose: PURPOSE_BUGFIX - } -} - -flag { name: "ensure_keyguard_does_transition_starting" namespace: "windowing_frontend" description: "Ensure that keyguard is the one starting transitions, instead of delegating to Core" diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index ca4d1b63a928..3bdf3d65e99c 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -21,6 +21,7 @@ import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT_SHARE_WITH_PERSONAL; import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT_SHARE_WITH_WORK; import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CROSS_PROFILE_BLOCKED_TITLE; +import static android.content.ContentProvider.getUriWithoutUserId; import static android.content.ContentProvider.getUserIdFromUri; import static android.stats.devicepolicy.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_PERSONAL; import static android.stats.devicepolicy.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK; @@ -40,7 +41,9 @@ import android.annotation.Nullable; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityOptions; +import android.app.IUriGrantsManager; import android.app.SharedElementCallback; +import android.app.UriGrantsManager; import android.app.prediction.AppPredictionContext; import android.app.prediction.AppPredictionManager; import android.app.prediction.AppPredictor; @@ -77,6 +80,7 @@ import android.graphics.Paint; import android.graphics.Path; import android.graphics.drawable.AnimatedVectorDrawable; import android.graphics.drawable.Drawable; +import android.graphics.drawable.Icon; import android.metrics.LogMaker; import android.net.Uri; import android.os.AsyncTask; @@ -86,6 +90,7 @@ import android.os.Handler; import android.os.Message; import android.os.Parcelable; import android.os.PatternMatcher; +import android.os.RemoteException; import android.os.ResultReceiver; import android.os.UserHandle; import android.os.UserManager; @@ -692,7 +697,11 @@ public class ChooserActivity extends ResolverActivity implements targets = null; break; } - targets[i] = (ChooserTarget) pa[i]; + ChooserTarget chooserTarget = (ChooserTarget) pa[i]; + if (!hasValidIcon(chooserTarget)) { + chooserTarget = removeIcon(chooserTarget); + } + targets[i] = chooserTarget; } mCallerChooserTargets = targets; } @@ -4214,4 +4223,43 @@ public class ChooserActivity extends ResolverActivity implements private boolean shouldNearbyShareBeIncludedAsActionButton() { return !shouldNearbyShareBeFirstInRankedRow(); } + + private boolean hasValidIcon(ChooserTarget target) { + Icon icon = target.getIcon(); + if (icon == null) { + return true; + } + if (icon.getType() == Icon.TYPE_URI || icon.getType() == Icon.TYPE_URI_ADAPTIVE_BITMAP) { + Uri uri = icon.getUri(); + try { + getUriGrantsManager().checkGrantUriPermission_ignoreNonSystem( + getLaunchedFromUid(), + getPackageName(), + getUriWithoutUserId(uri), + Intent.FLAG_GRANT_READ_URI_PERMISSION, + getUserIdFromUri(uri) + ); + } catch (SecurityException | RemoteException e) { + Log.e(TAG, "Failed to get URI permission for: " + uri, e); + return false; + } + } + return true; + } + + private IUriGrantsManager getUriGrantsManager() { + return UriGrantsManager.getService(); + } + + private static ChooserTarget removeIcon(ChooserTarget target) { + if (target == null) { + return null; + } + return new ChooserTarget( + target.getTitle(), + null, + target.getScore(), + target.getComponentName(), + target.getIntentExtras()); + } } diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl index c834dde56bfe..555374a05592 100644 --- a/core/java/com/android/internal/statusbar/IStatusBar.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl @@ -124,6 +124,11 @@ oneway interface IStatusBar void onCameraLaunchGestureDetected(int source); /** + * Notifies the status bar that a wallet launch gesture has been detected. + */ + void onWalletLaunchGestureDetected(); + + /** * Notifies the status bar that the Emergency Action launch gesture has been detected. * * TODO(b/169175022) Update method name and docs when feature name is locked. diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml index 4d96adeb8e09..1578bc23dfe8 100644 --- a/core/res/res/values-af/strings.xml +++ b/core/res/res/values-af/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Kan nie selnetwerk bereik nie"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Probeer die voorkeurnetwerk verander. Tik om te verander."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Noodoproepe is onbeskikbaar"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Noodoproepe vereis ’n selnetwerk."</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Opletberigte"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Oproepaanstuur"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Eenhandmodus"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Ekstra donker"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Gehoortoestelle"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Het volumesleutels ingehou. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> aangeskakel."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Het volumesleutels ingehou. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> is afgeskakel"</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Los die volumesleutels. Druk en hou albei volumesleutels weer 3 sekondes lank in om <xliff:g id="SERVICE_NAME">%1$s</xliff:g> aan te skakel."</string> diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml index ecfce08a6ae8..114013007fbe 100644 --- a/core/res/res/values-am/strings.xml +++ b/core/res/res/values-am/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"የሞባይል አውታረ መረብን መድረስ አልተቻለም"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"ተመራጭ አውታረ መረብን ለመለወጥ ይሞክሩ። ለመለወጥ መታ ያድርጉ።"</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"የአደጋ ጊዜ ጥሪ አይገኝም"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"የአደጋ ጥሪዎች የተንቀሳቃሽ ስልክ አውታረ መረብ ያስፈልጋቸዋል"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"ማንቂያዎች"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"ጥሪ ማስተላለፍ"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"የአንድ እጅ ሁነታ"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ተጨማሪ ደብዛዛ"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"የመስሚያ መሣሪያዎች"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"የድምፅ ቁልፎችን ይዟል። <xliff:g id="SERVICE_NAME">%1$s</xliff:g> በርቷል።"</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"የድምፅ ቁልፎችን ይዟል። <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ጠፍተዋል።"</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"የድምጽ መጠን ቁልፎቹን ይልቀቁ። <xliff:g id="SERVICE_NAME">%1$s</xliff:g>ን ለማብራት ሁለቱንም የድምጽ መጠን ቁልፎች በድጋሚ ለ3 ሰከንዶች ተጭነው ይያዙ።"</string> diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml index dc047acfc03b..02e5be1a36b1 100644 --- a/core/res/res/values-ar/strings.xml +++ b/core/res/res/values-ar/strings.xml @@ -76,8 +76,8 @@ <string name="CLIRDefaultOffNextCallOn" msgid="1022781126694885017">"الإعداد التلقائي لمعرف المتصل هو غير محظور . الاتصال التالي: محظور"</string> <string name="CLIRDefaultOffNextCallOff" msgid="2491576172356463443">"الإعداد التلقائي لمعرف المتصل هو غير محظور . الاتصال التالي: غير محظور"</string> <string name="page_size_compat_apk_warning" msgid="2982396798449041224">"هذا التطبيق غير متوافق مع حجم الصفحة الذي يبلغ 16 كيلوبايت. وتعذَّر إكمال عملية التأكُّد من محاذاة ملفات APK. وسيتم تشغيل هذا التطبيق باستخدام الوضع المتوافق مع حجم الصفحة. ولكي يتوافق التطبيق مع الأجهزة بشكلٍ أفضل، يُرجى إعادة تحويله برمجيًا ليصبح متوافقًا مع حجم الصفحة الذي يبلغ 16 كيلوبايت. لمزيد من المعلومات، يُرجى الاطّلاع على الرابط <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> - <string name="page_size_compat_elf_warning" msgid="6753874059564812651">"هذا التطبيق غير متوافق مع حجم الصفحة الذي يبلغ 16 كيلوبايت. وتعذَّر إكمال عملية التأكُّد من محاذاة ملفات ELF. وسيتم تشغيل هذا التطبيق باستخدام الوضع المتوافق مع حجم الصفحة. ولكي يتوافق التطبيق مع الأجهزة بشكلٍ أفضل، يُرجى إعادة تحويله برمجيًا ليصبح متوافقًا مع حجم الصفحة الذي يبلغ 16 كيلوبايت. لمزيد من المعلومات، يُرجى الاطّلاع على الرابط <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> - <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"هذا التطبيق غير متوافق مع حجم الصفحة الذي يبلغ 16 كيلوبايت. وتعذَّر إكمال عمليات التأكُّد من محاذاة ملفات APK وELF. وسيتم تشغيل هذا التطبيق باستخدام الوضع المتوافق مع حجم الصفحة. ولكي يتوافق التطبيق مع الأجهزة بشكلٍ أفضل، يُرجى إعادة تحويله برمجيًا ليصبح متوافقًا مع حجم الصفحة الذي يبلغ 16 كيلوبايت. لمزيد من المعلومات، يُرجى الاطّلاع على الرابط <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> + <string name="page_size_compat_elf_warning" msgid="6753874059564812651">"هذا التطبيق غير متوافق مع حجم الصفحة الذي يبلغ 16 كيلوبايت. تعذَّر إكمال عملية التأكُّد من محاذاة ملفات ELF. سيتم تشغيل هذا التطبيق باستخدام الوضع المتوافق مع حجم الصفحة. لكي يتوافق التطبيق مع الأجهزة بشكلٍ أفضل، يُرجى إعادة تحويله برمجيًا ليصبح متوافقًا مع حجم الصفحة الذي يبلغ 16 كيلوبايت. لمزيد من المعلومات، يُرجى الانتقال إلى الرابط <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> + <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"هذا التطبيق غير متوافق مع حجم الصفحة الذي يبلغ 16 كيلوبايت. تعذَّر إكمال عمليات التأكُّد من محاذاة ملفات APK وELF. سيتم تشغيل هذا التطبيق باستخدام الوضع المتوافق مع حجم الصفحة. لكي يتوافق التطبيق مع الأجهزة بشكلٍ أفضل، يُرجى إعادة تحويله برمجيًا ليصبح متوافقًا مع حجم 16 كيلوبايت. لمزيد من المعلومات، يُرجى الاتنقال إلى الرابط <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> <string name="serviceNotProvisioned" msgid="8289333510236766193">"الخدمة غير متوفرة."</string> <string name="CLIRPermanent" msgid="166443681876381118">"لا يمكنك تغيير إعداد معرّف المتصل."</string> <string name="auto_data_switch_title" msgid="3286350716870518297">"تم تبديل البيانات إلى <xliff:g id="CARRIERDISPLAY">%s</xliff:g>"</string> @@ -91,6 +91,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"يتعذّر الوصول إلى شبكة الجوّال."</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"حاول تغيير الشبكة المفضلة. انقر لتغييرها."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"لا تتوفر إمكانية الاتصال في حالات الطوارئ."</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"يتطلّب إجراء مكالمات الطوارئ الاتصال بشبكة جوّال"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"التنبيهات"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"إعادة توجيه المكالمة"</string> @@ -1782,6 +1784,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"وضع \"التصفح بيد واحدة\""</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"زيادة تعتيم الشاشة"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"سماعات الأذن الطبية"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"تم الضغط مع الاستمرار على مفتاحَي التحكّم في مستوى الصوت. تم تفعيل <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"تم الضغط مع الاستمرار على مفتاحَي التحكّم في مستوى الصوت. تم إيقاف <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"ارفع إصبعَيك عن مفتاحَي مستوى الصوت. لتفعيل خدمة \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\"، اضغط مع الاستمرار على كلا مفتاحَي مستوى الصوت مجددًا لمدة 3 ثوانٍ."</string> diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml index 402394d07770..9f3b263f84a6 100644 --- a/core/res/res/values-as/strings.xml +++ b/core/res/res/values-as/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"ম’বাইল নেটৱৰ্কৰ লগত সংযোগ কৰিব পৰা নাই"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"পচন্দৰ নেটৱৰ্ক সলনি কৰি চেষ্টা কৰি চাওক। সলনি কৰিবলৈ টিপক।"</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"জৰুৰীকালীন কল কৰাৰ সুবিধা উপলব্ধ নহয়"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"জৰুৰীকালীন কল কৰিবলৈ ম’বাইল নেটৱৰ্কৰ প্ৰয়োজন"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"সতৰ্কবাণীসমূহ"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"কল ফৰৱাৰ্ডিং"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"এখন হাতেৰে ব্যৱহাৰ কৰাৰ ম’ড"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"অতিৰিক্তভাৱে পোহৰ কমোৱাৰ সুবিধা"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"শুনাৰ ডিভাইচ"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ভলিউম কীসমূহ ধৰি ৰাখক। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> অন কৰা হ\'ল।"</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ভলিউম কী ধৰি ৰাখিছিল। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> অফ কৰা হ\'ল।"</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"ভলিউম কী এৰি দিয়ক। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> অন কৰিবলৈ, দুয়োটা ভলিউম কী পুনৰ ৩ ছেকেণ্ডৰ বাবে টিপি হেঁচি ৰাখক।"</string> diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml index c696e63ed1af..54062de9536b 100644 --- a/core/res/res/values-az/strings.xml +++ b/core/res/res/values-az/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Mobil şəbəkəyə daxil olmaq mümkün deyil"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Tərcih edilən şəbəkəni dəyişin. Dəyişmək üçün klikləyin."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Təcili zəng əlçatan deyil"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Təcili zənglər üçün mobil şəbəkə tələb olunur"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Siqnallar"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Zəng yönləndirmə"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Birəlli rejim"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Əlavə tündləşmə"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Eşitmə cihazları"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Səs səviyyəsi düymələrinə basıb saxlayın. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> aktiv edildi."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Səs səviyyəsi düymələrinə basılaraq saxlanıb. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> deaktiv edilib."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Səs düymələrini buraxın. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> xidmətini aktiv etmək üçün hər iki səs düyməsinə yenidən 3 saniyə basıb saxlayın."</string> diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml index dc393463af87..69b46124cec1 100644 --- a/core/res/res/values-b+sr+Latn/strings.xml +++ b/core/res/res/values-b+sr+Latn/strings.xml @@ -88,6 +88,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Povezivanje sa mobilnom mrežom nije uspelo"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Probajte da promenite željenu mrežu. Dodirnite da biste promenili."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Hitni pozivi nisu dostupni"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Hitni pozivi zahtevaju mobilnu mrežu"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Upozorenja"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Preusmeravanje poziva"</string> @@ -1779,6 +1781,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Režim jednom rukom"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Dodatno zatamni"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Slušni aparati"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Držali ste tastere za jačinu zvuka. Usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je uključena."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Držali ste tastere za jačinu zvuka. Usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je isključena."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Pustite tastere za jačinu zvuka. Da biste uključili <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, ponovo pritisnite i zadržite oba tastera za jačinu zvuka 3 sekunde."</string> diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml index d1a2104dfa25..9f7f823fdec0 100644 --- a/core/res/res/values-be/strings.xml +++ b/core/res/res/values-be/strings.xml @@ -89,6 +89,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Сетка мабільнай сувязі недаступная"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Націсніце, каб выбраць іншую сетку."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Экстранныя выклікі недаступныя"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Для экстранных выклікаў патрабуецца мабільная сетка"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Абвесткі"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Пераадрасацыя выкліку"</string> @@ -1780,6 +1782,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Рэжым кіравання адной рукой"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Дадатковае памяншэнне яркасці"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Слыхавыя апараты"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Клавішы гучнасці ўтрымліваліся націснутымі. Уключана служба \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\"."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Клавішы гучнасці ўтрымліваліся націснутымі. Служба \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\" выключана."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Адпусціце клавішы гучнасці. Каб уключыць сэрвіс \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\", націсніце абедзве клавішы гучнасці яшчэ раз і ўтрымлівайце іх на працягу 3 секунд."</string> diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml index 3332195635c4..1353d2287c09 100644 --- a/core/res/res/values-bg/strings.xml +++ b/core/res/res/values-bg/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Не може да се установи връзка с мобилната мрежа"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Изберете друга предпочитана мрежа. Докоснете за промяна."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Няма достъп до спешните обаждания"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"За спешните обаждания се изисква мобилна мрежа"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Сигнали"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Пренасочване на обаждания"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Работа с една ръка"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Допълнително затъмняване"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Слухови апарати"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Задържахте бутоните за силата на звука. Услугата <xliff:g id="SERVICE_NAME">%1$s</xliff:g> е включена."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Задържахте бутоните за силата на звука. Услугата <xliff:g id="SERVICE_NAME">%1$s</xliff:g> е изключена."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Освободете бутоните за силата на звука. За да включите <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, отново натиснете двата бутона за силата на звука и задръжте за 3 секунди."</string> diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml index 2b19c573e04a..d74a3a375159 100644 --- a/core/res/res/values-bn/strings.xml +++ b/core/res/res/values-bn/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"মোবাইল নেটওয়ার্কে কানেক্ট করা যাচ্ছে না"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"পছন্দের নেটওয়ার্ক পরিবর্তন করে দেখুন। অন্য নেটওয়ার্ক বেছে নিতে ট্যাপ করুন।"</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"জরুরি কল করা যাবে না"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"জরুরি কলের জন্য মোবাইল নেটওয়ার্ক থাকতে হবে"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"সতর্কতা"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"কল ফরওয়ার্ড করা"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"এক হাতে ব্যবহার করার মোড"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"অতিরিক্ত কম উজ্জ্বলতা"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"হিয়ারিং ডিভাইস"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ভলিউম কী ধরে ছিলেন। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> চালু করা হয়েছে।"</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ভলিউম কী ধরে ছিলেন। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> বন্ধ করা হয়েছে।"</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"ভলিউম \'কী\' রিলিজ করুন। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> চালু করুন, দু\'টি ভলিউম \'কী\' আবার প্রেস করে ৩ সেকেন্ড ধরে রাখুন।"</string> diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml index c49e337d6fe5..c9168709eb08 100644 --- a/core/res/res/values-bs/strings.xml +++ b/core/res/res/values-bs/strings.xml @@ -88,6 +88,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Nije moguće dosegnuti mobilnu mrežu"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Pokušajte promijeniti preferiranu mrežu. Dodirnite za promjenu."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Hitni pozivi su nedostupni"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Za hitne pozive potrebna je mreža"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Upozorenja"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Prosljeđivanje poziva"</string> @@ -1779,6 +1781,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Način rada jednom rukom"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Dodatno zatamnjenje"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Slušni aparati"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Držali ste tipke za jačinu zvuka. Usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je uključena."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Držali ste tipke za jačinu zvuka. Usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je isključena."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Pustite tipke za jačinu zvuka. Da uključite uslugu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, ponovo pritisnite i zadržite obje tipke za jačinu zvuka 3 sekunde."</string> diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index 196f9ac14f3f..5c53857c5902 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -88,6 +88,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"No es pot accedir a la xarxa mòbil"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Prova de canviar de xarxa preferent. Toca per canviar-la."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Les trucades d\'emergència no estan disponibles"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Per poder fer trucades d\'emergència, cal tenir connexió de xarxa mòbil"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Alertes"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Desviació de trucades"</string> @@ -1779,6 +1781,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Mode d\'una mà"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Atenuació extra"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Audiòfons"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"S\'han mantingut premudes les tecles de volum. S\'ha activat <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"S\'han mantingut premudes les tecles de volum. S\'ha desactivat <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Deixa anar les tecles de volum. Per activar <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, torna a mantenir premudes totes dues tecles de volum durant 3 segons."</string> diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index 8038a296ab7a..8d595d893ead 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -73,9 +73,9 @@ <string name="CLIRDefaultOnNextCallOff" msgid="5036749051007098105">"Ve výchozím nastavení je funkce ID volajícího omezena. Příští hovor: Neomezeno"</string> <string name="CLIRDefaultOffNextCallOn" msgid="1022781126694885017">"Ve výchozím nastavení není funkce ID volajícího omezena. Příští hovor: Omezeno"</string> <string name="CLIRDefaultOffNextCallOff" msgid="2491576172356463443">"Ve výchozím nastavení není funkce ID volajícího omezena. Příští hovor: Neomezeno"</string> - <string name="page_size_compat_apk_warning" msgid="2982396798449041224">"Tato aplikace není kompatibilní s 16KB režimem. Kontrola zarovnání souboru APK selhala. Tato aplikace poběží v režimu kompatibilním s velikostmi stránek. Pro optimální kompatibilitu ji překompilujte s podporou 16KB režimu. Další informace najdete na stránce <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> - <string name="page_size_compat_elf_warning" msgid="6753874059564812651">"Tato aplikace není kompatibilní s 16KB režimem. Kontrola zarovnání souboru ELF selhala. Tato aplikace poběží v režimu kompatibilním s velikostmi stránek. Pro optimální kompatibilitu ji překompilujte s podporou 16KB režimu. Další informace najdete na stránce <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> - <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"Tato aplikace není kompatibilní s 16KB režimem. Kontroly zarovnání souborů APK a ELF selhaly. Tato aplikace poběží v režimu kompatibilním s velikostmi stránek. Pro optimální kompatibilitu ji překompilujte s podporou 16KB režimu. Další informace najdete na stránce <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> + <string name="page_size_compat_apk_warning" msgid="2982396798449041224">"Tato aplikace není kompatibilní s 16KB stránkováním. Kontrola zarovnání v souboru APK selhala. Tato aplikace poběží v režimu kompatibility s velikostí stránky. Pro optimální kompatibilitu ji překompilujte s podporou 16KB stránkování. Další informace najdete na stránce <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> + <string name="page_size_compat_elf_warning" msgid="6753874059564812651">"Tato aplikace není kompatibilní s 16KB stránkováním. Kontrola zarovnání v souboru ELF selhala. Tato aplikace poběží v režimu kompatibility s velikostí stránky. Pro optimální kompatibilitu ji překompilujte s podporou 16KB stránkování. Další informace najdete na stránce <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> + <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"Tato aplikace není kompatibilní s 16KB stránkováním. Kontroly zarovnání v souborech APK a ELF selhaly. Tato aplikace poběží v režimu kompatibility s velikostí stránky. Pro optimální kompatibilitu ji překompilujte s podporou 16KB stránkování. Další informace najdete na stránce <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> <string name="serviceNotProvisioned" msgid="8289333510236766193">"Služba není zřízena."</string> <string name="CLIRPermanent" msgid="166443681876381118">"Nastavení ID volajícího nesmíte měnit."</string> <string name="auto_data_switch_title" msgid="3286350716870518297">"Datové připojení bylo přepnuto na operátora <xliff:g id="CARRIERDISPLAY">%s</xliff:g>"</string> @@ -89,6 +89,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Mobilní síť není dostupná"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Zkuste změnit preferovanou síť. Změníte ji klepnutím."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Tísňová volání jsou nedostupná"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Tísňová volání vyžadují mobilní síť"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Upozornění"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Přesměrování hovorů"</string> @@ -1780,6 +1782,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Režim jedné ruky"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Velmi tmavé zobrazení"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Naslouchátka"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Byla podržena tlačítka hlasitosti. Služba <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je zapnutá."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Byla podržena tlačítka hlasitosti. Služba <xliff:g id="SERVICE_NAME">%1$s</xliff:g> byla vypnuta."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Uvolněte tlačítka hlasitosti. Pokud chcete zapnout službu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, znovu tři sekundy podržte obě tlačítka hlasitosti."</string> diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml index 5403cce30944..66e3402c1ebf 100644 --- a/core/res/res/values-da/strings.xml +++ b/core/res/res/values-da/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Der er ingen forbindelse til mobilnetværket"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Prøv at skifte dit foretrukne netværk. Tryk for skifte."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Det er ikke muligt at foretage nødopkald"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Nødopkald kræver adgang til et mobilnetværk"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Underretninger"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Viderestilling af opkald"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Enhåndstilstand"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Ekstra dæmpet belysning"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Høreapparater"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Lydstyrkeknapperne blev holdt nede. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> er aktiveret."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Lydstyrkeknapperne blev holdt nede. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> er deaktiveret."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Slip lydstyrkeknapperne. Du kan aktivere <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ved at holde begge lydstyrkeknapper nede igen i 3 sekunder."</string> diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index 66bc41fbb82b..6311880bb24a 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Mobilfunknetz nicht erreichbar"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Versuche, das bevorzugte Netzwerk zu ändern. Tippe, um ein anderes auszuwählen."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Notrufe nicht möglich"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Für Notrufe ist ein Mobilfunknetz erforderlich"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Warnmeldungen"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Anrufweiterleitung"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Einhandmodus"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Extradunkel"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Hörgeräte"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Lautstärketasten wurden gedrückt gehalten. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ist aktiviert."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Lautstärketasten wurden gedrückt gehalten. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ist deaktiviert."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Lass die Lautstärketasten los. Halte zum Aktivieren von <xliff:g id="SERVICE_NAME">%1$s</xliff:g> beide Lautstärketasten noch einmal 3 Sekunden lang gedrückt."</string> diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml index 1aae63feb546..23fc44ca9dcc 100644 --- a/core/res/res/values-el/strings.xml +++ b/core/res/res/values-el/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Δεν είναι δυνατή η σύνδεση στο δίκτυο κινητής τηλεφωνίας"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Δοκιμάστε να αλλάξετε το προτιμώμενο δίκτυο. Πατήστε για αλλαγή."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Οι κλήσεις έκτακτης ανάγκης δεν είναι διαθέσιμες"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Για τις κλήσεις έκτακτης ανάγκης απαιτείται δίκτυο κινητής τηλεφωνίας"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Ειδοποιήσεις"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Προώθηση κλήσης"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Λειτουργία ενός χεριού"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Επιπλέον μείωση φωτεινότητας"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Συσκευές ακοής"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Τα πλήκτρα έντασης είναι πατημένα. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ενεργοποιήθηκε."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Τα πλήκτρα έντασης είναι πατημένα. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>: απενεργοποιημένο"</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Αφήστε τα κουμπιά έντασης ήχου. Για να ενεργοποιήσετε την υπηρεσία <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, πατήστε ξανά παρατεταμένα και τα δύο κουμπιά έντασης ήχου για τρία δευτερόλεπτα."</string> diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml index 3c5e02ad6322..823db75ca6f4 100644 --- a/core/res/res/values-en-rAU/strings.xml +++ b/core/res/res/values-en-rAU/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Can’t reach mobile network"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Try changing preferred network. Tap to change."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Emergency calling unavailable"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Emergency calls require a mobile network"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Alerts"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Call forwarding"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"One-handed mode"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Extra dim"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Hearing devices"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned on."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned off."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Release the volume keys. To turn on <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, press and hold both volume keys again for three seconds."</string> diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml index a2128088e715..83fd1186e006 100644 --- a/core/res/res/values-en-rCA/strings.xml +++ b/core/res/res/values-en-rCA/strings.xml @@ -87,6 +87,7 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Can’t reach mobile network"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Try changing preferred network. Tap to change."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Emergency calling unavailable"</string> + <string name="emergency_calling_do_not_show_again" msgid="5034171343309733068">"Do Not Show Again"</string> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Emergency calls require a mobile network"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Alerts"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Call forwarding"</string> @@ -1778,6 +1779,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"One-Handed mode"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Extra dim"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Hearing devices"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned on."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned off."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Release the volume keys. To turn on <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, press and hold both volume keys again for 3 seconds."</string> diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml index cf02080120e5..46a0d2b96869 100644 --- a/core/res/res/values-en-rGB/strings.xml +++ b/core/res/res/values-en-rGB/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Can’t reach mobile network"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Try changing preferred network. Tap to change."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Emergency calling unavailable"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Emergency calls require a mobile network"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Alerts"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Call forwarding"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"One-handed mode"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Extra dim"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Hearing devices"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned on."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned off."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Release the volume keys. To turn on <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, press and hold both volume keys again for three seconds."</string> diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml index 30b60117cd19..22cf48f71439 100644 --- a/core/res/res/values-en-rIN/strings.xml +++ b/core/res/res/values-en-rIN/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Can’t reach mobile network"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Try changing preferred network. Tap to change."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Emergency calling unavailable"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Emergency calls require a mobile network"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Alerts"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Call forwarding"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"One-handed mode"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Extra dim"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Hearing devices"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned on."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Held volume keys. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> turned off."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Release the volume keys. To turn on <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, press and hold both volume keys again for three seconds."</string> diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index 867e8c52a4cf..b956286b7d2f 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -73,8 +73,8 @@ <string name="CLIRDefaultOffNextCallOn" msgid="1022781126694885017">"El identificador de llamadas está predeterminado en no restringido. Llamada siguiente: restringida"</string> <string name="CLIRDefaultOffNextCallOff" msgid="2491576172356463443">"El Identificador de llamadas está predeterminado en no restringido. Llamada siguiente: no restringido"</string> <string name="page_size_compat_apk_warning" msgid="2982396798449041224">"Esta app no es compatible con 16 KB. No se pudo verificar la alineación del APK. Esta app se ejecutará con el modo de compatibilidad de tamaño de página. Para obtener mejores resultados, vuelve a compilar la aplicación con la compatibilidad de 16 KB. Para obtener más información, consulta el siguiente vínculo: <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> - <string name="page_size_compat_elf_warning" msgid="6753874059564812651">"Esta app no es compatible con 16 KB. No se pudo verificar la alineación de ELF. Esta app se ejecutará con el modo de compatibilidad de tamaño de página. Para obtener mejores resultados, vuelve a compilar la aplicación con la compatibilidad de 16 KB. Para obtener más información, consulta el siguiente vínculo: <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> - <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"Esta app no es compatible con 16 KB. No se pudieron verificar las alineaciones de APK y ELF. Esta app se ejecutará con el modo de compatibilidad de tamaño de página. Para obtener mejores resultados, vuelve a compilar la aplicación con la compatibilidad de 16 KB. Para obtener más información, consulta el siguiente vínculo: <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> + <string name="page_size_compat_elf_warning" msgid="6753874059564812651">"Esta app no es compatible con 16 KB. No se pudo verificar la alineación de ELF. La app se ejecutará con el modo de compatibilidad de tamaño de página. Para obtener mejores resultados, vuelve a compilar la aplicación con la compatibilidad de 16 KB. Si necesitas más información, consulta el siguiente vínculo: <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> + <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"Esta app no es compatible con 16 KB. No se pudieron verificar las alineaciones de APK y ELF. La app se ejecutará con el modo de compatibilidad de tamaño de página. Para obtener mejores resultados, vuelve a compilar la aplicación con la compatibilidad de 16 KB. Si necesitas más información, consulta el siguiente vínculo: <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> <string name="serviceNotProvisioned" msgid="8289333510236766193">"Servicio no suministrado."</string> <string name="CLIRPermanent" msgid="166443681876381118">"No puedes cambiar la configuración del identificador de llamadas."</string> <string name="auto_data_switch_title" msgid="3286350716870518297">"Se cambiaron los datos a <xliff:g id="CARRIERDISPLAY">%s</xliff:g>"</string> @@ -88,6 +88,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"No se puede acceder a la red móvil"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Presiona para cambiar la red preferida."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Servicio de llamadas de emergencia no disponible"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Las llamadas de emergencia requieren una red móvil"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Alertas"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Desvío de llamada"</string> @@ -1779,6 +1781,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modo de una mano"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Atenuación extra"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Dispositivos auditivos"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Como mantuviste presionadas las teclas de volumen, se activó <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Se presionaron las teclas de volumen. Se desactivó <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Suelta las teclas de volumen. Para activar <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, vuelve a mantener presionadas las teclas de volumen durante 3 segundos."</string> diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index 1f10c5d0fb88..c50fbc7910ec 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -88,6 +88,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"No se puede establecer conexión con la red móvil"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Toca para cambiar la red preferida."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Servicio de llamadas de emergencia no disponible"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Para hacer llamadas de emergencia, necesitas conectarte a una red móvil"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Alertas"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Desvío de llamadas"</string> @@ -1779,6 +1781,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modo Una mano"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Atenuación extra"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Audífonos"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Al mantener pulsadas las teclas de volumen, se ha activado <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Se han mantenido pulsadas las teclas de volumen. Se ha desactivado <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Suelta las teclas de volumen. Para activar <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, mantén pulsadas las dos teclas de volumen de nuevo durante 3 segundos."</string> diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml index 58f5f20fe35f..3e3e5db60163 100644 --- a/core/res/res/values-et/strings.xml +++ b/core/res/res/values-et/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Mobiilsidevõrguga ei saa ühendust"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Proovige eelistatud võrku vahetada. Puudutage muutmiseks."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Hädaabikõned pole saadaval"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Hädaabikõnede jaoks on vajalik mobiilsidevõrk"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Teatised"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Kõnede suunamine"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Ühekäerežiim"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Eriti tume"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Kuuldeseadmed"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Helitugevuse klahve hoiti all. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> lülitati sisse."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Helitugevuse klahve hoiti all. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> lülitati välja."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Vabastage helitugevuse klahvid. Teenuse <xliff:g id="SERVICE_NAME">%1$s</xliff:g> sisselülitamiseks vajutage uuesti mõlemat helitugevuse klahvi ja hoidke neid 3 sekundit all."</string> diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml index e470f0e0a69c..2f477f3b2010 100644 --- a/core/res/res/values-eu/strings.xml +++ b/core/res/res/values-eu/strings.xml @@ -73,7 +73,7 @@ <string name="CLIRDefaultOffNextCallOff" msgid="2491576172356463443">"Deitzailearen identitatea zerbitzuaren balio lehenetsiak ez du murriztapenik ezartzen. Hurrengo deia: murriztapenik gabe."</string> <string name="page_size_compat_apk_warning" msgid="2982396798449041224">"Aplikazio hau ez da bateragarria 16 KBko bertsioarekin. Ezin izan da egiaztatu APKren lerrokatzea. Orriaren tamainarekin bateragarria den modua erabilita exekutatuko da aplikazioa. Emaitza onenak lortzeko, konpilatu aplikazioa berriro 16 KBko bertsioarekin bateragarria izan dadin. Informazio gehiago lortzeko, joan hona: <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>."</string> <string name="page_size_compat_elf_warning" msgid="6753874059564812651">"Aplikazio hau ez da bateragarria 16 KBko bertsioarekin. Ezin izan da egiaztatu ELFaren lerrokatzea. Orriaren tamainarekin bateragarria den modua erabilita exekutatuko da aplikazioa. Emaitza onenak lortzeko, konpilatu aplikazioa berriro 16 KBko bertsioarekin bateragarria izan dadin. Informazio gehiago lortzeko, joan hona: <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>."</string> - <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"Aplikazio hau ez da bateragarria 16 KBko bertsioarekin. Ezin izan da egiaztatu APK eta ELF arteko lerrokatzea. Orriaren tamainarekin bateragarria den modua erabilita exekutatuko da aplikazioa. Emaitza onenak lortzeko, konpilatu aplikazioa berriro 16 KBko bertsioarekin bateragarria izan dadin. Informazio gehiago lortzeko, joan hona: <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>."</string> + <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"Aplikazio hau ez da bateragarria 16 KB-ko bertsioarekin. Ezin izan da egiaztatu APK eta ELF arteko lerrokatzea. Orriaren tamainarekin bateragarria den modua erabilita exekutatuko da aplikazioa. Emaitza onenak lortzeko, konpilatu aplikazioa berriro 16 KB-ko bertsioarekin bateragarria izan dadin. Informazio gehiago lortzeko, joan hona: <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>."</string> <string name="serviceNotProvisioned" msgid="8289333510236766193">"Zerbitzua ez da hornitu."</string> <string name="CLIRPermanent" msgid="166443681876381118">"Ezin duzu aldatu deitzailearen identitatearen ezarpena."</string> <string name="auto_data_switch_title" msgid="3286350716870518297">"<xliff:g id="CARRIERDISPLAY">%s</xliff:g> operadorearen datu-konexiora aldatu zara"</string> @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Ezin da konektatu sare mugikorrera"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Aldatu sare hobetsia. Sakatu aldatzeko."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Ezin da egin larrialdi-deirik"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Sare mugikorrera konektatuta egon behar duzu larrialdi-deiak egin ahal izateko"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Alertak"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Dei-desbideratzea"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Esku bakarreko modua"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Are ilunago"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Entzumen-gailuak"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Bolumen-botoiak sakatuta eduki direnez, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> aktibatu egin da."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Bolumen-botoiak sakatuta eduki direnez, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desaktibatu egin da."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Askatu bolumen-botoiak. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> aktibatzeko, eduki sakatuta berriro bi bolumen-botoiak hiru segundoz."</string> diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index 954f6ba6ae1b..d8fdff631b7d 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"شبکه تلفن همراه دردسترس نیست"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"تغییر شبکه ترجیحی را امتحان کنید. برای تغییر، تکضرب بزنید."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"تماس اضطراری امکانپذیر نیست"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"برای برقراری تماس اضطراری به شبکه تلفن همراه نیاز دارید"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"هشدارها"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"بازارسال تماس"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"حالت یکدستی"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"بسیار کمنور"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"دستگاههای کمکشنوایی"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"کلیدهای میزان صدا پایین نگه داشته شد. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> روشن شد."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"کلیدهای میزان صدا پایین نگه داشته شد. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> خاموش شد."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"کلیدهای میزان صدا را رها کنید. برای روشن کردن <xliff:g id="SERVICE_NAME">%1$s</xliff:g>، هر دو کلید میزان صدا را مجدداً بهمدت ۳ ثانیه فشار دهید و نگه دارید."</string> diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml index 96609c99cd48..9f88732cd7b4 100644 --- a/core/res/res/values-fi/strings.xml +++ b/core/res/res/values-fi/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Mobiiliverkkoon ei saada yhteyttä"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Kokeile vaihtaa ensisijaista verkkoa. Vaihda se napauttamalla."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Hätäpuhelut eivät ole käytettävissä"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Hätäpuhelu edellyttää mobiiliverkkoa"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Ilmoitukset"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Soitonsiirto"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Yhden käden moodi"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Erittäin himmeä"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Kuulolaitteet"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Äänenvoimakkuuspainikkeita painettiin pitkään. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> laitettiin päälle."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Äänenvoimakkuuspainikkeita painettiin pitkään. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> laitettiin pois päältä."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Vapauta äänenvoimakkuuspainikkeet. Laita <xliff:g id="SERVICE_NAME">%1$s</xliff:g> päälle painamalla äänenvoimakkuuspainikkeita uudelleen kolmen sekunnin ajan."</string> diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml index 50a769626808..c535bc078b4d 100644 --- a/core/res/res/values-fr-rCA/strings.xml +++ b/core/res/res/values-fr-rCA/strings.xml @@ -88,6 +88,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Impossible de joindre le réseau cellulaire"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Essayez de changer de réseau préféré. Touchez l\'écran pour changer."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Le service d\'appel d\'urgence n\'est pas accessible"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Les appels d\'urgence nécessitent un réseau cellulaire"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Alertes"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Transfert d\'appel"</string> @@ -1779,6 +1781,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Mode Une main"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Très sombre"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Appareils auditifs"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Touches de volume maintenues enfoncées. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> activé."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Touches de volume maintenues enfoncées. Service <xliff:g id="SERVICE_NAME">%1$s</xliff:g> désactivé."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Relâchez les touches de volume. Pour activer <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, maintenez les deux touches de volume enfoncées pendant 3 secondes."</string> diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index a72444d2bbd7..aa45f91f0975 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -73,8 +73,8 @@ <string name="CLIRDefaultOffNextCallOn" msgid="1022781126694885017">"Par défaut, les numéros des appelants ne sont pas restreints. Appel suivant : restreint"</string> <string name="CLIRDefaultOffNextCallOff" msgid="2491576172356463443">"Par défaut, les numéros des appelants ne sont pas restreints. Appel suivant : non restreint"</string> <string name="page_size_compat_apk_warning" msgid="2982396798449041224">"Cette appli n\'est pas compatible avec les pages de 16 ko. Échec de la vérification de l\'alignement de l\'APK. Cette appli sera exécutée dans un mode compatible avec la taille de la page. Pour une compatibilité optimale, veuillez recompiler l\'application de manière à ce que la taille de 16 ko soit prise en charge. Pour en savoir plus, consultez <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> - <string name="page_size_compat_elf_warning" msgid="6753874059564812651">"Cette appli n\'est pas compatible avec les pages de 16 ko. Échec de la vérification de l\'alignement de l\'ELF. Cette appli sera exécutée dans un mode compatible avec la taille de la page. Pour une compatibilité optimale, veuillez recompiler l\'application de manière à ce que la taille de 16 ko soit prise en charge. Pour en savoir plus, consultez <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> - <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"Cette appli n\'est pas compatible avec les pages de 16 ko. Échec des vérifications de l\'alignement de l\'APK et de l\'ELF. Cette appli sera exécutée dans un mode compatible avec la taille de la page. Pour une compatibilité optimale, veuillez recompiler l\'application de manière à ce que la taille de 16 ko soit prise en charge. Pour en savoir plus, consultez <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> + <string name="page_size_compat_elf_warning" msgid="6753874059564812651">"Cette appli n\'est pas compatible avec les pages de 16 ko. Échec de la vérification de l\'alignement de l\'ELF. Cette appli sera exécutée dans un mode compatible avec la taille de la page. Pour une compatibilité optimale, veuillez recompiler l\'application afin de prendre en charge les pages de 16 ko. Pour en savoir plus, consultez <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> + <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"Cette appli n\'est pas compatible avec les pages de 16 ko. Échec des vérifications de l\'alignement de l\'APK et de l\'ELF. Cette appli sera exécutée dans un mode compatible avec la taille de la page. Pour une compatibilité optimale, veuillez recompiler l\'application afin de prendre en charge les pages de 16 ko. Pour en savoir plus, consultez <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> <string name="serviceNotProvisioned" msgid="8289333510236766193">"Ce service n\'est pas pris en charge."</string> <string name="CLIRPermanent" msgid="166443681876381118">"Impossible de modifier le paramètre relatif au numéro de l\'appelant."</string> <string name="auto_data_switch_title" msgid="3286350716870518297">"Données transférées vers <xliff:g id="CARRIERDISPLAY">%s</xliff:g>"</string> @@ -88,6 +88,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Impossible d\'accéder au réseau mobile"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Essayez de changer le réseau préféré. Appuyez pour le modifier."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Appels d\'urgence non disponibles"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Les appels d\'urgence requièrent un réseau mobile"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Alertes"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Transfert d\'appel"</string> @@ -1779,6 +1781,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Mode une main"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Luminosité ultra-réduite"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Appareils auditifs"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Touches de volume appuyées de manière prolongée. Service <xliff:g id="SERVICE_NAME">%1$s</xliff:g> activé."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Touches de volume appuyées de manière prolongée. Service <xliff:g id="SERVICE_NAME">%1$s</xliff:g> désactivé."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Relâchez les boutons de volume. Pour activer <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, appuyez de nouveau sur les deux boutons de volume pendant trois secondes."</string> diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml index 27454b9319ec..a1016b688282 100644 --- a/core/res/res/values-gl/strings.xml +++ b/core/res/res/values-gl/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Non se puido conectar coa rede de telefonía móbil"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Proba a cambiar a rede preferida. Toca para cambiar."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"As chamadas de emerxencia non están dispoñibles"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"As chamadas de emerxencia precisan unha rede de telefonía móbil"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Alertas"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Desvío de chamadas"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modo dunha soa man"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Atenuación extra"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Dispositivos auditivos"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Teclas de volume premidas. Activouse o servizo <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Teclas de volume premidas. Desactivouse <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Solta as teclas de volume. Para activar <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, mantenas premidas de novo durante 3 segundos."</string> diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml index 4e4c9ffe1235..046939b3bf3c 100644 --- a/core/res/res/values-gu/strings.xml +++ b/core/res/res/values-gu/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"મોબાઇલ નેટવર્ક સુધી પહોંચી શકાતું નથી"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"પસંદગીનું નેટવર્ક બદલવાનો પ્રયાસ કરો. બદલવા માટે ટૅપ કરો."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"કટોકટીની કૉલિંગ સેવા અનુપલબ્ધ"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"ઇમર્જન્સી કૉલ માટે મોબાઇલ નેટવર્કની આવશ્યકતા છે"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"અલર્ટ"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"કૉલ ફૉર્વર્ડિંગ"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"એક-હાથે વાપરો મોડ"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"એક્સ્ટ્રા ડિમ"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"સાંભળવામાં સહાય કરતા ડિવાઇસ"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"વૉલ્યૂમ કી દબાવી રાખો. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ચાલુ કરી."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"વૉલ્યૂમ કી દબાવી રાખો. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> બંધ કરી."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"વૉલ્યૂમ કી છોડી દો. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>ને ચાલુ કરવા માટે, 3 સેકન્ડ માટે બન્ને વૉલ્યૂમ કીને ફરીથી દબાવી રાખો."</string> diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml index 624d7a507c05..7717d0276916 100644 --- a/core/res/res/values-hi/strings.xml +++ b/core/res/res/values-hi/strings.xml @@ -72,8 +72,8 @@ <string name="CLIRDefaultOffNextCallOn" msgid="1022781126694885017">"कॉलर आईडी डिफ़ॉल्ट रूप से सीमित नहीं है. अगली कॉल: सीमित"</string> <string name="CLIRDefaultOffNextCallOff" msgid="2491576172356463443">"कॉलर आईडी डिफ़ॉल्ट रूप से सीमित नहीं है. अगली कॉल: सीमित नहीं"</string> <string name="page_size_compat_apk_warning" msgid="2982396798449041224">"यह ऐप्लिकेशन 16 केबी वाले पेजों के साथ काम नहीं करता. APK के अलाइनमेंट की जांच नहीं की जा सकी. यह ऐप्लिकेशन, पेज साइज़ के साथ काम करने वाले मोड का इस्तेमाल करके चलेगा. पेज साइज़ के साथ बेहतर तरीके से काम के लिए, कृपया 16 केबी वाले पेजों के साथ ऐप्लिकेशन को फिर से कंपाइल करें. ज़्यादा जानकारी के लिए, <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a> पर जाएं"</string> - <string name="page_size_compat_elf_warning" msgid="6753874059564812651">"यह ऐप्लिकेशन 16 केबी वाले पेजों के साथ काम नहीं करता. ईएलएफ़ अलाइनमेंट की जांच नहीं की जा सकी. यह ऐप्लिकेशन, पेज साइज़ के साथ काम करने वाले मोड का इस्तेमाल करके चलेगा. पेज साइज़ के साथ बेहतर तरीके से काम के लिए, कृपया 16 केबी वाले पेजों के साथ ऐप्लिकेशन को फिर से कंपाइल करें. ज़्यादा जानकारी के लिए, <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a> पर जाएं"</string> - <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"यह ऐप्लिकेशन 16 केबी वाले पेजों के साथ काम नहीं करता. APK और ईएलएफ़ के अलाइनमेंट की जांच नहीं की जा सकी. यह ऐप्लिकेशन, पेज साइज़ के साथ काम करने वाले मोड का इस्तेमाल करके चलेगा. पेज साइज़ के साथ बेहतर तरीके से काम के लिए, कृपया 16 केबी वाले पेजों के साथ ऐप्लिकेशन को फिर से कंपाइल करें. ज़्यादा जानकारी के लिए, <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a> पर जाएं"</string> + <string name="page_size_compat_elf_warning" msgid="6753874059564812651">"यह ऐप्लिकेशन 16 केबी वाले पेज साइज़ के साथ काम नहीं करता. इसके लिए ज़रूरी ईएलएफ़ अलाइनमेंट की जांच भी पूरी नहीं हो सकी. यह ऐप्लिकेशन, इस पेज साइज़ के साथ काम करने वाले मोड का इस्तेमाल करके चलेगा. इस पेज साइज़ के साथ बेहतर तरीके से काम के लिए, कृपया ऐप्लिकेशन को 16 केबी वाले पेज साइज़ के साथ फिर से कंपाइल करें. ज़्यादा जानकारी के लिए, <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a> पर जाएं"</string> + <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"यह ऐप्लिकेशन 16 केबी वाले पेज साइज़ के साथ काम नहीं करता. APK और ईएलएफ़ के अलाइनमेंट से जुड़ी ज़रूरी जांच भी पूरी नहीं हो सकी. यह ऐप्लिकेशन, इस पेज साइज़ के साथ काम करने वाले मोड का इस्तेमाल करके चलेगा. इस पेज साइज़ के साथ बेहतर तरीके से काम के लिए, कृपया ऐप्लिकेशन को 16 केबी वाले पेज साइज़ के साथ फिर से कंपाइल करें. ज़्यादा जानकारी के लिए, <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a> पर जाएं"</string> <string name="serviceNotProvisioned" msgid="8289333510236766193">"सेवा प्रावधान की हुई नहीं है."</string> <string name="CLIRPermanent" msgid="166443681876381118">"आप कॉलर आईडी सेटिंग नहीं बदल सकते."</string> <string name="auto_data_switch_title" msgid="3286350716870518297">"डेटा को <xliff:g id="CARRIERDISPLAY">%s</xliff:g> पर स्विच किया गया"</string> @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"मोबाइल नेटवर्क से कनेक्ट नहीं किया जा सका"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"पसंदीदा नेटवर्क बदलकर देखें. बदलने के लिए टैप करें."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"आपातकालीन कॉल करने की सुविधा उपलब्ध नहीं है"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"आपातकालीन कॉल के लिए मोबाइल नेटवर्क ज़रूरी है"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"सूचनाएं"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"कॉल को दूसरे नंबर पर भेजना"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"वन-हैंडेड मोड"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"स्क्रीन की रोशनी को सामान्य लेवल से और कम करने की सुविधा"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"कान की मशीन"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"आवाज़ कम-ज़्यादा करने वाले दोनों बटन दबाकर रखें. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> को चालू कर दिया गया."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"आवाज़ कम-ज़्यादा करने वाले दोनों बटन दबाकर रखें. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> को बंद कर दिया गया."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"आवाज़ बटन को छोड़ें. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> की सुविधा चालू करने के लिए, आवाज़ वाले दोनों बटन तीन सेकंड तक दबाकर रखें."</string> diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml index 3429c140e70a..118b53928b61 100644 --- a/core/res/res/values-hr/strings.xml +++ b/core/res/res/values-hr/strings.xml @@ -72,9 +72,9 @@ <string name="CLIRDefaultOnNextCallOff" msgid="5036749051007098105">"Zadana postavka ID-a pozivatelja ima ograničenje. Sljedeći poziv: Nije ograničen"</string> <string name="CLIRDefaultOffNextCallOn" msgid="1022781126694885017">"Zadana postavka ID-a pozivatelja nema ograničenje. Sljedeći poziv: Ograničen"</string> <string name="CLIRDefaultOffNextCallOff" msgid="2491576172356463443">"Zadana postavka ID-a pozivatelja nema ograničenje. Sljedeći poziv: Nije ograničen"</string> - <string name="page_size_compat_apk_warning" msgid="2982396798449041224">"Ova aplikacija nije kompatibilna s veličinom stranice od 16 KB. Provjera poravnanja APK-a nije uspjela. Ova će se aplikacija pokrenuti pomoću načina kompatibilnog s veličinom stranice. Za najbolju kompatibilnost ponovo kompilirajte aplikaciju s podrškom od 16 KB. Više informacija potražite na stranici <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> - <string name="page_size_compat_elf_warning" msgid="6753874059564812651">"Ova aplikacija nije kompatibilna s veličinom stranice od 16 KB. Provjera poravnanja ELF-a nije uspjela. Ova će se aplikacija pokrenuti pomoću načina kompatibilnog s veličinom stranice. Za najbolju kompatibilnost ponovo kompilirajte aplikaciju s podrškom od 16 KB. Više informacija potražite na stranici <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> - <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"Ova aplikacija nije kompatibilna s veličinom stranice od 16 KB. Provjere poravnanja APK-a i ELF-a nisu uspjele. Ova će se aplikacija pokrenuti pomoću načina kompatibilnog s veličinom stranice. Za najbolju kompatibilnost ponovo kompilirajte aplikaciju s podrškom od 16 KB. Više informacija potražite na stranici <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> + <string name="page_size_compat_apk_warning" msgid="2982396798449041224">"Ova aplikacija nije kompatibilna sa 16 KB stranicama. Provjera usklađenosti APK-a nije uspjela. Aplikacija će se pokrenuti u načinu kompatibilnom s formatom stranice. Da biste postigli kompatibilnost, ponovo kompilirajte aplikaciju s podrškom za 16 KB stranice. Više informacija potražite na stranici <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> + <string name="page_size_compat_elf_warning" msgid="6753874059564812651">"Ova aplikacija nije kompatibilna sa 16 KB stranicama. Provjera usklađenosti ELF-a nije uspjela. Aplikacija će se pokrenuti u načinu kompatibilnom s formatom stranice. Da biste postigli kompatibilnost, ponovo kompilirajte aplikaciju s podrškom za 16 KB stranice. Više informacija potražite na stranici <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> + <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"Ova aplikacija nije kompatibilna sa 16 KB stranicama. Provjere usklađenosti APK-a i ELF-a nisu uspjele. Aplikacija će se pokrenuti u načinu kompatibilnom s formatom stranice. Da biste postigli kompatibilnost, ponovo kompilirajte aplikaciju s podrškom za 16 KB stranice. Više informacija potražite na stranici <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> <string name="serviceNotProvisioned" msgid="8289333510236766193">"Usluga nije rezervirana."</string> <string name="CLIRPermanent" msgid="166443681876381118">"Ne možete promijeniti postavku ID-a pozivatelja."</string> <string name="auto_data_switch_title" msgid="3286350716870518297">"Podaci su prebačeni na <xliff:g id="CARRIERDISPLAY">%s</xliff:g>"</string> @@ -88,6 +88,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Mobilna mreža nije dostupna"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Pokušajte promijeniti preferiranu mrežu. Dodirnite da biste je promijenili."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Hitni pozivi nisu dostupni"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Za hitne pozive potrebna je mobilna mreža"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Upozorenja"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Preusmjeravanje poziva"</string> @@ -1779,6 +1781,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Način rada jednom rukom"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Još tamnije"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Slušna pomagala"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Držali ste tipke za glasnoću. Uključila se usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Držali ste tipke za glasnoću. Isključila se usluga <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Pustite tipke za glasnoću. Da biste uključili uslugu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, ponovo pritisnite i zadržite obje tipke za glasnoću tri sekunde."</string> diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml index 2d46a3cb2929..09f162eba32e 100644 --- a/core/res/res/values-hu/strings.xml +++ b/core/res/res/values-hu/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"A mobilhálózat nem érhető el"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Próbálja meg módosítani a preferált hálózatot. Koppintson a módosításhoz."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Segélyhívás nem lehetséges"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"A segélyhíváshoz mobilhálózatra van szükség"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Értesítések"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Hívásátirányítás"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Egykezes mód"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Extrasötét"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Hallásjavító eszközök"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Nyomva tartotta a hangerőgombokat. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> bekapcsolva."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Nyomva tartotta a hangerőgombokat. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> kikapcsolva."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Engedje fel a hangerőszabályzó gombokat. A(z) <xliff:g id="SERVICE_NAME">%1$s</xliff:g> bekapcsolásához tartsa újra lenyomva a hangerőszabályzó gombokat három másodpercig."</string> diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml index 82d141f26af9..7a821a695edc 100644 --- a/core/res/res/values-hy/strings.xml +++ b/core/res/res/values-hy/strings.xml @@ -71,9 +71,9 @@ <string name="CLIRDefaultOnNextCallOff" msgid="5036749051007098105">"Զանգողի ID-ն լռելյայն սահմանափակված է: Հաջորդ զանգը` չսահմանափակված"</string> <string name="CLIRDefaultOffNextCallOn" msgid="1022781126694885017">"Զանգողի ID-ն լռելյայն չսահմանափակված է: Հաջորդ զանգը` Սահմանափակված"</string> <string name="CLIRDefaultOffNextCallOff" msgid="2491576172356463443">"Զանգողի ID-ն լռելյայն չսահմանափակված է: Հաջորդ զանգը` չսահմանափակված"</string> - <string name="page_size_compat_apk_warning" msgid="2982396798449041224">"Այս հավելվածը հարմարեցված չէ 16 ԿԲ չափի համար։ APK-ի հետ համատեղելիությունը ձախողվել է։ Այս հավելվածը կաշխատի էջի չափի հետ համատեղելի ռեժիմում։ Համատեղելիությունն ապահովելու համար նորից կոմպիլացրեք հավելվածը 16 ԿԲ չափն աջակցելու համար։ Լրացուցիչ տեղեկություններ ստանալու համար այցելեք <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> - <string name="page_size_compat_elf_warning" msgid="6753874059564812651">"Այս հավելվածը հարմարեցված չէ 16 ԿԲ չափի համար։ ELF-ի հետ համատեղելիությունը ձախողվել է։ Այս հավելվածը կաշխատի էջի չափի հետ համատեղելի ռեժիմում։ Համատեղելիությունն ապահովելու համար նորից կոմպիլացրեք հավելվածը 16 ԿԲ չափն աջակցելու համար։ Լրացուցիչ տեղեկություններ ստանալու համար այցելեք <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> - <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"Այս հավելվածը հարմարեցված չէ 16 ԿԲ չափի համար։ APK-ի և ELF-ի հետ համատեղելիության ստուգումը ձախողվել է։ Այս հավելվածը կաշխատի էջի չափի հետ համատեղելի ռեժիմում։ Համատեղելիությունն ապահովելու համար նորից կոմպիլացրեք հավելվածը 16 ԿԲ չափն աջակցելու համար։ Լրացուցիչ տեղեկություններ ստանալու համար այցելեք <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> + <string name="page_size_compat_apk_warning" msgid="2982396798449041224">"Այս հավելվածը հարմարեցված չէ 16 ԿԲ ծավալի համար։ APK-ի հետ համատեղելիության ստուգումը ձախողվել է։ Այս հավելվածը կաշխատի էջի ծավալի հետ համատեղելի ռեժիմում։ Համատեղելիությունն ապահովելու համար նորից կոմպիլացրեք հավելվածը 16 ԿԲ ծավալն աջակցելու համար։ Լրացուցիչ տեղեկություններ ստանալու համար այցելեք <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> + <string name="page_size_compat_elf_warning" msgid="6753874059564812651">"Այս հավելվածը հարմարեցված չէ 16 ԿԲ ծավալի համար։ ELF-ի հետ համատեղելիության ստուգումը ձախողվել է։ Այս հավելվածը կաշխատի էջի ծավալի հետ համատեղելի ռեժիմում։ Համատեղելիությունն ապահովելու համար նորից կոմպիլացրեք հավելվածը 16 ԿԲ ծավալն աջակցելու համար։ Լրացուցիչ տեղեկություններ ստանալու համար այցելեք <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> + <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"Այս հավելվածը հարմարեցված չէ 16 ԿԲ ծավալի համար։ APK-ի և ELF-ի հետ համատեղելիության ստուգումը ձախողվել է։ Այս հավելվածը կաշխատի էջի ծավալի հետ համատեղելի ռեժիմում։ Համատեղելիությունն ապահովելու համար նորից կոմպիլացրեք հավելվածը 16 ԿԲ ծավալն աջակցելու համար։ Լրացուցիչ տեղեկություններ ստանալու համար այցելեք <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> <string name="serviceNotProvisioned" msgid="8289333510236766193">"Ծառայությունը չի տրամադրվում:"</string> <string name="CLIRPermanent" msgid="166443681876381118">"Դուք չեք կարող փոխել զանգողի ID-ի կարգավորումները:"</string> <string name="auto_data_switch_title" msgid="3286350716870518297">"Օգտագործվում է <xliff:g id="CARRIERDISPLAY">%s</xliff:g>-ի բջջային ինտերնետը"</string> @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Չհաջողվեց միանալ բջջային ցանցին"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Փորձեք այլ ցանցի միանալ: Հպեք՝ նախընտրած ցանցը փոխելու համար:"</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Շտապ կանչերը հասանելի չեն"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Շտապ կանչերի համար բջջային ցանց է անհրաժեշտ"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Ծանուցումներ"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Զանգի վերահասցեավորում"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Մեկ ձեռքի ռեժիմ"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Հավելյալ խամրեցում"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Լսողական սարքեր"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Ձայնի կարգավորման կոճակները սեղմվեցին։ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ծառայությունը միացավ։"</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Ձայնի կարգավորման կոճակները սեղմվեցին։ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ծառայությունն անջատվեց։"</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Բաց թողեք ձայնի ուժգնության կոճակները։ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ծառայությունը միացնելու համար սեղմեք և 3 վայրկյան պահեք ձայնի ուժգնության երկու կոճակը։"</string> diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml index 63bc9cf223af..3c0deb7c62ce 100644 --- a/core/res/res/values-in/strings.xml +++ b/core/res/res/values-in/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Tidak dapat menjangkau jaringan seluler"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Coba ubah jaringan pilihan. Ketuk untuk mengubah."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Panggilan darurat tidak tersedia"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Panggilan darurat memerlukan jaringan seluler"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Notifikasi"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Penerusan panggilan"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Mode satu tangan"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Ekstra redup"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Alat bantu dengar"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tombol volume ditahan. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> diaktifkan."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tombol volume ditahan. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> dinonaktifkan."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Lepaskan tombol volume. Untuk mengaktifkan <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, tekan kedua tombol volume lagi selama 3 detik."</string> diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml index 1b4309908629..6a3519134688 100644 --- a/core/res/res/values-is/strings.xml +++ b/core/res/res/values-is/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Ekki næst samband við farsímakerfi"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Prófaðu að velja annað símkerfi. Ýttu til að breyta."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Neyðarsímtöl eru ekki í boði"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Neyðarsímtöl krefjast farsímakerfis"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Tilkynningar"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Símtalsflutningur"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Einhent stilling"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Mjög dökkt"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Heyrnartæki"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Hljóðstyrkstökkum haldið inni. Kveikt á <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Hljóðstyrkstökkum haldið inni. Slökkt á <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Slepptu hljóðstyrkstökkunum. Til að kveikja á <xliff:g id="SERVICE_NAME">%1$s</xliff:g> skaltu halda báðum hljóðstyrkstökkunum aftur inni í 3 sekúndur."</string> diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index 9fd7913c934c..db402c50205b 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -72,9 +72,9 @@ <string name="CLIRDefaultOnNextCallOff" msgid="5036749051007098105">"ID chiamante generalmente limitato. Prossima chiamata: non limitato"</string> <string name="CLIRDefaultOffNextCallOn" msgid="1022781126694885017">"ID chiamante generalmente non limitato. Prossima chiamata: limitato"</string> <string name="CLIRDefaultOffNextCallOff" msgid="2491576172356463443">"ID chiamante generalmente non limitato. Prossima chiamata: non limitato"</string> - <string name="page_size_compat_apk_warning" msgid="2982396798449041224">"Questa app non è compatibile con 16 kB. Controllo allineamento APK non riuscito. Questa app verrà eseguita utilizzando la modalità compatibile con le dimensioni della pagina. Per la massima compatibilità, ricompila l\'applicazione con il supporto a 16 kB. Per maggiori dettagli, consulta <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> - <string name="page_size_compat_elf_warning" msgid="6753874059564812651">"Questa app non è compatibile con 16 kB. Controllo allineamento ELF non riuscito. Questa app verrà eseguita utilizzando la modalità compatibile con le dimensioni della pagina. Per la massima compatibilità, ricompila l\'applicazione con il supporto a 16 kB. Per maggiori dettagli, consulta <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> - <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"Questa app non è compatibile con 16 kB. Controlli di allineamento APK ed ELF non riusciti. Questa app verrà eseguita utilizzando la modalità compatibile con le dimensioni della pagina. Per la massima compatibilità, ricompila l\'applicazione con il supporto a 16 kB. Per maggiori dettagli, consulta <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> + <string name="page_size_compat_apk_warning" msgid="2982396798449041224">"Questa app non è compatibile con le pagine di 16 kB. Controllo allineamento APK non riuscito. Questa app verrà eseguita utilizzando la modalità compatibile con le dimensioni della pagina. Per la massima compatibilità, ricompila l\'applicazione con il supporto a 16 kB. Per maggiori dettagli, consulta <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> + <string name="page_size_compat_elf_warning" msgid="6753874059564812651">"Questa app non è compatibile con le pagine di 16 kB. Controllo allineamento ELF non riuscito. Questa app verrà eseguita utilizzando la modalità compatibile con le dimensioni della pagina. Per la massima compatibilità, ricompila l\'applicazione con il supporto a 16 kB. Per maggiori dettagli, consulta <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> + <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"Questa app non è compatibile con le pagine di 16 kB. Controlli di allineamento APK ed ELF non riusciti. Questa app verrà eseguita utilizzando la modalità compatibile con le dimensioni della pagina. Per la massima compatibilità, ricompila l\'applicazione con il supporto a 16 kB. Per maggiori dettagli, consulta <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> <string name="serviceNotProvisioned" msgid="8289333510236766193">"Servizio non fornito."</string> <string name="CLIRPermanent" msgid="166443681876381118">"Non è possibile modificare l\'impostazione ID chiamante."</string> <string name="auto_data_switch_title" msgid="3286350716870518297">"I dati sono stati trasferiti a <xliff:g id="CARRIERDISPLAY">%s</xliff:g>"</string> @@ -88,6 +88,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Impossibile raggiungere la rete mobile"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Prova a cambiare la rete preferita. Tocca per cambiare."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Chiamate di emergenza non disponibili"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Per le chiamate di emergenza è necessaria una rete mobile"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Avvisi"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Deviazione chiamate"</string> @@ -1779,6 +1781,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modalità a una mano"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Attenuazione extra"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Protesi uditive"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tieni premuti i tasti del volume. Servizio <xliff:g id="SERVICE_NAME">%1$s</xliff:g> attivato."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tieni premuti i tasti del volume. Servizio <xliff:g id="SERVICE_NAME">%1$s</xliff:g> disattivato."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Rilascia i tasti del volume. Per attivare <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, tieni di nuovo premuti entrambi i tasti del volume per 3 secondi."</string> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index 3a5c63c8b7e7..503eb9747c96 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -72,9 +72,9 @@ <string name="CLIRDefaultOnNextCallOff" msgid="5036749051007098105">"שירות השיחה המזוהה עובר כברירת מחדל למצב מוגבל. השיחה הבאה: לא מוגבלת"</string> <string name="CLIRDefaultOffNextCallOn" msgid="1022781126694885017">"שירות \'שיחה מזוהה\' עובר כברירת מחדל למצב לא מוגבל. השיחה הבאה: מוגבלת"</string> <string name="CLIRDefaultOffNextCallOff" msgid="2491576172356463443">"זיהוי מתקשר עובר כברירת מחדל למצב לא מוגבל. השיחה הבאה: לא מוגבלת"</string> - <string name="page_size_compat_apk_warning" msgid="2982396798449041224">"האפליקציה הזו לא תואמת לדפים בגודל 16KB. בדיקות ההתאמה ל-APK נכשלה. האפליקציה הזו תופעל במצב תואם לגודל הדף. כדי לקבל את התאימות הטובה ביותר, צריך להדר מחדש (recompile) את האפליקציה לתמיכה בדפים בגודל 16KB. מידע נוסף זמין בכתובת <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> - <string name="page_size_compat_elf_warning" msgid="6753874059564812651">"האפליקציה הזו לא תואמת לדפים בגודל 16KB. בדיקות ההתאמה ל-ELF נכשלה. האפליקציה הזו תופעל במצב תואם לגודל הדף. כדי לקבל את התאימות הטובה ביותר, צריך להדר מחדש (recompile) את האפליקציה לתמיכה בדפים בגודל 16KB. מידע נוסף זמין בכתובת <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> - <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"האפליקציה הזו לא תואמת לדפים בגודל 16KB. בדיקות ההתאמה ל-APK ול-ELF נכשלו. האפליקציה הזו תופעל במצב תואם לגודל הדף. כדי לקבל את התאימות הטובה ביותר, צריך להדר מחדש (recompile) את האפליקציה לתמיכה בדפים בגודל 16KB. מידע נוסף זמין בכתובת <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> + <string name="page_size_compat_apk_warning" msgid="2982396798449041224">"האפליקציה הזו לא תואמת לגודל דף של 16KB. בדיקות ההתאמה ל-APK נכשלה. האפליקציה הזו תופעל במצב תואם לגודל הדף. כדי לקבל את התאימות הטובה ביותר, צריך לקמפל את האפליקציה מחדש ולדאוג שהיא תומכת בגודל דף של 16KB. מידע נוסף זמין בכתובת <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> + <string name="page_size_compat_elf_warning" msgid="6753874059564812651">"האפליקציה הזו לא תואמת לגודל דף של 16KB. בדיקות ההתאמה ל-ELF נכשלה. האפליקציה הזו תופעל במצב תואם לגודל הדף. כדי לקבל את התאימות הטובה ביותר, צריך לקמפל את האפליקציה מחדש ולדאוג שהיא תומכת בגודל דף של 16KB. מידע נוסף זמין בכתובת <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> + <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"האפליקציה הזו לא תואמת לגודל דף של 16KB. בדיקות ההתאמה ל-APK ול-ELF נכשלו. האפליקציה הזו תופעל במצב תואם לגודל הדף. כדי לקבל את התאימות הטובה ביותר, צריך לקמפל את האפליקציה מחדש ולדאוג שהיא תומכת בגודל דף של 16KB. מידע נוסף זמין בכתובת <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> <string name="serviceNotProvisioned" msgid="8289333510236766193">"השירות לא הוקצה."</string> <string name="CLIRPermanent" msgid="166443681876381118">"אינך יכול לשנות את הגדרת זיהוי המתקשר."</string> <string name="auto_data_switch_title" msgid="3286350716870518297">"הנתונים עברו אל <xliff:g id="CARRIERDISPLAY">%s</xliff:g>"</string> @@ -88,6 +88,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"לא ניתן להתחבר לרשת הסלולרית"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"אפשר לנסות לשנות את הרשת המועדפת. יש להקיש כדי לשנות אותה."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"שיחות חירום לא זמינות"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"כדי לבצע שיחות חירום, צריך להתחבר לרשת סלולרית"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"התראות"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"העברת שיחות"</string> @@ -1779,6 +1781,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"מצב שימוש ביד אחת"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"מעומעם במיוחד"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"מכשירי שמיעה"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"לחצני עוצמת הקול נלחצו בלחיצה ארוכה. שירות <xliff:g id="SERVICE_NAME">%1$s</xliff:g> הופעל."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"לחצני עוצמת הקול נלחצו בלחיצה ארוכה. שירות <xliff:g id="SERVICE_NAME">%1$s</xliff:g> הושבת."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"אפשר לשחרר את מקש עוצמת הקול. כדי להפעיל את השירות <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, צריך ללחוץ לחיצה ארוכה על שני המקשים של עוצמת הקול שוב במשך 3 שניות."</string> diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index 3d7c91cdbcf2..05adb2b13e4d 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -73,7 +73,7 @@ <string name="CLIRDefaultOffNextCallOff" msgid="2491576172356463443">"既定: 発信者番号通知、次の発信: 通知"</string> <string name="page_size_compat_apk_warning" msgid="2982396798449041224">"このアプリは 16 KB アライメントではありません。APK のアライメント チェックが失敗しました。このアプリはページサイズ互換モードを使用して実行されます。最適な互換性を実現するには、16 KB をサポートするようにアプリケーションを再コンパイルしてください。詳しくは、<a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a> をご覧ください。"</string> <string name="page_size_compat_elf_warning" msgid="6753874059564812651">"このアプリは 16 KB アライメントではありません。ELF のアライメント チェックに失敗しました。このアプリはページサイズ互換モードを使用して実行されます。最適な互換性を実現するには、16 KB をサポートするようにアプリケーションを再コンパイルしてください。詳しくは、<a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a> をご覧ください。"</string> - <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"このアプリは 16 KB アライメントではありません。APK と ELF のアライメント チェックが失敗しました。このアプリはページサイズ互換モードを使用して実行されます。最適な互換性を実現するには、16 KB をサポートするようにアプリケーションを再コンパイルしてください。詳しくは、<a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a> をご覧ください。"</string> + <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"このアプリは 16 KB アライメントではありません。APK と ELF のアライメント チェックに失敗しました。このアプリはページサイズ互換モードを使用して実行されます。最適な互換性を実現するには、16 KB をサポートするようにアプリケーションを再コンパイルしてください。詳しくは、<a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a> をご覧ください。"</string> <string name="serviceNotProvisioned" msgid="8289333510236766193">"提供可能なサービスがありません。"</string> <string name="CLIRPermanent" msgid="166443681876381118">"発信者番号の設定は変更できません。"</string> <string name="auto_data_switch_title" msgid="3286350716870518297">"データが <xliff:g id="CARRIERDISPLAY">%s</xliff:g> に切り替わりました"</string> @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"モバイル ネットワークにアクセスできません"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"タップして、優先ネットワークを変更してください。"</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"緊急通報は利用できません"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"緊急通報にはモバイル ネットワークが必要です"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"通知"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"電話の転送"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"片手モード"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"さらに輝度を下げる"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"補聴器"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"音量ボタンを長押ししました。<xliff:g id="SERVICE_NAME">%1$s</xliff:g> が ON になりました。"</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"音量ボタンを長押ししました。<xliff:g id="SERVICE_NAME">%1$s</xliff:g> が OFF になりました。"</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"音量ボタンを離してください。<xliff:g id="SERVICE_NAME">%1$s</xliff:g> を有効にするには音量大と音量小の両方のボタンを 3 秒ほど長押ししてください。"</string> diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml index 10cb0c3b87eb..552f52e0c128 100644 --- a/core/res/res/values-ka/strings.xml +++ b/core/res/res/values-ka/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"მობილურ ქსელთან დაკავშირება ვერ ხერხდება"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"ცადეთ უპირატესი ქსელის შეცვლა. შეეხეთ შესაცვლელად."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"გადაუდებელი ზარი მიუწვდომელია"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"გადაუდებელი ზარები საჭიროებს მობილურ ქსელს"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"გაფრთხილებები"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"ზარის გადამისამართება"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"ცალი ხელის რეჟიმი"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"დამატებითი დაბინდვა"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"სმენის აპარატები"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ხანგრძლივად დააჭირეთ ხმის ღილაკებს. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ჩართულია."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ხანგრძლივად დააჭირეთ ხმის ღილაკებს. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> გამორთულია."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"ხელი აუშვით ხმის ღილაკებს. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>-ის ჩასართველად, ხელმეორედ ხანგრძლივად დააჭირეთ ორივე ხმის ღილაკს 3 წამის განმავლობაში."</string> diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml index 49b4bfc77b42..3c118ac715b5 100644 --- a/core/res/res/values-kk/strings.xml +++ b/core/res/res/values-kk/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Мобильдік желіге қосылу мүмкін емес"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Таңдаулы желіні өзгертіп көріңіз. Өзгерту үшін түртіңіз."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Жедел қызметке қоңырау шалу мүмкін емес"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Құтқару қызметіне қоңырау шалу үшін мобильдік желі қажет."</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Дабылдар"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Қоңырауды басқа нөмірге бағыттау"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Бір қолмен басқару режимі"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Экранды қарайту"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Есту аппараттары"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Пайдаланушы дыбыс деңгейі пернелерін басып ұстап тұрды. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> қосулы."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Дыбыс деңгейі пернелерін басып тұрған соң, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> өшірілді."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Дыбыс деңгейі пернелерін жіберіңіз. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> қызметін қосу үшін дыбыс деңгейі пернесінің екеуін де қайтадан 3 секундқа басып тұрыңыз."</string> diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml index 2db0fcd0999b..737fe883930c 100644 --- a/core/res/res/values-km/strings.xml +++ b/core/res/res/values-km/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"មិនអាចភ្ជាប់បណ្ដាញទូរសព្ទចល័តបានទេ"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"សាកល្បងប្ដូរទៅបណ្ដាញដែលចង់ប្រើ។ សូមចុចដើម្បីផ្លាស់ប្ដូរ។"</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"មិនអាចប្រើការហៅបន្ទាន់បានទេ"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"ការហៅទៅលេខសង្គ្រោះបន្ទាន់តម្រូវឱ្យមានបណ្ដាញទូរសព្ទចល័ត"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"ការជូនដំណឹង"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"ការបញ្ជូនការហៅទូរសព្ទបន្ត"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"មុខងារប្រើដៃម្ខាង"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ងងឹតខ្លាំង"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"ឧបករណ៍ជំនួយការស្ដាប់"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"បានសង្កត់គ្រាប់ចុចកម្រិតសំឡេងជាប់។ បានបើក <xliff:g id="SERVICE_NAME">%1$s</xliff:g>។"</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"បានសង្កត់គ្រាប់ចុចកម្រិតសំឡេងជាប់។ បានបិទ <xliff:g id="SERVICE_NAME">%1$s</xliff:g>។"</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"លែងគ្រាប់ចុចកម្រិតសំឡេង។ ដើម្បីបើក <xliff:g id="SERVICE_NAME">%1$s</xliff:g> សូមចុចគ្រាប់ចុចកម្រិតសំឡេងទាំងពីរឱ្យជាប់ម្ដងទៀតរយៈពេល 3 វិនាទី។"</string> diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml index ad62f42ef8dc..87a0bef2ceb6 100644 --- a/core/res/res/values-kn/strings.xml +++ b/core/res/res/values-kn/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"ಮೊಬೈಲ್ ನೆಟ್ವರ್ಕ್ ತಲುಪಲು ಸಾಧ್ಯವಿಲ್ಲ"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"ಆದ್ಯತೆಗೊಳಿಸಿದ ನೆಟ್ವರ್ಕ್ಗಳನ್ನು ಬದಲಾಯಿಸಲು ಪ್ರಯತ್ನಿಸಿ. ಬದಲಾಯಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"ತುರ್ತು ಕರೆ ಮಾಡುವಿಕೆ ಲಭ್ಯವಿಲ್ಲ"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"ತುರ್ತು ಕರೆಗಳಿಗೆ ಮೊಬೈಲ್ ನೆಟ್ವರ್ಕ್ನ ಅಗತ್ಯವಿದೆ"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"ಎಚ್ಚರಿಕೆಗಳು"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"ಕರೆ ಫಾರ್ವರ್ಡ್ ಮಾಡುವಿಕೆ"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"ಒಂದು ಕೈ ಮೋಡ್"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ಇನ್ನಷ್ಟು ಮಬ್ಬು"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"ಶ್ರವಣ ಸಾಧನಗಳು"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ವಾಲ್ಯೂಮ್ ಕೀಗಳನ್ನು ಹಿಡಿದುಕೊಳ್ಳಿ. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ಅನ್ನು ಆನ್ ಮಾಡಲಾಗಿದೆ."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ವಾಲ್ಯೂಮ್ ಕೀಗಳನ್ನು ಹಿಡಿದಿಟ್ಟುಕೊಳ್ಳಲಾಗಿದೆ. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, ಆಫ್ ಮಾಡಲಾಗಿದೆ."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"ವಾಲ್ಯೂಮ್ ಕೀಗಳನ್ನು ಬಿಡುಗಡೆ ಮಾಡಿ. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ಅನ್ನು ಆನ್ ಮಾಡಲು, ಎರಡೂ ವಾಲ್ಯೂಮ್ ಕೀಗಳನ್ನು ಮತ್ತೊಮ್ಮೆ 3 ಸೆಕೆಂಡ್ಗಳ ಕಾಲ ಒತ್ತಿ ಹಿಡಿದುಕೊಳ್ಳಿ."</string> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index 38e5bb573222..51921be8b6b4 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"모바일 네트워크에 연결할 수 없습니다."</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"기본 네트워크를 변경해 보세요. 탭하여 변경할 수 있습니다."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"긴급 전화를 사용할 수 없습니다."</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"긴급 전화를 걸려면 모바일 네트워크 연결이 필요함"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"알림"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"착신전환"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"한 손 모드"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"더 어둡게"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"청각 보조 기기"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"볼륨 키를 길게 눌렀습니다. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>이(가) 사용 설정되었습니다."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"볼륨 키를 길게 눌렀습니다. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>이(가) 사용 중지되었습니다."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"볼륨 키에서 손을 뗍니다. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>을 켜려면 볼륨 키 2개를 3초 동안 길게 누르세요."</string> diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml index 60e2749d9f45..7ca2092dddf0 100644 --- a/core/res/res/values-ky/strings.xml +++ b/core/res/res/values-ky/strings.xml @@ -73,7 +73,7 @@ <string name="CLIRDefaultOffNextCallOff" msgid="2491576172356463443">"Номурду аныктоонун демейки абалы \"чектелбейт\" деп коюлган. Кийинки чалуу: Чектелбейт"</string> <string name="page_size_compat_apk_warning" msgid="2982396798449041224">"Бул колдонмо 16 Кб өлчөмүнө туура келбейт. APK\'дин тегизделиши тейшерилбей калды. Колдонмо беттин өлчөмүнө туура келген режимде иштейт. Эң жакшы шайкештик үчүн колдонмону 16 Кб колдоосу менен кайра түзүңүз. Кеңири маалымат: <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> <string name="page_size_compat_elf_warning" msgid="6753874059564812651">"Бул колдонмо 16 Кб өлчөмүнө туура келбейт. ELF\'тин тегизделиши тейшерилбей калды. Колдонмо беттин өлчөмүнө туура келген режимде иштейт. Эң жакшы шайкештик үчүн колдонмону 16 Кб колдоосу менен кайра түзүңүз. Кеңири маалымат: <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> - <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"Бул колдонмо 16 Кб өлчөмүнө туура келбейт. APK менен ELF\'тин тегизделиши тейшерилбей калды. Колдонмо беттин өлчөмүнө туура келген режимде иштейт. Эң жакшы шайкештик үчүн колдонмону 16 Кб колдоосу менен кайра түзүңүз. Кеңири маалымат: <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> + <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"Бул колдонмо 16 Кб өлчөмүнө туура келбейт. APK менен ELF\'тин тегизделиши текшерилбей калды. Колдонмо беттин өлчөмүнө туура келген режимде иштейт. Эң жакшы шайкештик үчүн колдонмону 16 Кб колдоосу менен кайра түзүңүз. Кеңири маалымат: <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> <string name="serviceNotProvisioned" msgid="8289333510236766193">"Кызмат камсыздалган эмес."</string> <string name="CLIRPermanent" msgid="166443681876381118">"Чалуучунун далдаштырма дайындары параметрлерин өзгөртө албайсыз."</string> <string name="auto_data_switch_title" msgid="3286350716870518297">"Мобилдик Интернет <xliff:g id="CARRIERDISPLAY">%s</xliff:g> которулду"</string> @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Мобилдик тармакка туташпай жатат"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Тандалган тармакты өзгөртүп көрүңүз. Өзгөртүү үчүн таптаңыз."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Шашылыш чалуу жеткиликсиз"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Шашылыш чалуу үчүн мобилдик тармак талап кылынат"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Шашылыш билдирүүлөр"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Чалууну башка номерге багыттоо"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Бир кол режими"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Кошумча караңгылатуу"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Угуу түзмөктөрү"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Үндү катуулатуу/акырындатуу баскычтары басылып, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> күйгүзүлдү."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Үндү катуулатуу/акырындатуу баскычтары басылып, <xliff:g id="SERVICE_NAME">%1$s</xliff:g> өчүрүлдү."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Үн баскычтарын коё бериңиз. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> кызматын күйгүзүү үчүн үн баскычтарын кайра 3 секунд коё бербей басып туруңуз."</string> diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml index da2d1ad8ac86..32b0605b1128 100644 --- a/core/res/res/values-lo/strings.xml +++ b/core/res/res/values-lo/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"ບໍ່ສາມາດຕິດຕໍ່ເຄືອຂ່າຍມືຖືໄດ້"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"ໃຫ້ລອງປ່ຽນເຄືອຂ່າຍທີ່ຕ້ອງການ. ແຕະເພື່ອປ່ຽນ."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"ບໍ່ສາມາດໃຊ້ການໂທສຸກເສີນໄດ້"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"ໂທສຸກເສີນຕ້ອງໃຊ້ເຄືອຂ່າຍມືຖື"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"ການເຕືອນ"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"ການໂອນສາຍ"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"ໂໝດມືດຽວ"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ຫຼຸດແສງເປັນພິເສດ"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"ອຸປະກອນຊ່ວຍຟັງ"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ກົດປຸ່ມລະດັບສຽງຄ້າງໄວ້. ເປີດໃຊ້ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ແລ້ວ."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ກົດປຸ່ມລະດັບສຽງຄ້າງໄວ້. ປິດ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ໄວ້ແລ້ວ."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"ປ່ອຍປຸ່ມລະດັບສຽງ. ເພື່ອເປີດ <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, ໃຫ້ກົດປຸ່ມລະດັບສຽງທັງສອງຄ້າງໄວ້ 3 ວິນາທີ."</string> diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml index 5de98814032f..ff7919e4e55a 100644 --- a/core/res/res/values-lt/strings.xml +++ b/core/res/res/values-lt/strings.xml @@ -89,6 +89,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Nepavyko pasiekti mobiliojo ryšio tinklo"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Pabandykite pakeisti pageidaujamą tinklą. Palieskite, kad pakeistumėte."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Skambučių pagalbos numeriu paslauga nepasiekiama"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Kad būtų galima skambinti pagalbos numeriais, būtina naudoti mobiliojo ryšio tinklą"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Įspėjimai"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Skambučio peradresavimas"</string> @@ -1780,6 +1782,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Vienos rankos režimas"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Itin blanku"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Klausos įrenginiai"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Laikomi garsumo klavišai. „<xliff:g id="SERVICE_NAME">%1$s</xliff:g>“ įjungta."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Laikomi garsumo klavišai. „<xliff:g id="SERVICE_NAME">%1$s</xliff:g>“ išjungta."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Atleiskite garsumo klavišus. Kad įjungtumėte „<xliff:g id="SERVICE_NAME">%1$s</xliff:g>“, paspauskite ir 3 sekundes palaikykite garsumo klavišus."</string> diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml index ac109a87e88d..ab2c242cb55c 100644 --- a/core/res/res/values-lv/strings.xml +++ b/core/res/res/values-lv/strings.xml @@ -88,6 +88,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Nevar sasniegt mobilo tīklu"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Mēģiniet nomainīt vēlamo tīklu. Pieskarieties, lai to mainītu."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Nav pieejami ārkārtas izsaukumi"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Lai veiktu ārkārtas zvanus, ir nepieciešams mobilais tīkls."</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Brīdinājumi"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Zvanu pāradresācija"</string> @@ -1779,6 +1781,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Vienas rokas režīms"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Papildu aptumšošana"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Dzirdes aparāti"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Turējāt nospiestas skaļuma pogas. Pakalpojums <xliff:g id="SERVICE_NAME">%1$s</xliff:g> tika ieslēgts."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Turējāt nospiestas skaļuma pogas. Pakalpojums <xliff:g id="SERVICE_NAME">%1$s</xliff:g> tika izslēgts."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Atlaidiet skaļuma pogas. Lai ieslēgtu pakalpojumu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, vēlreiz nospiediet un trīs sekundes turiet nospiestas abas skaļuma pogas."</string> diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml index b626194d46d3..c10b1ef78361 100644 --- a/core/res/res/values-mk/strings.xml +++ b/core/res/res/values-mk/strings.xml @@ -71,9 +71,9 @@ <string name="CLIRDefaultOnNextCallOff" msgid="5036749051007098105">"Стандардно, ID на повикувач е скриен. Следен повик: не е скриен"</string> <string name="CLIRDefaultOffNextCallOn" msgid="1022781126694885017">"Стандардно, ID на повикувач не е скриен. Следен повик: скриен"</string> <string name="CLIRDefaultOffNextCallOff" msgid="2491576172356463443">"Стандардно, ID на повикувач не е скриен. Следен повик: не е скриен"</string> - <string name="page_size_compat_apk_warning" msgid="2982396798449041224">"Апликацијава не е компатибилна со 16 KB. Проверката за усогласување на АПК не успеа. Апликацијава ќе се извршува со режим компатибилен со големината на страницата. За најдобра компатибилност, рекомпилирајте ја апликацијата со поддршка за 16 KB. За повеќе информации, одете на <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> + <string name="page_size_compat_apk_warning" msgid="2982396798449041224">"Апликацијава не е компатибилна со 16 KB. Проверката за усогласување на APK не успеа. Апликацијава ќе се извршува со режим компатибилен со големината на страницата. За најдобра компатибилност, рекомпилирајте ја апликацијата со поддршка за 16 KB. За повеќе информации, одете на <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> <string name="page_size_compat_elf_warning" msgid="6753874059564812651">"Апликацијава не е компатибилна со 16 KB. Проверката за усогласување на ELF не успеа. Апликацијава ќе се извршува со режим компатибилен со големината на страницата. За најдобра компатибилност, рекомпилирајте ја апликацијата со поддршка за 16 KB. За повеќе информации, одете на <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> - <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"Апликацијава не е компатибилна со 16 KB. Проверките за усогласување на АПК и ELF се неуспешни. Апликацијава ќе се извршува со режим компатибилен со големината на страницата. За најдобра компатибилност, рекомпилирајте ја апликацијата со поддршка за 16 KB. За повеќе информации, одете на <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> + <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"Апликацијава не е компатибилна со 16 KB. Проверките за усогласување на APK и ELF се неуспешни. Апликацијава ќе се извршува со режим компатибилен со големината на страницата. За најдобра компатибилност, рекомпилирајте ја апликацијата со поддршка за 16 KB. За повеќе информации, одете на <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> <string name="serviceNotProvisioned" msgid="8289333510236766193">"Услугата не е предвидена."</string> <string name="CLIRPermanent" msgid="166443681876381118">"Не може да го промените поставувањето за ID на повикувач."</string> <string name="auto_data_switch_title" msgid="3286350716870518297">"Мобилниот интернет се префрли на <xliff:g id="CARRIERDISPLAY">%s</xliff:g>"</string> @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Мобилната мрежа е недостапна"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Сменете ја претпочитаната мрежа. Допрете за промена."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Итните повици се недостапни"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"За итните повици е потребна мобилна мрежа"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Предупредувања"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Проследување повик"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Режим со една рака"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Дополнително затемнување"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Слушни помагала"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Ги задржавте копчињата за јачина на звук. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> е вклучена."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Ги задржавте копчињата за јачина на звук. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> е исклучена."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Ослободете ги копчињата за јачина на звукот. Притиснете ги и задржете ги двете копчиња за јачина на звукот во траење од 3 секунди за да вклучите <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string> diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml index 7f8027dff916..3eef4930796f 100644 --- a/core/res/res/values-ml/strings.xml +++ b/core/res/res/values-ml/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"മൊബൈൽ നെറ്റ്വർക്കിലേക്ക് കണക്റ്റ് ചെയ്യാനാവുന്നില്ല"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"തിരഞ്ഞെടുത്ത നെറ്റ്വർക്ക് മാറ്റുന്നത് പരീക്ഷിക്കുക. മാറ്റാൻ ടാപ്പ് ചെയ്യുക."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"എമർജൻസി കോളിംഗ് ലഭ്യമല്ല"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"എമർജൻസി കോളുകൾ ചെയ്യാൻ ഒരു മൊബൈൽ നെറ്റ്വർക്ക് ആവശ്യമാണ്"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"അലേർട്ടുകൾ"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"കോൾ ഫോർവേഡിംഗ്"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"ഒറ്റക്കൈ മോഡ്"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"കൂടുതൽ ഡിം ചെയ്യൽ"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"ശ്രവണ ഉപകരണങ്ങൾ"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"വോളിയം കീകൾ പിടിച്ചു. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ഓണാക്കി."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"വോളിയം കീകൾ അമർത്തിപ്പിടിച്ചു. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ഓഫാക്കി."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"വോളിയം കീകൾ വിടുക. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ഓണാക്കാൻ, രണ്ട് വോളിയം കീകളും വീണ്ടും മൂന്ന് സെക്കൻഡ് അമർത്തിപ്പിടിക്കുക."</string> diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml index 8043baec1b4e..f81cff89ca21 100644 --- a/core/res/res/values-mn/strings.xml +++ b/core/res/res/values-mn/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Хөдөлгөөнт холбооны сүлжээнд холбогдох боломжгүй байна"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Сонгосон сүлжээг өөрчлөхөөр оролдоно уу. Өөрчлөхийн тулд товшино уу."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Яаралтай дуудлага хийх боломжгүй"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Яаралтай дуудлагуудад хөдөлгөөнт холбооны сүлжээ шаардлагатай"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Сануулга"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Дуудлага шилжүүлэх"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Нэг гарын горим"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Хэт бүүдгэр"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Сонсголын төхөөрөмжүүд"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Дууны түвшний түлхүүрийг удаан дарсан. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>-г асаалаа."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Дууны түвшний түлхүүрийг удаан дарсан. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>-г унтраалаа."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Дууны түвшний товчнуудыг суллана уу. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>-г асаахын тулд дууны түвшний 2 товчийг зэрэг 3 секундийн турш удаан дарна уу."</string> diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml index 7bdd94254966..98fedef134b9 100644 --- a/core/res/res/values-mr/strings.xml +++ b/core/res/res/values-mr/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"मोबाइल नेटवर्क उपलब्ध नाही"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"प्राधान्य दिलेले नेटवर्क बदलण्याचा प्रयत्न करा. बदलण्यासाठी टॅप करा."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"आणीबाणी कॉलिंग अनुपलब्ध"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"आणीबाणी कॉलसाठी मोबाइल नेटवर्क आवश्यक आहे"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"अलर्ट"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"कॉल फॉरवर्डिंग"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"एकहाती मोड"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"आणखी डिम"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"श्रवणयंत्रे"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"धरून ठेवलेल्या व्हॉल्यूम की. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> सुरू केला आहे."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"धरून ठेवलेल्या व्हॉल्यूम की. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> बंद केले आहे."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"व्हॉल्यूम की रिलीझ करा. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> सुरू करण्यासाठी, दोन्ही व्हॉल्यूम की पुन्हा प्रेस करा आणि तीन सेकंदांसाठी धरून ठेवा."</string> diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml index 21925f8aaab1..2ce54d0ffc39 100644 --- a/core/res/res/values-ms/strings.xml +++ b/core/res/res/values-ms/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Tidak dapat mencapai rangkaian mudah alih"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Cuba tukar rangkaian pilihan. Ketik untuk menukar."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Panggilan kecemasan tidak tersedia"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Rangkaian mudah alih diperlukan untuk membuat panggilan kecemasan"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Makluman"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Pemajuan panggilan"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Mod sebelah tangan"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Amat malap"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Peranti pendengaran"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Kekunci kelantangan ditahan. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> dihidupkan."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Kekunci kelantangan ditahan. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> dimatikan."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Lepaskan kekunci kelantangan. Untuk menghidupkan <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, sila tekan dan tahan kedua-dua kekunci kelantangan sekali lagi selama 3 saat."</string> diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml index 61af771b5818..3e0187a225a0 100644 --- a/core/res/res/values-my/strings.xml +++ b/core/res/res/values-my/strings.xml @@ -72,8 +72,8 @@ <string name="CLIRDefaultOffNextCallOn" msgid="1022781126694885017">"ပုံသေအားဖြင့် ခေါ်ဆိုသူအိုင်ဒီ(Caller ID)အား ကန့်သတ်မထားပါ။ နောက်ထပ်အဝင်ခေါ်ဆိုမှု-ကန့်သတ်ထားသည်။"</string> <string name="CLIRDefaultOffNextCallOff" msgid="2491576172356463443">"ပုံသေအားဖြင့် ခေါ်ဆိုသူအိုင်ဒီ(Caller ID)အား ကန့်သတ်မထားပါ။ နောက်ထပ်အဝင်ခေါ်ဆိုမှု-ကန့်သတ်မထားပါ။"</string> <string name="page_size_compat_apk_warning" msgid="2982396798449041224">"ဤအက်ပ်သည် ၁၆ KB နှင့် တွဲမသုံးနိုင်ပါ။ APK ချိန်ညှိခြင်း စစ်ဆေးမှု မအောင်မြင်ပါ။ ဤအက်ပ်သည် တွဲသုံးနိုင်သော စာမျက်နှာအရွယ်အစားမုဒ်သုံး၍ လုပ်ဆောင်ပါမည်။ အကောင်းဆုံး တွဲသုံးနိုင်မှုအတွက် အပလီကေးရှင်းကို ၁၆ KB ပံ့ပိုးမှုဖြင့် ပြန်လည်တည်ဆောက်ပါ။ နောက်ထပ်အချက်အလက်အတွက် <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a> တွင် ကြည့်ပါ"</string> - <string name="page_size_compat_elf_warning" msgid="6753874059564812651">"ဤအက်ပ်သည် ၁၆ KB နှင့် တွဲမသုံးနိုင်ပါ။ ELF ချိန်ညှိခြင်း စစ်ဆေးမှု မအောင်မြင်ပါ။ ဤအက်ပ်သည် တွဲသုံးနိုင်သော စာမျက်နှာအရွယ်အစားမုဒ်သုံး၍ လုပ်ဆောင်ပါမည်။ အကောင်းဆုံး တွဲသုံးနိုင်မှုအတွက် အပလီကေးရှင်းကို ၁၆ KB ပံ့ပိုးမှုဖြင့် ပြန်လည်တည်ဆောက်ပါ။ နောက်ထပ်အချက်အလက်အတွက် <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a> တွင် ကြည့်ပါ"</string> - <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"ဤအက်ပ်သည် ၁၆ KB နှင့် တွဲမသုံးနိုင်ပါ။ APK နှင့် ELF ချိန်ညှိခြင်း စစ်ဆေးမှု မအောင်မြင်ပါ။ ဤအက်ပ်သည် တွဲသုံးနိုင်သော စာမျက်နှာအရွယ်အစားမုဒ်သုံး၍ လုပ်ဆောင်ပါမည်။ အကောင်းဆုံး တွဲသုံးနိုင်မှုအတွက် အပလီကေးရှင်းကို ၁၆ KB ပံ့ပိုးမှုဖြင့် ပြန်လည်တည်ဆောက်ပါ။ နောက်ထပ်အချက်အလက်အတွက် <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a> တွင် ကြည့်ပါ"</string> + <string name="page_size_compat_elf_warning" msgid="6753874059564812651">"ဤအက်ပ်ကို ၁၆ KB နှင့် တွဲမသုံးနိုင်ပါ။ ELF ချိန်ညှိခြင်း စစ်ဆေးမှု မအောင်မြင်ပါ။ ဤအက်ပ်ကို တွဲသုံးနိုင်သော စာမျက်နှာအရွယ်အစားမုဒ်သုံး၍ လုပ်ဆောင်ပါမည်။ အကောင်းဆုံး တွဲသုံးနိုင်မှုအတွက် အပလီကေးရှင်းကို ၁၆ KB ပံ့ပိုးမှုဖြင့် ပြန်လည်တည်ဆောက်ပါ။ နောက်ထပ်အချက်အလက်အတွက် <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a> တွင် ကြည့်ပါ"</string> + <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"ဤအက်ပ်ကို ၁၆ KB နှင့် တွဲမသုံးနိုင်ပါ။ APK နှင့် ELF ချိန်ညှိခြင်း စစ်ဆေးမှု မအောင်မြင်ပါ။ ဤအက်ပ်ကို တွဲသုံးနိုင်သော စာမျက်နှာအရွယ်အစားမုဒ်သုံး၍ လုပ်ဆောင်ပါမည်။ အကောင်းဆုံး တွဲသုံးနိုင်မှုအတွက် အပလီကေးရှင်းကို ၁၆ KB ပံ့ပိုးမှုဖြင့် ပြန်လည်တည်ဆောက်ပါ။ နောက်ထပ်အချက်အလက်အတွက် <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a> တွင် ကြည့်ပါ"</string> <string name="serviceNotProvisioned" msgid="8289333510236766193">"ဝန်ဆောင်မှုအား ကန့်သတ်မထားပါ"</string> <string name="CLIRPermanent" msgid="166443681876381118">"သင်သည် ခေါ်ဆိုသူ ID ဆက်တင်ကို မပြောင်းလဲနိုင်ပါ။"</string> <string name="auto_data_switch_title" msgid="3286350716870518297">"ဒေတာကို <xliff:g id="CARRIERDISPLAY">%s</xliff:g> သို့ ပြောင်းထားသည်"</string> @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"မိုဘိုင်းကွန်ရက် လိုင်းမရပါ"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"ဦးစားပေးကွန်ရက်သို့ ပြောင်းကြည့်ပါ။ ပြောင်းရန် တို့ပါ။"</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"အရေးပေါ်ခေါ်ဆိုမှု မရနိုင်ပါ"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"အရေးပေါ်ဖုန်းခေါ်ရန် မိုဘိုင်းကွန်ရက် လိုအပ်သည်"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"သတိပေးချက်များ"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"အဝင်ခေါ်ဆိုမှုအား ထပ်ဆင့်ပို့ခြင်း"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"လက်တစ်ဖက်သုံးမုဒ်"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ပိုမှိန်ခြင်း"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"နားကြားကိရိယာ"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"အသံခလုတ်များကို ဖိထားသည်။ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ဖွင့်လိုက်သည်။"</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"အသံခလုတ်များကို ဖိထားသည်။ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ပိတ်လိုက်သည်။"</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"အသံထိန်းခလုတ်များကို လွှတ်လိုက်ပါ။ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ဖွင့်ရန် အသံထိန်းခလုတ်နှစ်ခုစလုံးကို ၃ စက္ကန့်ကြာအောင် ထပ်နှိပ်ပါ။"</string> diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index 0c7d868e02f3..d21296d28696 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Får ikke kontakt med mobilnettverket"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Prøv å endre foretrukket nettverk. Trykk for å endre."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Nødanrop er utilgjengelig"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Du må være koblet til et mobilnettverk for å utføre nødanrop"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Varsler"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Viderekobling"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Enhåndsmodus"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Ekstra dimmet"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Høreapparater"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Volumtastene holdes inne. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> er slått på."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Volumtastene holdes inne. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> er slått av."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Slipp opp volumtastene. For å slå på <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, trykk og hold på begge volumtastene igjen i 3 sekunder."</string> diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml index 3414644ed80e..c524a4847c69 100644 --- a/core/res/res/values-ne/strings.xml +++ b/core/res/res/values-ne/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"मोबाइल नेटवर्कमाथि पहुँच राख्न सकिएन"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"रुचाइएको नेटवर्क परिवर्तन गरी हेर्नुहोस्। परिवर्तन गर्न ट्याप गर्नुहोस्।"</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"आपत्कालीन कल सेवा अनुपलब्ध छ"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"आपत्कालीन कलहरू गर्न मोबाइल नेटवर्क चाहिन्छ"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"अलर्टहरू"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"कल फर्वार्ड गर्ने सेवा"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"एक हाते मोड"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"अझै मधुरो"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"हियरिङ डिभाइसहरू"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"तपाईंले भोल्युम बटनहरू थिचिराख्नुभयो। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> अन भयो।"</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"तपाईंले भोल्युम बटनहरू थिचिराख्नुभयो। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> अफ भयो।"</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"भोल्युम बटनहरू थिच्न छाड्नुहोस्। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> अन गर्न दुवै भोल्युम बटन फेरि ३ सेकेन्डसम्म थिचिराख्नुहोस्।"</string> diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index e88384b48c7f..609d642a5672 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Kan mobiel netwerk niet bereiken"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Probeer een ander voorkeursnetwerk. Tik om te wijzigen."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Noodoproepen niet beschikbaar"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Voor noodoproepen is een mobiel netwerk vereist"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Meldingen"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Gesprek doorschakelen"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Bediening met 1 hand"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Extra dimmen"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Hoortoestellen"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Volumetoetsen ingedrukt gehouden. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> staat aan."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Volumetoetsen ingedrukt gehouden. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> staat uit."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Laat de volumeknoppen los. Als je <xliff:g id="SERVICE_NAME">%1$s</xliff:g> wilt aanzetten, houd je beide volumeknoppen weer 3 seconden ingedrukt."</string> diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml index 9960691d7206..51c4e3143586 100644 --- a/core/res/res/values-or/strings.xml +++ b/core/res/res/values-or/strings.xml @@ -71,9 +71,9 @@ <string name="CLIRDefaultOnNextCallOff" msgid="5036749051007098105">"କଲର୍ ଆଇଡି ଡିଫଲ୍ଟ ଭାବରେ ପ୍ରତିବନ୍ଧିତ। ପରବର୍ତ୍ତୀ କଲ୍: ପ୍ରତିବନ୍ଧିତ ନୁହେଁ"</string> <string name="CLIRDefaultOffNextCallOn" msgid="1022781126694885017">"କଲର୍ ଆଇଡି ଡିଫଲ୍ଟ ଭାବରେ ପ୍ରତିବନ୍ଧିତ ନୁହେଁ। ପରବର୍ତ୍ତୀ କଲ୍: ପ୍ରତିବନ୍ଧିତ"</string> <string name="CLIRDefaultOffNextCallOff" msgid="2491576172356463443">"କଲର୍ ଆଇଡି ଡିଫଲ୍ଟ ଭାବରେ ପ୍ରତିବନ୍ଧିତ ନୁହେଁ। ପରବର୍ତ୍ତୀ କଲ୍: ପ୍ରତିବନ୍ଧିତ ନୁହେଁ"</string> - <string name="page_size_compat_apk_warning" msgid="2982396798449041224">"ଏହି ଆପ 16 KB କମ୍ପାଟିବଲ ନୁହେଁ। APK ଆଲାଇନମେଣ୍ଟ ଯାଞ୍ଚ ବିଫଳ ହୋଇଛି। ପୃଷ୍ଠା ସାଇଜ କମ୍ପାଟିବଲ ମୋଡ ବ୍ୟବହାର କରି ଏହି ଆପକୁ ଚଲାଯିବ। ସର୍ବୋତ୍ତମ କମ୍ପାଟିବିଲିଟୀ ପାଇଁ ଦୟାକରି 16 KB ସପୋର୍ଟ ସହ ଆପ୍ଲିକେସନକୁ ପୁଣି କମ୍ପାଇଲ କରନ୍ତୁ। ଅଧିକ ସୂଚନା ପାଇଁ <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>କୁ ଦେଖନ୍ତୁ"</string> - <string name="page_size_compat_elf_warning" msgid="6753874059564812651">"ଏହି ଆପ 16 KB କମ୍ପାଟିବଲ ନୁହେଁ। ELF ଆଲାଇନମେଣ୍ଟ ଯାଞ୍ଚ ବିଫଳ ହୋଇଛି। ପୃଷ୍ଠା ସାଇଜ କମ୍ପାଟିବଲ ମୋଡ ବ୍ୟବହାର କରି ଏହି ଆପକୁ ଚଲାଯିବ। ସର୍ବୋତ୍ତମ କମ୍ପାଟିବିଲିଟୀ ପାଇଁ ଦୟାକରି 16 KB ସପୋର୍ଟ ସହ ଆପ୍ଲିକେସନକୁ ପୁଣି କମ୍ପାଇଲ କରନ୍ତୁ। ଅଧିକ ସୂଚନା ପାଇଁ <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>କୁ ଦେଖନ୍ତୁ"</string> - <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"ଏହି ଆପ 16 KB କମ୍ପାଟିବଲ ନୁହେଁ। APK ଏବଂ ELF ଆଲାଇନମେଣ୍ଟ ଯାଞ୍ଚଗୁଡ଼ିକ ବିଫଳ ହୋଇଛି। ପୃଷ୍ଠା ସାଇଜ କମ୍ପାଟିବଲ ମୋଡ ବ୍ୟବହାର କରି ଏହି ଆପକୁ ଚଲାଯିବ। ସର୍ବୋତ୍ତମ କମ୍ପାଟିବିଲିଟୀ ପାଇଁ ଦୟାକରି 16 KB ସପୋର୍ଟ ସହ ଆପ୍ଲିକେସନକୁ ପୁଣି କମ୍ପାଇଲ କରନ୍ତୁ। ଅଧିକ ସୂଚନା ପାଇଁ <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>କୁ ଦେଖନ୍ତୁ"</string> + <string name="page_size_compat_apk_warning" msgid="2982396798449041224">"ଏହି ଆପ 16 KB ପାଇଁ କମ୍ପାଟିବିଲ ନୁହେଁ। APK ଏବଂ ELF ଆଲାଇନମେଣ୍ଟ ଯାଞ୍ଚଗୁଡ଼ିକ ବିଫଳ ହୋଇଛି। ପୃଷ୍ଠା ସାଇଜ କମ୍ପାଟିବିଲ ମୋଡ ବ୍ୟବହାର କରି ଏହି ଆପକୁ ଚଲାଯିବ। ସର୍ବୋତ୍ତମ କମ୍ପାଟିବିଲିଟୀ ପାଇଁ ଦୟାକରି 16 KB ସପୋର୍ଟ ସହ ଆପ୍ଲିକେସନକୁ ପୁଣି କମ୍ପାଇଲ କରନ୍ତୁ। ଅଧିକ ସୂଚନା ପାଇଁ <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>କୁ ଦେଖନ୍ତୁ"</string> + <string name="page_size_compat_elf_warning" msgid="6753874059564812651">"ଏହି ଆପ 16 KB ପାଇଁ କମ୍ପାଟିବିଲ ନୁହେଁ। APK ଏବଂ ELF ଆଲାଇନମେଣ୍ଟ ଯାଞ୍ଚଗୁଡ଼ିକ ବିଫଳ ହୋଇଛି। ପୃଷ୍ଠା ସାଇଜ କମ୍ପାଟିବିଲ ମୋଡ ବ୍ୟବହାର କରି ଏହି ଆପକୁ ଚଲାଯିବ। ସର୍ବୋତ୍ତମ କମ୍ପାଟିବିଲିଟୀ ପାଇଁ ଦୟାକରି 16 KB ସପୋର୍ଟ ସହ ଆପ୍ଲିକେସନକୁ ପୁଣି କମ୍ପାଇଲ କରନ୍ତୁ। ଅଧିକ ସୂଚନା ପାଇଁ <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>କୁ ଦେଖନ୍ତୁ"</string> + <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"ଏହି ଆପ 16 KB ପାଇଁ କମ୍ପାଟିବିଲ ନୁହେଁ। APK ଏବଂ ELF ଆଲାଇନମେଣ୍ଟ ଯାଞ୍ଚଗୁଡ଼ିକ ବିଫଳ ହୋଇଛି। ପୃଷ୍ଠା ସାଇଜ କମ୍ପାଟିବିଲ ମୋଡ ବ୍ୟବହାର କରି ଏହି ଆପକୁ ଚଲାଯିବ। ସର୍ବୋତ୍ତମ କମ୍ପାଟିବିଲିଟୀ ପାଇଁ ଦୟାକରି 16 KB ସପୋର୍ଟ ସହ ଆପ୍ଲିକେସନକୁ ପୁଣି କମ୍ପାଇଲ କରନ୍ତୁ। ଅଧିକ ସୂଚନା ପାଇଁ <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>କୁ ଦେଖନ୍ତୁ"</string> <string name="serviceNotProvisioned" msgid="8289333510236766193">"ସେବାର ସୁବିଧା ନାହିଁ।"</string> <string name="CLIRPermanent" msgid="166443681876381118">"ଆପଣ କଲର୍ ID ସେଟିଙ୍ଗ ବଦଳାଇପାରିବେ ନାହିଁ।"</string> <string name="auto_data_switch_title" msgid="3286350716870518297">"<xliff:g id="CARRIERDISPLAY">%s</xliff:g>କୁ ଡାଟା ସ୍ୱିଚ କରାଯାଇଛି"</string> @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"ମୋବାଇଲ୍ ନେଟ୍ୱର୍କ ମିଳୁନାହିଁ"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"ନିଜ ପସନ୍ଦର ନେଟ୍ୱର୍କକୁ ଯିବାପାଇଁ ଚେଷ୍ଟା କରନ୍ତୁ। ବଦଳାଇବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ।"</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"ଜରୁରୀକାଳୀନ କଲ୍ ଉପଲବ୍ଧ ନାହିଁ"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"ଜରୁରୀକାଳୀନ କଲ କରିବା ପାଇଁ ଏକ ମୋବାଇଲ ନେଟୱାର୍କ ଆବଶ୍ୟକ"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"ଆଲର୍ଟ"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"କଲ୍ ଫରୱାର୍ଡିଂ"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"ଏକ-ହାତ ମୋଡ୍"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ଅତ୍ୟଧିକ ଡିମ"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"ଶ୍ରବଣ ଡିଭାଇସଗୁଡ଼ିକ"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ଭଲ୍ୟୁମ୍ କୀ\'ଗୁଡ଼ିକୁ ଧରି ରଖାଯାଇଛି। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ଚାଲୁ ହୋଇଛି।"</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ଭଲ୍ୟୁମ୍ କୀ\'ଗୁଡ଼ିକୁ ଧରି ରଖାଯାଇଛି। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ବନ୍ଦ ହୋଇଛି।"</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"ଭଲ୍ୟୁମ କୀ\'ଗୁଡ଼ିକୁ ରିଲିଜ କରନ୍ତୁ। <xliff:g id="SERVICE_NAME">%1$s</xliff:g>କୁ ଚାଲୁ କରିବା ପାଇଁ ଉଭୟ ଭଲ୍ୟୁମ କୀ\'କୁ ପୁଣି 3 ସେକେଣ୍ଡ ପାଇଁ ଦବାଇ ଧରି ରଖନ୍ତୁ।"</string> diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml index 6d92e0148d78..12f4e901ce07 100644 --- a/core/res/res/values-pa/strings.xml +++ b/core/res/res/values-pa/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"ਮੋਬਾਈਲ ਨੈੱਟਵਰਕ ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"ਤਰਜੀਹੀ ਨੈੱਟਵਰਕ ਨੂੰ ਬਦਲ ਕੇ ਦੇਖੋ। ਬਦਲਣ ਲਈ ਟੈਪ ਕਰੋ।"</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"ਸੰਕਟਕਾਲੀਨ ਕਾਲਿੰਗ ਉਪਲਬਧ ਨਹੀਂ"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"ਐਮਰਜੈਂਸੀ ਕਾਲਾਂ ਲਈ ਕਿਸੇ ਮੋਬਾਈਲ ਨੈੱਟਵਰਕ ਦੀ ਲੋੜ ਹੁੰਦੀ ਹੈ"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"ਅਲਰਟ"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"ਕਾਲ ਫਾਰਵਰਡਿੰਗ"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"ਇੱਕ ਹੱਥ ਮੋਡ"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ਜ਼ਿਆਦਾ ਘੱਟ ਚਮਕ"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"ਸੁਣਨ ਵਾਲੇ ਡੀਵਾਈਸ"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ਅਵਾਜ਼ੀ ਕੁੰਜੀਆਂ ਦਬਾ ਕੇ ਰੱਖੀਆਂ ਗਈਆਂ। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ਨੂੰ ਚਾਲੂ ਕੀਤਾ ਗਿਆ।"</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ਅਵਾਜ਼ੀ ਕੁੰਜੀਆਂ ਦਬਾ ਕੇ ਰੱਖੀਆਂ ਗਈਆਂ। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ਨੂੰ ਬੰਦ ਕੀਤਾ ਗਿਆ।"</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"ਅਵਾਜ਼ ਕੁੰਜੀਆਂ ਨੂੰ ਛੱਡੋ। <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ਨੂੰ ਚਾਲੂ ਕਰਨ ਲਈ, ਦੋਵੇਂ ਅਵਾਜ਼ ਕੁੰਜੀਆਂ ਨੂੰ 3 ਸਕਿੰਟਾਂ ਲਈ ਦੁਬਾਰਾ ਦਬਾਈ ਰੱਖੋ।"</string> diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index ec37251a7394..113ffa37084e 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -73,9 +73,9 @@ <string name="CLIRDefaultOnNextCallOff" msgid="5036749051007098105">"ID rozmówcy ustawiony jest domyślnie na „zastrzeżony”. Następne połączenie: nie zastrzeżony"</string> <string name="CLIRDefaultOffNextCallOn" msgid="1022781126694885017">"ID rozmówcy ustawiony jest domyślnie na „nie zastrzeżony”. Następne połączenie: zastrzeżony"</string> <string name="CLIRDefaultOffNextCallOff" msgid="2491576172356463443">"ID rozmówcy ustawiony jest domyślnie na „nie zastrzeżony”. Następne połączenie: nie zastrzeżony"</string> - <string name="page_size_compat_apk_warning" msgid="2982396798449041224">"Ta aplikacja nie jest zgodna z trybem 16 KB. Sprawdzenie zgodności pliku APK się nie powiodło. Ta aplikacja będzie działać w trybie zgodnym z rozmiarem strony. Aby zapewnić najlepszą zgodność, rekompiluj aplikację, żeby obsługiwała 16 KB. Więcej informacji znajdziesz na stronie <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> - <string name="page_size_compat_elf_warning" msgid="6753874059564812651">"Ta aplikacja nie jest zgodna z trybem 16 KB. Sprawdzenie zgodności ELF się nie powiodło. Ta aplikacja będzie działać w trybie zgodnym z rozmiarem strony. Aby zapewnić najlepszą zgodność, rekompiluj aplikację, żeby obsługiwała 16 KB. Więcej informacji znajdziesz na stronie <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> - <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"Ta aplikacja nie jest zgodna z trybem 16 KB. Sprawdzenie zgodności pliku APK i ELF się nie powiodło. Ta aplikacja będzie działać w trybie zgodnym z rozmiarem strony. Aby zapewnić najlepszą zgodność, rekompiluj aplikację, żeby obsługiwała 16 KB. Więcej informacji znajdziesz na stronie <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> + <string name="page_size_compat_apk_warning" msgid="2982396798449041224">"Ta aplikacja nie jest zgodna z trybem 16 KB. Sprawdzenie zgodności pliku APK się nie powiodło. Aplikacja będzie działać w trybie zgodnym z rozmiarem strony. Aby zapewnić najlepszą zgodność, dokonaj ponownej kompilacji, żeby aplikacja obsługiwała 16 KB. Więcej informacji znajdziesz na stronie <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> + <string name="page_size_compat_elf_warning" msgid="6753874059564812651">"Ta aplikacja nie jest zgodna z trybem 16 KB. Sprawdzenie zgodności ELF się nie powiodło. Aplikacja będzie działać w trybie zgodnym z rozmiarem strony. Aby zapewnić najlepszą zgodność, dokonaj ponownej kompilacji, żeby aplikacja obsługiwała 16 KB. Więcej informacji znajdziesz na stronie <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> + <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"Ta aplikacja nie jest zgodna z trybem 16 KB. Sprawdzenie zgodności pliku APK i ELF się nie powiodło. Aplikacja będzie działać w trybie zgodnym z rozmiarem strony. Aby zapewnić najlepszą zgodność, dokonaj ponownej kompilacji, żeby aplikacja obsługiwała 16 KB. Więcej informacji znajdziesz na stronie <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> <string name="serviceNotProvisioned" msgid="8289333510236766193">"Usługa nie jest świadczona."</string> <string name="CLIRPermanent" msgid="166443681876381118">"Nie możesz zmienić ustawienia ID rozmówcy."</string> <string name="auto_data_switch_title" msgid="3286350716870518297">"Przełączono mobilną transmisję danych na: <xliff:g id="CARRIERDISPLAY">%s</xliff:g>"</string> @@ -89,6 +89,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Brak zasięgu sieci komórkowej"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Spróbuj zmienić preferowaną sieć. Kliknij, by zmienić."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Połączenia alarmowe są niedostępne"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Połączenia alarmowe wymagają sieci komórkowej"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Alerty"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Przekierowanie połączeń"</string> @@ -1780,6 +1782,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Tryb jednej ręki"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Dodatkowe przyciemnienie"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Urządzenia słuchowe"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Przytrzymano klawisze głośności. Usługa <xliff:g id="SERVICE_NAME">%1$s</xliff:g> została włączona."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Przytrzymano klawisze głośności. Usługa <xliff:g id="SERVICE_NAME">%1$s</xliff:g> została wyłączona."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Zwolnij przyciski głośności. Aby włączyć usługę <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, naciśnij i przytrzymaj oba przyciski głośności przez 3 sekundy."</string> diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml index 5ff383df1770..2daa730b4a31 100644 --- a/core/res/res/values-pt-rBR/strings.xml +++ b/core/res/res/values-pt-rBR/strings.xml @@ -88,6 +88,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Não foi possível acessar a rede móvel"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Tente alterar a rede preferencial. Toque para alterar."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Chamadas de emergência indisponíveis"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"As chamadas de emergência exigem uma rede móvel"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Alertas"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Encaminhamento de chamada"</string> @@ -1779,6 +1781,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modo para uma mão"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Escurecer ainda mais a tela"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Aparelhos auditivos"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Teclas de volume pressionadas. Serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ativado."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Teclas de volume pressionadas. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desativado."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Solte as teclas de volume. Para ativar o serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, toque e pressione as duas teclas de volume por três segundos."</string> diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index 38a071a5cbb2..5572de130221 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -88,6 +88,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Não é possível estabelecer ligação à rede móvel."</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Experimente alterar a rede preferida. Toque para alterar."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Chamadas de emergência indisponíveis"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"As chamadas de emergência requerem uma rede móvel"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Alertas"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Reencaminhamento de chamadas"</string> @@ -1779,6 +1781,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modo para uma mão"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Mais escuro"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Dispositivos auditivos"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Teclas do volume premidas. Serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ativado."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Teclas de volume premidas. Serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desativado."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Solte as teclas de volume. Para ativar o serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, prima sem soltar ambas as teclas de volume novamente durante 3 segundos."</string> diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index 5ff383df1770..2daa730b4a31 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -88,6 +88,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Não foi possível acessar a rede móvel"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Tente alterar a rede preferencial. Toque para alterar."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Chamadas de emergência indisponíveis"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"As chamadas de emergência exigem uma rede móvel"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Alertas"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Encaminhamento de chamada"</string> @@ -1779,6 +1781,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modo para uma mão"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Escurecer ainda mais a tela"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Aparelhos auditivos"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Teclas de volume pressionadas. Serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ativado."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Teclas de volume pressionadas. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> desativado."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Solte as teclas de volume. Para ativar o serviço <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, toque e pressione as duas teclas de volume por três segundos."</string> diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml index 738951eac18b..cf0f771b190c 100644 --- a/core/res/res/values-ro/strings.xml +++ b/core/res/res/values-ro/strings.xml @@ -88,6 +88,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Nu se poate stabili conexiunea la rețeaua mobilă"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Încearcă să schimbi rețeaua preferată. Atinge pentru a schimba."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Apelurile de urgență nu sunt disponibile"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Apelurile de urgență necesită o rețea mobilă"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Alerte"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Redirecționarea apelurilor"</string> @@ -1779,6 +1781,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modul cu o mână"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Luminozitate redusă suplimentar"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Aparate auditive"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"S-au apăsat lung tastele de volum. S-a activat <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"S-au apăsat lung tastele de volum. S-a dezactivat <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Eliberează butoanele de volum. Pentru a activa <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, apasă lung pe ambele butoane de volum timp de trei secunde încă o dată."</string> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index 285e941070ba..387cd338bb9c 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -89,6 +89,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Мобильная сеть недоступна"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Нажмите, чтобы выбрать другую сеть."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Экстренные вызовы недоступны"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Для экстренных вызовов нужна мобильная сеть."</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Оповещения"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Переадресация вызовов"</string> @@ -1551,7 +1553,7 @@ <string name="forward_intent_to_work" msgid="3620262405636021151">"Вы перешли в рабочий профиль"</string> <string name="input_method_binding_label" msgid="1166731601721983656">"Способ ввода"</string> <string name="sync_binding_label" msgid="469249309424662147">"Синхр."</string> - <string name="accessibility_binding_label" msgid="1974602776545801715">"Спец. возможности"</string> + <string name="accessibility_binding_label" msgid="1974602776545801715">"Специальные возможности"</string> <string name="wallpaper_binding_label" msgid="1197440498000786738">"Фоновый рисунок"</string> <string name="chooser_wallpaper" msgid="3082405680079923708">"Сменить обои"</string> <string name="notification_listener_binding_label" msgid="2702165274471499713">"Служба просмотра уведомлений"</string> @@ -1780,6 +1782,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Режим управления одной рукой"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Дополнительное уменьшение яркости"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Слуховые аппараты"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Использован жест с кнопками регулировки громкости. Функция \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\" включена."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Использован жест с кнопками регулировки громкости. Функция \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\" отключена."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Отпустите кнопки громкости. Чтобы включить <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, нажмите и удерживайте обе кнопки регулировки громкости в течение трех секунд."</string> diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml index 0cb6f3096167..9fd63e471962 100644 --- a/core/res/res/values-si/strings.xml +++ b/core/res/res/values-si/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"ජංගම ජාලය වෙත ළඟා විය නොහැකිය"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"කැමති ජාලය වෙනස් කිරීමට උත්සාහ කරන්න. වෙනස් කිරීමට තට්ටු කරන්න."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"හදිසි ඇමතුම් ලබා ගත නොහැකිය"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"හදිසි ඇමතුම් සඳහා ජංගම ජාලයක් අවශ්ය වේ"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"ඇඟවීම්"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"ඇමතුම ප්රතියොමු කිරීම"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"තනි අත් ප්රකාරය"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"තවත් අඳුරු"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"ශ්රවණ උපාංග"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"හඬ පරිමා යතුරු අල්ලා ගන්න <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ක්රියාත්මකයි."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"හඬ පරිමා යතුරු අල්ලා ගන්න <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ක්රියාවිරහිතයි."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"හඬ පරිමා යතුරු මුදා හරින්න. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> සක්රීය කිරීමට, හඬ පරිමා යතුරු දෙකම නැවත තත්පර 3ක් ඔබා අල්ලා සිටින්න."</string> diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml index 9d0efef85a72..35283675c9ef 100644 --- a/core/res/res/values-sk/strings.xml +++ b/core/res/res/values-sk/strings.xml @@ -89,6 +89,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Nepodarilo sa pripojiť k mobilnej sieti"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Skúste zmeniť predvolenú sieť. Zmeníte ju klepnutím."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Tiesňové volania nie sú k dispozícii"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Tiesňové volania vyžadujú mobilnú sieť"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Upozornenia"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Presmerovanie hovorov"</string> @@ -1780,6 +1782,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Režim jednej ruky"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Mimoriadne stmavenie"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Načúvacie zariadenia"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Pridržali ste tlačidlá hlasitosti. Služba <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je zapnutá."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Pridržali ste tlačidlá hlasitosti. Služba <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je vypnutá."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Uvoľnite tlačidlá hlasitosti. Ak chcete zapnúť službu <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, znova pridržte tri sekundy obe tlačidlá hlasitosti."</string> diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml index 2cadf4b7ea15..af6c95c70db4 100644 --- a/core/res/res/values-sl/strings.xml +++ b/core/res/res/values-sl/strings.xml @@ -89,6 +89,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Mobilnega omrežja ni mogoče doseči"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Poskusite spremeniti prednostno omrežje. Dotaknite se, če ga želite spremeniti."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Klicanje v sili ni na voljo"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Za klice v sili potrebujete mobilno omrežje"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Opozorila"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Preusmerjanje klicev"</string> @@ -1780,6 +1782,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Enoročni način"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Zelo zatemnjen zaslon"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Slušni pripomočki"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tipki za glasnost sta pridržani. Storitev <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je vklopljena."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tipki za glasnost sta pridržani. Storitev <xliff:g id="SERVICE_NAME">%1$s</xliff:g> je izklopljena."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Spustite gumba za glasnost. Če želite vklopiti storitev <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, znova pritisnite in 3 sekunde pridržite oba gumba za glasnost."</string> diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml index 744b5577904f..d8fdb9a30d56 100644 --- a/core/res/res/values-sq/strings.xml +++ b/core/res/res/values-sq/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Rrjeti celular është i paarritshëm"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Provo të ndryshosh rrjetin e preferuar. Trokit për ta ndryshuar."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Telefonatat e urgjencës nuk ofrohen"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Telefonatat e urgjencës kërkojnë një rrjet celular"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Sinjalizimet"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Transferimi i telefonatave"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Modaliteti i përdorimit me një dorë"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Shumë më i zbehtë"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Pajisjet e dëgjimit"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tastet e volumit të mbajtura shtypur. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> i aktivizuar."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tastet e volumit të mbajtura shtypur. U çaktivizua \"<xliff:g id="SERVICE_NAME">%1$s</xliff:g>\"."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Lësho tastet e volumit. Për të aktivizuar <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, shtyp dhe mbaj shtypur të dy tastet e volumit sërish për 3 sekonda."</string> diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml index 45fb8ee60e1e..146855e730bb 100644 --- a/core/res/res/values-sr/strings.xml +++ b/core/res/res/values-sr/strings.xml @@ -88,6 +88,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Повезивање са мобилном мрежом није успело"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Пробајте да промените жељену мрежу. Додирните да бисте променили."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Хитни позиви нису доступни"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Хитни позиви захтевају мобилну мрежу"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Упозорења"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Преусмеравање позива"</string> @@ -1779,6 +1781,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Режим једном руком"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Додатно затамни"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Слушни апарати"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Држали сте тастере за јачину звука. Услуга <xliff:g id="SERVICE_NAME">%1$s</xliff:g> је укључена."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Држали сте тастере за јачину звука. Услуга <xliff:g id="SERVICE_NAME">%1$s</xliff:g> је искључена."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Пустите тастере за јачину звука. Да бисте укључили <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, поново притисните и задржите оба тастера за јачину звука 3 секунде."</string> diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml index 4b22b7df0c8c..ecb3c79cff45 100644 --- a/core/res/res/values-sv/strings.xml +++ b/core/res/res/values-sv/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Det går inte att nå mobilnätverket"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Testa att byta föredraget nätverk. Tryck om du vill ändra."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Det går inte att ringa nödsamtal"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Mobilnätverk krävs för att ringa nödsamtal"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Aviseringar"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Vidarekoppla samtal"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Enhandsläge"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Extradimmat"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Hörhjälpmedel"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Volymknapparna har tryckts ned. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> har aktiverats."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Volymknapparna har tryckts ned. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> har inaktiverats."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Släpp volymknapparna. Du kan aktivera <xliff:g id="SERVICE_NAME">%1$s</xliff:g> genom att hålla båda volymknapparna nedtryckta i tre sekunder igen."</string> diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml index d6565bfe33aa..98c973140a65 100644 --- a/core/res/res/values-sw/strings.xml +++ b/core/res/res/values-sw/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Imeshindwa kufikia mtandao wa simu"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Jaribu kutumia mtandao unaopendelea. Gusa ili ubadilishe."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Huduma ya kupiga simu za dharura haipatikani"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Huduma ya kupiga simu za dharura inahitaji mtandao wa simu"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Arifa"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Kupeleka simu kwenye namba nyingine"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Hali ya kutumia kwa mkono mmoja"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Kipunguza mwangaza zaidi"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Vifaa vya kusaidia kusikia"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Vitufe vya sauti vilivyoshikiliwa. Umewasha <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Vitufe vya sauti vimeshikiliwa. Umezima <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Achilia vitufe vya sauti. Ili uwashe <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, bonyeza na ushikilie tena vitufe vyote vya sauti kwa sekunde 3."</string> diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml index 17119a6b974e..f8b2bbc35b7d 100644 --- a/core/res/res/values-ta/strings.xml +++ b/core/res/res/values-ta/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"மொபைல் நெட்வொர்க் கிடைக்கவில்லை"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"விருப்ப நெட்வொர்க்கை மாற்றவும். மாற்ற, தட்டவும்."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"அவசர அழைப்பைச் செய்ய முடியாது"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"அவசர அழைப்புகளுக்கு மொபைல் நெட்வொர்க் தேவை"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"விழிப்பூட்டல்கள்"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"அழைப்பு திருப்பிவிடுதல்"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"ஒற்றைக் கைப் பயன்முறை"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"மிகக் குறைவான வெளிச்சம்"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"செவித்துணைக் கருவிகள்"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"ஒலியளவுக்கான விசைகளைப் பிடித்திருந்தீர்கள். <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ஆன் செய்யப்பட்டது."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"ஒலியளவுக்கான விசைகளைப் பிடித்திருந்தீர்கள். <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ஆஃப் செய்யப்பட்டது."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"ஒலியளவு பட்டன்களை அழுத்துவதை நிறுத்துங்கள். <xliff:g id="SERVICE_NAME">%1$s</xliff:g> சேவையை இயக்க, ஒலியளவு பட்டன்கள் இரண்டையும் 3 வினாடிகளுக்கு மீண்டும் அழுத்திப் பிடிக்கவும்."</string> diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml index 2b97029a5e24..bcd2865173d4 100644 --- a/core/res/res/values-te/strings.xml +++ b/core/res/res/values-te/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"మొబైల్ నెట్వర్క్ అందుబాటులో లేదు"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"ప్రాధాన్య నెట్వర్క్ను మార్చుకోవడానికి ప్రయత్నించండి. మార్చడానికి నొక్కండి."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"అత్యవసర కాలింగ్ అందుబాటులో లేదు"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"ఎమర్జెన్సీ కాల్స్కు మొబైల్ నెట్వర్క్ అవసరమవుతుంది"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"అలర్ట్లు"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"కాల్ ఫార్వార్డింగ్"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"వన్-హ్యాండెడ్ మోడ్"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"ఎక్స్ట్రా డిమ్"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"వినికిడి పరికరాలు"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"వాల్యూమ్ కీలు నొక్కి ఉంచబడ్డాయి. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ఆన్ చేయబడింది"</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"వాల్యూమ్ కీలు నొక్కి ఉంచబడ్డాయి. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ఆఫ్ చేయబడింది"</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"వాల్యూమ్ కీలను రిలీజ్ చేయండి. <xliff:g id="SERVICE_NAME">%1$s</xliff:g>ను ఆన్ చేయడానికి, రెండు వాల్యూమ్ కీలను మళ్లీ 3 సెకన్ల పాటు నొక్కి పట్టుకోండి."</string> diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml index 7e70a3b573d8..0e66e371f722 100644 --- a/core/res/res/values-th/strings.xml +++ b/core/res/res/values-th/strings.xml @@ -71,9 +71,9 @@ <string name="CLIRDefaultOnNextCallOff" msgid="5036749051007098105">"หมายเลขผู้โทรได้รับการตั้งค่าเริ่มต้นเป็นถูกจำกัด การโทรครั้งต่อไป: ไม่จำกัด"</string> <string name="CLIRDefaultOffNextCallOn" msgid="1022781126694885017">"หมายเลขผู้โทรได้รับการตั้งค่าเริ่มต้นเป็นไม่จำกัด การโทรครั้งต่อไป: ถูกจำกัด"</string> <string name="CLIRDefaultOffNextCallOff" msgid="2491576172356463443">"หมายเลขผู้โทรได้รับการตั้งค่าเริ่มต้นเป็นไม่จำกัด การโทรครั้งต่อไป: ไม่จำกัด"</string> - <string name="page_size_compat_apk_warning" msgid="2982396798449041224">"แอปนี้ไม่รองรับขนาดหน้า 16 KB ผลการตรวจสอบการจัดตำแหน่ง APK คือไม่ผ่าน ด้วยเหตุนี้ แอปจะทำงานโดยใช้โหมดการใช้งานร่วมกับขนาดหน้าได้ เพื่อให้ใช้งานร่วมกันได้อย่างดีที่สุด โปรดคอมไพล์แอปพลิเคชันอีกครั้งโดยมีการรองรับขนาดหน้า 16 KB ดูข้อมูลเพิ่มเติมได้ที่ <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> - <string name="page_size_compat_elf_warning" msgid="6753874059564812651">"แอปนี้ไม่รองรับขนาดหน้า 16 KB ผลการตรวจสอบการจัดตำแหน่ง ELF คือไม่ผ่าน ด้วยเหตุนี้ แอปจะทำงานโดยใช้โหมดการใช้งานร่วมกับขนาดหน้าได้ เพื่อให้ใช้งานร่วมกันได้อย่างดีที่สุด โปรดคอมไพล์แอปพลิเคชันอีกครั้งโดยมีการรองรับขนาดหน้า 16 KB ดูข้อมูลเพิ่มเติมได้ที่ <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> - <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"แอปนี้ไม่รองรับขนาดหน้า 16 KB ผลการตรวจสอบการจัดตำแหน่งของ APK และ ELF คือไม่ผ่าน ด้วยเหตุนี้ แอปจะทำงานโดยใช้โหมดการใช้งานร่วมกับขนาดหน้าได้ เพื่อให้ใช้งานร่วมกันได้อย่างดีที่สุด โปรดคอมไพล์แอปพลิเคชันอีกครั้งโดยมีการรองรับขนาดหน้า 16 KB ดูข้อมูลเพิ่มเติมได้ที่ <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> + <string name="page_size_compat_apk_warning" msgid="2982396798449041224">"แอปนี้ไม่รองรับขนาดหน้า 16 KB ผลตรวจสอบการจัดตำแหน่ง APK คือไม่ผ่าน ด้วยเหตุนี้แอปจะทำงานโดยใช้โหมดเข้ากันได้กับขนาดหน้า โปรดคอมไพล์แอปพลิเคชันอีกครั้งโดยมีการรองรับขนาดหน้า 16 KB เพื่อให้ใช้งานร่วมกันได้อย่างดีที่สุด ดูข้อมูลเพิ่มเติมได้ที่ <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> + <string name="page_size_compat_elf_warning" msgid="6753874059564812651">"แอปนี้ไม่รองรับขนาดหน้า 16 KB ผลตรวจสอบการจัดตำแหน่ง ELF คือไม่ผ่าน ด้วยเหตุนี้แอปจะทำงานโดยใช้โหมดเข้ากันได้กับขนาดหน้า โปรดคอมไพล์แอปพลิเคชันอีกครั้งโดยมีการรองรับขนาดหน้า 16 KB เพื่อให้ใช้งานร่วมกันได้อย่างดีที่สุด ดูข้อมูลเพิ่มเติมได้ที่ <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> + <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"แอปนี้ไม่รองรับขนาดหน้า 16 KB ผลตรวจสอบการจัดตำแหน่ง APK และ ELF คือไม่ผ่าน ด้วยเหตุนี้แอปจะทำงานโดยใช้โหมดเข้ากันได้กับขนาดหน้า โปรดคอมไพล์แอปพลิเคชันอีกครั้งโดยมีการรองรับขนาดหน้า 16 KB เพื่อให้ใช้งานร่วมกันได้อย่างดีที่สุด ดูข้อมูลเพิ่มเติมได้ที่ <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a>"</string> <string name="serviceNotProvisioned" msgid="8289333510236766193">"ไม่มีการนำเสนอบริการ"</string> <string name="CLIRPermanent" msgid="166443681876381118">"คุณไม่สามารถเปลี่ยนการตั้งค่าหมายเลขผู้โทร"</string> <string name="auto_data_switch_title" msgid="3286350716870518297">"เปลี่ยนไปใช้อินเทอร์เน็ตมือถือของ <xliff:g id="CARRIERDISPLAY">%s</xliff:g> แล้ว"</string> @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"เชื่อมต่อเครือข่ายมือถือไม่ได้"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"ลองเปลี่ยนเครือข่ายที่ต้องการ แตะเพื่อเปลี่ยน"</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"โทรหาหมายเลขฉุกเฉินไม่ได้"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"การโทรหาหมายเลขฉุกเฉินต้องใช้เครือข่ายมือถือ"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"การแจ้งเตือน"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"การโอนสาย"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"โหมดมือเดียว"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"หรี่แสงเพิ่มเติม"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"เครื่องช่วยฟัง"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"กดปุ่มปรับระดับเสียงค้างไว้แล้ว เปิด <xliff:g id="SERVICE_NAME">%1$s</xliff:g> แล้ว"</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"กดปุ่มปรับระดับเสียงค้างไว้แล้ว ปิด <xliff:g id="SERVICE_NAME">%1$s</xliff:g> แล้ว"</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"ปล่อยปุ่มปรับระดับเสียง หากต้องการเปิด <xliff:g id="SERVICE_NAME">%1$s</xliff:g> ให้กดปุ่มปรับระดับเสียงทั้ง 2 ปุ่มค้างไว้อีกครั้งเป็นเวลา 3 วินาที"</string> diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml index 6fd93bc5823c..0ab4fb2901b6 100644 --- a/core/res/res/values-tl/strings.xml +++ b/core/res/res/values-tl/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Hindi makakonekta sa mobile network"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Subukang baguhin ang gustong network. I-tap para baguhin."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Hindi available ang pang-emergency na pagtawag"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Kailangan ng mobile network para sa mga emergency na tawag"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Mga Alerto"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Pagpasa ng tawag"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"One-Hand mode"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Extra dim"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Mga hearing device"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Pinindot nang matagal ang volume keys. Na-on ang <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Pinindot nang matagal ang volume keys. Na-off ang <xliff:g id="SERVICE_NAME">%1$s</xliff:g>."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Bitawan ang mga volume key. Para i-on ang <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, muling pindutin nang matagal ang dalawang volume key sa loob ng 3 segundo."</string> diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml index 16915b5b43f7..78ce9d4d3ae5 100644 --- a/core/res/res/values-tr/strings.xml +++ b/core/res/res/values-tr/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Mobil ağa erişilemiyor"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Tercih edilen ağı değiştirmeyi deneyin. Değiştirmek için dokunun."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Acil durum çağrısı kullanılamaz"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Acil durum aramaları için mobil ağ gereklidir"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Uyarılar"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Çağrı yönlendirme"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Tek El modu"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Ekstra loş"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"İşitme cihazları"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Ses tuşlarını basılı tuttunuz. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> açıldı."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Ses tuşlarını basılı tuttunuz. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> kapatıldı."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Ses seviyesi tuşlarını bırakın. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> hizmetini etkinleştirmek için her iki ses seviyesi tuşuna yeniden basıp 3 saniye boyunca basılı tutun."</string> diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml index dcf15a0ff01c..a98fda433f8f 100644 --- a/core/res/res/values-uk/strings.xml +++ b/core/res/res/values-uk/strings.xml @@ -89,6 +89,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Не вдається під’єднатися до мобільної мережі"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Спробуйте змінити вибрану мережу. Торкніться, щоб це зробити."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Екстрені виклики недоступні"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Щоб здійснювати екстрені виклики, потрібне з’єднання з мобільною мережею"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Сповіщення"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Переадресація виклику"</string> @@ -1780,6 +1782,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Режим керування однією рукою"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Додаткове зменшення яскравості"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Слухові апарати"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Утримано клавіші гучності. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> увімкнено."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Утримано клавіші гучності. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> вимкнено."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Відпустіть клавіші гучності. Щоб увімкнути сервіс <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, натисніть і втримуйте обидві клавіші гучності протягом 3 секунд."</string> diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml index 8c75e818fb97..0a0047422a74 100644 --- a/core/res/res/values-ur/strings.xml +++ b/core/res/res/values-ur/strings.xml @@ -71,9 +71,9 @@ <string name="CLIRDefaultOnNextCallOff" msgid="5036749051007098105">"کالر ID کی ڈیفالٹ ترتیب محدود کردہ ہے۔ اگلی کال: غیر محدود کردہ"</string> <string name="CLIRDefaultOffNextCallOn" msgid="1022781126694885017">"کالر ID کی ڈیفالٹ ترتیب غیر محدود کردہ ہے۔ اگلی کال: محدود کردہ"</string> <string name="CLIRDefaultOffNextCallOff" msgid="2491576172356463443">"کالر ID کی ڈیفالٹ ترتیب غیر محدود کردہ ہے۔ اگلی کال: غیر محدود کردہ"</string> - <string name="page_size_compat_apk_warning" msgid="2982396798449041224">"یہ ایپ 16 KB کے موافق نہیں ہے۔ APK الائنمنٹ چیک ناکام ہو گیا۔ یہ ایپ صفحہ کے سائز کے ساتھ موافقت رکھنے والے موڈ کے ساتھ چلے گی۔ بہترین موافقت کے لیے، براہ کرم 16 KB کے سپورٹ کے ساتھ ایپلیکیشن کو دوبارہ مرتب کریں۔ مزید معلومات کے لیے، <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a> دیکھیں"</string> - <string name="page_size_compat_elf_warning" msgid="6753874059564812651">"یہ ایپ 16 KB کے موافق نہیں ہے۔ ELF الائنمنٹ چیک ناکام ہو گیا۔ یہ ایپ صفحہ کے سائز کے ساتھ موافقت رکھنے والے موڈ کے ساتھ چلے گی۔ بہترین موافقت کے لیے، براہ کرم 16 KB کے سپورٹ کے ساتھ ایپلیکیشن کو دوبارہ مرتب کریں۔ مزید معلومات کے لیے، <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a> دیکھیں"</string> - <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"یہ ایپ 16 KB کے موافق نہیں ہے۔ APK اور ELF الائنمنٹ چیکس ناکام ہو گئے۔ یہ ایپ صفحہ کے سائز کے ساتھ موافقت رکھنے والے موڈ کے ساتھ چلے گی۔ بہترین موافقت کے لیے، براہ کرم 16 KB کے سپورٹ کے ساتھ ایپلیکیشن کو دوبارہ مرتب کریں۔ مزید معلومات کے لیے، <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a> دیکھیں"</string> + <string name="page_size_compat_apk_warning" msgid="2982396798449041224">"یہ ایپ 16 KB کے موافق نہیں ہے۔ APK الائنمنٹ چیک ناکام ہو گیا۔ یہ ایپ صفحہ کے سائز کے ساتھ موافقت رکھنے والے موڈ کے ساتھ چلائی جائے گی۔ بہترین موافقت کے لیے، براہ کرم 16 KB کے سپورٹ کے ساتھ ایپلیکیشن کو دوبارہ کمپائل کریں۔ مزید معلومات کے لیے <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a> دیکھیں"</string> + <string name="page_size_compat_elf_warning" msgid="6753874059564812651">"یہ ایپ 16 KB کے موافق نہیں ہے۔ ELF الائنمنٹ چیک ناکام ہو گیا۔ یہ ایپ صفحہ کے سائز کے ساتھ موافقت رکھنے والے موڈ کے ساتھ چلائی جائے گی۔ بہترین موافقت کے لیے، براہ کرم 16 KB کے سپورٹ کے ساتھ ایپلیکیشن کو دوبارہ کمپائل کریں۔ مزید معلومات کے لیے <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a> دیکھیں"</string> + <string name="page_size_compat_apk_and_elf_warning" msgid="7628675779500605390">"یہ ایپ 16 KB کے موافق نہیں ہے۔ APK اور ELF الائنمنٹ چیکس ناکام ہو گئے۔ یہ ایپ صفحہ کے سائز کے ساتھ موافقت رکھنے والے موڈ کے ساتھ چلائی جائے گی۔ بہترین موافقت کے لیے، براہ کرم 16 KB کے سپورٹ کے ساتھ ایپلیکیشن کو دوبارہ کمپائل کریں۔ مزید معلومات کے لیے <a href=\"https://developer.android.com/16kb-page-size\">https://developer.android.com/16kb-page-size</a> دیکھیں"</string> <string name="serviceNotProvisioned" msgid="8289333510236766193">"سروس فراہم نہیں کی گئی۔"</string> <string name="CLIRPermanent" msgid="166443681876381118">"آپ کالر ID کی ترتیبات تبدیل نہیں کر سکتے ہیں۔"</string> <string name="auto_data_switch_title" msgid="3286350716870518297">"ڈیٹا <xliff:g id="CARRIERDISPLAY">%s</xliff:g> پر سوئچ کیا گیا"</string> @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"موبائل نیٹ ورک تک رسائی نہیں ہو سکتی"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"ترجیحی نیٹ ورک تبدیل کر کے دیکھیں۔ تبدیل کرنے کے لیے تھپتھپائیں۔"</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"ایمرجنسی کالنگ دستیاب نہیں ہے"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"ہنگامی کالز کو موبائل نیٹ ورک کی ضرورت ہے"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"الرٹس"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"کال فارورڈنگ"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"ایک ہاتھ کی وضع"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"اضافی مدھم"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"سماعتی آلات"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"والیوم کی کلیدوں کو دبائے رکھا گیا۔ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> آن ہے۔"</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"والیوم کی کلیدوں کو دبائے رکھا گیا۔ <xliff:g id="SERVICE_NAME">%1$s</xliff:g> آف ہے۔"</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"والیوم کی کلیدوں کو ریلیز کریں <xliff:g id="SERVICE_NAME">%1$s</xliff:g> کو آن کرنے کے لیے، والیوم کی دونوں کلیدوں کو دوبارہ 3 سیکنڈ تک چھوئیں اور دبائے رکھیں۔"</string> diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml index 89e2e6859137..2f158f411a47 100644 --- a/core/res/res/values-uz/strings.xml +++ b/core/res/res/values-uz/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Mobil tarmoqqa ulanib bo‘lmadi"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Tarmoq turini almashtiring. Almashtirish uchun bosing."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Favqulodda chaqiruv ishlamayapti"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Favqulodda chaqiruvlar uchun mobil tarmoq zarur"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Ogohlantirishlar"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Chaqiruvlarni uzatish"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Ixcham rejim"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Juda xira"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Eshitish qurilmalari"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Tovush tugmalari bosib turildi. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> yoqildi."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Tovush tugmalari bosib turildi. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> faolsizlantirildi."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Tovush tugmalarini qoʻyib yuboring. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> xizmatini yoqish uchun ikkala tovush tugmasini 3 soniya bosib turing."</string> diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml index ad0f42d2b868..adb3e023d59a 100644 --- a/core/res/res/values-vi/strings.xml +++ b/core/res/res/values-vi/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Không thể kết nối với mạng di động"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Hãy thử thay đổi mạng ưu tiên. Nhấn để thay đổi."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Không có dịch vụ gọi khẩn cấp"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Cần có mạng di động để thực hiện các cuộc gọi khẩn cấp"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Thông báo"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Chuyển tiếp cuộc gọi"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Chế độ một tay"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Siêu tối"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Thiết bị trợ thính"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Bạn đã giữ các phím âm lượng. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> đã bật."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Bạn đã giữ các phím âm lượng. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> đã tắt."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Thả phím âm lượng. Để bật <xliff:g id="SERVICE_NAME">%1$s</xliff:g>, hãy nhấn và giữ cả 2 phím âm lượng trong 3 giây một lần nữa."</string> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index 120c08c75505..dd90e25114d8 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"无法连接到移动网络"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"请尝试更改首选网络。点按即可更改。"</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"无法使用紧急呼救服务"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"紧急呼叫需要使用移动网络"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"提醒"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"来电转接"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"单手模式"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"极暗"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"助听装置"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"已按住音量键。<xliff:g id="SERVICE_NAME">%1$s</xliff:g>已开启。"</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"已按住音量键。<xliff:g id="SERVICE_NAME">%1$s</xliff:g>已关闭。"</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"松开音量键。如要启用 <xliff:g id="SERVICE_NAME">%1$s</xliff:g>,请再次同时按住两个音量键 3 秒。"</string> diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml index 9d6a2322fc48..d34ed3d68dbc 100644 --- a/core/res/res/values-zh-rHK/strings.xml +++ b/core/res/res/values-zh-rHK/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"無法連線至流動網絡"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"請嘗試變更偏好的網絡。輕按即可變更。"</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"無法撥打緊急電話"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"撥打緊急電話需要使用流動網絡"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"通知"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"來電轉駁"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"單手模式"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"超暗"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"助聽器"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"已按住音量鍵。<xliff:g id="SERVICE_NAME">%1$s</xliff:g> 已開啟。"</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"已按住音量鍵。<xliff:g id="SERVICE_NAME">%1$s</xliff:g> 已關閉。"</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"鬆開音量鍵。如果要開 <xliff:g id="SERVICE_NAME">%1$s</xliff:g>,請同時㩒住兩個音量鍵 3 秒。"</string> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index 7f22ab4a8d17..09d1a7b4e1ce 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"無法連上行動網路"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"請嘗試變更偏好的網路。輕觸即可變更。"</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"無法撥打緊急電話"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"撥打緊急電話需要使用行動網路"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"快訊"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"來電轉接"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"單手模式"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"超暗"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"助聽器"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"已按住音量鍵。「<xliff:g id="SERVICE_NAME">%1$s</xliff:g>」已開啟。"</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"已按住音量鍵。「<xliff:g id="SERVICE_NAME">%1$s</xliff:g>」已關閉。"</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"放開音量鍵。如要開啟 <xliff:g id="SERVICE_NAME">%1$s</xliff:g>,請同時按住音量調高鍵和調低鍵 3 秒。"</string> diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml index 0ac3e4af9554..cfc060ac4bab 100644 --- a/core/res/res/values-zu/strings.xml +++ b/core/res/res/values-zu/strings.xml @@ -87,6 +87,8 @@ <string name="NetworkPreferenceSwitchTitle" msgid="1008329951315753038">"Ayikwazi ukufinyelela kunethiwekhi yeselula"</string> <string name="NetworkPreferenceSwitchSummary" msgid="2086506181486324860">"Zama ukushintsha inethiwekhi encanyelwayo. Thepha ukuze ushintshe."</string> <string name="EmergencyCallWarningTitle" msgid="1615688002899152860">"Ukushaya okuphuthumayo akutholakali"</string> + <!-- no translation found for emergency_calling_do_not_show_again (5034171343309733068) --> + <skip /> <string name="EmergencyCallWarningSummary" msgid="9102799172089265268">"Amakholi aphuthumayo adinga inethiwekhi yeselula"</string> <string name="notification_channel_network_alert" msgid="4788053066033851841">"Izexwayiso"</string> <string name="notification_channel_call_forward" msgid="8230490317314272406">"Ukudlulisa ikholi"</string> @@ -1778,6 +1780,14 @@ <string name="one_handed_mode_feature_name" msgid="2334330034828094891">"Imodi yesandla esisodwa"</string> <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Ukufiphaza okwengeziwe"</string> <string name="hearing_aids_feature_name" msgid="1125892105105852542">"Amadivayizi okuzwa"</string> + <!-- no translation found for hearing_device_status_disconnected (497547752953543832) --> + <skip /> + <!-- no translation found for hearing_device_status_connected (2149385149669918764) --> + <skip /> + <!-- no translation found for hearing_device_status_active (4770378695482566032) --> + <skip /> + <!-- no translation found for hearing_device_status_loading (5717083847663109747) --> + <skip /> <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Ubambe okhiye bevolumu. I-<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ivuliwe."</string> <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Ubambe okhiye bevolumu. I-<xliff:g id="SERVICE_NAME">%1$s</xliff:g> ivaliwe."</string> <string name="accessibility_shortcut_spoken_feedback" msgid="3760999147597564314">"Khipha okhiye bevolumu. Ukuze uvule i-<xliff:g id="SERVICE_NAME">%1$s</xliff:g>, cindezela bese ubamba bobabili okhiye bevolumu futhi imizuzwana emi-3."</string> diff --git a/core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java b/core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java index e9dfdd826572..5da2564e5b7f 100644 --- a/core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java +++ b/core/tests/coretests/src/android/app/PropertyInvalidatedCacheTests.java @@ -194,38 +194,38 @@ public class PropertyInvalidatedCacheTests { new ServerQuery(tester)); // Caches are enabled upon creation. - assertEquals(false, cache1.getDisabledState()); - assertEquals(false, cache2.getDisabledState()); - assertEquals(false, cache3.getDisabledState()); + assertFalse(cache1.isDisabled()); + assertFalse(cache2.isDisabled()); + assertFalse(cache3.isDisabled()); // Disable the cache1 instance. Only cache1 is disabled cache1.disableInstance(); - assertEquals(true, cache1.getDisabledState()); - assertEquals(false, cache2.getDisabledState()); - assertEquals(false, cache3.getDisabledState()); + assertTrue(cache1.isDisabled()); + assertFalse(cache2.isDisabled()); + assertFalse(cache3.isDisabled()); // Disable cache1. This will disable cache1 and cache2 because they share the // same name. cache3 has a different name and will not be disabled. cache1.disableLocal(); - assertEquals(true, cache1.getDisabledState()); - assertEquals(true, cache2.getDisabledState()); - assertEquals(false, cache3.getDisabledState()); + assertTrue(cache1.isDisabled()); + assertTrue(cache2.isDisabled()); + assertFalse(cache3.isDisabled()); // Create a new cache1. Verify that the new instance is disabled. cache1 = new PropertyInvalidatedCache<>(4, MODULE, API, "cache1", new ServerQuery(tester)); - assertEquals(true, cache1.getDisabledState()); + assertTrue(cache1.isDisabled()); // Remove the record of caches being locally disabled. This is a clean-up step. cache1.forgetDisableLocal(); - assertEquals(true, cache1.getDisabledState()); - assertEquals(true, cache2.getDisabledState()); - assertEquals(false, cache3.getDisabledState()); + assertTrue(cache1.isDisabled()); + assertTrue(cache2.isDisabled()); + assertFalse(cache3.isDisabled()); // Create a new cache1. Verify that the new instance is not disabled. cache1 = new PropertyInvalidatedCache<>(4, MODULE, API, "cache1", new ServerQuery(tester)); - assertEquals(false, cache1.getDisabledState()); + assertFalse(cache1.isDisabled()); } private static class TestQuery @@ -280,7 +280,7 @@ public class PropertyInvalidatedCacheTests { public void testCacheRecompute() { TestCache cache = new TestCache(); cache.invalidateCache(); - assertEquals(cache.isDisabled(), false); + assertFalse(cache.isDisabled()); assertEquals("foo5", cache.query(5)); assertEquals(1, cache.getRecomputeCount()); assertEquals("foo5", cache.query(5)); @@ -383,15 +383,15 @@ public class PropertyInvalidatedCacheTests { @Test public void testLocalProcessDisable() { TestCache cache = new TestCache(); - assertEquals(cache.isDisabled(), false); + assertFalse(cache.isDisabled()); cache.invalidateCache(); assertEquals("foo5", cache.query(5)); assertEquals(1, cache.getRecomputeCount()); assertEquals("foo5", cache.query(5)); assertEquals(1, cache.getRecomputeCount()); - assertEquals(cache.isDisabled(), false); + assertFalse(cache.isDisabled()); cache.disableLocal(); - assertEquals(cache.isDisabled(), true); + assertTrue(cache.isDisabled()); assertEquals("foo5", cache.query(5)); assertEquals("foo5", cache.query(5)); assertEquals(3, cache.getRecomputeCount()); diff --git a/core/tests/coretests/src/android/os/IpcDataCacheTest.java b/core/tests/coretests/src/android/os/IpcDataCacheTest.java index fc04e6438ac6..74b32a17d964 100644 --- a/core/tests/coretests/src/android/os/IpcDataCacheTest.java +++ b/core/tests/coretests/src/android/os/IpcDataCacheTest.java @@ -19,6 +19,8 @@ package android.os; import static android.app.Flags.FLAG_PIC_ISOLATE_CACHE_BY_UID; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import android.app.PropertyInvalidatedCache; @@ -195,9 +197,9 @@ public class IpcDataCacheTest { try { testCache.query(9); - assertEquals(false, true); // The code should not reach this point. + fail(); // The code should not reach this point. } catch (RuntimeException e) { - assertEquals(e.getCause() instanceof RemoteException, true); + assertTrue(e.getCause() instanceof RemoteException); } tester.verify(4); } @@ -256,38 +258,38 @@ public class IpcDataCacheTest { new ServerQuery(tester)); // Caches are enabled upon creation. - assertEquals(false, cache1.getDisabledState()); - assertEquals(false, cache2.getDisabledState()); - assertEquals(false, cache3.getDisabledState()); + assertFalse(cache1.isDisabled()); + assertFalse(cache2.isDisabled()); + assertFalse(cache3.isDisabled()); // Disable the cache1 instance. Only cache1 is disabled cache1.disableInstance(); - assertEquals(true, cache1.getDisabledState()); - assertEquals(false, cache2.getDisabledState()); - assertEquals(false, cache3.getDisabledState()); + assertTrue(cache1.isDisabled()); + assertFalse(cache2.isDisabled()); + assertFalse(cache3.isDisabled()); // Disable cache1. This will disable cache1 and cache2 because they share the // same name. cache3 has a different name and will not be disabled. cache1.disableForCurrentProcess(); - assertEquals(true, cache1.getDisabledState()); - assertEquals(true, cache2.getDisabledState()); - assertEquals(false, cache3.getDisabledState()); + assertTrue(cache1.isDisabled()); + assertTrue(cache2.isDisabled()); + assertFalse(cache3.isDisabled()); // Create a new cache1. Verify that the new instance is disabled. cache1 = new IpcDataCache<>(4, MODULE, API, "cacheA", new ServerQuery(tester)); - assertEquals(true, cache1.getDisabledState()); + assertTrue(cache1.isDisabled()); // Remove the record of caches being locally disabled. This is a clean-up step. cache1.forgetDisableLocal(); - assertEquals(true, cache1.getDisabledState()); - assertEquals(true, cache2.getDisabledState()); - assertEquals(false, cache3.getDisabledState()); + assertTrue(cache1.isDisabled()); + assertTrue(cache2.isDisabled()); + assertFalse(cache3.isDisabled()); // Create a new cache1. Verify that the new instance is not disabled. cache1 = new IpcDataCache<>(4, MODULE, API, "cacheA", new ServerQuery(tester)); - assertEquals(false, cache1.getDisabledState()); + assertFalse(cache1.isDisabled()); } private static class TestQuery @@ -345,7 +347,7 @@ public class IpcDataCacheTest { public void testCacheRecompute() { TestCache cache = new TestCache(); cache.invalidateCache(); - assertEquals(cache.isDisabled(), false); + assertFalse(cache.isDisabled()); assertEquals("foo5", cache.query(5)); assertEquals(1, cache.getRecomputeCount()); assertEquals("foo5", cache.query(5)); @@ -407,15 +409,15 @@ public class IpcDataCacheTest { @Test public void testLocalProcessDisable() { TestCache cache = new TestCache(); - assertEquals(cache.isDisabled(), false); + assertFalse(cache.isDisabled()); cache.invalidateCache(); assertEquals("foo5", cache.query(5)); assertEquals(1, cache.getRecomputeCount()); assertEquals("foo5", cache.query(5)); assertEquals(1, cache.getRecomputeCount()); - assertEquals(cache.isDisabled(), false); + assertFalse(cache.isDisabled()); cache.disableForCurrentProcess(); - assertEquals(cache.isDisabled(), true); + assertTrue(cache.isDisabled()); assertEquals("foo5", cache.query(5)); assertEquals("foo5", cache.query(5)); assertEquals(3, cache.getRecomputeCount()); @@ -434,20 +436,20 @@ public class IpcDataCacheTest { TestCache dc = new TestCache(d); a.disableForCurrentProcess(); - assertEquals(ac.isDisabled(), true); - assertEquals(bc.isDisabled(), false); - assertEquals(cc.isDisabled(), false); - assertEquals(dc.isDisabled(), false); + assertTrue(ac.isDisabled()); + assertFalse(bc.isDisabled()); + assertFalse(cc.isDisabled()); + assertFalse(dc.isDisabled()); a.disableAllForCurrentProcess(); - assertEquals(ac.isDisabled(), true); - assertEquals(bc.isDisabled(), false); - assertEquals(cc.isDisabled(), false); - assertEquals(dc.isDisabled(), true); + assertTrue(ac.isDisabled()); + assertFalse(bc.isDisabled()); + assertFalse(cc.isDisabled()); + assertTrue(dc.isDisabled()); IpcDataCache.Config e = a.child("nameE"); TestCache ec = new TestCache(e); - assertEquals(ec.isDisabled(), true); + assertTrue(ec.isDisabled()); } diff --git a/core/tests/coretests/src/android/security/advancedprotection/AdvancedProtectionManagerTest.java b/core/tests/coretests/src/android/security/advancedprotection/AdvancedProtectionManagerTest.java new file mode 100644 index 000000000000..45864b01c795 --- /dev/null +++ b/core/tests/coretests/src/android/security/advancedprotection/AdvancedProtectionManagerTest.java @@ -0,0 +1,97 @@ +/* + * 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 android.security.advancedprotection; + +import static android.security.advancedprotection.AdvancedProtectionManager.ACTION_SHOW_ADVANCED_PROTECTION_SUPPORT_DIALOG; +import static android.security.advancedprotection.AdvancedProtectionManager.EXTRA_SUPPORT_DIALOG_FEATURE; +import static android.security.advancedprotection.AdvancedProtectionManager.EXTRA_SUPPORT_DIALOG_TYPE; +import static android.security.advancedprotection.AdvancedProtectionManager.FEATURE_ID_DISALLOW_CELLULAR_2G; +import static android.security.advancedprotection.AdvancedProtectionManager.SUPPORT_DIALOG_TYPE_BLOCKED_INTERACTION; +import static android.security.advancedprotection.AdvancedProtectionManager.SUPPORT_DIALOG_TYPE_DISABLED_SETTING; +import static android.security.advancedprotection.AdvancedProtectionManager.SUPPORT_DIALOG_TYPE_UNKNOWN; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; + +import android.content.Intent; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class AdvancedProtectionManagerTest { + private static final int FEATURE_ID_INVALID = -1; + private static final int SUPPORT_DIALOG_TYPE_INVALID = -1; + + @Test + public void testCreateSupportIntent_validFeature_validTypeUnknown_createsIntent() { + Intent intent = AdvancedProtectionManager.createSupportIntent( + FEATURE_ID_DISALLOW_CELLULAR_2G, SUPPORT_DIALOG_TYPE_UNKNOWN); + + assertEquals(ACTION_SHOW_ADVANCED_PROTECTION_SUPPORT_DIALOG, intent.getAction()); + assertEquals(FEATURE_ID_DISALLOW_CELLULAR_2G, intent.getIntExtra( + EXTRA_SUPPORT_DIALOG_FEATURE, FEATURE_ID_INVALID)); + assertEquals(SUPPORT_DIALOG_TYPE_UNKNOWN, intent.getIntExtra(EXTRA_SUPPORT_DIALOG_TYPE, + SUPPORT_DIALOG_TYPE_INVALID)); + } + + @Test + public void testCreateSupportIntent_validFeature_validTypeBlockedInteraction_createsIntent() { + Intent intent = AdvancedProtectionManager.createSupportIntent( + FEATURE_ID_DISALLOW_CELLULAR_2G, SUPPORT_DIALOG_TYPE_BLOCKED_INTERACTION); + + assertEquals(ACTION_SHOW_ADVANCED_PROTECTION_SUPPORT_DIALOG, intent.getAction()); + assertEquals(FEATURE_ID_DISALLOW_CELLULAR_2G, intent.getIntExtra( + EXTRA_SUPPORT_DIALOG_FEATURE, FEATURE_ID_INVALID)); + assertEquals(SUPPORT_DIALOG_TYPE_BLOCKED_INTERACTION, intent.getIntExtra( + EXTRA_SUPPORT_DIALOG_TYPE, SUPPORT_DIALOG_TYPE_INVALID)); + } + + @Test + public void testCreateSupportIntent_validFeature_validTypeDisabledSetting_createsIntent() { + Intent intent = AdvancedProtectionManager.createSupportIntent( + FEATURE_ID_DISALLOW_CELLULAR_2G, SUPPORT_DIALOG_TYPE_DISABLED_SETTING); + + assertEquals(ACTION_SHOW_ADVANCED_PROTECTION_SUPPORT_DIALOG, intent.getAction()); + assertEquals(FEATURE_ID_DISALLOW_CELLULAR_2G, intent.getIntExtra( + EXTRA_SUPPORT_DIALOG_FEATURE, FEATURE_ID_INVALID)); + assertEquals(SUPPORT_DIALOG_TYPE_DISABLED_SETTING, intent.getIntExtra( + EXTRA_SUPPORT_DIALOG_TYPE, SUPPORT_DIALOG_TYPE_INVALID)); + } + + @Test + public void testCreateSupportIntent_validFeature_invalidType_throwsIllegalArgument() { + assertThrows(IllegalArgumentException.class, () -> + AdvancedProtectionManager.createSupportIntent(FEATURE_ID_DISALLOW_CELLULAR_2G, + SUPPORT_DIALOG_TYPE_INVALID)); + } + + @Test + public void testCreateSupportIntent_invalidFeature_validType_throwsIllegalArgument() { + assertThrows(IllegalArgumentException.class, () -> + AdvancedProtectionManager.createSupportIntent(FEATURE_ID_INVALID, + SUPPORT_DIALOG_TYPE_BLOCKED_INTERACTION)); + } + + @Test + public void testCreateSupportIntent_invalidFeature_invalidType_throwsIllegalArgument() { + assertThrows(IllegalArgumentException.class, () -> + AdvancedProtectionManager.createSupportIntent(FEATURE_ID_INVALID, + SUPPORT_DIALOG_TYPE_INVALID)); + } +} diff --git a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelperTest.kt b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelperTest.kt index 957f0ca502a1..c45f6903c2e1 100644 --- a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelperTest.kt +++ b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarAnimationHelperTest.kt @@ -232,11 +232,16 @@ class BubbleBarAnimationHelperTest { val taskController = mock<TaskViewTaskController>() val bubble = createBubble("key", taskController).initialize(container) + val semaphore = Semaphore(0) + val after = Runnable { semaphore.release() } + activityScenario.onActivity { - animationHelper.animateExpansion(bubble) {} + animationHelper.animateExpansion(bubble, after) animatorTestRule.advanceTimeBy(1000) } getInstrumentation().waitForIdleSync() + assertThat(semaphore.tryAcquire(5, TimeUnit.SECONDS)).isTrue() + getInstrumentation().runOnMainSync { animationHelper.animateToRestPosition() animatorTestRule.advanceTimeBy(100) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java index 77891297a1bf..e96bc02c1198 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java @@ -1459,8 +1459,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont } moveToTop = change.hasFlags(FLAG_MOVED_TO_TOP); info.getChanges().remove(j); - } else if ((openShowWallpaper && change.hasFlags(FLAG_IS_WALLPAPER)) - || !change.hasFlags(FLAG_BACK_GESTURE_ANIMATED)) { + } else if ((openShowWallpaper && change.hasFlags(FLAG_IS_WALLPAPER))) { info.getChanges().remove(j); } else if (!mergePredictive && TransitionUtil.isClosingMode(change.getMode())) { mergePredictive = true; @@ -1483,6 +1482,13 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont if (moveToTop) { change.setFlags(change.getFlags() | FLAG_MOVED_TO_TOP); } + } else if (Flags.unifyBackNavigationTransition() + && change.hasFlags(FLAG_BACK_GESTURE_ANIMATED) + && change.getMode() == TRANSIT_CHANGE + && isCloseChangeExist(info, change)) { + // This is the original top target, don't add it into current transition + // if it is closing. + continue; } info.getChanges().add(i, change); } @@ -1814,6 +1820,17 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont return findComponentName(change) != null || findTaskId(change) != INVALID_TASK_ID; } + private static boolean isCloseChangeExist(TransitionInfo info, TransitionInfo.Change change) { + for (int j = info.getChanges().size() - 1; j >= 0; --j) { + final TransitionInfo.Change current = info.getChanges().get(j); + if (TransitionUtil.isClosingMode(current.getMode()) + && change.getLeash().isSameSurface(current.getLeash())) { + return true; + } + } + return false; + } + // Record the latest back gesture happen on which task. static class BackTransitionObserver implements Transitions.TransitionObserver { int mFocusedTaskId = INVALID_TASK_ID; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java index a73d43c54064..28da8bf3dd4d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java @@ -33,14 +33,12 @@ import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.app.ActivityManager; import android.content.Context; -import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.graphics.Color; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Binder; -import android.os.Trace; import android.view.IWindow; import android.view.LayoutInflater; import android.view.SurfaceControl; @@ -52,12 +50,10 @@ import android.widget.FrameLayout; import android.widget.ImageView; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import com.android.launcher3.icons.IconProvider; import com.android.wm.shell.R; import com.android.wm.shell.common.ScreenshotUtils; -import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SurfaceUtils; import java.util.function.Consumer; @@ -83,19 +79,9 @@ public class SplitDecorManager extends WindowlessWindowManager { private static final String RESIZING_BACKGROUND_SURFACE_NAME = "ResizingBackground"; private static final String GAP_BACKGROUND_SURFACE_NAME = "GapBackground"; - // Indicates the loading state of mIcon - enum IconLoadState { - NOT_LOADED, - LOADING, - LOADED - } - private final IconProvider mIconProvider; - private final ShellExecutor mMainExecutor; - private final ShellExecutor mBgExecutor; private Drawable mIcon; - private IconLoadState mIconLoadState = IconLoadState.NOT_LOADED; private ImageView mVeilIconView; private SurfaceControlViewHost mViewHost; /** The parent surface that this is attached to. Should be the stage root. */ @@ -123,14 +109,9 @@ public class SplitDecorManager extends WindowlessWindowManager { private int mOffsetY; private int mRunningAnimationCount = 0; - public SplitDecorManager(Configuration configuration, - IconProvider iconProvider, - ShellExecutor mainExecutor, - ShellExecutor bgExecutor) { + public SplitDecorManager(Configuration configuration, IconProvider iconProvider) { super(configuration, null /* rootSurface */, null /* hostInputToken */); mIconProvider = iconProvider; - mMainExecutor = mainExecutor; - mBgExecutor = bgExecutor; } @Override @@ -218,7 +199,6 @@ public class SplitDecorManager extends WindowlessWindowManager { } mHostLeash = null; mIcon = null; - mIconLoadState = IconLoadState.NOT_LOADED; mVeilIconView = null; mIsCurrentlyChanging = false; mShown = false; @@ -310,11 +290,10 @@ public class SplitDecorManager extends WindowlessWindowManager { .setWindowCrop(mGapBackgroundLeash, sideBounds.width(), sideBounds.height()); } - if (mIconLoadState == IconLoadState.NOT_LOADED && resizingTask.topActivityInfo != null) { - loadIconInBackground(resizingTask.topActivityInfo, () -> { - mVeilIconView.setImageDrawable(mIcon); - mVeilIconView.setVisibility(View.VISIBLE); - }); + if (mIcon == null && resizingTask.topActivityInfo != null) { + mIcon = mIconProvider.getIcon(resizingTask.topActivityInfo); + mVeilIconView.setImageDrawable(mIcon); + mVeilIconView.setVisibility(View.VISIBLE); WindowManager.LayoutParams lp = (WindowManager.LayoutParams) mViewHost.getView().getLayoutParams(); @@ -468,10 +447,10 @@ public class SplitDecorManager extends WindowlessWindowManager { } if (mIcon == null && resizingTask.topActivityInfo != null) { - loadIconInBackground(resizingTask.topActivityInfo, () -> { - mVeilIconView.setImageDrawable(mIcon); - mVeilIconView.setVisibility(View.VISIBLE); - }); + // Initialize icon + mIcon = mIconProvider.getIcon(resizingTask.topActivityInfo); + mVeilIconView.setImageDrawable(mIcon); + mVeilIconView.setVisibility(View.VISIBLE); WindowManager.LayoutParams lp = (WindowManager.LayoutParams) mViewHost.getView().getLayoutParams(); @@ -504,7 +483,7 @@ public class SplitDecorManager extends WindowlessWindowManager { return; } - // Re-center icon + // Recenter icon t.setPosition(mIconLeash, mInstantaneousBounds.width() / 2f - mIconSize / 2f, mInstantaneousBounds.height() / 2f - mIconSize / 2f); @@ -647,38 +626,9 @@ public class SplitDecorManager extends WindowlessWindowManager { mVeilIconView.setImageDrawable(null); t.hide(mIconLeash); mIcon = null; - mIconLoadState = IconLoadState.NOT_LOADED; } } - /** - * Loads the icon for the given {@param info}, calling {@param postLoadCb} on the main thread - * if provided. - */ - private void loadIconInBackground(@NonNull ActivityInfo info, @Nullable Runnable postLoadCb) { - mIconLoadState = IconLoadState.LOADING; - mBgExecutor.setBoost(); - mBgExecutor.execute(() -> { - Trace.beginSection("SplitDecorManager.loadIconInBackground(" - + info.applicationInfo.packageName + ")"); - final Drawable icon = mIconProvider.getIcon(info); - Trace.endSection(); - mMainExecutor.execute(() -> { - if (mIconLoadState != IconLoadState.LOADING) { - // The request was canceled while loading in the background, just drop the - // result - return; - } - mIcon = icon; - mIconLoadState = IconLoadState.LOADED; - if (postLoadCb != null) { - postLoadCb.run(); - } - }); - mBgExecutor.resetBoost(); - }); - } - private static float[] getResizingBackgroundColor(ActivityManager.RunningTaskInfo taskInfo) { final int taskBgColor = taskInfo.taskDescription.getBackgroundColor(); return Color.valueOf(taskBgColor == -1 ? Color.WHITE : taskBgColor).getComponents(); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java index fc274d6e7174..cd5c135691d7 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java @@ -799,10 +799,6 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange } void onStartDragging() { - // This triggers initialization of things like the resize veil in preparation for - // showing it when the user moves the divider past the slop - updateDividerBounds(getDividerPosition(), false /* shouldUseParallaxEffect */); - mInteractionJankMonitor.begin(getDividerLeash(), mContext, mHandler, CUJ_SPLIT_SCREEN_RESIZE); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java index 5b6b897e55d9..aebd94fc173a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java @@ -34,7 +34,6 @@ import com.android.wm.shell.common.split.SplitState; import com.android.wm.shell.dagger.pip.TvPipModule; import com.android.wm.shell.recents.RecentTasksController; import com.android.wm.shell.shared.TransactionPool; -import com.android.wm.shell.shared.annotations.ShellBackgroundThread; import com.android.wm.shell.shared.annotations.ShellMainThread; import com.android.wm.shell.splitscreen.SplitScreenController; import com.android.wm.shell.splitscreen.tv.TvSplitScreenController; @@ -94,12 +93,11 @@ public class TvWMShellModule { SplitState splitState, @ShellMainThread ShellExecutor mainExecutor, Handler mainHandler, - @ShellBackgroundThread ShellExecutor bgExecutor, SystemWindows systemWindows) { return new TvSplitScreenController(context, shellInit, shellCommandHandler, shellController, shellTaskOrganizer, syncQueue, rootTDAOrganizer, displayController, displayImeController, displayInsetsController, transitions, transactionPool, iconProvider, recentTasks, launchAdjacentController, multiInstanceHelper, - splitState, mainExecutor, mainHandler, bgExecutor, systemWindows); + splitState, mainExecutor, mainHandler, systemWindows); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java index 48b0a6cb364b..1916215dea74 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java @@ -520,8 +520,7 @@ public abstract class WMShellModule { MultiInstanceHelper multiInstanceHelper, SplitState splitState, @ShellMainThread ShellExecutor mainExecutor, - @ShellMainThread Handler mainHandler, - @ShellBackgroundThread ShellExecutor bgExecutor) { + @ShellMainThread Handler mainHandler) { return new SplitScreenController( context, shellInit, @@ -545,8 +544,7 @@ public abstract class WMShellModule { multiInstanceHelper, splitState, mainExecutor, - mainHandler, - bgExecutor); + mainHandler); } // diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUiEventLogger.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUiEventLogger.kt index 301ba9e76fc5..b96b9d2adddf 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUiEventLogger.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeUiEventLogger.kt @@ -145,7 +145,11 @@ class DesktopModeUiEventLogger( @UiEvent(doc = "Moving the desktop window by dragging the header") DESKTOP_WINDOW_MOVE_BY_HEADER_DRAG(2021), @UiEvent(doc = "Double tap on the window header to refocus a desktop window") - DESKTOP_WINDOW_HEADER_TAP_TO_REFOCUS(2022); + DESKTOP_WINDOW_HEADER_TAP_TO_REFOCUS(2022), + @UiEvent(doc = "Enter multi-instance by using the New Window button") + DESKTOP_WINDOW_MULTI_INSTANCE_NEW_WINDOW_CLICK(2069), + @UiEvent(doc = "Enter multi-instance by clicking an icon in the Manage Windows menu") + DESKTOP_WINDOW_MULTI_INSTANCE_MANAGE_WINDOWS_ICON_CLICK(2070); override fun getId(): Int = mId } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java index 55e90e74a404..bec75b3d865c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java @@ -664,10 +664,12 @@ public class PipAnimationController { // TODO(b/375977163): polish the animation to restoring the PIP task back from // swipe-pip-to-home. Ideally we should send the transitionInfo after reparenting // the PIP activity back to the original task. - if (shouldUseMainWindowFrame) { + if (shouldUseMainWindowFrame && isOutPipDirection) { // If we should animate the main window frame, set it to the rotatedRect // instead. The end bounds reported by transitionInfo is the bounds before // rotation, while main window frame is calculated after the rotation. + // Note that we only override main window frame for leaving pip animation as + // the pip activity should match parent. rotatedEndRect.set(mainWindowFrame); } else { // Rotate the end bounds according to the rotation delta because the display @@ -810,11 +812,19 @@ public class PipAnimationController { } } final Rect sourceBounds = new Rect(initialContainerRect); + Rect relativeEndWindowFrame = null; + if (isOutPipDirection) { + relativeEndWindowFrame = rotatedEndRect; + } + if (relativeEndWindowFrame != null) { + relativeEndWindowFrame.offset(leashOffset.x, leashOffset.y); + } sourceBounds.inset(insets); getSurfaceTransactionHelper() .rotateAndScaleWithCrop(tx, leash, initialContainerRect, bounds, insets, degree, x, y, isOutPipDirection, - rotationDelta == ROTATION_270 /* clockwise */) + rotationDelta == ROTATION_270 /* clockwise */, + relativeEndWindowFrame) .round(tx, leash, sourceBounds, bounds) .shadow(tx, leash, shouldApplyShadowRadius()); if (!handlePipTransaction(leash, tx, bounds, 1f /* alpha */)) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java index b02bd0ffec6c..955a981799f5 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java @@ -25,6 +25,8 @@ import android.graphics.RectF; import android.view.Choreographer; import android.view.SurfaceControl; +import androidx.annotation.Nullable; + import com.android.wm.shell.R; import com.android.wm.shell.transition.Transitions; @@ -224,12 +226,17 @@ public class PipSurfaceTransactionHelper { /** * Operates the rotation according to the given degrees and scale (setMatrix) according to the * source bounds and rotated destination bounds. The crop will be the unscaled source bounds. + * + * @param relativeEndWindowFrame specified if + * {@link android.app.TaskInfo#topActivityMainWindowFrame} is provided. It's only applied for + * the animation that {@code isExpanding} PIP to original task. * @return same {@link PipSurfaceTransactionHelper} instance for method chaining */ - public PipSurfaceTransactionHelper rotateAndScaleWithCrop(SurfaceControl.Transaction tx, - SurfaceControl leash, Rect sourceBounds, Rect destinationBounds, Rect insets, + public PipSurfaceTransactionHelper rotateAndScaleWithCrop( + @NonNull SurfaceControl.Transaction tx, @NonNull SurfaceControl leash, + @NonNull Rect sourceBounds, @NonNull Rect destinationBounds, @NonNull Rect insets, float degrees, float positionX, float positionY, boolean isExpanding, - boolean clockwise) { + boolean clockwise, @Nullable Rect relativeEndWindowFrame) { mTmpDestinationRect.set(sourceBounds); mTmpDestinationRect.inset(insets); final int srcW = mTmpDestinationRect.width(); @@ -240,23 +247,31 @@ public class PipSurfaceTransactionHelper { // destination are different. final float scale = srcW <= srcH ? (float) destW / srcW : (float) destH / srcH; final Rect crop = mTmpDestinationRect; - crop.set(0, 0, Transitions.SHELL_TRANSITIONS_ROTATION ? destH - : destW, Transitions.SHELL_TRANSITIONS_ROTATION ? destW : destH); - // Inverse scale for crop to fit in screen coordinates. - crop.scale(1 / scale); - crop.offset(insets.left, insets.top); - if (isExpanding) { - // Expand bounds (shrink insets) in source orientation. - positionX -= insets.left * scale; - positionY -= insets.top * scale; + if (isExpanding && relativeEndWindowFrame != null) { + // If relative end window frame is provided, it usually means the top activity chooses + // a customized layout which may not match parent. In this case, we should crop the + // task surface with the window frame. Note that we don't need to consider the insets + // because the main window frame excludes the insets. + crop.set(relativeEndWindowFrame); } else { - // Shrink bounds (expand insets) in destination orientation. - if (clockwise) { - positionX -= insets.top * scale; - positionY += insets.left * scale; + crop.set(0, 0, Transitions.SHELL_TRANSITIONS_ROTATION ? destH + : destW, Transitions.SHELL_TRANSITIONS_ROTATION ? destW : destH); + // Inverse scale for crop to fit in screen coordinates. + crop.scale(1 / scale); + crop.offset(insets.left, insets.top); + if (isExpanding) { + // Expand bounds (shrink insets) in source orientation. + positionX -= insets.left * scale; + positionY -= insets.top * scale; } else { - positionX += insets.top * scale; - positionY -= insets.left * scale; + // Shrink bounds (expand insets) in destination orientation. + if (clockwise) { + positionX -= insets.top * scale; + positionY += insets.left * scale; + } else { + positionX += insets.top * scale; + positionY -= insets.left * scale; + } } } mTmpTransform.setScale(scale, scale); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java index 0042ec954f32..bd676ce69cfe 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java @@ -844,7 +844,8 @@ public class PipTransition extends PipTransitionController { } mSurfaceTransactionHelper.rotateAndScaleWithCrop(finishTransaction, pipLeash, endBounds, endBounds, new Rect(), degree, x, y, - true /* isExpanding */, rotationDelta == ROTATION_270 /* clockwise */); + true /* isExpanding */, rotationDelta == ROTATION_270 /* clockwise */, + null /* relativeEndWindowFrame */); } else { rotationDelta = Surface.ROTATION_0; } @@ -868,7 +869,9 @@ public class PipTransition extends PipTransitionController { // Get the start bounds in new orientation. final Rect startBounds = new Rect(pipChange.getStartAbsBounds()); rotateBounds(startBounds, displayRotationChange.getStartAbsBounds(), rotateDelta); - final Rect endBounds = new Rect(pipChange.getEndAbsBounds()); + final Rect windowFrame = taskInfo.topActivityMainWindowFrame; + final Rect endBounds = new Rect(windowFrame != null + ? windowFrame : pipChange.getEndAbsBounds()); startBounds.offset(-offset.x, -offset.y); endBounds.offset(-offset.x, -offset.y); @@ -888,7 +891,7 @@ public class PipTransition extends PipTransitionController { } mSurfaceTransactionHelper.rotateAndScaleWithCrop(startTransaction, pipChange.getLeash(), endBounds, startBounds, new Rect(), degree, x, y, true /* isExpanding */, - pipRotateDelta == ROTATION_270 /* clockwise */); + pipRotateDelta == ROTATION_270 /* clockwise */, null /* relativeEndWindowFrame */); startTransaction.apply(); rotator.cleanUp(finishTransaction); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java index 39ed2061c675..c724135aeced 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java @@ -185,7 +185,6 @@ public class SplitScreenController implements SplitDragPolicy.Starter, private final LauncherApps mLauncherApps; private final RootTaskDisplayAreaOrganizer mRootTDAOrganizer; private final ShellExecutor mMainExecutor; - private final ShellExecutor mBgExecutor; private final Handler mMainHandler; private final SplitScreenImpl mImpl = new SplitScreenImpl(); private final DisplayController mDisplayController; @@ -232,8 +231,7 @@ public class SplitScreenController implements SplitDragPolicy.Starter, MultiInstanceHelper multiInstanceHelper, SplitState splitState, ShellExecutor mainExecutor, - Handler mainHandler, - ShellExecutor bgExecutor) { + Handler mainHandler) { mShellCommandHandler = shellCommandHandler; mShellController = shellController; mTaskOrganizer = shellTaskOrganizer; @@ -243,7 +241,6 @@ public class SplitScreenController implements SplitDragPolicy.Starter, mRootTDAOrganizer = rootTDAOrganizer; mMainExecutor = mainExecutor; mMainHandler = mainHandler; - mBgExecutor = bgExecutor; mDisplayController = displayController; mDisplayImeController = displayImeController; mDisplayInsetsController = displayInsetsController; @@ -301,9 +298,8 @@ public class SplitScreenController implements SplitDragPolicy.Starter, return new StageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue, mTaskOrganizer, mDisplayController, mDisplayImeController, mDisplayInsetsController, mTransitions, mTransactionPool, mIconProvider, - mMainExecutor, mMainHandler, mBgExecutor, mRecentTasksOptional, - mLaunchAdjacentController, mWindowDecorViewModel, mSplitState, - mDesktopTasksController); + mMainExecutor, mMainHandler, mRecentTasksOptional, mLaunchAdjacentController, + mWindowDecorViewModel, mSplitState, mDesktopTasksController); } @Override diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java index 8ecf483a7e75..90c59176b991 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java @@ -217,7 +217,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, private final SplitscreenEventLogger mLogger; private final ShellExecutor mMainExecutor; private final Handler mMainHandler; - private final ShellExecutor mBgExecutor; // Cache live tile tasks while entering recents, evict them from stages in finish transaction // if user is opening another task(s). private final ArrayList<Integer> mPausingTasks = new ArrayList<>(); @@ -346,20 +345,12 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } }; - protected StageCoordinator(Context context, - int displayId, - SyncTransactionQueue syncQueue, - ShellTaskOrganizer taskOrganizer, - DisplayController displayController, + protected StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue, + ShellTaskOrganizer taskOrganizer, DisplayController displayController, DisplayImeController displayImeController, - DisplayInsetsController displayInsetsController, - Transitions transitions, - TransactionPool transactionPool, - IconProvider iconProvider, - ShellExecutor mainExecutor, - Handler mainHandler, - ShellExecutor bgExecutor, - Optional<RecentTasksController> recentTasks, + DisplayInsetsController displayInsetsController, Transitions transitions, + TransactionPool transactionPool, IconProvider iconProvider, ShellExecutor mainExecutor, + Handler mainHandler, Optional<RecentTasksController> recentTasks, LaunchAdjacentController launchAdjacentController, Optional<WindowDecorViewModel> windowDecorViewModel, SplitState splitState, Optional<DesktopTasksController> desktopTasksController) { @@ -370,7 +361,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mLogger = new SplitscreenEventLogger(); mMainExecutor = mainExecutor; mMainHandler = mainHandler; - mBgExecutor = bgExecutor; mRecentTasks = recentTasks; mLaunchAdjacentController = launchAdjacentController; mWindowDecorViewModel = windowDecorViewModel; @@ -387,8 +377,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, this /*stageListenerCallbacks*/, mSyncQueue, iconProvider, - mMainExecutor, - mBgExecutor, mWindowDecorViewModel); } else { mMainStage = new StageTaskListener( @@ -398,8 +386,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, this /*stageListenerCallbacks*/, mSyncQueue, iconProvider, - mMainExecutor, - mBgExecutor, mWindowDecorViewModel, STAGE_TYPE_MAIN); mSideStage = new StageTaskListener( mContext, @@ -408,8 +394,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, this /*stageListenerCallbacks*/, mSyncQueue, iconProvider, - mMainExecutor, - mBgExecutor, mWindowDecorViewModel, STAGE_TYPE_SIDE); } mDisplayController = displayController; @@ -431,22 +415,13 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } @VisibleForTesting - StageCoordinator(Context context, - int displayId, - SyncTransactionQueue syncQueue, - ShellTaskOrganizer taskOrganizer, - StageTaskListener mainStage, - StageTaskListener sideStage, - DisplayController displayController, + StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue, + ShellTaskOrganizer taskOrganizer, StageTaskListener mainStage, + StageTaskListener sideStage, DisplayController displayController, DisplayImeController displayImeController, - DisplayInsetsController displayInsetsController, - SplitLayout splitLayout, - Transitions transitions, - TransactionPool transactionPool, - ShellExecutor mainExecutor, - Handler mainHandler, - ShellExecutor bgExecutor, - Optional<RecentTasksController> recentTasks, + DisplayInsetsController displayInsetsController, SplitLayout splitLayout, + Transitions transitions, TransactionPool transactionPool, ShellExecutor mainExecutor, + Handler mainHandler, Optional<RecentTasksController> recentTasks, LaunchAdjacentController launchAdjacentController, Optional<WindowDecorViewModel> windowDecorViewModel, SplitState splitState, Optional<DesktopTasksController> desktopTasksController) { @@ -466,7 +441,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mLogger = new SplitscreenEventLogger(); mMainExecutor = mainExecutor; mMainHandler = mainHandler; - mBgExecutor = bgExecutor; mRecentTasks = recentTasks; mLaunchAdjacentController = launchAdjacentController; mWindowDecorViewModel = windowDecorViewModel; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageOrderOperator.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageOrderOperator.kt index 5256e7867499..a92100410d3d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageOrderOperator.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageOrderOperator.kt @@ -20,7 +20,6 @@ import android.content.Context import com.android.internal.protolog.ProtoLog import com.android.launcher3.icons.IconProvider import com.android.wm.shell.ShellTaskOrganizer -import com.android.wm.shell.common.ShellExecutor import com.android.wm.shell.common.SyncTransactionQueue import com.android.wm.shell.protolog.ShellProtoLogGroup import com.android.wm.shell.shared.split.SplitScreenConstants @@ -53,8 +52,6 @@ class StageOrderOperator ( stageCallbacks: StageTaskListener.StageListenerCallbacks, syncQueue: SyncTransactionQueue, iconProvider: IconProvider, - mainExecutor: ShellExecutor, - bgExecutor: ShellExecutor, windowDecorViewModel: Optional<WindowDecorViewModel> ) { @@ -86,8 +83,6 @@ class StageOrderOperator ( stageCallbacks, syncQueue, iconProvider, - mainExecutor, - bgExecutor, windowDecorViewModel, stageIds[i]) ) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java index 29751986959b..bfe74122c5c2 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java @@ -48,7 +48,6 @@ import com.android.internal.protolog.ProtoLog; import com.android.internal.util.ArrayUtils; import com.android.launcher3.icons.IconProvider; import com.android.wm.shell.ShellTaskOrganizer; -import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SurfaceUtils; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.split.SplitDecorManager; @@ -96,8 +95,6 @@ public class StageTaskListener implements ShellTaskOrganizer.TaskListener { private final StageListenerCallbacks mCallbacks; private final SyncTransactionQueue mSyncQueue; private final IconProvider mIconProvider; - private final ShellExecutor mMainExecutor; - private final ShellExecutor mBgExecutor; private final Optional<WindowDecorViewModel> mWindowDecorViewModel; /** Whether or not the root task has been created. */ @@ -114,21 +111,14 @@ public class StageTaskListener implements ShellTaskOrganizer.TaskListener { // TODO(b/204308910): Extracts SplitDecorManager related code to common package. private SplitDecorManager mSplitDecorManager; - StageTaskListener(Context context, - ShellTaskOrganizer taskOrganizer, - int displayId, - StageListenerCallbacks callbacks, - SyncTransactionQueue syncQueue, + StageTaskListener(Context context, ShellTaskOrganizer taskOrganizer, int displayId, + StageListenerCallbacks callbacks, SyncTransactionQueue syncQueue, IconProvider iconProvider, - ShellExecutor mainExecutor, - ShellExecutor bgExecutor, Optional<WindowDecorViewModel> windowDecorViewModel, int id) { mContext = context; mCallbacks = callbacks; mSyncQueue = syncQueue; mIconProvider = iconProvider; - mMainExecutor = mainExecutor; - mBgExecutor = bgExecutor; mWindowDecorViewModel = windowDecorViewModel; taskOrganizer.createRootTask(displayId, WINDOWING_MODE_MULTI_WINDOW, this); mId = id; @@ -224,8 +214,9 @@ public class StageTaskListener implements ShellTaskOrganizer.TaskListener { if (mRootTaskInfo == null) { mRootLeash = leash; mRootTaskInfo = taskInfo; - mSplitDecorManager = new SplitDecorManager(mRootTaskInfo.configuration, mIconProvider, - mMainExecutor, mBgExecutor); + mSplitDecorManager = new SplitDecorManager( + mRootTaskInfo.configuration, + mIconProvider); mHasRootTask = true; mCallbacks.onRootTaskAppeared(); if (mVisible != mRootTaskInfo.isVisible) { @@ -353,6 +344,12 @@ public class StageTaskListener implements ShellTaskOrganizer.TaskListener { } } + void screenshotIfNeeded(SurfaceControl.Transaction t) { + if (mSplitDecorManager != null) { + mSplitDecorManager.screenshotIfNeeded(t); + } + } + void fadeOutDecor(Runnable finishedCallback) { if (mSplitDecorManager != null) { mSplitDecorManager.fadeOutDecor(finishedCallback, false /* addDelay */); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java index ea7553061137..c5e158c6b452 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java @@ -53,7 +53,6 @@ public class TvSplitScreenController extends SplitScreenController { private final SyncTransactionQueue mSyncQueue; private final Context mContext; private final ShellExecutor mMainExecutor; - private final ShellExecutor mBgExecutor; private final DisplayController mDisplayController; private final DisplayImeController mDisplayImeController; private final DisplayInsetsController mDisplayInsetsController; @@ -86,20 +85,18 @@ public class TvSplitScreenController extends SplitScreenController { SplitState splitState, ShellExecutor mainExecutor, Handler mainHandler, - ShellExecutor bgExecutor, SystemWindows systemWindows) { super(context, shellInit, shellCommandHandler, shellController, shellTaskOrganizer, syncQueue, rootTDAOrganizer, displayController, displayImeController, displayInsetsController, null, transitions, transactionPool, iconProvider, recentTasks, launchAdjacentController, Optional.empty(), Optional.empty(), null /* stageCoordinator */, multiInstanceHelper, splitState, - mainExecutor, mainHandler, bgExecutor); + mainExecutor, mainHandler); + mTaskOrganizer = shellTaskOrganizer; mSyncQueue = syncQueue; mContext = context; mMainExecutor = mainExecutor; - mMainHandler = mainHandler; - mBgExecutor = bgExecutor; mDisplayController = displayController; mDisplayImeController = displayImeController; mDisplayInsetsController = displayInsetsController; @@ -109,6 +106,8 @@ public class TvSplitScreenController extends SplitScreenController { mRecentTasksOptional = recentTasks; mLaunchAdjacentController = launchAdjacentController; mSplitState = splitState; + + mMainHandler = mainHandler; mSystemWindows = systemWindows; } @@ -121,7 +120,7 @@ public class TvSplitScreenController extends SplitScreenController { return new TvStageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue, mTaskOrganizer, mDisplayController, mDisplayImeController, mDisplayInsetsController, mTransitions, mTransactionPool, - mIconProvider, mMainExecutor, mMainHandler, mBgExecutor, + mIconProvider, mMainExecutor, mMainHandler, mRecentTasksOptional, mLaunchAdjacentController, mSplitState, mSystemWindows); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvStageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvStageCoordinator.java index 9d85bea421ae..e1bf12fc6082 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvStageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvStageCoordinator.java @@ -51,14 +51,14 @@ public class TvStageCoordinator extends StageCoordinator DisplayInsetsController displayInsetsController, Transitions transitions, TransactionPool transactionPool, IconProvider iconProvider, ShellExecutor mainExecutor, - Handler mainHandler, ShellExecutor bgExecutor, + Handler mainHandler, Optional<RecentTasksController> recentTasks, LaunchAdjacentController launchAdjacentController, SplitState splitState, SystemWindows systemWindows) { super(context, displayId, syncQueue, taskOrganizer, displayController, displayImeController, displayInsetsController, transitions, transactionPool, iconProvider, - mainExecutor, mainHandler, bgExecutor, recentTasks, launchAdjacentController, + mainExecutor, mainHandler, recentTasks, launchAdjacentController, Optional.empty(), splitState, Optional.empty()); mTvSplitMenuController = new TvSplitMenuController(context, this, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java index 046cb202fb11..9fbda46bd2b7 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java @@ -795,6 +795,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, } decoration.closeHandleMenu(); mDesktopTasksController.openNewWindow(decoration.mTaskInfo); + mDesktopModeUiEventLogger.log(decoration.mTaskInfo, + DesktopUiEventEnum.DESKTOP_WINDOW_MULTI_INSTANCE_NEW_WINDOW_CLICK); } private void onManageWindows(DesktopModeWindowDecoration decoration) { @@ -811,6 +813,9 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, decoration.closeManageWindowsMenu(); mDesktopTasksController.openInstance(decoration.mTaskInfo, requestedTaskId); + mDesktopModeUiEventLogger.log(decoration.mTaskInfo, + DesktopUiEventEnum + .DESKTOP_WINDOW_MULTI_INSTANCE_MANAGE_WINDOWS_ICON_CLICK); return Unit.INSTANCE; } ) diff --git a/libs/WindowManager/Shell/tests/flicker/pip/Android.bp b/libs/WindowManager/Shell/tests/flicker/pip/Android.bp index 6e0dcdb21fa8..c760cf1d2094 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/Android.bp +++ b/libs/WindowManager/Shell/tests/flicker/pip/Android.bp @@ -75,8 +75,8 @@ android_test { ], static_libs: ["WMShellFlickerTestsBase"], test_suites: [ - "device-tests", "csuite", + "device-tests", ], data: ["trace_config/*"], } @@ -117,9 +117,11 @@ test_module_config { "com.android.wm.shell.flicker.pip.ShowPipAndRotateDisplay", "com.android.wm.shell.flicker.pip.nonmatchparent.BottomHalfAutoEnterPipOnGoToHomeTest", "com.android.wm.shell.flicker.pip.nonmatchparent.BottomHalfEnterPipOnUserLeaveHintTest", + "com.android.wm.shell.flicker.pip.nonmatchparent.BottomHalfEnterPipToOtherOrientation", "com.android.wm.shell.flicker.pip.nonmatchparent.BottomHalfEnterPipViaAppUiButtonTest", "com.android.wm.shell.flicker.pip.nonmatchparent.BottomHalfExitPipToAppViaExpandButtonTest", "com.android.wm.shell.flicker.pip.nonmatchparent.BottomHalfExitPipToAppViaIntentTest", + "com.android.wm.shell.flicker.pip.nonmatchparent.BottomHalfSetRequestedOrientationWhilePinned", ], test_suites: ["device-tests"], } @@ -308,5 +310,19 @@ test_module_config { test_suites: ["device-tests"], } +test_module_config { + name: "WMShellFlickerTestsPip-BottomHalfEnterPipToOtherOrientation", + base: "WMShellFlickerTestsPip", + include_filters: ["com.android.wm.shell.flicker.pip.nonmatchparent.BottomHalfEnterPipToOtherOrientation"], + test_suites: ["device-tests"], +} + +test_module_config { + name: "WMShellFlickerTestsPip-BottomHalfSetRequestedOrientationWhilePinned", + base: "WMShellFlickerTestsPip", + include_filters: ["com.android.wm.shell.flicker.pip.nonmatchparent.BottomHalfSetRequestedOrientationWhilePinned"], + test_suites: ["device-tests"], +} + // End breakdowns for WMShellFlickerTestsPip module //////////////////////////////////////////////////////////////////////////////// diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt index 49efd1d56256..636549fa0662 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt @@ -16,7 +16,6 @@ package com.android.wm.shell.flicker.pip -import android.app.Activity import android.platform.test.annotations.Postsubmit import android.platform.test.annotations.Presubmit import android.platform.test.annotations.RequiresFlagsDisabled @@ -38,9 +37,10 @@ import com.android.wm.shell.Flags import com.android.wm.shell.flicker.pip.common.PipTransition import com.android.wm.shell.flicker.pip.common.PipTransition.BroadcastActionTrigger.Companion.ORIENTATION_LANDSCAPE import com.android.wm.shell.flicker.pip.common.PipTransition.BroadcastActionTrigger.Companion.ORIENTATION_PORTRAIT -import org.junit.Assume -import org.junit.Before +import org.junit.Assume.assumeFalse +import org.junit.Assume.assumeTrue import org.junit.FixMethodOrder +import org.junit.Ignore import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.MethodSorters @@ -72,10 +72,10 @@ import org.junit.runners.Parameterized @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) @RequiresFlagsDisabled(Flags.FLAG_ENABLE_PIP2) -class EnterPipToOtherOrientation(flicker: LegacyFlickerTest) : PipTransition(flicker) { +open class EnterPipToOtherOrientation(flicker: LegacyFlickerTest) : PipTransition(flicker) { override val pipApp: PipAppHelper = PipAppHelper(instrumentation) - private val testApp = FixedOrientationAppHelper(instrumentation) - private val startingBounds = WindowUtils.getDisplayBounds(Rotation.ROTATION_90) + internal val testApp = FixedOrientationAppHelper(instrumentation) + internal val startingBounds = WindowUtils.getDisplayBounds(Rotation.ROTATION_90) private val endingBounds = WindowUtils.getDisplayBounds(Rotation.ROTATION_0) override val thisTransition: FlickerBuilder.() -> Unit = { @@ -112,32 +112,27 @@ class EnterPipToOtherOrientation(flicker: LegacyFlickerTest) : PipTransition(fli } /** - * This test is not compatible with Tablets. When using [Activity.setRequestedOrientation] to - * fix a orientation, Tablets instead keep the same orientation and add letterboxes - */ - @Before - fun setup() { - Assume.assumeFalse(tapl.isTablet) - } - - /** * Checks that all parts of the screen are covered at the start and end of the transition */ @Presubmit @Test - fun entireScreenCoveredAtStartAndEnd() = flicker.entireScreenCovered() + fun entireScreenCoveredAtStartAndEnd() { + assumeFalse(tapl.isTablet) + flicker.entireScreenCovered() + } /** Checks [pipApp] window remains visible and on top throughout the transition */ @Presubmit @Test fun pipAppWindowIsAlwaysOnTop() { + assumeFalse(tapl.isTablet) flicker.assertWm { isAppWindowOnTop(pipApp) } } /** Checks that [testApp] window is not visible at the start */ @Presubmit @Test - fun testAppWindowInvisibleOnStart() { + open fun testAppWindowInvisibleOnStart() { flicker.assertWmStart { isAppWindowInvisible(testApp) } } @@ -145,13 +140,15 @@ class EnterPipToOtherOrientation(flicker: LegacyFlickerTest) : PipTransition(fli @Presubmit @Test fun testAppWindowVisibleOnEnd() { + assumeFalse(tapl.isTablet) flicker.assertWmEnd { isAppWindowVisible(testApp) } } /** Checks that [testApp] layer is not visible at the start */ @Presubmit @Test - fun testAppLayerInvisibleOnStart() { + open fun testAppLayerInvisibleOnStart() { + assumeFalse(tapl.isTablet) flicker.assertLayersStart { isInvisible(testApp) } } @@ -159,6 +156,7 @@ class EnterPipToOtherOrientation(flicker: LegacyFlickerTest) : PipTransition(fli @Presubmit @Test fun testAppLayerVisibleOnEnd() { + assumeFalse(tapl.isTablet) flicker.assertLayersEnd { isVisible(testApp) } } @@ -168,8 +166,8 @@ class EnterPipToOtherOrientation(flicker: LegacyFlickerTest) : PipTransition(fli */ @Presubmit @Test - fun pipAppLayerCoversFullScreenOnStart() { - Assume.assumeFalse(tapl.isTablet) + open fun pipAppLayerCoversFullScreenOnStart() { + assumeFalse(tapl.isTablet) flicker.assertLayersStart { visibleRegion(pipApp).coversExactly(startingBounds) } } @@ -177,10 +175,11 @@ class EnterPipToOtherOrientation(flicker: LegacyFlickerTest) : PipTransition(fli * Checks that the visible region of [pipApp] covers the full display area at the start of the * transition */ + @Ignore("TODO(b/356277166): enable the tablet test") @Postsubmit @Test - fun pipAppLayerPlusLetterboxCoversFullScreenOnStartTablet() { - Assume.assumeFalse(tapl.isTablet) + open fun pipAppLayerPlusLetterboxCoversFullScreenOnStartTablet() { + assumeTrue(tapl.isTablet) flicker.assertLayersStart { visibleRegion(pipApp.or(ComponentNameMatcher.LETTERBOX)).coversExactly(startingBounds) } @@ -193,6 +192,7 @@ class EnterPipToOtherOrientation(flicker: LegacyFlickerTest) : PipTransition(fli @Presubmit @Test fun testAppPlusPipLayerCoversFullScreenOnEnd() { + assumeFalse(tapl.isTablet) flicker.assertLayersEnd { val pipRegion = visibleRegion(pipApp).region visibleRegion(testApp).plus(pipRegion).coversExactly(endingBounds) @@ -202,6 +202,7 @@ class EnterPipToOtherOrientation(flicker: LegacyFlickerTest) : PipTransition(fli @Postsubmit @Test fun menuOverlayMatchesTaskSurface() { + assumeFalse(tapl.isTablet) flicker.assertLayersEnd { val pipAppRegion = visibleRegion(pipApp) val pipMenuRegion = visibleRegion(ComponentNameMatcher.PIP_MENU_OVERLAY) @@ -212,6 +213,7 @@ class EnterPipToOtherOrientation(flicker: LegacyFlickerTest) : PipTransition(fli @Presubmit @Test fun pipLayerRemainInsideVisibleBounds() { + assumeFalse(tapl.isTablet) // during the transition we assert the center point is within the display bounds, since it // might go outside of bounds as we resize from landscape fullscreen to destination bounds, // and once the animation is over we assert that it's fully within the display bounds, at diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt index f9a9df43a009..2f4c8008f220 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/ExitPipToAppViaIntentTest.kt @@ -64,7 +64,7 @@ class ExitPipToAppViaIntentTest(flicker: LegacyFlickerTest) : ExitPipToAppTransi } transitions { // This will bring PipApp to fullscreen - pipApp.exitPipToFullScreenViaIntent(wmHelper) + pipApp.exitPipToOriginalTaskViaIntent(wmHelper) // Wait until the other app is no longer visible wmHelper.StateSyncBuilder().withWindowSurfaceDisappeared(testApp).waitForAndVerify() } diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinned.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinned.kt index 9d46ac1d6e00..86c32de6461d 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinned.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinned.kt @@ -43,8 +43,26 @@ import org.junit.runners.MethodSorters import org.junit.runners.Parameterized /** - * Test exiting Pip with orientation changes. To run this test: - * `atest WMShellFlickerTestsPip1:SetRequestedOrientationWhilePinned` + * Test leaving pip while changing orientation (from pip window in portrait to app in landscape) + * + * To run this test: `atest WMShellFlickerTestsPip:SetRequestedOrientationWhilePinned` + * + * Actions: + * ``` + * Launch [pipApp] on a fixed landscape orientation + * Broadcast action [ACTION_ENTER_PIP] to enter pip mode in portrait + * Restore PIP from the original task to landscape + * ``` + * + * Notes: + * ``` + * 1. Some default assertions (e.g., nav bar, status bar and screen covered) + * are inherited [PipTransition] + * 2. Part of the test setup occurs automatically via + * [android.tools.flicker.legacy.runner.TransitionRunner], + * including configuring navigation mode, initial orientation and ensuring no + * apps are running before setup + * ``` */ @RequiresDevice @RunWith(Parameterized::class) @@ -53,7 +71,7 @@ import org.junit.runners.Parameterized @RequiresFlagsDisabled(Flags.FLAG_ENABLE_PIP2) open class SetRequestedOrientationWhilePinned(flicker: LegacyFlickerTest) : PipTransition(flicker) { private val startingBounds = WindowUtils.getDisplayBounds(Rotation.ROTATION_0) - private val endingBounds = WindowUtils.getDisplayBounds(Rotation.ROTATION_90) + internal open val endingBounds = WindowUtils.getDisplayBounds(Rotation.ROTATION_90) override val thisTransition: FlickerBuilder.() -> Unit = { transitions { @@ -131,7 +149,7 @@ open class SetRequestedOrientationWhilePinned(flicker: LegacyFlickerTest) : PipT @Presubmit @Test - fun pipAppLayerCoversFullScreen() { + open fun pipAppLayerCoversDisplayBoundsOnEnd() { flicker.assertLayersEnd { visibleRegion(pipApp).coversExactly(endingBounds) } } diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/nonmatchparent/BottomHalfEnterPipToOtherOrientation.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/nonmatchparent/BottomHalfEnterPipToOtherOrientation.kt new file mode 100644 index 000000000000..4987ab7b9344 --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/nonmatchparent/BottomHalfEnterPipToOtherOrientation.kt @@ -0,0 +1,102 @@ +/* + * 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.wm.shell.flicker.pip.nonmatchparent + +import android.platform.test.annotations.Presubmit +import android.platform.test.annotations.RequiresFlagsDisabled +import android.platform.test.annotations.RequiresFlagsEnabled +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.traces.component.ComponentNameMatcher +import com.android.server.wm.flicker.helpers.BottomHalfPipAppHelper +import com.android.server.wm.flicker.helpers.PipAppHelper +import com.android.wm.shell.Flags +import com.android.wm.shell.flicker.pip.EnterPipToOtherOrientation +import org.junit.Assume.assumeFalse +import org.junit.Assume.assumeTrue +import org.junit.FixMethodOrder +import org.junit.Ignore +import org.junit.Test +import org.junit.runners.MethodSorters +import org.junit.runners.Parameterized + +/** + * Test entering pip while changing orientation (from bottom half app in landscape to pip window in + * portrait) + * + * To run this test: `atest WMShellFlickerTestsPip:BottomHalfEnterPipToOtherOrientation` + * + * Actions: + * ``` + * Launch [testApp] on a fixed portrait orientation + * Launch [pipApp] on a fixed landscape orientation + * Broadcast action [ACTION_ENTER_PIP] to enter pip mode + * ``` + * + * Notes: + * ``` + * 1. Some default assertions (e.g., nav bar, status bar and screen covered) + * are inherited [PipTransition] + * 2. Part of the test setup occurs automatically via + * [android.tools.flicker.legacy.runner.TransitionRunner], + * including configuring navigation mode, initial orientation and ensuring no + * apps are running before setup + * ``` + */ +// TODO(b/380796448): re-enable tests after the support of non-match parent PIP animation for PIP2. +@RequiresFlagsDisabled(Flags.FLAG_ENABLE_PIP2) +@RequiresFlagsEnabled(com.android.window.flags.Flags.FLAG_BETTER_SUPPORT_NON_MATCH_PARENT_ACTIVITY) +@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +class BottomHalfEnterPipToOtherOrientation(flicker: LegacyFlickerTest) : + EnterPipToOtherOrientation(flicker) +{ + override val pipApp: PipAppHelper = BottomHalfPipAppHelper(instrumentation) + + @Presubmit + @Test + override fun pipAppLayerCoversFullScreenOnStart() { + // Test app and pip app should covers the entire screen on start. + assumeFalse(tapl.isTablet) + flicker.assertLayersStart { + visibleRegion(pipApp.or(testApp)).coversExactly(startingBounds) + } + } + + @Ignore("TODO(b/356277166): enable the tablet test") + @Presubmit + @Test + override fun pipAppLayerPlusLetterboxCoversFullScreenOnStartTablet() { + // Test app and pip app should covers the entire screen on start. + assumeTrue(tapl.isTablet) + flicker.assertLayersStart { + visibleRegion(pipApp.or(ComponentNameMatcher.LETTERBOX)).coversExactly(startingBounds) + } + } + + @Presubmit + @Test + override fun testAppWindowInvisibleOnStart() { + // Test app and pip app should covers the entire screen on start. + } + + @Presubmit + @Test + override fun testAppLayerInvisibleOnStart() { + // Test app and pip app should covers the entire screen on start. + } +}
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/nonmatchparent/BottomHalfExitPipToAppViaIntentTest.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/nonmatchparent/BottomHalfExitPipToAppViaIntentTest.kt index 8ed9cd23005b..8a10c78465bc 100644 --- a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/nonmatchparent/BottomHalfExitPipToAppViaIntentTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/nonmatchparent/BottomHalfExitPipToAppViaIntentTest.kt @@ -67,7 +67,7 @@ class BottomHalfExitPipToAppViaIntentTest(flicker: LegacyFlickerTest) : } transitions { // This will bring PipApp to fullscreen - pipApp.exitPipToFullScreenViaIntent(wmHelper) + pipApp.exitPipToOriginalTaskViaIntent(wmHelper) // Wait until the transition idle and test and pip app still shows. wmHelper.StateSyncBuilder().withLayerVisible(testApp).withLayerVisible(pipApp) .withAppTransitionIdle().waitForAndVerify() diff --git a/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/nonmatchparent/BottomHalfSetRequestedOrientationWhilePinned.kt b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/nonmatchparent/BottomHalfSetRequestedOrientationWhilePinned.kt new file mode 100644 index 000000000000..42f5a50c3310 --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/pip/src/com/android/wm/shell/flicker/pip/nonmatchparent/BottomHalfSetRequestedOrientationWhilePinned.kt @@ -0,0 +1,97 @@ +/* + * 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.wm.shell.flicker.pip.nonmatchparent + +import android.platform.test.annotations.Presubmit +import android.platform.test.annotations.RequiresFlagsDisabled +import android.platform.test.annotations.RequiresFlagsEnabled +import android.tools.Rotation +import android.tools.flicker.junit.FlickerParametersRunnerFactory +import android.tools.flicker.legacy.FlickerBuilder +import android.tools.flicker.legacy.LegacyFlickerTest +import android.tools.traces.parsers.toFlickerComponent +import com.android.server.wm.flicker.helpers.BottomHalfPipAppHelper +import com.android.server.wm.flicker.helpers.PipAppHelper +import com.android.server.wm.flicker.testapp.ActivityOptions.BottomHalfPip +import com.android.wm.shell.Flags +import com.android.wm.shell.flicker.pip.SetRequestedOrientationWhilePinned +import org.junit.FixMethodOrder +import org.junit.Test +import org.junit.runners.MethodSorters +import org.junit.runners.Parameterized + +/** + * Test leaving pip while changing orientation (from pip window in portrait to bottom half app in + * landscape) + * + * To run this test: `atest WMShellFlickerTestsPip:BottomHalfSetRequestedOrientationWhilePinned` + * + * Actions: + * ``` + * Launch bottom half [pipApp] on a fixed landscape orientation via launching app + * Broadcast action [ACTION_ENTER_PIP] to enter pip mode + * Restore PIP from the original task to landscape + * ``` + * + * Notes: + * ``` + * 1. Some default assertions (e.g., nav bar, status bar and screen covered) + * are inherited [PipTransition] + * 2. Part of the test setup occurs automatically via + * [android.tools.flicker.legacy.runner.TransitionRunner], + * including configuring navigation mode, initial orientation and ensuring no + * apps are running before setup + * ``` + */ +// TODO(b/380796448): re-enable tests after the support of non-match parent PIP animation for PIP2. +@RequiresFlagsDisabled(Flags.FLAG_ENABLE_PIP2) +@RequiresFlagsEnabled(com.android.window.flags.Flags.FLAG_BETTER_SUPPORT_NON_MATCH_PARENT_ACTIVITY) +@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +class BottomHalfSetRequestedOrientationWhilePinned(flicker: LegacyFlickerTest) : + SetRequestedOrientationWhilePinned(flicker) +{ + override val pipApp: PipAppHelper = BottomHalfPipAppHelper( + instrumentation, + useLaunchingActivity = true + ) + + override val thisTransition: FlickerBuilder.() -> Unit = { + transitions { + // Launch the activity back into fullscreen and ensure that it is now in landscape + pipApp.exitPipToOriginalTaskViaIntent(wmHelper) + // System bar may fade out during fixed rotation. + wmHelper + .StateSyncBuilder() + .withTopVisibleApp(pipApp) + .withRotation(Rotation.ROTATION_90) + .withNavOrTaskBarVisible() + .withStatusBarVisible() + .waitForAndVerify() + } + } + + @Presubmit + @Test + override fun pipAppLayerCoversDisplayBoundsOnEnd() { + flicker.assertLayersEnd { + visibleRegion(pipApp + .or(BottomHalfPip.LAUNCHING_APP_COMPONENT.toFlickerComponent())) + .coversExactly(endingBounds) + } + } +}
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java index 6d37ed766aef..53f6cda62f55 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java @@ -189,7 +189,7 @@ public class PipAnimationControllerTest extends ShellTestCase { // Apply fraction 1 to compute the end value. animator.applySurfaceControlTransaction(mLeash, tx, 1); - assertEquals("Expect use main window frame", mTaskInfo.topActivityMainWindowFrame, + assertEquals("Expect main window frame", mTaskInfo.topActivityMainWindowFrame, animator.mCurrentValue); // PiP to fullscreen. @@ -200,9 +200,11 @@ public class PipAnimationControllerTest extends ShellTestCase { endBounds, null, TRANSITION_DIRECTION_TO_PIP, 0, ROTATION_270, false /* alwaysAnimateTaskBounds */); animator.applySurfaceControlTransaction(mLeash, tx, 1); + final Rect rotatedEndBounds = new Rect(endBounds); + rotateBounds(rotatedEndBounds, startBounds, ROTATION_270); - assertEquals("Expect use main window frame", mTaskInfo.topActivityMainWindowFrame, - animator.mCurrentValue); + assertEquals("Expect rotated bounds. We only use main window frame for " + + "leave-pip animation", rotatedEndBounds, animator.mCurrentValue); } @Test diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java index bca9c3fdda39..bb9703fce2e3 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java @@ -106,7 +106,6 @@ public class SplitScreenControllerTests extends ShellTestCase { @Mock RootTaskDisplayAreaOrganizer mRootTDAOrganizer; @Mock ShellExecutor mMainExecutor; @Mock Handler mMainHandler; - @Mock ShellExecutor mBgExecutor; @Mock DisplayController mDisplayController; @Mock DisplayImeController mDisplayImeController; @Mock DisplayInsetsController mDisplayInsetsController; @@ -138,8 +137,7 @@ public class SplitScreenControllerTests extends ShellTestCase { mDisplayInsetsController, mDragAndDropController, mTransitions, mTransactionPool, mIconProvider, Optional.of(mRecentTasks), mLaunchAdjacentController, Optional.of(mWindowDecorViewModel), Optional.of(mDesktopTasksController), - mStageCoordinator, mMultiInstanceHelper, mSplitState, mMainExecutor, mMainHandler, - mBgExecutor)); + mStageCoordinator, mMultiInstanceHelper, mSplitState, mMainExecutor, mMainHandler)); } @Test diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java index ada7b4aff37d..ae0c9d6cbf7c 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java @@ -79,15 +79,15 @@ public class SplitTestUtils { StageTaskListener sideStage, DisplayController displayController, DisplayImeController imeController, DisplayInsetsController insetsController, SplitLayout splitLayout, Transitions transitions, TransactionPool transactionPool, - ShellExecutor mainExecutor, Handler mainHandler, ShellExecutor bgExecutor, + ShellExecutor mainExecutor, Handler mainHandler, Optional<RecentTasksController> recentTasks, LaunchAdjacentController launchAdjacentController, Optional<WindowDecorViewModel> windowDecorViewModel, SplitState splitState, Optional<DesktopTasksController> desktopTasksController) { super(context, displayId, syncQueue, taskOrganizer, mainStage, sideStage, displayController, imeController, insetsController, splitLayout, - transitions, transactionPool, mainExecutor, mainHandler, bgExecutor, - recentTasks, launchAdjacentController, windowDecorViewModel, splitState, + transitions, transactionPool, mainExecutor, mainHandler, recentTasks, + launchAdjacentController, windowDecorViewModel, splitState, desktopTasksController); // Prepare root task for testing. diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java index ffa8b6089660..b0fdfacd7d83 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java @@ -111,7 +111,6 @@ public class SplitTransitionTests extends ShellTestCase { @Mock private WindowDecorViewModel mWindowDecorViewModel; @Mock private SplitState mSplitState; @Mock private ShellExecutor mMainExecutor; - @Mock private ShellExecutor mBgExecutor; @Mock private Handler mMainHandler; @Mock private LaunchAdjacentController mLaunchAdjacentController; @Mock private DefaultMixedHandler mMixedHandler; @@ -137,19 +136,18 @@ public class SplitTransitionTests extends ShellTestCase { mSplitLayout = SplitTestUtils.createMockSplitLayout(); mMainStage = spy(new StageTaskListener(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mock( StageTaskListener.StageListenerCallbacks.class), mSyncQueue, - mIconProvider, mMainExecutor, mBgExecutor, Optional.of(mWindowDecorViewModel), - STAGE_TYPE_MAIN)); + mIconProvider, Optional.of(mWindowDecorViewModel), STAGE_TYPE_MAIN)); mMainStage.onTaskAppeared(new TestRunningTaskInfoBuilder().build(), createMockSurface()); mSideStage = spy(new StageTaskListener(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mock( StageTaskListener.StageListenerCallbacks.class), mSyncQueue, - mIconProvider, mMainExecutor, mBgExecutor, Optional.of(mWindowDecorViewModel), - STAGE_TYPE_SIDE)); + mIconProvider, Optional.of(mWindowDecorViewModel), STAGE_TYPE_SIDE)); mSideStage.onTaskAppeared(new TestRunningTaskInfoBuilder().build(), createMockSurface()); mStageCoordinator = new SplitTestUtils.TestStageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue, mTaskOrganizer, mMainStage, mSideStage, mDisplayController, mDisplayImeController, mDisplayInsetsController, mSplitLayout, mTransitions, - mTransactionPool, mMainExecutor, mMainHandler, mBgExecutor, Optional.empty(), + mTransactionPool, mMainExecutor, mMainHandler, Optional.empty(), mLaunchAdjacentController, Optional.empty(), mSplitState, Optional.empty()); + mStageCoordinator.setMixedHandler(mMixedHandler); mSplitScreenTransitions = mStageCoordinator.getSplitTransitions(); doAnswer((Answer<IBinder>) invocation -> mock(IBinder.class)) diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java index 9d1df864764f..2d0ea5fdc884 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java @@ -119,8 +119,6 @@ public class StageCoordinatorTests extends ShellTestCase { private DefaultMixedHandler mDefaultMixedHandler; @Mock private SplitState mSplitState; - @Mock - private ShellExecutor mBgExecutor; private final Rect mBounds1 = new Rect(10, 20, 30, 40); private final Rect mBounds2 = new Rect(5, 10, 15, 20); @@ -143,9 +141,9 @@ public class StageCoordinatorTests extends ShellTestCase { mStageCoordinator = spy(new StageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue, mTaskOrganizer, mMainStage, mSideStage, mDisplayController, mDisplayImeController, mDisplayInsetsController, mSplitLayout, mTransitions, mTransactionPool, - mMainExecutor, mMainHandler, mBgExecutor, Optional.empty(), - mLaunchAdjacentController, Optional.empty(), mSplitState, - Optional.empty())); + mMainExecutor, mMainHandler, Optional.empty(), mLaunchAdjacentController, + Optional.empty(), mSplitState, Optional.empty())); + mDividerLeash = new SurfaceControl.Builder().setName("fakeDivider").build(); when(mSplitLayout.getTopLeftBounds()).thenReturn(mBounds1); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageOrderOperatorTests.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageOrderOperatorTests.kt index 62b830dfd691..3b4a86a71d90 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageOrderOperatorTests.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageOrderOperatorTests.kt @@ -23,7 +23,6 @@ import com.android.launcher3.icons.IconProvider import com.android.wm.shell.Flags.enableFlexibleSplit import com.android.wm.shell.ShellTaskOrganizer import com.android.wm.shell.ShellTestCase -import com.android.wm.shell.common.ShellExecutor import com.android.wm.shell.common.SyncTransactionQueue import com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_2_33_66 import com.android.wm.shell.shared.split.SplitScreenConstants.SNAP_TO_2_50_50 @@ -42,10 +41,6 @@ import java.util.Optional class StageOrderOperatorTests : ShellTestCase() { @Mock - lateinit var mMainExecutor: ShellExecutor - @Mock - lateinit var mBgExecutor: ShellExecutor - @Mock lateinit var mTaskOrganizer: ShellTaskOrganizer @Mock lateinit var mSyncQueue: SyncTransactionQueue @@ -67,8 +62,6 @@ class StageOrderOperatorTests : ShellTestCase() { stageListenerCallbacks, mSyncQueue, iconProvider, - mMainExecutor, - mBgExecutor, windowDecorViewModel, ) assert(stageOrderOperator.activeStages.size == 0) diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java index effc6a7daf62..fe91440b106f 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java @@ -43,7 +43,6 @@ import com.android.launcher3.icons.IconProvider; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.TestRunningTaskInfoBuilder; -import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.windowdecor.WindowDecorViewModel; @@ -74,10 +73,6 @@ public final class StageTaskListenerTests extends ShellTestCase { @Mock private SyncTransactionQueue mSyncQueue; @Mock - private ShellExecutor mMainExecutor; - @Mock - private ShellExecutor mBgExecutor; - @Mock private IconProvider mIconProvider; @Mock private WindowDecorViewModel mWindowDecorViewModel; @@ -100,8 +95,6 @@ public final class StageTaskListenerTests extends ShellTestCase { mCallbacks, mSyncQueue, mIconProvider, - mMainExecutor, - mBgExecutor, Optional.of(mWindowDecorViewModel), STAGE_TYPE_UNDEFINED); mRootTask = new TestRunningTaskInfoBuilder().build(); diff --git a/libs/androidfw/LocaleDataTables.cpp b/libs/androidfw/LocaleDataTables.cpp index 94351182871a..f56315f29c54 100644 --- a/libs/androidfw/LocaleDataTables.cpp +++ b/libs/androidfw/LocaleDataTables.cpp @@ -9,2291 +9,14580 @@ const char SCRIPT_CODES[][4] = { /* 5 */ {'A', 'v', 's', 't'}, /* 6 */ {'B', 'a', 'm', 'u'}, /* 7 */ {'B', 'a', 's', 's'}, - /* 8 */ {'B', 'e', 'n', 'g'}, - /* 9 */ {'B', 'r', 'a', 'h'}, - /* 10 */ {'C', 'a', 'k', 'm'}, - /* 11 */ {'C', 'a', 'n', 's'}, - /* 12 */ {'C', 'a', 'r', 'i'}, - /* 13 */ {'C', 'h', 'a', 'm'}, - /* 14 */ {'C', 'h', 'e', 'r'}, - /* 15 */ {'C', 'h', 'r', 's'}, - /* 16 */ {'C', 'o', 'p', 't'}, - /* 17 */ {'C', 'p', 'r', 't'}, - /* 18 */ {'C', 'y', 'r', 'l'}, - /* 19 */ {'D', 'e', 'v', 'a'}, - /* 20 */ {'E', 'g', 'y', 'p'}, - /* 21 */ {'E', 't', 'h', 'i'}, - /* 22 */ {'G', 'e', 'o', 'r'}, - /* 23 */ {'G', 'o', 'n', 'g'}, - /* 24 */ {'G', 'o', 'n', 'm'}, - /* 25 */ {'G', 'o', 't', 'h'}, - /* 26 */ {'G', 'r', 'e', 'k'}, - /* 27 */ {'G', 'u', 'j', 'r'}, - /* 28 */ {'G', 'u', 'r', 'u'}, - /* 29 */ {'H', 'a', 'n', 's'}, - /* 30 */ {'H', 'a', 'n', 't'}, - /* 31 */ {'H', 'e', 'b', 'r'}, - /* 32 */ {'H', 'l', 'u', 'w'}, - /* 33 */ {'H', 'm', 'n', 'p'}, - /* 34 */ {'I', 't', 'a', 'l'}, - /* 35 */ {'J', 'p', 'a', 'n'}, - /* 36 */ {'K', 'a', 'l', 'i'}, - /* 37 */ {'K', 'a', 'n', 'a'}, - /* 38 */ {'K', 'a', 'w', 'i'}, - /* 39 */ {'K', 'h', 'a', 'r'}, - /* 40 */ {'K', 'h', 'm', 'r'}, - /* 41 */ {'K', 'i', 't', 's'}, - /* 42 */ {'K', 'n', 'd', 'a'}, - /* 43 */ {'K', 'o', 'r', 'e'}, - /* 44 */ {'L', 'a', 'n', 'a'}, - /* 45 */ {'L', 'a', 'o', 'o'}, - /* 46 */ {'L', 'a', 't', 'n'}, - /* 47 */ {'L', 'e', 'p', 'c'}, - /* 48 */ {'L', 'i', 'n', 'a'}, - /* 49 */ {'L', 'i', 's', 'u'}, - /* 50 */ {'L', 'y', 'c', 'i'}, - /* 51 */ {'L', 'y', 'd', 'i'}, - /* 52 */ {'M', 'a', 'n', 'd'}, - /* 53 */ {'M', 'a', 'n', 'i'}, - /* 54 */ {'M', 'e', 'd', 'f'}, - /* 55 */ {'M', 'e', 'r', 'c'}, - /* 56 */ {'M', 'l', 'y', 'm'}, - /* 57 */ {'M', 'o', 'n', 'g'}, - /* 58 */ {'M', 'r', 'o', 'o'}, - /* 59 */ {'M', 'y', 'm', 'r'}, - /* 60 */ {'N', 'a', 'r', 'b'}, - /* 61 */ {'N', 'k', 'o', 'o'}, - /* 62 */ {'N', 's', 'h', 'u'}, - /* 63 */ {'O', 'g', 'a', 'm'}, - /* 64 */ {'O', 'l', 'c', 'k'}, - /* 65 */ {'O', 'r', 'k', 'h'}, - /* 66 */ {'O', 'r', 'y', 'a'}, - /* 67 */ {'O', 's', 'g', 'e'}, - /* 68 */ {'O', 'u', 'g', 'r'}, - /* 69 */ {'P', 'a', 'u', 'c'}, - /* 70 */ {'P', 'h', 'l', 'i'}, - /* 71 */ {'P', 'h', 'n', 'x'}, - /* 72 */ {'P', 'l', 'r', 'd'}, - /* 73 */ {'P', 'r', 't', 'i'}, - /* 74 */ {'R', 'o', 'h', 'g'}, - /* 75 */ {'R', 'u', 'n', 'r'}, - /* 76 */ {'S', 'a', 'm', 'r'}, - /* 77 */ {'S', 'a', 'r', 'b'}, - /* 78 */ {'S', 'a', 'u', 'r'}, - /* 79 */ {'S', 'g', 'n', 'w'}, - /* 80 */ {'S', 'i', 'n', 'h'}, - /* 81 */ {'S', 'o', 'g', 'd'}, - /* 82 */ {'S', 'o', 'r', 'a'}, - /* 83 */ {'S', 'o', 'y', 'o'}, - /* 84 */ {'S', 'y', 'r', 'c'}, - /* 85 */ {'T', 'a', 'l', 'e'}, - /* 86 */ {'T', 'a', 'l', 'u'}, - /* 87 */ {'T', 'a', 'm', 'l'}, - /* 88 */ {'T', 'a', 'n', 'g'}, - /* 89 */ {'T', 'a', 'v', 't'}, - /* 90 */ {'T', 'e', 'l', 'u'}, - /* 91 */ {'T', 'f', 'n', 'g'}, - /* 92 */ {'T', 'h', 'a', 'a'}, - /* 93 */ {'T', 'h', 'a', 'i'}, - /* 94 */ {'T', 'i', 'b', 't'}, - /* 95 */ {'T', 'n', 's', 'a'}, - /* 96 */ {'T', 'o', 't', 'o'}, - /* 97 */ {'U', 'g', 'a', 'r'}, - /* 98 */ {'V', 'a', 'i', 'i'}, - /* 99 */ {'W', 'c', 'h', 'o'}, - /* 100 */ {'X', 'p', 'e', 'o'}, - /* 101 */ {'X', 's', 'u', 'x'}, - /* 102 */ {'Y', 'i', 'i', 'i'}, - /* 103 */ {'~', '~', '~', 'A'}, - /* 104 */ {'~', '~', '~', 'B'}, + /* 8 */ {'B', 'a', 't', 'k'}, + /* 9 */ {'B', 'e', 'n', 'g'}, + /* 10 */ {'B', 'o', 'p', 'o'}, + /* 11 */ {'B', 'r', 'a', 'h'}, + /* 12 */ {'C', 'a', 'k', 'm'}, + /* 13 */ {'C', 'a', 'n', 's'}, + /* 14 */ {'C', 'a', 'r', 'i'}, + /* 15 */ {'C', 'h', 'a', 'm'}, + /* 16 */ {'C', 'h', 'e', 'r'}, + /* 17 */ {'C', 'h', 'r', 's'}, + /* 18 */ {'C', 'o', 'p', 't'}, + /* 19 */ {'C', 'p', 'r', 't'}, + /* 20 */ {'C', 'y', 'r', 'l'}, + /* 21 */ {'D', 'e', 'v', 'a'}, + /* 22 */ {'E', 'g', 'y', 'p'}, + /* 23 */ {'E', 'l', 'y', 'm'}, + /* 24 */ {'E', 't', 'h', 'i'}, + /* 25 */ {'G', 'e', 'o', 'r'}, + /* 26 */ {'G', 'o', 'n', 'g'}, + /* 27 */ {'G', 'o', 'n', 'm'}, + /* 28 */ {'G', 'o', 't', 'h'}, + /* 29 */ {'G', 'r', 'a', 'n'}, + /* 30 */ {'G', 'r', 'e', 'k'}, + /* 31 */ {'G', 'u', 'j', 'r'}, + /* 32 */ {'G', 'u', 'r', 'u'}, + /* 33 */ {'H', 'a', 'n', 'g'}, + /* 34 */ {'H', 'a', 'n', 'i'}, + /* 35 */ {'H', 'a', 'n', 's'}, + /* 36 */ {'H', 'a', 'n', 't'}, + /* 37 */ {'H', 'e', 'b', 'r'}, + /* 38 */ {'H', 'l', 'u', 'w'}, + /* 39 */ {'H', 'm', 'n', 'p'}, + /* 40 */ {'I', 't', 'a', 'l'}, + /* 41 */ {'J', 'a', 'v', 'a'}, + /* 42 */ {'J', 'p', 'a', 'n'}, + /* 43 */ {'K', 'a', 'l', 'i'}, + /* 44 */ {'K', 'a', 'n', 'a'}, + /* 45 */ {'K', 'a', 'w', 'i'}, + /* 46 */ {'K', 'h', 'a', 'r'}, + /* 47 */ {'K', 'h', 'm', 'r'}, + /* 48 */ {'K', 'i', 't', 's'}, + /* 49 */ {'K', 'n', 'd', 'a'}, + /* 50 */ {'K', 'o', 'r', 'e'}, + /* 51 */ {'L', 'a', 'n', 'a'}, + /* 52 */ {'L', 'a', 'o', 'o'}, + /* 53 */ {'L', 'a', 't', 'f'}, + /* 54 */ {'L', 'a', 't', 'g'}, + /* 55 */ {'L', 'a', 't', 'n'}, + /* 56 */ {'L', 'e', 'p', 'c'}, + /* 57 */ {'L', 'i', 'n', 'a'}, + /* 58 */ {'L', 'i', 'n', 'b'}, + /* 59 */ {'L', 'i', 's', 'u'}, + /* 60 */ {'L', 'y', 'c', 'i'}, + /* 61 */ {'L', 'y', 'd', 'i'}, + /* 62 */ {'M', 'a', 'n', 'd'}, + /* 63 */ {'M', 'a', 'n', 'i'}, + /* 64 */ {'M', 'a', 'r', 'c'}, + /* 65 */ {'M', 'e', 'd', 'f'}, + /* 66 */ {'M', 'e', 'r', 'c'}, + /* 67 */ {'M', 'l', 'y', 'm'}, + /* 68 */ {'M', 'o', 'd', 'i'}, + /* 69 */ {'M', 'o', 'n', 'g'}, + /* 70 */ {'M', 'r', 'o', 'o'}, + /* 71 */ {'M', 't', 'e', 'i'}, + /* 72 */ {'M', 'y', 'm', 'r'}, + /* 73 */ {'N', 'a', 'r', 'b'}, + /* 74 */ {'N', 'e', 'w', 'a'}, + /* 75 */ {'N', 'k', 'o', 'o'}, + /* 76 */ {'N', 's', 'h', 'u'}, + /* 77 */ {'O', 'g', 'a', 'm'}, + /* 78 */ {'O', 'l', 'c', 'k'}, + /* 79 */ {'O', 'r', 'k', 'h'}, + /* 80 */ {'O', 'r', 'y', 'a'}, + /* 81 */ {'O', 's', 'g', 'e'}, + /* 82 */ {'O', 'u', 'g', 'r'}, + /* 83 */ {'P', 'a', 'u', 'c'}, + /* 84 */ {'P', 'h', 'l', 'i'}, + /* 85 */ {'P', 'h', 'n', 'x'}, + /* 86 */ {'P', 'l', 'r', 'd'}, + /* 87 */ {'P', 'r', 't', 'i'}, + /* 88 */ {'R', 'j', 'n', 'g'}, + /* 89 */ {'R', 'o', 'h', 'g'}, + /* 90 */ {'R', 'u', 'n', 'r'}, + /* 91 */ {'S', 'a', 'm', 'r'}, + /* 92 */ {'S', 'a', 'r', 'b'}, + /* 93 */ {'S', 'a', 'u', 'r'}, + /* 94 */ {'S', 'g', 'n', 'w'}, + /* 95 */ {'S', 'i', 'n', 'h'}, + /* 96 */ {'S', 'o', 'g', 'd'}, + /* 97 */ {'S', 'o', 'r', 'a'}, + /* 98 */ {'S', 'o', 'y', 'o'}, + /* 99 */ {'S', 'u', 'n', 'u'}, + /* 100 */ {'S', 'y', 'r', 'c'}, + /* 101 */ {'T', 'a', 'g', 'b'}, + /* 102 */ {'T', 'a', 'k', 'r'}, + /* 103 */ {'T', 'a', 'l', 'e'}, + /* 104 */ {'T', 'a', 'l', 'u'}, + /* 105 */ {'T', 'a', 'm', 'l'}, + /* 106 */ {'T', 'a', 'n', 'g'}, + /* 107 */ {'T', 'a', 'v', 't'}, + /* 108 */ {'T', 'e', 'l', 'u'}, + /* 109 */ {'T', 'f', 'n', 'g'}, + /* 110 */ {'T', 'h', 'a', 'a'}, + /* 111 */ {'T', 'h', 'a', 'i'}, + /* 112 */ {'T', 'i', 'b', 't'}, + /* 113 */ {'T', 'n', 's', 'a'}, + /* 114 */ {'T', 'o', 't', 'o'}, + /* 115 */ {'U', 'g', 'a', 'r'}, + /* 116 */ {'V', 'a', 'i', 'i'}, + /* 117 */ {'W', 'c', 'h', 'o'}, + /* 118 */ {'X', 'p', 'e', 'o'}, + /* 119 */ {'X', 's', 'u', 'x'}, + /* 120 */ {'Y', 'i', 'i', 'i'}, + /* 121 */ {'~', '~', '~', 'A'}, + /* 122 */ {'~', '~', '~', 'B'}, }; const std::unordered_map<uint32_t, uint8_t> LIKELY_SCRIPTS({ - {0x61610000u, 46u}, // aa -> Latn - {0xA0000000u, 46u}, // aai -> Latn - {0xA8000000u, 46u}, // aak -> Latn - {0xD0000000u, 46u}, // aau -> Latn - {0x61620000u, 18u}, // ab -> Cyrl - {0xA0200000u, 46u}, // abi -> Latn - {0xC0200000u, 18u}, // abq -> Cyrl - {0xC4200000u, 46u}, // abr -> Latn - {0xCC200000u, 46u}, // abt -> Latn - {0xE0200000u, 46u}, // aby -> Latn - {0x8C400000u, 46u}, // acd -> Latn - {0x90400000u, 46u}, // ace -> Latn - {0x9C400000u, 46u}, // ach -> Latn - {0x80600000u, 46u}, // ada -> Latn - {0x90600000u, 46u}, // ade -> Latn - {0xA4600000u, 46u}, // adj -> Latn - {0xBC600000u, 94u}, // adp -> Tibt - {0xE0600000u, 18u}, // ady -> Cyrl - {0xE4600000u, 46u}, // adz -> Latn + {0x61610000u, 55u}, // aa -> Latn + {0x80000000u, 55u}, // aaa -> Latn + {0x84000000u, 55u}, // aab -> Latn + {0x88000000u, 55u}, // aac -> Latn + {0x8C000000u, 55u}, // aad -> Latn + {0x90000000u, 55u}, // aae -> Latn + {0x94000000u, 67u}, // aaf -> Mlym + {0x98000000u, 55u}, // aag -> Latn + {0x9C000000u, 55u}, // aah -> Latn + {0xA0000000u, 55u}, // aai -> Latn + {0xA8000000u, 55u}, // aak -> Latn + {0xAC000000u, 55u}, // aal -> Latn + {0xB4000000u, 55u}, // aan -> Latn + {0xB8000000u, 2u}, // aao -> Arab + {0xBC000000u, 55u}, // aap -> Latn + {0xC0000000u, 55u}, // aaq -> Latn + {0xC8000000u, 55u}, // aas -> Latn + {0xCC000000u, 30u}, // aat -> Grek + {0xD0000000u, 55u}, // aau -> Latn + {0xD8000000u, 55u}, // aaw -> Latn + {0xDC000000u, 55u}, // aax -> Latn + {0xE4000000u, 55u}, // aaz -> Latn + {0x61620000u, 20u}, // ab -> Cyrl + {0x80200000u, 55u}, // aba -> Latn + {0x84200000u, 55u}, // abb -> Latn + {0x88200000u, 55u}, // abc -> Latn + {0x8C200000u, 55u}, // abd -> Latn + {0x90200000u, 55u}, // abe -> Latn + {0x94200000u, 55u}, // abf -> Latn + {0x98200000u, 55u}, // abg -> Latn + {0x9C200000u, 2u}, // abh -> Arab + {0xA0200000u, 55u}, // abi -> Latn + {0xAC200000u, 88u}, // abl -> Rjng + {0xB0200000u, 55u}, // abm -> Latn + {0xB4200000u, 55u}, // abn -> Latn + {0xB8200000u, 55u}, // abo -> Latn + {0xBC200000u, 55u}, // abp -> Latn + {0xC4200000u, 55u}, // abr -> Latn + {0xC8200000u, 55u}, // abs -> Latn + {0xCC200000u, 55u}, // abt -> Latn + {0xD0200000u, 55u}, // abu -> Latn + {0xD4200000u, 2u}, // abv -> Arab + {0xD8200000u, 55u}, // abw -> Latn + {0xDC200000u, 55u}, // abx -> Latn + {0xE0200000u, 55u}, // aby -> Latn + {0xE4200000u, 55u}, // abz -> Latn + {0x80400000u, 55u}, // aca -> Latn + {0x84400000u, 55u}, // acb -> Latn + {0x8C400000u, 55u}, // acd -> Latn + {0x90400000u, 55u}, // ace -> Latn + {0x94400000u, 55u}, // acf -> Latn + {0x9C400000u, 55u}, // ach -> Latn + {0xB0400000u, 2u}, // acm -> Arab + {0xB4400000u, 55u}, // acn -> Latn + {0xBC400000u, 55u}, // acp -> Latn + {0xC0400000u, 2u}, // acq -> Arab + {0xC4400000u, 55u}, // acr -> Latn + {0xC8400000u, 55u}, // acs -> Latn + {0xCC400000u, 55u}, // act -> Latn + {0xD0400000u, 55u}, // acu -> Latn + {0xD4400000u, 55u}, // acv -> Latn + {0xD8400000u, 2u}, // acw -> Arab + {0xDC400000u, 2u}, // acx -> Arab + {0xE0400000u, 55u}, // acy -> Latn + {0xE4400000u, 55u}, // acz -> Latn + {0x80600000u, 55u}, // ada -> Latn + {0x84600000u, 55u}, // adb -> Latn + {0x8C600000u, 55u}, // add -> Latn + {0x90600000u, 55u}, // ade -> Latn + {0x94600000u, 2u}, // adf -> Arab + {0x98600000u, 55u}, // adg -> Latn + {0x9C600000u, 55u}, // adh -> Latn + {0xA0600000u, 55u}, // adi -> Latn + {0xA4600000u, 55u}, // adj -> Latn + {0xAC600000u, 55u}, // adl -> Latn + {0xB4600000u, 55u}, // adn -> Latn + {0xB8600000u, 55u}, // ado -> Latn + {0xC0600000u, 55u}, // adq -> Latn + {0xC4600000u, 55u}, // adr -> Latn + {0xCC600000u, 55u}, // adt -> Latn + {0xD0600000u, 55u}, // adu -> Latn + {0xD8600000u, 55u}, // adw -> Latn + {0xDC600000u, 112u}, // adx -> Tibt + {0xE0600000u, 20u}, // ady -> Cyrl + {0xE4600000u, 55u}, // adz -> Latn {0x61650000u, 5u}, // ae -> Avst + {0x80800000u, 55u}, // aea -> Latn {0x84800000u, 2u}, // aeb -> Arab - {0xE0800000u, 46u}, // aey -> Latn - {0x61660000u, 46u}, // af -> Latn - {0x88C00000u, 46u}, // agc -> Latn - {0x8CC00000u, 46u}, // agd -> Latn - {0x98C00000u, 46u}, // agg -> Latn - {0xB0C00000u, 46u}, // agm -> Latn - {0xB8C00000u, 46u}, // ago -> Latn - {0xC0C00000u, 46u}, // agq -> Latn - {0x80E00000u, 46u}, // aha -> Latn - {0xACE00000u, 46u}, // ahl -> Latn + {0x88800000u, 2u}, // aec -> Arab + {0x90800000u, 2u}, // aee -> Arab + {0xA8800000u, 55u}, // aek -> Latn + {0xAC800000u, 55u}, // ael -> Latn + {0xB0800000u, 55u}, // aem -> Latn + {0xC0800000u, 2u}, // aeq -> Arab + {0xC4800000u, 55u}, // aer -> Latn + {0xD0800000u, 55u}, // aeu -> Latn + {0xD8800000u, 55u}, // aew -> Latn + {0xE0800000u, 55u}, // aey -> Latn + {0xE4800000u, 55u}, // aez -> Latn + {0x61660000u, 55u}, // af -> Latn + {0x84A00000u, 2u}, // afb -> Arab + {0x8CA00000u, 55u}, // afd -> Latn + {0x90A00000u, 55u}, // afe -> Latn + {0x9CA00000u, 55u}, // afh -> Latn + {0xA0A00000u, 55u}, // afi -> Latn + {0xA8A00000u, 55u}, // afk -> Latn + {0xB4A00000u, 55u}, // afn -> Latn + {0xB8A00000u, 55u}, // afo -> Latn + {0xBCA00000u, 55u}, // afp -> Latn + {0xC8A00000u, 55u}, // afs -> Latn + {0xD0A00000u, 55u}, // afu -> Latn + {0xE4A00000u, 55u}, // afz -> Latn + {0x80C00000u, 55u}, // aga -> Latn + {0x84C00000u, 55u}, // agb -> Latn + {0x88C00000u, 55u}, // agc -> Latn + {0x8CC00000u, 55u}, // agd -> Latn + {0x90C00000u, 55u}, // age -> Latn + {0x94C00000u, 55u}, // agf -> Latn + {0x98C00000u, 55u}, // agg -> Latn + {0x9CC00000u, 55u}, // agh -> Latn + {0xA0C00000u, 21u}, // agi -> Deva + {0xA4C00000u, 24u}, // agj -> Ethi + {0xA8C00000u, 55u}, // agk -> Latn + {0xACC00000u, 55u}, // agl -> Latn + {0xB0C00000u, 55u}, // agm -> Latn + {0xB4C00000u, 55u}, // agn -> Latn + {0xB8C00000u, 55u}, // ago -> Latn + {0xC0C00000u, 55u}, // agq -> Latn + {0xC4C00000u, 55u}, // agr -> Latn + {0xC8C00000u, 55u}, // ags -> Latn + {0xCCC00000u, 55u}, // agt -> Latn + {0xD0C00000u, 55u}, // agu -> Latn + {0xD4C00000u, 55u}, // agv -> Latn + {0xD8C00000u, 55u}, // agw -> Latn + {0xDCC00000u, 20u}, // agx -> Cyrl + {0xE0C00000u, 55u}, // agy -> Latn + {0xE4C00000u, 55u}, // agz -> Latn + {0x80E00000u, 55u}, // aha -> Latn + {0x84E00000u, 55u}, // ahb -> Latn + {0x98E00000u, 24u}, // ahg -> Ethi + {0x9CE00000u, 55u}, // ahh -> Latn + {0xA0E00000u, 55u}, // ahi -> Latn + {0xA8E00000u, 55u}, // ahk -> Latn + {0xACE00000u, 55u}, // ahl -> Latn + {0xB0E00000u, 55u}, // ahm -> Latn + {0xB4E00000u, 55u}, // ahn -> Latn {0xB8E00000u, 1u}, // aho -> Ahom - {0x99200000u, 46u}, // ajg -> Latn - {0xCD200000u, 2u}, // ajt -> Arab - {0x616B0000u, 46u}, // ak -> Latn - {0xA9400000u, 101u}, // akk -> Xsux - {0x81600000u, 46u}, // ala -> Latn - {0xA1600000u, 46u}, // ali -> Latn - {0xB5600000u, 46u}, // aln -> Latn - {0xCD600000u, 18u}, // alt -> Cyrl - {0x616D0000u, 21u}, // am -> Ethi - {0xB1800000u, 46u}, // amm -> Latn - {0xB5800000u, 46u}, // amn -> Latn - {0xB9800000u, 46u}, // amo -> Latn - {0xBD800000u, 46u}, // amp -> Latn - {0x616E0000u, 46u}, // an -> Latn - {0x89A00000u, 46u}, // anc -> Latn - {0xA9A00000u, 46u}, // ank -> Latn - {0xB5A00000u, 46u}, // ann -> Latn - {0xE1A00000u, 46u}, // any -> Latn - {0xA5C00000u, 46u}, // aoj -> Latn - {0xB1C00000u, 46u}, // aom -> Latn - {0xE5C00000u, 46u}, // aoz -> Latn + {0xBCE00000u, 55u}, // ahp -> Latn + {0xC4E00000u, 21u}, // ahr -> Deva + {0xC8E00000u, 55u}, // ahs -> Latn + {0xCCE00000u, 55u}, // aht -> Latn + {0x81000000u, 55u}, // aia -> Latn + {0x85000000u, 2u}, // aib -> Arab + {0x89000000u, 55u}, // aic -> Latn + {0x8D000000u, 55u}, // aid -> Latn + {0x91000000u, 55u}, // aie -> Latn + {0x95000000u, 55u}, // aif -> Latn + {0x99000000u, 55u}, // aig -> Latn + {0xA1000000u, 100u}, // aii -> Syrc + {0xA5000000u, 37u}, // aij -> Hebr + {0xA9000000u, 55u}, // aik -> Latn + {0xAD000000u, 55u}, // ail -> Latn + {0xB1000000u, 55u}, // aim -> Latn + {0xB5000000u, 44u}, // ain -> Kana + {0xB9000000u, 72u}, // aio -> Mymr + {0xBD000000u, 55u}, // aip -> Latn + {0xC1000000u, 2u}, // aiq -> Arab + {0xC5000000u, 55u}, // air -> Latn + {0xCD000000u, 55u}, // ait -> Latn + {0xD9000000u, 55u}, // aiw -> Latn + {0xDD000000u, 55u}, // aix -> Latn + {0xE1000000u, 55u}, // aiy -> Latn + {0x81200000u, 55u}, // aja -> Latn + {0x99200000u, 55u}, // ajg -> Latn + {0xA1200000u, 55u}, // aji -> Latn + {0xB5200000u, 55u}, // ajn -> Latn + {0xD9200000u, 55u}, // ajw -> Latn + {0xE5200000u, 55u}, // ajz -> Latn + {0x616B0000u, 55u}, // ak -> Latn + {0x85400000u, 55u}, // akb -> Latn + {0x89400000u, 55u}, // akc -> Latn + {0x8D400000u, 55u}, // akd -> Latn + {0x91400000u, 55u}, // ake -> Latn + {0x95400000u, 55u}, // akf -> Latn + {0x99400000u, 55u}, // akg -> Latn + {0x9D400000u, 55u}, // akh -> Latn + {0xA1400000u, 55u}, // aki -> Latn + {0xA9400000u, 119u}, // akk -> Xsux + {0xAD400000u, 55u}, // akl -> Latn + {0xB9400000u, 55u}, // ako -> Latn + {0xBD400000u, 55u}, // akp -> Latn + {0xC1400000u, 55u}, // akq -> Latn + {0xC5400000u, 55u}, // akr -> Latn + {0xC9400000u, 55u}, // aks -> Latn + {0xCD400000u, 55u}, // akt -> Latn + {0xD1400000u, 55u}, // aku -> Latn + {0xD5400000u, 20u}, // akv -> Cyrl + {0xD9400000u, 55u}, // akw -> Latn + {0xE5400000u, 55u}, // akz -> Latn + {0x81600000u, 55u}, // ala -> Latn + {0x89600000u, 55u}, // alc -> Latn + {0x8D600000u, 55u}, // ald -> Latn + {0x91600000u, 55u}, // ale -> Latn + {0x95600000u, 55u}, // alf -> Latn + {0x9D600000u, 55u}, // alh -> Latn + {0xA1600000u, 55u}, // ali -> Latn + {0xA5600000u, 55u}, // alj -> Latn + {0xA9600000u, 52u}, // alk -> Laoo + {0xAD600000u, 67u}, // all -> Mlym + {0xB1600000u, 55u}, // alm -> Latn + {0xB5600000u, 55u}, // aln -> Latn + {0xB9600000u, 55u}, // alo -> Latn + {0xBD600000u, 55u}, // alp -> Latn + {0xC1600000u, 55u}, // alq -> Latn + {0xC5600000u, 20u}, // alr -> Cyrl + {0xCD600000u, 20u}, // alt -> Cyrl + {0xD1600000u, 55u}, // alu -> Latn + {0xD9600000u, 24u}, // alw -> Ethi + {0xDD600000u, 55u}, // alx -> Latn + {0xE1600000u, 55u}, // aly -> Latn + {0xE5600000u, 55u}, // alz -> Latn + {0x616D0000u, 24u}, // am -> Ethi + {0x81800000u, 55u}, // ama -> Latn + {0x85800000u, 55u}, // amb -> Latn + {0x89800000u, 55u}, // amc -> Latn + {0x91800000u, 55u}, // ame -> Latn + {0x95800000u, 55u}, // amf -> Latn + {0x99800000u, 55u}, // amg -> Latn + {0xA1800000u, 55u}, // ami -> Latn + {0xA5800000u, 55u}, // amj -> Latn + {0xA9800000u, 55u}, // amk -> Latn + {0xB1800000u, 55u}, // amm -> Latn + {0xB5800000u, 55u}, // amn -> Latn + {0xB9800000u, 55u}, // amo -> Latn + {0xBD800000u, 55u}, // amp -> Latn + {0xC1800000u, 55u}, // amq -> Latn + {0xC5800000u, 55u}, // amr -> Latn + {0xC9800000u, 42u}, // ams -> Jpan + {0xCD800000u, 55u}, // amt -> Latn + {0xD1800000u, 55u}, // amu -> Latn + {0xD5800000u, 55u}, // amv -> Latn + {0xD9800000u, 100u}, // amw -> Syrc + {0xDD800000u, 55u}, // amx -> Latn + {0xE1800000u, 55u}, // amy -> Latn + {0xE5800000u, 55u}, // amz -> Latn + {0x616E0000u, 55u}, // an -> Latn + {0x81A00000u, 55u}, // ana -> Latn + {0x85A00000u, 55u}, // anb -> Latn + {0x89A00000u, 55u}, // anc -> Latn + {0x8DA00000u, 55u}, // and -> Latn + {0x91A00000u, 55u}, // ane -> Latn + {0x95A00000u, 55u}, // anf -> Latn + {0x99A00000u, 55u}, // ang -> Latn + {0x9DA00000u, 55u}, // anh -> Latn + {0xA1A00000u, 20u}, // ani -> Cyrl + {0xA5A00000u, 55u}, // anj -> Latn + {0xA9A00000u, 55u}, // ank -> Latn + {0xADA00000u, 55u}, // anl -> Latn + {0xB1A00000u, 55u}, // anm -> Latn + {0xB5A00000u, 55u}, // ann -> Latn + {0xB9A00000u, 55u}, // ano -> Latn + {0xBDA00000u, 21u}, // anp -> Deva + {0xC1A00000u, 21u}, // anq -> Deva + {0xC5A00000u, 21u}, // anr -> Deva + {0xC9A00000u, 55u}, // ans -> Latn + {0xCDA00000u, 55u}, // ant -> Latn + {0xD1A00000u, 24u}, // anu -> Ethi + {0xD5A00000u, 55u}, // anv -> Latn + {0xD9A00000u, 55u}, // anw -> Latn + {0xDDA00000u, 55u}, // anx -> Latn + {0xE1A00000u, 55u}, // any -> Latn + {0xE5A00000u, 55u}, // anz -> Latn + {0x81C00000u, 55u}, // aoa -> Latn + {0x85C00000u, 55u}, // aob -> Latn + {0x89C00000u, 55u}, // aoc -> Latn + {0x8DC00000u, 55u}, // aod -> Latn + {0x91C00000u, 55u}, // aoe -> Latn + {0x95C00000u, 55u}, // aof -> Latn + {0x99C00000u, 55u}, // aog -> Latn + {0xA1C00000u, 55u}, // aoi -> Latn + {0xA5C00000u, 55u}, // aoj -> Latn + {0xA9C00000u, 55u}, // aok -> Latn + {0xADC00000u, 55u}, // aol -> Latn + {0xB1C00000u, 55u}, // aom -> Latn + {0xB5C00000u, 55u}, // aon -> Latn + {0xC5C00000u, 55u}, // aor -> Latn + {0xC9C00000u, 55u}, // aos -> Latn + {0xCDC00000u, 9u}, // aot -> Beng + {0xDDC00000u, 55u}, // aox -> Latn + {0xE5C00000u, 55u}, // aoz -> Latn + {0x85E00000u, 55u}, // apb -> Latn {0x89E00000u, 2u}, // apc -> Arab {0x8DE00000u, 2u}, // apd -> Arab - {0x91E00000u, 46u}, // ape -> Latn - {0xC5E00000u, 46u}, // apr -> Latn - {0xC9E00000u, 46u}, // aps -> Latn - {0xE5E00000u, 46u}, // apz -> Latn + {0x91E00000u, 55u}, // ape -> Latn + {0x95E00000u, 55u}, // apf -> Latn + {0x99E00000u, 55u}, // apg -> Latn + {0x9DE00000u, 21u}, // aph -> Deva + {0xA1E00000u, 55u}, // api -> Latn + {0xA5E00000u, 55u}, // apj -> Latn + {0xA9E00000u, 55u}, // apk -> Latn + {0xADE00000u, 55u}, // apl -> Latn + {0xB1E00000u, 55u}, // apm -> Latn + {0xB5E00000u, 55u}, // apn -> Latn + {0xB9E00000u, 55u}, // apo -> Latn + {0xBDE00000u, 55u}, // app -> Latn + {0xC5E00000u, 55u}, // apr -> Latn + {0xC9E00000u, 55u}, // aps -> Latn + {0xCDE00000u, 55u}, // apt -> Latn + {0xD1E00000u, 55u}, // apu -> Latn + {0xD5E00000u, 55u}, // apv -> Latn + {0xD9E00000u, 55u}, // apw -> Latn + {0xDDE00000u, 55u}, // apx -> Latn + {0xE1E00000u, 55u}, // apy -> Latn + {0xE5E00000u, 55u}, // apz -> Latn + {0x8A000000u, 20u}, // aqc -> Cyrl + {0x8E000000u, 55u}, // aqd -> Latn + {0x9A000000u, 55u}, // aqg -> Latn + {0xAA000000u, 55u}, // aqk -> Latn + {0xB2000000u, 55u}, // aqm -> Latn + {0xB6000000u, 55u}, // aqn -> Latn + {0xC6000000u, 55u}, // aqr -> Latn + {0xCE000000u, 55u}, // aqt -> Latn + {0xE6000000u, 55u}, // aqz -> Latn {0x61720000u, 2u}, // ar -> Arab - {0x61725842u, 104u}, // ar-XB -> ~~~B + {0x61725842u, 122u}, // ar-XB -> ~~~B {0x8A200000u, 3u}, // arc -> Armi - {0x9E200000u, 46u}, // arh -> Latn - {0xB6200000u, 46u}, // arn -> Latn - {0xBA200000u, 46u}, // aro -> Latn + {0x8E200000u, 55u}, // ard -> Latn + {0x92200000u, 55u}, // are -> Latn + {0x9E200000u, 55u}, // arh -> Latn + {0xA2200000u, 55u}, // ari -> Latn + {0xA6200000u, 55u}, // arj -> Latn + {0xAA200000u, 55u}, // ark -> Latn + {0xAE200000u, 55u}, // arl -> Latn + {0xB6200000u, 55u}, // arn -> Latn + {0xBA200000u, 55u}, // aro -> Latn + {0xBE200000u, 55u}, // arp -> Latn {0xC2200000u, 2u}, // arq -> Arab + {0xC6200000u, 55u}, // arr -> Latn {0xCA200000u, 2u}, // ars -> Arab + {0xD2200000u, 55u}, // aru -> Latn + {0xDA200000u, 55u}, // arw -> Latn + {0xDE200000u, 55u}, // arx -> Latn {0xE2200000u, 2u}, // ary -> Arab {0xE6200000u, 2u}, // arz -> Arab - {0x61730000u, 8u}, // as -> Beng - {0x82400000u, 46u}, // asa -> Latn - {0x92400000u, 79u}, // ase -> Sgnw - {0x9A400000u, 46u}, // asg -> Latn - {0xBA400000u, 46u}, // aso -> Latn - {0xCE400000u, 46u}, // ast -> Latn - {0x82600000u, 46u}, // ata -> Latn - {0x9A600000u, 46u}, // atg -> Latn - {0xA6600000u, 46u}, // atj -> Latn - {0xE2800000u, 46u}, // auy -> Latn - {0x61760000u, 18u}, // av -> Cyrl + {0x61730000u, 9u}, // as -> Beng + {0x82400000u, 55u}, // asa -> Latn + {0x86400000u, 55u}, // asb -> Latn + {0x8A400000u, 55u}, // asc -> Latn + {0x92400000u, 94u}, // ase -> Sgnw + {0x9A400000u, 55u}, // asg -> Latn + {0x9E400000u, 55u}, // ash -> Latn + {0xA2400000u, 55u}, // asi -> Latn + {0xA6400000u, 55u}, // asj -> Latn + {0xAA400000u, 2u}, // ask -> Arab + {0xAE400000u, 55u}, // asl -> Latn + {0xB6400000u, 55u}, // asn -> Latn + {0xBA400000u, 55u}, // aso -> Latn + {0xC6400000u, 21u}, // asr -> Deva + {0xCA400000u, 55u}, // ass -> Latn + {0xCE400000u, 55u}, // ast -> Latn + {0xD2400000u, 55u}, // asu -> Latn + {0xD6400000u, 55u}, // asv -> Latn + {0xDE400000u, 55u}, // asx -> Latn + {0xE2400000u, 55u}, // asy -> Latn + {0xE6400000u, 55u}, // asz -> Latn + {0x82600000u, 55u}, // ata -> Latn + {0x86600000u, 55u}, // atb -> Latn + {0x8A600000u, 55u}, // atc -> Latn + {0x8E600000u, 55u}, // atd -> Latn + {0x92600000u, 55u}, // ate -> Latn + {0x9A600000u, 55u}, // atg -> Latn + {0xA2600000u, 55u}, // ati -> Latn + {0xA6600000u, 55u}, // atj -> Latn + {0xAA600000u, 55u}, // atk -> Latn + {0xAE600000u, 55u}, // atl -> Latn + {0xB2600000u, 55u}, // atm -> Latn + {0xB6600000u, 2u}, // atn -> Arab + {0xBA600000u, 55u}, // ato -> Latn + {0xBE600000u, 55u}, // atp -> Latn + {0xC2600000u, 55u}, // atq -> Latn + {0xC6600000u, 55u}, // atr -> Latn + {0xCA600000u, 55u}, // ats -> Latn + {0xCE600000u, 55u}, // att -> Latn + {0xD2600000u, 55u}, // atu -> Latn + {0xD6600000u, 20u}, // atv -> Cyrl + {0xDA600000u, 55u}, // atw -> Latn + {0xDE600000u, 55u}, // atx -> Latn + {0xE2600000u, 55u}, // aty -> Latn + {0xE6600000u, 55u}, // atz -> Latn + {0x82800000u, 55u}, // aua -> Latn + {0x8A800000u, 55u}, // auc -> Latn + {0x8E800000u, 55u}, // aud -> Latn + {0x9A800000u, 55u}, // aug -> Latn + {0x9E800000u, 55u}, // auh -> Latn + {0xA2800000u, 55u}, // aui -> Latn + {0xA6800000u, 2u}, // auj -> Arab + {0xAA800000u, 55u}, // auk -> Latn + {0xAE800000u, 55u}, // aul -> Latn + {0xB2800000u, 55u}, // aum -> Latn + {0xB6800000u, 55u}, // aun -> Latn + {0xBA800000u, 55u}, // auo -> Latn + {0xBE800000u, 55u}, // aup -> Latn + {0xC2800000u, 55u}, // auq -> Latn + {0xC6800000u, 55u}, // aur -> Latn + {0xCE800000u, 55u}, // aut -> Latn + {0xD2800000u, 55u}, // auu -> Latn + {0xDA800000u, 55u}, // auw -> Latn + {0xE2800000u, 55u}, // auy -> Latn + {0xE6800000u, 2u}, // auz -> Arab + {0x61760000u, 20u}, // av -> Cyrl + {0x86A00000u, 55u}, // avb -> Latn + {0x8EA00000u, 2u}, // avd -> Arab + {0xA2A00000u, 55u}, // avi -> Latn + {0xAAA00000u, 55u}, // avk -> Latn {0xAEA00000u, 2u}, // avl -> Arab - {0xB6A00000u, 46u}, // avn -> Latn - {0xCEA00000u, 46u}, // avt -> Latn - {0xD2A00000u, 46u}, // avu -> Latn - {0x82C00000u, 19u}, // awa -> Deva - {0x86C00000u, 46u}, // awb -> Latn - {0xBAC00000u, 46u}, // awo -> Latn - {0xDEC00000u, 46u}, // awx -> Latn - {0x61790000u, 46u}, // ay -> Latn - {0x87000000u, 46u}, // ayb -> Latn - {0x617A0000u, 46u}, // az -> Latn + {0xB2A00000u, 55u}, // avm -> Latn + {0xB6A00000u, 55u}, // avn -> Latn + {0xBAA00000u, 55u}, // avo -> Latn + {0xCAA00000u, 55u}, // avs -> Latn + {0xCEA00000u, 55u}, // avt -> Latn + {0xD2A00000u, 55u}, // avu -> Latn + {0xD6A00000u, 55u}, // avv -> Latn + {0x82C00000u, 21u}, // awa -> Deva + {0x86C00000u, 55u}, // awb -> Latn + {0x8AC00000u, 55u}, // awc -> Latn + {0x92C00000u, 55u}, // awe -> Latn + {0x9AC00000u, 55u}, // awg -> Latn + {0x9EC00000u, 55u}, // awh -> Latn + {0xA2C00000u, 55u}, // awi -> Latn + {0xAAC00000u, 55u}, // awk -> Latn + {0xB2C00000u, 55u}, // awm -> Latn + {0xB6C00000u, 24u}, // awn -> Ethi + {0xBAC00000u, 55u}, // awo -> Latn + {0xC6C00000u, 55u}, // awr -> Latn + {0xCAC00000u, 55u}, // aws -> Latn + {0xCEC00000u, 55u}, // awt -> Latn + {0xD2C00000u, 55u}, // awu -> Latn + {0xD6C00000u, 55u}, // awv -> Latn + {0xDAC00000u, 55u}, // aww -> Latn + {0xDEC00000u, 55u}, // awx -> Latn + {0xE2C00000u, 55u}, // awy -> Latn + {0x86E00000u, 55u}, // axb -> Latn + {0x92E00000u, 55u}, // axe -> Latn + {0x9AE00000u, 55u}, // axg -> Latn + {0xAAE00000u, 55u}, // axk -> Latn + {0xAEE00000u, 55u}, // axl -> Latn + {0xB2E00000u, 4u}, // axm -> Armn + {0xDEE00000u, 55u}, // axx -> Latn + {0x61790000u, 55u}, // ay -> Latn + {0x83000000u, 55u}, // aya -> Latn + {0x87000000u, 55u}, // ayb -> Latn + {0x8B000000u, 55u}, // ayc -> Latn + {0x8F000000u, 55u}, // ayd -> Latn + {0x93000000u, 55u}, // aye -> Latn + {0x9B000000u, 55u}, // ayg -> Latn + {0x9F000000u, 2u}, // ayh -> Arab + {0xA3000000u, 55u}, // ayi -> Latn + {0xAB000000u, 55u}, // ayk -> Latn + {0xAF000000u, 2u}, // ayl -> Arab + {0xB7000000u, 2u}, // ayn -> Arab + {0xBB000000u, 55u}, // ayo -> Latn + {0xBF000000u, 2u}, // ayp -> Arab + {0xC3000000u, 55u}, // ayq -> Latn + {0xCB000000u, 55u}, // ays -> Latn + {0xCF000000u, 55u}, // ayt -> Latn + {0xD3000000u, 55u}, // ayu -> Latn + {0xE7000000u, 55u}, // ayz -> Latn + {0x617A0000u, 55u}, // az -> Latn {0x617A4951u, 2u}, // az-IQ -> Arab {0x617A4952u, 2u}, // az-IR -> Arab - {0x617A5255u, 18u}, // az-RU -> Cyrl - {0x62610000u, 18u}, // ba -> Cyrl + {0x617A5255u, 20u}, // az-RU -> Cyrl + {0x87200000u, 2u}, // azb -> Arab + {0x8F200000u, 55u}, // azd -> Latn + {0x9B200000u, 55u}, // azg -> Latn + {0xB3200000u, 55u}, // azm -> Latn + {0xB7200000u, 55u}, // azn -> Latn + {0xBB200000u, 55u}, // azo -> Latn + {0xCF200000u, 55u}, // azt -> Latn + {0xE7200000u, 55u}, // azz -> Latn + {0x62610000u, 20u}, // ba -> Cyrl + {0x80010000u, 55u}, // baa -> Latn + {0x84010000u, 55u}, // bab -> Latn + {0x88010000u, 55u}, // bac -> Latn + {0x90010000u, 55u}, // bae -> Latn + {0x94010000u, 55u}, // baf -> Latn + {0x98010000u, 55u}, // bag -> Latn + {0x9C010000u, 55u}, // bah -> Latn + {0xA4010000u, 55u}, // baj -> Latn {0xAC010000u, 2u}, // bal -> Arab - {0xB4010000u, 46u}, // ban -> Latn - {0xBC010000u, 19u}, // bap -> Deva - {0xC4010000u, 46u}, // bar -> Latn - {0xC8010000u, 46u}, // bas -> Latn - {0xD4010000u, 46u}, // bav -> Latn + {0xB4010000u, 55u}, // ban -> Latn + {0xB8010000u, 55u}, // bao -> Latn + {0xBC010000u, 21u}, // bap -> Deva + {0xC4010000u, 55u}, // bar -> Latn + {0xC8010000u, 55u}, // bas -> Latn + {0xD0010000u, 55u}, // bau -> Latn + {0xD4010000u, 55u}, // bav -> Latn + {0xD8010000u, 55u}, // baw -> Latn {0xDC010000u, 6u}, // bax -> Bamu - {0x80210000u, 46u}, // bba -> Latn - {0x84210000u, 46u}, // bbb -> Latn - {0x88210000u, 46u}, // bbc -> Latn - {0x8C210000u, 46u}, // bbd -> Latn - {0xA4210000u, 46u}, // bbj -> Latn - {0xBC210000u, 46u}, // bbp -> Latn - {0xC4210000u, 46u}, // bbr -> Latn - {0x94410000u, 46u}, // bcf -> Latn - {0x9C410000u, 46u}, // bch -> Latn - {0xA0410000u, 46u}, // bci -> Latn - {0xB0410000u, 46u}, // bcm -> Latn - {0xB4410000u, 46u}, // bcn -> Latn - {0xB8410000u, 46u}, // bco -> Latn - {0xC0410000u, 21u}, // bcq -> Ethi - {0xD0410000u, 46u}, // bcu -> Latn - {0x8C610000u, 46u}, // bdd -> Latn - {0x62650000u, 18u}, // be -> Cyrl - {0x94810000u, 46u}, // bef -> Latn - {0x9C810000u, 46u}, // beh -> Latn + {0xE0010000u, 55u}, // bay -> Latn + {0x80210000u, 55u}, // bba -> Latn + {0x84210000u, 55u}, // bbb -> Latn + {0x88210000u, 55u}, // bbc -> Latn + {0x8C210000u, 55u}, // bbd -> Latn + {0x90210000u, 55u}, // bbe -> Latn + {0x94210000u, 55u}, // bbf -> Latn + {0x98210000u, 55u}, // bbg -> Latn + {0xA0210000u, 55u}, // bbi -> Latn + {0xA4210000u, 55u}, // bbj -> Latn + {0xA8210000u, 55u}, // bbk -> Latn + {0xAC210000u, 25u}, // bbl -> Geor + {0xB0210000u, 55u}, // bbm -> Latn + {0xB4210000u, 55u}, // bbn -> Latn + {0xB8210000u, 55u}, // bbo -> Latn + {0xBC210000u, 55u}, // bbp -> Latn + {0xC0210000u, 55u}, // bbq -> Latn + {0xC4210000u, 55u}, // bbr -> Latn + {0xC8210000u, 55u}, // bbs -> Latn + {0xCC210000u, 55u}, // bbt -> Latn + {0xD0210000u, 55u}, // bbu -> Latn + {0xD4210000u, 55u}, // bbv -> Latn + {0xD8210000u, 55u}, // bbw -> Latn + {0xDC210000u, 55u}, // bbx -> Latn + {0xE0210000u, 55u}, // bby -> Latn + {0x80410000u, 55u}, // bca -> Latn + {0x84410000u, 55u}, // bcb -> Latn + {0x8C410000u, 55u}, // bcd -> Latn + {0x90410000u, 55u}, // bce -> Latn + {0x94410000u, 55u}, // bcf -> Latn + {0x98410000u, 55u}, // bcg -> Latn + {0x9C410000u, 55u}, // bch -> Latn + {0xA0410000u, 55u}, // bci -> Latn + {0xA4410000u, 55u}, // bcj -> Latn + {0xA8410000u, 55u}, // bck -> Latn + {0xB0410000u, 55u}, // bcm -> Latn + {0xB4410000u, 55u}, // bcn -> Latn + {0xB8410000u, 55u}, // bco -> Latn + {0xBC410000u, 55u}, // bcp -> Latn + {0xC0410000u, 24u}, // bcq -> Ethi + {0xC4410000u, 55u}, // bcr -> Latn + {0xC8410000u, 55u}, // bcs -> Latn + {0xCC410000u, 55u}, // bct -> Latn + {0xD0410000u, 55u}, // bcu -> Latn + {0xD4410000u, 55u}, // bcv -> Latn + {0xD8410000u, 55u}, // bcw -> Latn + {0xE0410000u, 55u}, // bcy -> Latn + {0xE4410000u, 55u}, // bcz -> Latn + {0x80610000u, 55u}, // bda -> Latn + {0x84610000u, 55u}, // bdb -> Latn + {0x88610000u, 55u}, // bdc -> Latn + {0x8C610000u, 55u}, // bdd -> Latn + {0x90610000u, 55u}, // bde -> Latn + {0x94610000u, 55u}, // bdf -> Latn + {0x98610000u, 55u}, // bdg -> Latn + {0x9C610000u, 55u}, // bdh -> Latn + {0xA0610000u, 55u}, // bdi -> Latn + {0xA4610000u, 55u}, // bdj -> Latn + {0xA8610000u, 55u}, // bdk -> Latn + {0xAC610000u, 55u}, // bdl -> Latn + {0xB0610000u, 55u}, // bdm -> Latn + {0xB4610000u, 55u}, // bdn -> Latn + {0xB8610000u, 55u}, // bdo -> Latn + {0xBC610000u, 55u}, // bdp -> Latn + {0xC0610000u, 55u}, // bdq -> Latn + {0xC4610000u, 55u}, // bdr -> Latn + {0xC8610000u, 55u}, // bds -> Latn + {0xCC610000u, 55u}, // bdt -> Latn + {0xD0610000u, 55u}, // bdu -> Latn + {0xD4610000u, 80u}, // bdv -> Orya + {0xD8610000u, 55u}, // bdw -> Latn + {0xDC610000u, 55u}, // bdx -> Latn + {0xE0610000u, 55u}, // bdy -> Latn + {0xE4610000u, 2u}, // bdz -> Arab + {0x62650000u, 20u}, // be -> Cyrl + {0x80810000u, 55u}, // bea -> Latn + {0x84810000u, 55u}, // beb -> Latn + {0x88810000u, 55u}, // bec -> Latn + {0x8C810000u, 55u}, // bed -> Latn + {0x90810000u, 21u}, // bee -> Deva + {0x94810000u, 55u}, // bef -> Latn + {0x9C810000u, 55u}, // beh -> Latn + {0xA0810000u, 55u}, // bei -> Latn {0xA4810000u, 2u}, // bej -> Arab - {0xB0810000u, 46u}, // bem -> Latn - {0xCC810000u, 46u}, // bet -> Latn - {0xD8810000u, 46u}, // bew -> Latn - {0xDC810000u, 46u}, // bex -> Latn - {0xE4810000u, 46u}, // bez -> Latn - {0x8CA10000u, 46u}, // bfd -> Latn - {0xC0A10000u, 87u}, // bfq -> Taml + {0xA8810000u, 55u}, // bek -> Latn + {0xB0810000u, 55u}, // bem -> Latn + {0xB8810000u, 55u}, // beo -> Latn + {0xBC810000u, 55u}, // bep -> Latn + {0xC0810000u, 55u}, // beq -> Latn + {0xC8810000u, 55u}, // bes -> Latn + {0xCC810000u, 55u}, // bet -> Latn + {0xD0810000u, 55u}, // beu -> Latn + {0xD4810000u, 55u}, // bev -> Latn + {0xD8810000u, 55u}, // bew -> Latn + {0xDC810000u, 55u}, // bex -> Latn + {0xE0810000u, 55u}, // bey -> Latn + {0xE4810000u, 55u}, // bez -> Latn + {0x80A10000u, 55u}, // bfa -> Latn + {0x84A10000u, 21u}, // bfb -> Deva + {0x88A10000u, 55u}, // bfc -> Latn + {0x8CA10000u, 55u}, // bfd -> Latn + {0x90A10000u, 55u}, // bfe -> Latn + {0x94A10000u, 55u}, // bff -> Latn + {0x98A10000u, 55u}, // bfg -> Latn + {0x9CA10000u, 55u}, // bfh -> Latn + {0xA4A10000u, 55u}, // bfj -> Latn + {0xACA10000u, 55u}, // bfl -> Latn + {0xB0A10000u, 55u}, // bfm -> Latn + {0xB4A10000u, 55u}, // bfn -> Latn + {0xB8A10000u, 55u}, // bfo -> Latn + {0xBCA10000u, 55u}, // bfp -> Latn + {0xC0A10000u, 105u}, // bfq -> Taml + {0xC8A10000u, 55u}, // bfs -> Latn {0xCCA10000u, 2u}, // bft -> Arab - {0xE0A10000u, 19u}, // bfy -> Deva - {0x62670000u, 18u}, // bg -> Cyrl - {0x88C10000u, 19u}, // bgc -> Deva + {0xD0A10000u, 112u}, // bfu -> Tibt + {0xD8A10000u, 80u}, // bfw -> Orya + {0xDCA10000u, 55u}, // bfx -> Latn + {0xE0A10000u, 21u}, // bfy -> Deva + {0xE4A10000u, 21u}, // bfz -> Deva + {0x62670000u, 20u}, // bg -> Cyrl + {0x80C10000u, 55u}, // bga -> Latn + {0x84C10000u, 55u}, // bgb -> Latn + {0x88C10000u, 21u}, // bgc -> Deva + {0x8CC10000u, 21u}, // bgd -> Deva + {0x94C10000u, 55u}, // bgf -> Latn + {0x98C10000u, 55u}, // bgg -> Latn + {0xA0C10000u, 55u}, // bgi -> Latn + {0xA4C10000u, 55u}, // bgj -> Latn {0xB4C10000u, 2u}, // bgn -> Arab - {0xDCC10000u, 26u}, // bgx -> Grek - {0x84E10000u, 19u}, // bhb -> Deva - {0x98E10000u, 46u}, // bhg -> Latn - {0xA0E10000u, 19u}, // bhi -> Deva - {0xACE10000u, 46u}, // bhl -> Latn - {0xB8E10000u, 19u}, // bho -> Deva - {0xE0E10000u, 46u}, // bhy -> Latn - {0x62690000u, 46u}, // bi -> Latn - {0x85010000u, 46u}, // bib -> Latn - {0x99010000u, 46u}, // big -> Latn - {0xA9010000u, 46u}, // bik -> Latn - {0xB1010000u, 46u}, // bim -> Latn - {0xB5010000u, 46u}, // bin -> Latn - {0xB9010000u, 46u}, // bio -> Latn - {0xC1010000u, 46u}, // biq -> Latn - {0x9D210000u, 46u}, // bjh -> Latn - {0xA1210000u, 21u}, // bji -> Ethi - {0xA5210000u, 19u}, // bjj -> Deva - {0xB5210000u, 46u}, // bjn -> Latn - {0xB9210000u, 46u}, // bjo -> Latn - {0xC5210000u, 46u}, // bjr -> Latn - {0xCD210000u, 46u}, // bjt -> Latn - {0xE5210000u, 46u}, // bjz -> Latn - {0x89410000u, 46u}, // bkc -> Latn - {0xB1410000u, 46u}, // bkm -> Latn - {0xC1410000u, 46u}, // bkq -> Latn - {0xD1410000u, 46u}, // bku -> Latn - {0xD5410000u, 46u}, // bkv -> Latn - {0x81610000u, 46u}, // bla -> Latn - {0x99610000u, 46u}, // blg -> Latn - {0xCD610000u, 89u}, // blt -> Tavt - {0x626D0000u, 46u}, // bm -> Latn - {0x9D810000u, 46u}, // bmh -> Latn - {0xA9810000u, 46u}, // bmk -> Latn - {0xC1810000u, 46u}, // bmq -> Latn - {0xD1810000u, 46u}, // bmu -> Latn - {0x626E0000u, 8u}, // bn -> Beng - {0x99A10000u, 46u}, // bng -> Latn - {0xB1A10000u, 46u}, // bnm -> Latn - {0xBDA10000u, 46u}, // bnp -> Latn - {0x626F0000u, 94u}, // bo -> Tibt - {0xA5C10000u, 46u}, // boj -> Latn - {0xB1C10000u, 46u}, // bom -> Latn - {0xB5C10000u, 46u}, // bon -> Latn - {0xE1E10000u, 8u}, // bpy -> Beng - {0x8A010000u, 46u}, // bqc -> Latn + {0xB8C10000u, 55u}, // bgo -> Latn + {0xBCC10000u, 2u}, // bgp -> Arab + {0xC0C10000u, 21u}, // bgq -> Deva + {0xC4C10000u, 55u}, // bgr -> Latn + {0xC8C10000u, 55u}, // bgs -> Latn + {0xCCC10000u, 55u}, // bgt -> Latn + {0xD0C10000u, 55u}, // bgu -> Latn + {0xD4C10000u, 55u}, // bgv -> Latn + {0xD8C10000u, 21u}, // bgw -> Deva + {0xDCC10000u, 30u}, // bgx -> Grek + {0xE0C10000u, 55u}, // bgy -> Latn + {0xE4C10000u, 55u}, // bgz -> Latn + {0x80E10000u, 21u}, // bha -> Deva + {0x84E10000u, 21u}, // bhb -> Deva + {0x88E10000u, 55u}, // bhc -> Latn + {0x8CE10000u, 21u}, // bhd -> Deva + {0x90E10000u, 2u}, // bhe -> Arab + {0x94E10000u, 55u}, // bhf -> Latn + {0x98E10000u, 55u}, // bhg -> Latn + {0x9CE10000u, 20u}, // bhh -> Cyrl + {0xA0E10000u, 21u}, // bhi -> Deva + {0xA4E10000u, 21u}, // bhj -> Deva + {0xACE10000u, 55u}, // bhl -> Latn + {0xB0E10000u, 2u}, // bhm -> Arab + {0xB4E10000u, 100u}, // bhn -> Syrc + {0xB8E10000u, 21u}, // bho -> Deva + {0xBCE10000u, 55u}, // bhp -> Latn + {0xC0E10000u, 55u}, // bhq -> Latn + {0xC4E10000u, 55u}, // bhr -> Latn + {0xC8E10000u, 55u}, // bhs -> Latn + {0xCCE10000u, 21u}, // bht -> Deva + {0xD0E10000u, 21u}, // bhu -> Deva + {0xD4E10000u, 55u}, // bhv -> Latn + {0xD8E10000u, 55u}, // bhw -> Latn + {0xE0E10000u, 55u}, // bhy -> Latn + {0xE4E10000u, 55u}, // bhz -> Latn + {0x62690000u, 55u}, // bi -> Latn + {0x81010000u, 55u}, // bia -> Latn + {0x85010000u, 55u}, // bib -> Latn + {0x8D010000u, 55u}, // bid -> Latn + {0x91010000u, 55u}, // bie -> Latn + {0x95010000u, 55u}, // bif -> Latn + {0x99010000u, 55u}, // big -> Latn + {0xA9010000u, 55u}, // bik -> Latn + {0xAD010000u, 55u}, // bil -> Latn + {0xB1010000u, 55u}, // bim -> Latn + {0xB5010000u, 55u}, // bin -> Latn + {0xB9010000u, 55u}, // bio -> Latn + {0xBD010000u, 55u}, // bip -> Latn + {0xC1010000u, 55u}, // biq -> Latn + {0xC5010000u, 55u}, // bir -> Latn + {0xCD010000u, 55u}, // bit -> Latn + {0xD1010000u, 55u}, // biu -> Latn + {0xD5010000u, 55u}, // biv -> Latn + {0xD9010000u, 55u}, // biw -> Latn + {0xE1010000u, 21u}, // biy -> Deva + {0xE5010000u, 55u}, // biz -> Latn + {0x81210000u, 55u}, // bja -> Latn + {0x85210000u, 55u}, // bjb -> Latn + {0x89210000u, 55u}, // bjc -> Latn + {0x95210000u, 100u}, // bjf -> Syrc + {0x99210000u, 55u}, // bjg -> Latn + {0x9D210000u, 55u}, // bjh -> Latn + {0xA1210000u, 55u}, // bji -> Latn + {0xA5210000u, 21u}, // bjj -> Deva + {0xA9210000u, 55u}, // bjk -> Latn + {0xAD210000u, 55u}, // bjl -> Latn + {0xB1210000u, 2u}, // bjm -> Arab + {0xB5210000u, 55u}, // bjn -> Latn + {0xB9210000u, 55u}, // bjo -> Latn + {0xBD210000u, 55u}, // bjp -> Latn + {0xC5210000u, 55u}, // bjr -> Latn + {0xC9210000u, 55u}, // bjs -> Latn + {0xCD210000u, 55u}, // bjt -> Latn + {0xD1210000u, 55u}, // bju -> Latn + {0xD5210000u, 55u}, // bjv -> Latn + {0xD9210000u, 55u}, // bjw -> Latn + {0xDD210000u, 55u}, // bjx -> Latn + {0xE1210000u, 55u}, // bjy -> Latn + {0xE5210000u, 55u}, // bjz -> Latn + {0x81410000u, 55u}, // bka -> Latn + {0x89410000u, 55u}, // bkc -> Latn + {0x8D410000u, 55u}, // bkd -> Latn + {0x95410000u, 55u}, // bkf -> Latn + {0x99410000u, 55u}, // bkg -> Latn + {0x9D410000u, 55u}, // bkh -> Latn + {0xA1410000u, 55u}, // bki -> Latn + {0xA5410000u, 55u}, // bkj -> Latn + {0xA9410000u, 112u}, // bkk -> Tibt + {0xAD410000u, 55u}, // bkl -> Latn + {0xB1410000u, 55u}, // bkm -> Latn + {0xB5410000u, 55u}, // bkn -> Latn + {0xB9410000u, 55u}, // bko -> Latn + {0xBD410000u, 55u}, // bkp -> Latn + {0xC1410000u, 55u}, // bkq -> Latn + {0xC5410000u, 55u}, // bkr -> Latn + {0xC9410000u, 55u}, // bks -> Latn + {0xCD410000u, 55u}, // bkt -> Latn + {0xD1410000u, 55u}, // bku -> Latn + {0xD5410000u, 55u}, // bkv -> Latn + {0xD9410000u, 55u}, // bkw -> Latn + {0xDD410000u, 55u}, // bkx -> Latn + {0xE1410000u, 55u}, // bky -> Latn + {0xE5410000u, 55u}, // bkz -> Latn + {0x81610000u, 55u}, // bla -> Latn + {0x85610000u, 55u}, // blb -> Latn + {0x89610000u, 55u}, // blc -> Latn + {0x8D610000u, 55u}, // bld -> Latn + {0x91610000u, 55u}, // ble -> Latn + {0x95610000u, 55u}, // blf -> Latn + {0x9D610000u, 55u}, // blh -> Latn + {0xA1610000u, 55u}, // bli -> Latn + {0xA5610000u, 55u}, // blj -> Latn + {0xA9610000u, 72u}, // blk -> Mymr + {0xB1610000u, 55u}, // blm -> Latn + {0xB5610000u, 55u}, // bln -> Latn + {0xB9610000u, 55u}, // blo -> Latn + {0xBD610000u, 55u}, // blp -> Latn + {0xC1610000u, 55u}, // blq -> Latn + {0xC5610000u, 55u}, // blr -> Latn + {0xC9610000u, 55u}, // bls -> Latn + {0xCD610000u, 107u}, // blt -> Tavt + {0xD5610000u, 55u}, // blv -> Latn + {0xD9610000u, 55u}, // blw -> Latn + {0xDD610000u, 55u}, // blx -> Latn + {0xE1610000u, 55u}, // bly -> Latn + {0xE5610000u, 55u}, // blz -> Latn + {0x626D0000u, 55u}, // bm -> Latn + {0x81810000u, 55u}, // bma -> Latn + {0x85810000u, 55u}, // bmb -> Latn + {0x89810000u, 55u}, // bmc -> Latn + {0x8D810000u, 55u}, // bmd -> Latn + {0x91810000u, 55u}, // bme -> Latn + {0x95810000u, 55u}, // bmf -> Latn + {0x99810000u, 55u}, // bmg -> Latn + {0x9D810000u, 55u}, // bmh -> Latn + {0xA1810000u, 55u}, // bmi -> Latn + {0xA5810000u, 21u}, // bmj -> Deva + {0xA9810000u, 55u}, // bmk -> Latn + {0xAD810000u, 55u}, // bml -> Latn + {0xB1810000u, 55u}, // bmm -> Latn + {0xB5810000u, 55u}, // bmn -> Latn + {0xB9810000u, 55u}, // bmo -> Latn + {0xBD810000u, 55u}, // bmp -> Latn + {0xC1810000u, 55u}, // bmq -> Latn + {0xC5810000u, 55u}, // bmr -> Latn + {0xC9810000u, 55u}, // bms -> Latn + {0xD1810000u, 55u}, // bmu -> Latn + {0xD5810000u, 55u}, // bmv -> Latn + {0xD9810000u, 55u}, // bmw -> Latn + {0xDD810000u, 55u}, // bmx -> Latn + {0xE5810000u, 55u}, // bmz -> Latn + {0x626E0000u, 9u}, // bn -> Beng + {0x81A10000u, 55u}, // bna -> Latn + {0x85A10000u, 55u}, // bnb -> Latn + {0x89A10000u, 55u}, // bnc -> Latn + {0x8DA10000u, 55u}, // bnd -> Latn + {0x91A10000u, 55u}, // bne -> Latn + {0x95A10000u, 55u}, // bnf -> Latn + {0x99A10000u, 55u}, // bng -> Latn + {0xA1A10000u, 55u}, // bni -> Latn + {0xA5A10000u, 55u}, // bnj -> Latn + {0xA9A10000u, 55u}, // bnk -> Latn + {0xB1A10000u, 55u}, // bnm -> Latn + {0xB5A10000u, 55u}, // bnn -> Latn + {0xB9A10000u, 55u}, // bno -> Latn + {0xBDA10000u, 55u}, // bnp -> Latn + {0xC1A10000u, 55u}, // bnq -> Latn + {0xC5A10000u, 55u}, // bnr -> Latn + {0xC9A10000u, 21u}, // bns -> Deva + {0xD1A10000u, 55u}, // bnu -> Latn + {0xD5A10000u, 55u}, // bnv -> Latn + {0xD9A10000u, 55u}, // bnw -> Latn + {0xDDA10000u, 55u}, // bnx -> Latn + {0xE1A10000u, 55u}, // bny -> Latn + {0xE5A10000u, 55u}, // bnz -> Latn + {0x626F0000u, 112u}, // bo -> Tibt + {0x81C10000u, 55u}, // boa -> Latn + {0x85C10000u, 55u}, // bob -> Latn + {0x91C10000u, 55u}, // boe -> Latn + {0x95C10000u, 55u}, // bof -> Latn + {0x9DC10000u, 55u}, // boh -> Latn + {0xA5C10000u, 55u}, // boj -> Latn + {0xA9C10000u, 55u}, // bok -> Latn + {0xADC10000u, 55u}, // bol -> Latn + {0xB1C10000u, 55u}, // bom -> Latn + {0xB5C10000u, 55u}, // bon -> Latn + {0xB9C10000u, 55u}, // boo -> Latn + {0xBDC10000u, 55u}, // bop -> Latn + {0xC1C10000u, 55u}, // boq -> Latn + {0xC5C10000u, 55u}, // bor -> Latn + {0xCDC10000u, 55u}, // bot -> Latn + {0xD1C10000u, 55u}, // bou -> Latn + {0xD5C10000u, 55u}, // bov -> Latn + {0xD9C10000u, 55u}, // bow -> Latn + {0xDDC10000u, 55u}, // box -> Latn + {0xE1C10000u, 55u}, // boy -> Latn + {0xE5C10000u, 55u}, // boz -> Latn + {0x81E10000u, 55u}, // bpa -> Latn + {0x89E10000u, 55u}, // bpc -> Latn + {0x8DE10000u, 55u}, // bpd -> Latn + {0x91E10000u, 55u}, // bpe -> Latn + {0x99E10000u, 55u}, // bpg -> Latn + {0x9DE10000u, 20u}, // bph -> Cyrl + {0xA1E10000u, 55u}, // bpi -> Latn + {0xA5E10000u, 55u}, // bpj -> Latn + {0xA9E10000u, 55u}, // bpk -> Latn + {0xADE10000u, 55u}, // bpl -> Latn + {0xB1E10000u, 55u}, // bpm -> Latn + {0xB9E10000u, 55u}, // bpo -> Latn + {0xBDE10000u, 55u}, // bpp -> Latn + {0xC1E10000u, 55u}, // bpq -> Latn + {0xC5E10000u, 55u}, // bpr -> Latn + {0xC9E10000u, 55u}, // bps -> Latn + {0xCDE10000u, 55u}, // bpt -> Latn + {0xD1E10000u, 55u}, // bpu -> Latn + {0xD5E10000u, 55u}, // bpv -> Latn + {0xD9E10000u, 55u}, // bpw -> Latn + {0xDDE10000u, 21u}, // bpx -> Deva + {0xE1E10000u, 9u}, // bpy -> Beng + {0xE5E10000u, 55u}, // bpz -> Latn + {0x82010000u, 55u}, // bqa -> Latn + {0x86010000u, 55u}, // bqb -> Latn + {0x8A010000u, 55u}, // bqc -> Latn + {0x8E010000u, 55u}, // bqd -> Latn + {0x96010000u, 55u}, // bqf -> Latn + {0x9A010000u, 55u}, // bqg -> Latn {0xA2010000u, 2u}, // bqi -> Arab - {0xBE010000u, 46u}, // bqp -> Latn - {0xD6010000u, 46u}, // bqv -> Latn - {0x62720000u, 46u}, // br -> Latn - {0x82210000u, 19u}, // bra -> Deva + {0xA6010000u, 55u}, // bqj -> Latn + {0xAA010000u, 55u}, // bqk -> Latn + {0xAE010000u, 55u}, // bql -> Latn + {0xB2010000u, 55u}, // bqm -> Latn + {0xBA010000u, 55u}, // bqo -> Latn + {0xBE010000u, 55u}, // bqp -> Latn + {0xC2010000u, 55u}, // bqq -> Latn + {0xC6010000u, 55u}, // bqr -> Latn + {0xCA010000u, 55u}, // bqs -> Latn + {0xCE010000u, 55u}, // bqt -> Latn + {0xD2010000u, 55u}, // bqu -> Latn + {0xD6010000u, 55u}, // bqv -> Latn + {0xDA010000u, 55u}, // bqw -> Latn + {0xDE010000u, 55u}, // bqx -> Latn + {0xE6010000u, 55u}, // bqz -> Latn + {0x62720000u, 55u}, // br -> Latn + {0x82210000u, 21u}, // bra -> Deva + {0x86210000u, 47u}, // brb -> Khmr + {0x8A210000u, 55u}, // brc -> Latn + {0x8E210000u, 21u}, // brd -> Deva + {0x96210000u, 55u}, // brf -> Latn + {0x9A210000u, 55u}, // brg -> Latn {0x9E210000u, 2u}, // brh -> Arab - {0xDE210000u, 19u}, // brx -> Deva - {0xE6210000u, 46u}, // brz -> Latn - {0x62730000u, 46u}, // bs -> Latn - {0xA6410000u, 46u}, // bsj -> Latn + {0xA2210000u, 55u}, // bri -> Latn + {0xA6210000u, 55u}, // brj -> Latn + {0xAA210000u, 2u}, // brk -> Arab + {0xAE210000u, 55u}, // brl -> Latn + {0xB2210000u, 55u}, // brm -> Latn + {0xB6210000u, 55u}, // brn -> Latn + {0xBA210000u, 112u}, // bro -> Tibt + {0xBE210000u, 55u}, // brp -> Latn + {0xC2210000u, 55u}, // brq -> Latn + {0xC6210000u, 55u}, // brr -> Latn + {0xCA210000u, 55u}, // brs -> Latn + {0xCE210000u, 55u}, // brt -> Latn + {0xD2210000u, 55u}, // bru -> Latn + {0xD6210000u, 52u}, // brv -> Laoo + {0xDA210000u, 49u}, // brw -> Knda + {0xDE210000u, 21u}, // brx -> Deva + {0xE2210000u, 55u}, // bry -> Latn + {0xE6210000u, 55u}, // brz -> Latn + {0x62730000u, 55u}, // bs -> Latn + {0x82410000u, 55u}, // bsa -> Latn + {0x86410000u, 55u}, // bsb -> Latn + {0x8A410000u, 55u}, // bsc -> Latn + {0x92410000u, 55u}, // bse -> Latn + {0x96410000u, 55u}, // bsf -> Latn + {0x9E410000u, 2u}, // bsh -> Arab + {0xA2410000u, 55u}, // bsi -> Latn + {0xA6410000u, 55u}, // bsj -> Latn + {0xAA410000u, 2u}, // bsk -> Arab + {0xAE410000u, 55u}, // bsl -> Latn + {0xB2410000u, 55u}, // bsm -> Latn + {0xB6410000u, 55u}, // bsn -> Latn + {0xBA410000u, 55u}, // bso -> Latn + {0xBE410000u, 55u}, // bsp -> Latn {0xC2410000u, 7u}, // bsq -> Bass - {0xCA410000u, 46u}, // bss -> Latn - {0xCE410000u, 21u}, // bst -> Ethi - {0xBA610000u, 46u}, // bto -> Latn - {0xCE610000u, 46u}, // btt -> Latn - {0xD6610000u, 19u}, // btv -> Deva - {0x82810000u, 18u}, // bua -> Cyrl - {0x8A810000u, 46u}, // buc -> Latn - {0x8E810000u, 46u}, // bud -> Latn - {0x9A810000u, 46u}, // bug -> Latn - {0xAA810000u, 46u}, // buk -> Latn - {0xB2810000u, 46u}, // bum -> Latn - {0xBA810000u, 46u}, // buo -> Latn - {0xCA810000u, 46u}, // bus -> Latn - {0xD2810000u, 46u}, // buu -> Latn - {0x86A10000u, 46u}, // bvb -> Latn - {0x8EC10000u, 46u}, // bwd -> Latn - {0xC6C10000u, 46u}, // bwr -> Latn - {0x9EE10000u, 46u}, // bxh -> Latn - {0x93010000u, 46u}, // bye -> Latn - {0xB7010000u, 21u}, // byn -> Ethi - {0xC7010000u, 46u}, // byr -> Latn - {0xCB010000u, 46u}, // bys -> Latn - {0xD7010000u, 46u}, // byv -> Latn - {0xDF010000u, 46u}, // byx -> Latn - {0x83210000u, 46u}, // bza -> Latn - {0x93210000u, 46u}, // bze -> Latn - {0x97210000u, 46u}, // bzf -> Latn - {0x9F210000u, 46u}, // bzh -> Latn - {0xDB210000u, 46u}, // bzw -> Latn - {0x63610000u, 46u}, // ca -> Latn - {0x8C020000u, 46u}, // cad -> Latn - {0xB4020000u, 46u}, // can -> Latn - {0xA4220000u, 46u}, // cbj -> Latn - {0x9C420000u, 46u}, // cch -> Latn - {0xBC420000u, 10u}, // ccp -> Cakm - {0x63650000u, 18u}, // ce -> Cyrl - {0x84820000u, 46u}, // ceb -> Latn - {0x80A20000u, 46u}, // cfa -> Latn - {0x98C20000u, 46u}, // cgg -> Latn - {0x63680000u, 46u}, // ch -> Latn - {0xA8E20000u, 46u}, // chk -> Latn - {0xB0E20000u, 18u}, // chm -> Cyrl - {0xB8E20000u, 46u}, // cho -> Latn - {0xBCE20000u, 46u}, // chp -> Latn - {0xC4E20000u, 14u}, // chr -> Cher - {0x89020000u, 46u}, // cic -> Latn + {0xC6410000u, 55u}, // bsr -> Latn + {0xCA410000u, 55u}, // bss -> Latn + {0xCE410000u, 24u}, // bst -> Ethi + {0xD2410000u, 55u}, // bsu -> Latn + {0xD6410000u, 55u}, // bsv -> Latn + {0xDA410000u, 55u}, // bsw -> Latn + {0xDE410000u, 55u}, // bsx -> Latn + {0xE2410000u, 55u}, // bsy -> Latn + {0x82610000u, 55u}, // bta -> Latn + {0x8A610000u, 55u}, // btc -> Latn + {0x8E610000u, 8u}, // btd -> Batk + {0x92610000u, 55u}, // bte -> Latn + {0x96610000u, 55u}, // btf -> Latn + {0x9A610000u, 55u}, // btg -> Latn + {0x9E610000u, 55u}, // bth -> Latn + {0xA2610000u, 55u}, // bti -> Latn + {0xA6610000u, 55u}, // btj -> Latn + {0xB2610000u, 8u}, // btm -> Batk + {0xB6610000u, 55u}, // btn -> Latn + {0xBA610000u, 55u}, // bto -> Latn + {0xBE610000u, 55u}, // btp -> Latn + {0xC2610000u, 55u}, // btq -> Latn + {0xC6610000u, 55u}, // btr -> Latn + {0xCA610000u, 55u}, // bts -> Latn + {0xCE610000u, 55u}, // btt -> Latn + {0xD2610000u, 55u}, // btu -> Latn + {0xD6610000u, 21u}, // btv -> Deva + {0xDA610000u, 55u}, // btw -> Latn + {0xDE610000u, 55u}, // btx -> Latn + {0xE2610000u, 55u}, // bty -> Latn + {0xE6610000u, 55u}, // btz -> Latn + {0x82810000u, 20u}, // bua -> Cyrl + {0x86810000u, 55u}, // bub -> Latn + {0x8A810000u, 55u}, // buc -> Latn + {0x8E810000u, 55u}, // bud -> Latn + {0x92810000u, 55u}, // bue -> Latn + {0x96810000u, 55u}, // buf -> Latn + {0x9A810000u, 55u}, // bug -> Latn + {0x9E810000u, 55u}, // buh -> Latn + {0xA2810000u, 55u}, // bui -> Latn + {0xA6810000u, 55u}, // buj -> Latn + {0xAA810000u, 55u}, // buk -> Latn + {0xB2810000u, 55u}, // bum -> Latn + {0xB6810000u, 55u}, // bun -> Latn + {0xBA810000u, 55u}, // buo -> Latn + {0xBE810000u, 55u}, // bup -> Latn + {0xC2810000u, 55u}, // buq -> Latn + {0xCA810000u, 55u}, // bus -> Latn + {0xCE810000u, 55u}, // but -> Latn + {0xD2810000u, 55u}, // buu -> Latn + {0xD6810000u, 55u}, // buv -> Latn + {0xDA810000u, 55u}, // buw -> Latn + {0xDE810000u, 55u}, // bux -> Latn + {0xE2810000u, 55u}, // buy -> Latn + {0xE6810000u, 55u}, // buz -> Latn + {0x82A10000u, 55u}, // bva -> Latn + {0x86A10000u, 55u}, // bvb -> Latn + {0x8AA10000u, 55u}, // bvc -> Latn + {0x8EA10000u, 55u}, // bvd -> Latn + {0x92A10000u, 55u}, // bve -> Latn + {0x96A10000u, 55u}, // bvf -> Latn + {0x9AA10000u, 55u}, // bvg -> Latn + {0x9EA10000u, 55u}, // bvh -> Latn + {0xA2A10000u, 55u}, // bvi -> Latn + {0xA6A10000u, 55u}, // bvj -> Latn + {0xAAA10000u, 55u}, // bvk -> Latn + {0xB2A10000u, 55u}, // bvm -> Latn + {0xB6A10000u, 55u}, // bvn -> Latn + {0xBAA10000u, 55u}, // bvo -> Latn + {0xC2A10000u, 55u}, // bvq -> Latn + {0xC6A10000u, 55u}, // bvr -> Latn + {0xCEA10000u, 55u}, // bvt -> Latn + {0xD2A10000u, 55u}, // bvu -> Latn + {0xD6A10000u, 55u}, // bvv -> Latn + {0xDAA10000u, 55u}, // bvw -> Latn + {0xDEA10000u, 55u}, // bvx -> Latn + {0xE2A10000u, 55u}, // bvy -> Latn + {0xE6A10000u, 55u}, // bvz -> Latn + {0x82C10000u, 55u}, // bwa -> Latn + {0x86C10000u, 55u}, // bwb -> Latn + {0x8AC10000u, 55u}, // bwc -> Latn + {0x8EC10000u, 55u}, // bwd -> Latn + {0x92C10000u, 72u}, // bwe -> Mymr + {0x96C10000u, 55u}, // bwf -> Latn + {0x9AC10000u, 55u}, // bwg -> Latn + {0x9EC10000u, 55u}, // bwh -> Latn + {0xA2C10000u, 55u}, // bwi -> Latn + {0xA6C10000u, 55u}, // bwj -> Latn + {0xAAC10000u, 55u}, // bwk -> Latn + {0xAEC10000u, 55u}, // bwl -> Latn + {0xB2C10000u, 55u}, // bwm -> Latn + {0xBAC10000u, 55u}, // bwo -> Latn + {0xBEC10000u, 55u}, // bwp -> Latn + {0xC2C10000u, 55u}, // bwq -> Latn + {0xC6C10000u, 55u}, // bwr -> Latn + {0xCAC10000u, 55u}, // bws -> Latn + {0xCEC10000u, 55u}, // bwt -> Latn + {0xD2C10000u, 55u}, // bwu -> Latn + {0xDAC10000u, 55u}, // bww -> Latn + {0xDEC10000u, 55u}, // bwx -> Latn + {0xE2C10000u, 55u}, // bwy -> Latn + {0xE6C10000u, 55u}, // bwz -> Latn + {0x82E10000u, 55u}, // bxa -> Latn + {0x86E10000u, 55u}, // bxb -> Latn + {0x8AE10000u, 55u}, // bxc -> Latn + {0x96E10000u, 55u}, // bxf -> Latn + {0x9AE10000u, 55u}, // bxg -> Latn + {0x9EE10000u, 55u}, // bxh -> Latn + {0xA2E10000u, 55u}, // bxi -> Latn + {0xA6E10000u, 55u}, // bxj -> Latn + {0xAEE10000u, 55u}, // bxl -> Latn + {0xB2E10000u, 20u}, // bxm -> Cyrl + {0xB6E10000u, 55u}, // bxn -> Latn + {0xBAE10000u, 55u}, // bxo -> Latn + {0xBEE10000u, 55u}, // bxp -> Latn + {0xC2E10000u, 55u}, // bxq -> Latn + {0xCAE10000u, 55u}, // bxs -> Latn + {0xD2E10000u, 69u}, // bxu -> Mong + {0xD6E10000u, 55u}, // bxv -> Latn + {0xDAE10000u, 55u}, // bxw -> Latn + {0xE6E10000u, 55u}, // bxz -> Latn + {0x83010000u, 55u}, // bya -> Latn + {0x87010000u, 55u}, // byb -> Latn + {0x8B010000u, 55u}, // byc -> Latn + {0x8F010000u, 55u}, // byd -> Latn + {0x93010000u, 55u}, // bye -> Latn + {0x97010000u, 55u}, // byf -> Latn + {0x9F010000u, 21u}, // byh -> Deva + {0xA3010000u, 55u}, // byi -> Latn + {0xA7010000u, 55u}, // byj -> Latn + {0xAB010000u, 55u}, // byk -> Latn + {0xAF010000u, 55u}, // byl -> Latn + {0xB3010000u, 55u}, // bym -> Latn + {0xB7010000u, 24u}, // byn -> Ethi + {0xBF010000u, 55u}, // byp -> Latn + {0xC7010000u, 55u}, // byr -> Latn + {0xCB010000u, 55u}, // bys -> Latn + {0xD7010000u, 55u}, // byv -> Latn + {0xDB010000u, 21u}, // byw -> Deva + {0xDF010000u, 55u}, // byx -> Latn + {0xE7010000u, 55u}, // byz -> Latn + {0x83210000u, 55u}, // bza -> Latn + {0x87210000u, 55u}, // bzb -> Latn + {0x8B210000u, 55u}, // bzc -> Latn + {0x8F210000u, 55u}, // bzd -> Latn + {0x93210000u, 55u}, // bze -> Latn + {0x97210000u, 55u}, // bzf -> Latn + {0x9F210000u, 55u}, // bzh -> Latn + {0xA3210000u, 111u}, // bzi -> Thai + {0xA7210000u, 55u}, // bzj -> Latn + {0xAB210000u, 55u}, // bzk -> Latn + {0xAF210000u, 55u}, // bzl -> Latn + {0xB3210000u, 55u}, // bzm -> Latn + {0xB7210000u, 55u}, // bzn -> Latn + {0xBB210000u, 55u}, // bzo -> Latn + {0xBF210000u, 55u}, // bzp -> Latn + {0xC3210000u, 55u}, // bzq -> Latn + {0xC7210000u, 55u}, // bzr -> Latn + {0xCF210000u, 55u}, // bzt -> Latn + {0xD3210000u, 55u}, // bzu -> Latn + {0xD7210000u, 55u}, // bzv -> Latn + {0xDB210000u, 55u}, // bzw -> Latn + {0xDF210000u, 55u}, // bzx -> Latn + {0xE3210000u, 55u}, // bzy -> Latn + {0xE7210000u, 55u}, // bzz -> Latn + {0x63610000u, 55u}, // ca -> Latn + {0x80020000u, 55u}, // caa -> Latn + {0x84020000u, 55u}, // cab -> Latn + {0x88020000u, 55u}, // cac -> Latn + {0x8C020000u, 55u}, // cad -> Latn + {0x90020000u, 55u}, // cae -> Latn + {0x94020000u, 55u}, // caf -> Latn + {0x98020000u, 55u}, // cag -> Latn + {0x9C020000u, 55u}, // cah -> Latn + {0xA4020000u, 55u}, // caj -> Latn + {0xA8020000u, 55u}, // cak -> Latn + {0xAC020000u, 55u}, // cal -> Latn + {0xB0020000u, 55u}, // cam -> Latn + {0xB4020000u, 55u}, // can -> Latn + {0xB8020000u, 55u}, // cao -> Latn + {0xBC020000u, 55u}, // cap -> Latn + {0xC0020000u, 55u}, // caq -> Latn + {0xC4020000u, 55u}, // car -> Latn + {0xC8020000u, 55u}, // cas -> Latn + {0xD4020000u, 55u}, // cav -> Latn + {0xD8020000u, 55u}, // caw -> Latn + {0xDC020000u, 55u}, // cax -> Latn + {0xE0020000u, 55u}, // cay -> Latn + {0xE4020000u, 55u}, // caz -> Latn + {0x84220000u, 55u}, // cbb -> Latn + {0x88220000u, 55u}, // cbc -> Latn + {0x8C220000u, 55u}, // cbd -> Latn + {0x98220000u, 55u}, // cbg -> Latn + {0xA0220000u, 55u}, // cbi -> Latn + {0xA4220000u, 55u}, // cbj -> Latn + {0xA8220000u, 55u}, // cbk -> Latn + {0xAC220000u, 55u}, // cbl -> Latn + {0xB4220000u, 111u}, // cbn -> Thai + {0xB8220000u, 55u}, // cbo -> Latn + {0xC0220000u, 55u}, // cbq -> Latn + {0xC4220000u, 55u}, // cbr -> Latn + {0xC8220000u, 55u}, // cbs -> Latn + {0xCC220000u, 55u}, // cbt -> Latn + {0xD0220000u, 55u}, // cbu -> Latn + {0xD4220000u, 55u}, // cbv -> Latn + {0xD8220000u, 55u}, // cbw -> Latn + {0xE0220000u, 55u}, // cby -> Latn + {0x88420000u, 55u}, // ccc -> Latn + {0x8C420000u, 55u}, // ccd -> Latn + {0x90420000u, 55u}, // cce -> Latn + {0x98420000u, 55u}, // ccg -> Latn + {0x9C420000u, 55u}, // cch -> Latn + {0xA4420000u, 55u}, // ccj -> Latn + {0xAC420000u, 55u}, // ccl -> Latn + {0xB0420000u, 55u}, // ccm -> Latn + {0xB8420000u, 55u}, // cco -> Latn + {0xBC420000u, 12u}, // ccp -> Cakm + {0xC4420000u, 55u}, // ccr -> Latn + {0x90620000u, 108u}, // cde -> Telu + {0x94620000u, 55u}, // cdf -> Latn + {0x9C620000u, 21u}, // cdh -> Deva + {0xA0620000u, 31u}, // cdi -> Gujr + {0xA4620000u, 21u}, // cdj -> Deva + {0xB0620000u, 21u}, // cdm -> Deva + {0xB8620000u, 35u}, // cdo -> Hans + {0xC4620000u, 55u}, // cdr -> Latn + {0xE4620000u, 9u}, // cdz -> Beng + {0x63650000u, 20u}, // ce -> Cyrl + {0x80820000u, 55u}, // cea -> Latn + {0x84820000u, 55u}, // ceb -> Latn + {0x98820000u, 55u}, // ceg -> Latn + {0xA8820000u, 55u}, // cek -> Latn + {0xB4820000u, 55u}, // cen -> Latn + {0xCC820000u, 55u}, // cet -> Latn + {0xE0820000u, 55u}, // cey -> Latn + {0x80A20000u, 55u}, // cfa -> Latn + {0x8CA20000u, 55u}, // cfd -> Latn + {0x98A20000u, 55u}, // cfg -> Latn + {0xB0A20000u, 55u}, // cfm -> Latn + {0x80C20000u, 55u}, // cga -> Latn + {0x88C20000u, 55u}, // cgc -> Latn + {0x98C20000u, 55u}, // cgg -> Latn + {0xA8C20000u, 112u}, // cgk -> Tibt + {0x63680000u, 55u}, // ch -> Latn + {0x84E20000u, 55u}, // chb -> Latn + {0x8CE20000u, 55u}, // chd -> Latn + {0x94E20000u, 55u}, // chf -> Latn + {0x98E20000u, 2u}, // chg -> Arab + {0x9CE20000u, 55u}, // chh -> Latn + {0xA4E20000u, 55u}, // chj -> Latn + {0xA8E20000u, 55u}, // chk -> Latn + {0xACE20000u, 55u}, // chl -> Latn + {0xB0E20000u, 20u}, // chm -> Cyrl + {0xB4E20000u, 55u}, // chn -> Latn + {0xB8E20000u, 55u}, // cho -> Latn + {0xBCE20000u, 55u}, // chp -> Latn + {0xC0E20000u, 55u}, // chq -> Latn + {0xC4E20000u, 16u}, // chr -> Cher + {0xCCE20000u, 55u}, // cht -> Latn + {0xD8E20000u, 55u}, // chw -> Latn + {0xDCE20000u, 21u}, // chx -> Deva + {0xE0E20000u, 55u}, // chy -> Latn + {0xE4E20000u, 55u}, // chz -> Latn + {0x81020000u, 55u}, // cia -> Latn + {0x85020000u, 55u}, // cib -> Latn + {0x89020000u, 55u}, // cic -> Latn + {0x91020000u, 55u}, // cie -> Latn + {0x9D020000u, 21u}, // cih -> Deva + {0xB1020000u, 55u}, // cim -> Latn + {0xB5020000u, 55u}, // cin -> Latn + {0xBD020000u, 55u}, // cip -> Latn + {0xC5020000u, 55u}, // cir -> Latn + {0xD9020000u, 55u}, // ciw -> Latn + {0xE1020000u, 55u}, // ciy -> Latn {0x81220000u, 2u}, // cja -> Arab - {0xB1220000u, 13u}, // cjm -> Cham - {0xD5220000u, 46u}, // cjv -> Latn + {0x91220000u, 55u}, // cje -> Latn + {0x9D220000u, 55u}, // cjh -> Latn + {0xA1220000u, 20u}, // cji -> Cyrl + {0xA9220000u, 55u}, // cjk -> Latn + {0xB1220000u, 15u}, // cjm -> Cham + {0xB5220000u, 55u}, // cjn -> Latn + {0xB9220000u, 55u}, // cjo -> Latn + {0xBD220000u, 55u}, // cjp -> Latn + {0xC9220000u, 55u}, // cjs -> Latn + {0xD5220000u, 55u}, // cjv -> Latn + {0xE1220000u, 35u}, // cjy -> Hans {0x85420000u, 2u}, // ckb -> Arab - {0xAD420000u, 46u}, // ckl -> Latn - {0xB9420000u, 46u}, // cko -> Latn - {0xE1420000u, 46u}, // cky -> Latn - {0x81620000u, 46u}, // cla -> Latn - {0x89620000u, 46u}, // clc -> Latn - {0x91820000u, 46u}, // cme -> Latn - {0x99820000u, 83u}, // cmg -> Soyo - {0x636F0000u, 46u}, // co -> Latn - {0xBDC20000u, 16u}, // cop -> Copt - {0xC9E20000u, 46u}, // cps -> Latn - {0x63720000u, 11u}, // cr -> Cans - {0x9A220000u, 46u}, // crg -> Latn - {0x9E220000u, 18u}, // crh -> Cyrl - {0xAA220000u, 11u}, // crk -> Cans - {0xAE220000u, 11u}, // crl -> Cans - {0xCA220000u, 46u}, // crs -> Latn - {0x63730000u, 46u}, // cs -> Latn - {0x86420000u, 46u}, // csb -> Latn - {0xDA420000u, 11u}, // csw -> Cans - {0x8E620000u, 69u}, // ctd -> Pauc - {0x63750000u, 18u}, // cu -> Cyrl - {0x63760000u, 18u}, // cv -> Cyrl - {0x63790000u, 46u}, // cy -> Latn - {0x64610000u, 46u}, // da -> Latn - {0x8C030000u, 46u}, // dad -> Latn - {0x94030000u, 46u}, // daf -> Latn - {0x98030000u, 46u}, // dag -> Latn - {0x9C030000u, 46u}, // dah -> Latn - {0xA8030000u, 46u}, // dak -> Latn - {0xC4030000u, 18u}, // dar -> Cyrl - {0xD4030000u, 46u}, // dav -> Latn - {0x8C230000u, 46u}, // dbd -> Latn - {0xC0230000u, 46u}, // dbq -> Latn + {0xAD420000u, 55u}, // ckl -> Latn + {0xB1420000u, 55u}, // ckm -> Latn + {0xB5420000u, 55u}, // ckn -> Latn + {0xB9420000u, 55u}, // cko -> Latn + {0xC1420000u, 55u}, // ckq -> Latn + {0xC5420000u, 55u}, // ckr -> Latn + {0xC9420000u, 55u}, // cks -> Latn + {0xCD420000u, 20u}, // ckt -> Cyrl + {0xD1420000u, 55u}, // cku -> Latn + {0xD5420000u, 55u}, // ckv -> Latn + {0xDD420000u, 55u}, // ckx -> Latn + {0xE1420000u, 55u}, // cky -> Latn + {0xE5420000u, 55u}, // ckz -> Latn + {0x81620000u, 55u}, // cla -> Latn + {0x89620000u, 55u}, // clc -> Latn + {0x91620000u, 55u}, // cle -> Latn + {0x9D620000u, 2u}, // clh -> Arab + {0xA1620000u, 55u}, // cli -> Latn + {0xA5620000u, 55u}, // clj -> Latn + {0xA9620000u, 55u}, // clk -> Latn + {0xAD620000u, 55u}, // cll -> Latn + {0xB1620000u, 55u}, // clm -> Latn + {0xB9620000u, 55u}, // clo -> Latn + {0xCD620000u, 55u}, // clt -> Latn + {0xD1620000u, 55u}, // clu -> Latn + {0xD9620000u, 20u}, // clw -> Cyrl + {0xE1620000u, 55u}, // cly -> Latn + {0x81820000u, 55u}, // cma -> Latn + {0x91820000u, 55u}, // cme -> Latn + {0x99820000u, 98u}, // cmg -> Soyo + {0xA1820000u, 55u}, // cmi -> Latn + {0xAD820000u, 55u}, // cml -> Latn + {0xB9820000u, 55u}, // cmo -> Latn + {0xC5820000u, 55u}, // cmr -> Latn + {0xC9820000u, 55u}, // cms -> Latn + {0xCD820000u, 55u}, // cmt -> Latn + {0x81A20000u, 112u}, // cna -> Tibt + {0x85A20000u, 55u}, // cnb -> Latn + {0x89A20000u, 55u}, // cnc -> Latn + {0x99A20000u, 55u}, // cng -> Latn + {0x9DA20000u, 55u}, // cnh -> Latn + {0xA1A20000u, 55u}, // cni -> Latn + {0xA9A20000u, 55u}, // cnk -> Latn + {0xADA20000u, 55u}, // cnl -> Latn + {0xBDA20000u, 35u}, // cnp -> Hans + {0xC1A20000u, 55u}, // cnq -> Latn + {0xC9A20000u, 55u}, // cns -> Latn + {0xCDA20000u, 55u}, // cnt -> Latn + {0xD9A20000u, 55u}, // cnw -> Latn + {0xDDA20000u, 55u}, // cnx -> Latn + {0x636F0000u, 55u}, // co -> Latn + {0x81C20000u, 55u}, // coa -> Latn + {0x85C20000u, 55u}, // cob -> Latn + {0x89C20000u, 55u}, // coc -> Latn + {0x8DC20000u, 55u}, // cod -> Latn + {0x91C20000u, 55u}, // coe -> Latn + {0x95C20000u, 55u}, // cof -> Latn + {0x99C20000u, 111u}, // cog -> Thai + {0x9DC20000u, 55u}, // coh -> Latn + {0xA5C20000u, 55u}, // coj -> Latn + {0xA9C20000u, 55u}, // cok -> Latn + {0xADC20000u, 55u}, // col -> Latn + {0xB1C20000u, 55u}, // com -> Latn + {0xB9C20000u, 55u}, // coo -> Latn + {0xBDC20000u, 18u}, // cop -> Copt + {0xC1C20000u, 55u}, // coq -> Latn + {0xCDC20000u, 55u}, // cot -> Latn + {0xD1C20000u, 55u}, // cou -> Latn + {0xDDC20000u, 55u}, // cox -> Latn + {0xE5C20000u, 55u}, // coz -> Latn + {0x81E20000u, 55u}, // cpa -> Latn + {0x85E20000u, 55u}, // cpb -> Latn + {0x89E20000u, 55u}, // cpc -> Latn + {0x99E20000u, 30u}, // cpg -> Grek + {0xA1E20000u, 55u}, // cpi -> Latn + {0xB5E20000u, 55u}, // cpn -> Latn + {0xB9E20000u, 55u}, // cpo -> Latn + {0xC9E20000u, 55u}, // cps -> Latn + {0xD1E20000u, 55u}, // cpu -> Latn + {0xDDE20000u, 55u}, // cpx -> Latn + {0xE1E20000u, 55u}, // cpy -> Latn + {0x8E020000u, 55u}, // cqd -> Latn + {0x63720000u, 13u}, // cr -> Cans + {0x82220000u, 55u}, // cra -> Latn + {0x86220000u, 55u}, // crb -> Latn + {0x8A220000u, 55u}, // crc -> Latn + {0x8E220000u, 55u}, // crd -> Latn + {0x96220000u, 55u}, // crf -> Latn + {0x9A220000u, 55u}, // crg -> Latn + {0x9E220000u, 20u}, // crh -> Cyrl + {0xA2220000u, 55u}, // cri -> Latn + {0xA6220000u, 13u}, // crj -> Cans + {0xAA220000u, 13u}, // crk -> Cans + {0xAE220000u, 13u}, // crl -> Cans + {0xB2220000u, 13u}, // crm -> Cans + {0xB6220000u, 55u}, // crn -> Latn + {0xBA220000u, 55u}, // cro -> Latn + {0xC2220000u, 55u}, // crq -> Latn + {0xCA220000u, 55u}, // crs -> Latn + {0xCE220000u, 55u}, // crt -> Latn + {0xD6220000u, 55u}, // crv -> Latn + {0xDA220000u, 55u}, // crw -> Latn + {0xDE220000u, 55u}, // crx -> Latn + {0xE2220000u, 55u}, // cry -> Latn + {0xE6220000u, 55u}, // crz -> Latn + {0x63730000u, 55u}, // cs -> Latn + {0x82420000u, 55u}, // csa -> Latn + {0x86420000u, 55u}, // csb -> Latn + {0x9E420000u, 72u}, // csh -> Mymr + {0xA6420000u, 55u}, // csj -> Latn + {0xAA420000u, 55u}, // csk -> Latn + {0xB2420000u, 55u}, // csm -> Latn + {0xBA420000u, 55u}, // cso -> Latn + {0xBE420000u, 35u}, // csp -> Hans + {0xCA420000u, 55u}, // css -> Latn + {0xCE420000u, 55u}, // cst -> Latn + {0xD6420000u, 55u}, // csv -> Latn + {0xDA420000u, 13u}, // csw -> Cans + {0xE2420000u, 55u}, // csy -> Latn + {0xE6420000u, 55u}, // csz -> Latn + {0x82620000u, 55u}, // cta -> Latn + {0x8A620000u, 55u}, // ctc -> Latn + {0x8E620000u, 83u}, // ctd -> Pauc + {0x92620000u, 55u}, // cte -> Latn + {0x9A620000u, 9u}, // ctg -> Beng + {0x9E620000u, 55u}, // cth -> Latn + {0xAE620000u, 55u}, // ctl -> Latn + {0xB2620000u, 55u}, // ctm -> Latn + {0xB6620000u, 21u}, // ctn -> Deva + {0xBA620000u, 55u}, // cto -> Latn + {0xBE620000u, 55u}, // ctp -> Latn + {0xCA620000u, 55u}, // cts -> Latn + {0xCE620000u, 105u}, // ctt -> Taml + {0xD2620000u, 55u}, // ctu -> Latn + {0xE2620000u, 105u}, // cty -> Taml + {0xE6620000u, 55u}, // ctz -> Latn + {0x63750000u, 20u}, // cu -> Cyrl + {0x82820000u, 55u}, // cua -> Latn + {0x86820000u, 55u}, // cub -> Latn + {0x8A820000u, 55u}, // cuc -> Latn + {0x9E820000u, 55u}, // cuh -> Latn + {0xA2820000u, 55u}, // cui -> Latn + {0xA6820000u, 55u}, // cuj -> Latn + {0xAA820000u, 55u}, // cuk -> Latn + {0xAE820000u, 55u}, // cul -> Latn + {0xBA820000u, 55u}, // cuo -> Latn + {0xBE820000u, 55u}, // cup -> Latn + {0xCE820000u, 55u}, // cut -> Latn + {0xD2820000u, 51u}, // cuu -> Lana + {0xD6820000u, 55u}, // cuv -> Latn + {0xDE820000u, 55u}, // cux -> Latn + {0xE2820000u, 55u}, // cuy -> Latn + {0x63760000u, 20u}, // cv -> Cyrl + {0x9AA20000u, 55u}, // cvg -> Latn + {0xB6A20000u, 55u}, // cvn -> Latn + {0x82C20000u, 55u}, // cwa -> Latn + {0x86C20000u, 55u}, // cwb -> Latn + {0x92C20000u, 55u}, // cwe -> Latn + {0x9AC20000u, 55u}, // cwg -> Latn + {0xCEC20000u, 55u}, // cwt -> Latn + {0x9EE20000u, 55u}, // cxh -> Latn + {0x63790000u, 55u}, // cy -> Latn + {0x83020000u, 55u}, // cya -> Latn + {0x87020000u, 55u}, // cyb -> Latn + {0xBB020000u, 55u}, // cyo -> Latn + {0x9F220000u, 35u}, // czh -> Hans + {0xAB220000u, 37u}, // czk -> Hebr + {0xB7220000u, 55u}, // czn -> Latn + {0xCF220000u, 55u}, // czt -> Latn + {0x64610000u, 55u}, // da -> Latn + {0x80030000u, 55u}, // daa -> Latn + {0x88030000u, 55u}, // dac -> Latn + {0x8C030000u, 55u}, // dad -> Latn + {0x90030000u, 55u}, // dae -> Latn + {0x98030000u, 55u}, // dag -> Latn + {0x9C030000u, 55u}, // dah -> Latn + {0xA0030000u, 55u}, // dai -> Latn + {0xA4030000u, 55u}, // daj -> Latn + {0xA8030000u, 55u}, // dak -> Latn + {0xAC030000u, 55u}, // dal -> Latn + {0xB0030000u, 55u}, // dam -> Latn + {0xB8030000u, 55u}, // dao -> Latn + {0xC0030000u, 21u}, // daq -> Deva + {0xC4030000u, 20u}, // dar -> Cyrl + {0xC8030000u, 55u}, // das -> Latn + {0xD0030000u, 55u}, // dau -> Latn + {0xD4030000u, 55u}, // dav -> Latn + {0xD8030000u, 55u}, // daw -> Latn + {0xDC030000u, 55u}, // dax -> Latn + {0xE4030000u, 55u}, // daz -> Latn + {0x80230000u, 55u}, // dba -> Latn + {0x84230000u, 55u}, // dbb -> Latn + {0x8C230000u, 55u}, // dbd -> Latn + {0x90230000u, 55u}, // dbe -> Latn + {0x94230000u, 55u}, // dbf -> Latn + {0x98230000u, 55u}, // dbg -> Latn + {0xA0230000u, 55u}, // dbi -> Latn + {0xA4230000u, 55u}, // dbj -> Latn + {0xAC230000u, 55u}, // dbl -> Latn + {0xB0230000u, 55u}, // dbm -> Latn + {0xB4230000u, 55u}, // dbn -> Latn + {0xB8230000u, 55u}, // dbo -> Latn + {0xBC230000u, 55u}, // dbp -> Latn + {0xC0230000u, 55u}, // dbq -> Latn + {0xCC230000u, 55u}, // dbt -> Latn + {0xD0230000u, 55u}, // dbu -> Latn + {0xD4230000u, 55u}, // dbv -> Latn + {0xD8230000u, 55u}, // dbw -> Latn + {0xE0230000u, 55u}, // dby -> Latn {0x88430000u, 2u}, // dcc -> Arab - {0xB4630000u, 46u}, // ddn -> Latn - {0x64650000u, 46u}, // de -> Latn - {0x8C830000u, 46u}, // ded -> Latn - {0xB4830000u, 46u}, // den -> Latn - {0x80C30000u, 46u}, // dga -> Latn - {0x9CC30000u, 46u}, // dgh -> Latn - {0xA0C30000u, 46u}, // dgi -> Latn + {0xC4430000u, 55u}, // dcr -> Latn + {0x80630000u, 55u}, // dda -> Latn + {0x8C630000u, 55u}, // ddd -> Latn + {0x90630000u, 55u}, // dde -> Latn + {0x98630000u, 55u}, // ddg -> Latn + {0xA0630000u, 55u}, // ddi -> Latn + {0xA4630000u, 55u}, // ddj -> Latn + {0xB4630000u, 55u}, // ddn -> Latn + {0xB8630000u, 20u}, // ddo -> Cyrl + {0xC4630000u, 55u}, // ddr -> Latn + {0xC8630000u, 55u}, // dds -> Latn + {0xD8630000u, 55u}, // ddw -> Latn + {0x64650000u, 55u}, // de -> Latn + {0x88830000u, 55u}, // dec -> Latn + {0x8C830000u, 55u}, // ded -> Latn + {0x90830000u, 55u}, // dee -> Latn + {0x94830000u, 2u}, // def -> Arab + {0x98830000u, 55u}, // deg -> Latn + {0x9C830000u, 2u}, // deh -> Arab + {0xA0830000u, 55u}, // dei -> Latn + {0xA8830000u, 55u}, // dek -> Latn + {0xAC830000u, 55u}, // del -> Latn + {0xB0830000u, 55u}, // dem -> Latn + {0xB4830000u, 55u}, // den -> Latn + {0xC0830000u, 55u}, // deq -> Latn + {0xC4830000u, 9u}, // der -> Beng + {0xC8830000u, 55u}, // des -> Latn + {0xD4830000u, 55u}, // dev -> Latn + {0xE4830000u, 55u}, // dez -> Latn + {0x80C30000u, 55u}, // dga -> Latn + {0x84C30000u, 55u}, // dgb -> Latn + {0x88C30000u, 55u}, // dgc -> Latn + {0x8CC30000u, 55u}, // dgd -> Latn + {0x90C30000u, 55u}, // dge -> Latn + {0x98C30000u, 55u}, // dgg -> Latn + {0x9CC30000u, 55u}, // dgh -> Latn + {0xA0C30000u, 55u}, // dgi -> Latn + {0xA8C30000u, 55u}, // dgk -> Latn {0xACC30000u, 2u}, // dgl -> Arab - {0xC4C30000u, 46u}, // dgr -> Latn - {0xE4C30000u, 46u}, // dgz -> Latn - {0x81030000u, 46u}, // dia -> Latn - {0x91230000u, 46u}, // dje -> Latn - {0x95830000u, 54u}, // dmf -> Medf - {0xA5A30000u, 46u}, // dnj -> Latn - {0x85C30000u, 46u}, // dob -> Latn - {0xA1C30000u, 19u}, // doi -> Deva - {0xBDC30000u, 46u}, // dop -> Latn - {0xD9C30000u, 46u}, // dow -> Latn - {0x9E230000u, 57u}, // drh -> Mong - {0xA2230000u, 46u}, // dri -> Latn - {0xCA230000u, 21u}, // drs -> Ethi - {0x86430000u, 46u}, // dsb -> Latn - {0xB2630000u, 46u}, // dtm -> Latn - {0xBE630000u, 46u}, // dtp -> Latn - {0xCA630000u, 46u}, // dts -> Latn - {0xE2630000u, 19u}, // dty -> Deva - {0x82830000u, 46u}, // dua -> Latn - {0x8A830000u, 46u}, // duc -> Latn - {0x8E830000u, 46u}, // dud -> Latn - {0x9A830000u, 46u}, // dug -> Latn - {0x64760000u, 92u}, // dv -> Thaa - {0x82A30000u, 46u}, // dva -> Latn - {0xDAC30000u, 46u}, // dww -> Latn - {0xBB030000u, 46u}, // dyo -> Latn - {0xD3030000u, 46u}, // dyu -> Latn - {0x647A0000u, 94u}, // dz -> Tibt - {0x9B230000u, 46u}, // dzg -> Latn - {0xD0240000u, 46u}, // ebu -> Latn - {0x65650000u, 46u}, // ee -> Latn - {0xA0A40000u, 46u}, // efi -> Latn - {0xACC40000u, 46u}, // egl -> Latn - {0xE0C40000u, 20u}, // egy -> Egyp - {0x81440000u, 46u}, // eka -> Latn - {0xE1440000u, 36u}, // eky -> Kali - {0x656C0000u, 26u}, // el -> Grek - {0x81840000u, 46u}, // ema -> Latn - {0xA1840000u, 46u}, // emi -> Latn - {0x656E0000u, 46u}, // en -> Latn - {0x656E5841u, 103u}, // en-XA -> ~~~A - {0xB5A40000u, 46u}, // enn -> Latn - {0xC1A40000u, 46u}, // enq -> Latn - {0x656F0000u, 46u}, // eo -> Latn - {0xA2240000u, 46u}, // eri -> Latn - {0x65730000u, 46u}, // es -> Latn - {0x9A440000u, 24u}, // esg -> Gonm - {0xD2440000u, 46u}, // esu -> Latn - {0x65740000u, 46u}, // et -> Latn - {0xC6640000u, 46u}, // etr -> Latn - {0xCE640000u, 34u}, // ett -> Ital - {0xD2640000u, 46u}, // etu -> Latn - {0xDE640000u, 46u}, // etx -> Latn - {0x65750000u, 46u}, // eu -> Latn - {0xBAC40000u, 46u}, // ewo -> Latn - {0xCEE40000u, 46u}, // ext -> Latn - {0x83240000u, 46u}, // eza -> Latn + {0xB4C30000u, 55u}, // dgn -> Latn + {0xC4C30000u, 55u}, // dgr -> Latn + {0xC8C30000u, 55u}, // dgs -> Latn + {0xCCC30000u, 55u}, // dgt -> Latn + {0xD8C30000u, 55u}, // dgw -> Latn + {0xDCC30000u, 55u}, // dgx -> Latn + {0xE4C30000u, 55u}, // dgz -> Latn + {0x98E30000u, 55u}, // dhg -> Latn + {0xA0E30000u, 21u}, // dhi -> Deva + {0xACE30000u, 55u}, // dhl -> Latn + {0xB0E30000u, 55u}, // dhm -> Latn + {0xB4E30000u, 31u}, // dhn -> Gujr + {0xB8E30000u, 21u}, // dho -> Deva + {0xC4E30000u, 55u}, // dhr -> Latn + {0xC8E30000u, 55u}, // dhs -> Latn + {0xD0E30000u, 55u}, // dhu -> Latn + {0xD4E30000u, 55u}, // dhv -> Latn + {0xD8E30000u, 21u}, // dhw -> Deva + {0xDCE30000u, 55u}, // dhx -> Latn + {0x81030000u, 55u}, // dia -> Latn + {0x85030000u, 55u}, // dib -> Latn + {0x89030000u, 55u}, // dic -> Latn + {0x8D030000u, 55u}, // did -> Latn + {0x95030000u, 55u}, // dif -> Latn + {0x99030000u, 55u}, // dig -> Latn + {0x9D030000u, 55u}, // dih -> Latn + {0xA1030000u, 55u}, // dii -> Latn + {0xA5030000u, 55u}, // dij -> Latn + {0xAD030000u, 55u}, // dil -> Latn + {0xB5030000u, 55u}, // din -> Latn + {0xB9030000u, 55u}, // dio -> Latn + {0xBD030000u, 55u}, // dip -> Latn + {0xC5030000u, 55u}, // dir -> Latn + {0xC9030000u, 55u}, // dis -> Latn + {0xD1030000u, 55u}, // diu -> Latn + {0xD9030000u, 55u}, // diw -> Latn + {0xDD030000u, 55u}, // dix -> Latn + {0xE1030000u, 55u}, // diy -> Latn + {0xE5030000u, 55u}, // diz -> Latn + {0x81230000u, 55u}, // dja -> Latn + {0x85230000u, 55u}, // djb -> Latn + {0x89230000u, 55u}, // djc -> Latn + {0x8D230000u, 55u}, // djd -> Latn + {0x91230000u, 55u}, // dje -> Latn + {0x95230000u, 55u}, // djf -> Latn + {0xA1230000u, 55u}, // dji -> Latn + {0xA5230000u, 55u}, // djj -> Latn + {0xA9230000u, 55u}, // djk -> Latn + {0xB1230000u, 55u}, // djm -> Latn + {0xB5230000u, 55u}, // djn -> Latn + {0xB9230000u, 55u}, // djo -> Latn + {0xC5230000u, 55u}, // djr -> Latn + {0xD1230000u, 55u}, // dju -> Latn + {0xD9230000u, 55u}, // djw -> Latn + {0x81430000u, 112u}, // dka -> Tibt + {0x99430000u, 55u}, // dkg -> Latn + {0xA9430000u, 55u}, // dkk -> Latn + {0xC5430000u, 55u}, // dkr -> Latn + {0xC9430000u, 55u}, // dks -> Latn + {0xDD430000u, 55u}, // dkx -> Latn + {0x99630000u, 20u}, // dlg -> Cyrl + {0xB1630000u, 55u}, // dlm -> Latn + {0xB5630000u, 55u}, // dln -> Latn + {0x81830000u, 55u}, // dma -> Latn + {0x85830000u, 55u}, // dmb -> Latn + {0x89830000u, 55u}, // dmc -> Latn + {0x8D830000u, 55u}, // dmd -> Latn + {0x91830000u, 55u}, // dme -> Latn + {0x95830000u, 65u}, // dmf -> Medf + {0x99830000u, 55u}, // dmg -> Latn + {0xA9830000u, 2u}, // dmk -> Arab + {0xAD830000u, 2u}, // dml -> Arab + {0xB1830000u, 55u}, // dmm -> Latn + {0xB9830000u, 55u}, // dmo -> Latn + {0xC5830000u, 55u}, // dmr -> Latn + {0xC9830000u, 55u}, // dms -> Latn + {0xD1830000u, 55u}, // dmu -> Latn + {0xD5830000u, 55u}, // dmv -> Latn + {0xD9830000u, 55u}, // dmw -> Latn + {0xDD830000u, 55u}, // dmx -> Latn + {0xE1830000u, 55u}, // dmy -> Latn + {0x81A30000u, 55u}, // dna -> Latn + {0x8DA30000u, 55u}, // dnd -> Latn + {0x91A30000u, 55u}, // dne -> Latn + {0x99A30000u, 20u}, // dng -> Cyrl + {0xA1A30000u, 55u}, // dni -> Latn + {0xA5A30000u, 55u}, // dnj -> Latn + {0xA9A30000u, 55u}, // dnk -> Latn + {0xB5A30000u, 55u}, // dnn -> Latn + {0xB9A30000u, 55u}, // dno -> Latn + {0xC5A30000u, 55u}, // dnr -> Latn + {0xCDA30000u, 55u}, // dnt -> Latn + {0xD1A30000u, 72u}, // dnu -> Mymr + {0xD5A30000u, 72u}, // dnv -> Mymr + {0xD9A30000u, 55u}, // dnw -> Latn + {0xE1A30000u, 55u}, // dny -> Latn + {0x81C30000u, 55u}, // doa -> Latn + {0x85C30000u, 55u}, // dob -> Latn + {0x89C30000u, 55u}, // doc -> Latn + {0x91C30000u, 55u}, // doe -> Latn + {0x95C30000u, 55u}, // dof -> Latn + {0x9DC30000u, 55u}, // doh -> Latn + {0xA1C30000u, 21u}, // doi -> Deva + {0xA9C30000u, 55u}, // dok -> Latn + {0xADC30000u, 55u}, // dol -> Latn + {0xB5C30000u, 55u}, // don -> Latn + {0xB9C30000u, 55u}, // doo -> Latn + {0xBDC30000u, 55u}, // dop -> Latn + {0xC5C30000u, 55u}, // dor -> Latn + {0xC9C30000u, 55u}, // dos -> Latn + {0xCDC30000u, 55u}, // dot -> Latn + {0xD5C30000u, 55u}, // dov -> Latn + {0xD9C30000u, 55u}, // dow -> Latn + {0xDDC30000u, 24u}, // dox -> Ethi + {0xE1C30000u, 55u}, // doy -> Latn + {0xBDE30000u, 55u}, // dpp -> Latn + {0x8A230000u, 55u}, // drc -> Latn + {0x92230000u, 112u}, // dre -> Tibt + {0x9A230000u, 55u}, // drg -> Latn + {0xA2230000u, 55u}, // dri -> Latn + {0xAE230000u, 55u}, // drl -> Latn + {0xB6230000u, 55u}, // drn -> Latn + {0xBA230000u, 55u}, // dro -> Latn + {0xC2230000u, 21u}, // drq -> Deva + {0xCA230000u, 24u}, // drs -> Ethi + {0xCE230000u, 55u}, // drt -> Latn + {0xD2230000u, 55u}, // dru -> Latn + {0xE2230000u, 21u}, // dry -> Deva + {0x86430000u, 55u}, // dsb -> Latn + {0x9E430000u, 55u}, // dsh -> Latn + {0xA2430000u, 55u}, // dsi -> Latn + {0xAA430000u, 55u}, // dsk -> Latn + {0xB6430000u, 55u}, // dsn -> Latn + {0xBA430000u, 80u}, // dso -> Orya + {0xC2430000u, 55u}, // dsq -> Latn + {0x82630000u, 55u}, // dta -> Latn + {0x86630000u, 55u}, // dtb -> Latn + {0x8E630000u, 55u}, // dtd -> Latn + {0x9E630000u, 55u}, // dth -> Latn + {0xA2630000u, 55u}, // dti -> Latn + {0xAA630000u, 55u}, // dtk -> Latn + {0xB2630000u, 55u}, // dtm -> Latn + {0xBA630000u, 55u}, // dto -> Latn + {0xBE630000u, 55u}, // dtp -> Latn + {0xC6630000u, 55u}, // dtr -> Latn + {0xCA630000u, 55u}, // dts -> Latn + {0xCE630000u, 55u}, // dtt -> Latn + {0xD2630000u, 55u}, // dtu -> Latn + {0xE2630000u, 21u}, // dty -> Deva + {0x82830000u, 55u}, // dua -> Latn + {0x86830000u, 31u}, // dub -> Gujr + {0x8A830000u, 55u}, // duc -> Latn + {0x92830000u, 55u}, // due -> Latn + {0x96830000u, 55u}, // duf -> Latn + {0x9A830000u, 55u}, // dug -> Latn + {0x9E830000u, 21u}, // duh -> Deva + {0xA2830000u, 55u}, // dui -> Latn + {0xAA830000u, 55u}, // duk -> Latn + {0xAE830000u, 55u}, // dul -> Latn + {0xB2830000u, 55u}, // dum -> Latn + {0xB6830000u, 55u}, // dun -> Latn + {0xBA830000u, 55u}, // duo -> Latn + {0xBE830000u, 55u}, // dup -> Latn + {0xC2830000u, 55u}, // duq -> Latn + {0xC6830000u, 55u}, // dur -> Latn + {0xCA830000u, 21u}, // dus -> Deva + {0xD2830000u, 55u}, // duu -> Latn + {0xD6830000u, 55u}, // duv -> Latn + {0xDA830000u, 55u}, // duw -> Latn + {0xDE830000u, 55u}, // dux -> Latn + {0xE2830000u, 55u}, // duy -> Latn + {0xE6830000u, 55u}, // duz -> Latn + {0x64760000u, 110u}, // dv -> Thaa + {0x82A30000u, 55u}, // dva -> Latn + {0x82C30000u, 55u}, // dwa -> Latn + {0xAAC30000u, 80u}, // dwk -> Orya + {0xC6C30000u, 55u}, // dwr -> Latn + {0xCAC30000u, 55u}, // dws -> Latn + {0xD2C30000u, 55u}, // dwu -> Latn + {0xDAC30000u, 55u}, // dww -> Latn + {0xE2C30000u, 55u}, // dwy -> Latn + {0xE6C30000u, 21u}, // dwz -> Deva + {0x83030000u, 55u}, // dya -> Latn + {0x87030000u, 55u}, // dyb -> Latn + {0x8F030000u, 55u}, // dyd -> Latn + {0x9B030000u, 55u}, // dyg -> Latn + {0xA3030000u, 55u}, // dyi -> Latn + {0xB3030000u, 55u}, // dym -> Latn + {0xB7030000u, 55u}, // dyn -> Latn + {0xBB030000u, 55u}, // dyo -> Latn + {0xC7030000u, 55u}, // dyr -> Latn + {0xD3030000u, 55u}, // dyu -> Latn + {0xE3030000u, 55u}, // dyy -> Latn + {0x647A0000u, 112u}, // dz -> Tibt + {0x83230000u, 55u}, // dza -> Latn + {0x8F230000u, 55u}, // dzd -> Latn + {0x93230000u, 55u}, // dze -> Latn + {0x9B230000u, 55u}, // dzg -> Latn + {0xAF230000u, 112u}, // dzl -> Tibt + {0xB7230000u, 55u}, // dzn -> Latn + {0x80040000u, 55u}, // eaa -> Latn + {0x88240000u, 55u}, // ebc -> Latn + {0x98240000u, 55u}, // ebg -> Latn + {0xA8240000u, 55u}, // ebk -> Latn + {0xB8240000u, 55u}, // ebo -> Latn + {0xC4240000u, 55u}, // ebr -> Latn + {0xD0240000u, 55u}, // ebu -> Latn + {0xC4440000u, 30u}, // ecr -> Grek + {0xE0440000u, 19u}, // ecy -> Cprt + {0x65650000u, 55u}, // ee -> Latn + {0x80A40000u, 55u}, // efa -> Latn + {0x90A40000u, 55u}, // efe -> Latn + {0xA0A40000u, 55u}, // efi -> Latn + {0x80C40000u, 55u}, // ega -> Latn + {0xACC40000u, 55u}, // egl -> Latn + {0xB0C40000u, 55u}, // egm -> Latn + {0xB8C40000u, 55u}, // ego -> Latn + {0xE0C40000u, 22u}, // egy -> Egyp + {0xD0E40000u, 55u}, // ehu -> Latn + {0xBD040000u, 55u}, // eip -> Latn + {0xCD040000u, 55u}, // eit -> Latn + {0xD5040000u, 55u}, // eiv -> Latn + {0x81240000u, 55u}, // eja -> Latn + {0x81440000u, 55u}, // eka -> Latn + {0x91440000u, 55u}, // eke -> Latn + {0x99440000u, 55u}, // ekg -> Latn + {0xA1440000u, 55u}, // eki -> Latn + {0xAD440000u, 55u}, // ekl -> Latn + {0xB1440000u, 55u}, // ekm -> Latn + {0xB9440000u, 55u}, // eko -> Latn + {0xBD440000u, 55u}, // ekp -> Latn + {0xC5440000u, 55u}, // ekr -> Latn + {0xE1440000u, 43u}, // eky -> Kali + {0x656C0000u, 30u}, // el -> Grek + {0x91640000u, 55u}, // ele -> Latn + {0xA9640000u, 55u}, // elk -> Latn + {0xB1640000u, 55u}, // elm -> Latn + {0xB9640000u, 55u}, // elo -> Latn + {0xD1640000u, 55u}, // elu -> Latn + {0x81840000u, 55u}, // ema -> Latn + {0x85840000u, 55u}, // emb -> Latn + {0x91840000u, 55u}, // eme -> Latn + {0x99840000u, 21u}, // emg -> Deva + {0xA1840000u, 55u}, // emi -> Latn + {0xB1840000u, 55u}, // emm -> Latn + {0xB5840000u, 55u}, // emn -> Latn + {0xBD840000u, 55u}, // emp -> Latn + {0xC9840000u, 55u}, // ems -> Latn + {0xD1840000u, 21u}, // emu -> Deva + {0xD9840000u, 55u}, // emw -> Latn + {0xDD840000u, 55u}, // emx -> Latn + {0xE5840000u, 55u}, // emz -> Latn + {0x656E0000u, 55u}, // en -> Latn + {0x656E5841u, 121u}, // en-XA -> ~~~A + {0x81A40000u, 55u}, // ena -> Latn + {0x85A40000u, 55u}, // enb -> Latn + {0x89A40000u, 55u}, // enc -> Latn + {0x8DA40000u, 55u}, // end -> Latn + {0x95A40000u, 20u}, // enf -> Cyrl + {0x9DA40000u, 20u}, // enh -> Cyrl + {0xADA40000u, 55u}, // enl -> Latn + {0xB1A40000u, 55u}, // enm -> Latn + {0xB5A40000u, 55u}, // enn -> Latn + {0xB9A40000u, 55u}, // eno -> Latn + {0xC1A40000u, 55u}, // enq -> Latn + {0xC5A40000u, 55u}, // enr -> Latn + {0xD5A40000u, 55u}, // env -> Latn + {0xD9A40000u, 55u}, // enw -> Latn + {0xDDA40000u, 55u}, // enx -> Latn + {0x656F0000u, 55u}, // eo -> Latn + {0xCDC40000u, 55u}, // eot -> Latn + {0xA1E40000u, 55u}, // epi -> Latn + {0x82240000u, 105u}, // era -> Taml + {0x9A240000u, 55u}, // erg -> Latn + {0x9E240000u, 55u}, // erh -> Latn + {0xA2240000u, 55u}, // eri -> Latn + {0xAA240000u, 55u}, // erk -> Latn + {0xC6240000u, 55u}, // err -> Latn + {0xCA240000u, 55u}, // ers -> Latn + {0xCE240000u, 55u}, // ert -> Latn + {0xDA240000u, 55u}, // erw -> Latn + {0x65730000u, 55u}, // es -> Latn + {0x92440000u, 55u}, // ese -> Latn + {0x9A440000u, 27u}, // esg -> Gonm + {0x9E440000u, 2u}, // esh -> Arab + {0xA2440000u, 55u}, // esi -> Latn + {0xB2440000u, 55u}, // esm -> Latn + {0xCA440000u, 55u}, // ess -> Latn + {0xD2440000u, 55u}, // esu -> Latn + {0xE2440000u, 55u}, // esy -> Latn + {0x65740000u, 55u}, // et -> Latn + {0x86640000u, 55u}, // etb -> Latn + {0xB6640000u, 55u}, // etn -> Latn + {0xBA640000u, 55u}, // eto -> Latn + {0xC6640000u, 55u}, // etr -> Latn + {0xCA640000u, 55u}, // ets -> Latn + {0xCE640000u, 40u}, // ett -> Ital + {0xD2640000u, 55u}, // etu -> Latn + {0xDE640000u, 55u}, // etx -> Latn + {0xE6640000u, 55u}, // etz -> Latn + {0x65750000u, 55u}, // eu -> Latn + {0x8E840000u, 55u}, // eud -> Latn + {0x92A40000u, 20u}, // eve -> Cyrl + {0x9EA40000u, 55u}, // evh -> Latn + {0xB6A40000u, 20u}, // evn -> Cyrl + {0xBAC40000u, 55u}, // ewo -> Latn + {0xCEE40000u, 55u}, // ext -> Latn + {0x83040000u, 55u}, // eya -> Latn + {0xBB040000u, 55u}, // eyo -> Latn + {0x83240000u, 55u}, // eza -> Latn + {0x93240000u, 55u}, // eze -> Latn {0x66610000u, 2u}, // fa -> Arab - {0x80050000u, 46u}, // faa -> Latn - {0x84050000u, 46u}, // fab -> Latn - {0x98050000u, 46u}, // fag -> Latn - {0xA0050000u, 46u}, // fai -> Latn - {0xB4050000u, 46u}, // fan -> Latn - {0x66660000u, 46u}, // ff -> Latn - {0xA0A50000u, 46u}, // ffi -> Latn - {0xB0A50000u, 46u}, // ffm -> Latn - {0x66690000u, 46u}, // fi -> Latn + {0x80050000u, 55u}, // faa -> Latn + {0x84050000u, 55u}, // fab -> Latn + {0x8C050000u, 55u}, // fad -> Latn + {0x94050000u, 55u}, // faf -> Latn + {0x98050000u, 55u}, // fag -> Latn + {0x9C050000u, 55u}, // fah -> Latn + {0xA0050000u, 55u}, // fai -> Latn + {0xA4050000u, 55u}, // faj -> Latn + {0xA8050000u, 55u}, // fak -> Latn + {0xAC050000u, 55u}, // fal -> Latn + {0xB0050000u, 55u}, // fam -> Latn + {0xB4050000u, 55u}, // fan -> Latn + {0xBC050000u, 55u}, // fap -> Latn + {0xC4050000u, 55u}, // far -> Latn + {0xD0050000u, 55u}, // fau -> Latn + {0xDC050000u, 55u}, // fax -> Latn + {0xE0050000u, 2u}, // fay -> Arab + {0xE4050000u, 2u}, // faz -> Arab + {0xAC250000u, 55u}, // fbl -> Latn + {0xC4850000u, 55u}, // fer -> Latn + {0x66660000u, 55u}, // ff -> Latn + {0xA0A50000u, 55u}, // ffi -> Latn + {0xB0A50000u, 55u}, // ffm -> Latn + {0xC4C50000u, 55u}, // fgr -> Latn + {0x66690000u, 55u}, // fi -> Latn {0x81050000u, 2u}, // fia -> Arab - {0xAD050000u, 46u}, // fil -> Latn - {0xCD050000u, 46u}, // fit -> Latn - {0x666A0000u, 46u}, // fj -> Latn - {0xC5650000u, 46u}, // flr -> Latn - {0xBD850000u, 46u}, // fmp -> Latn - {0x666F0000u, 46u}, // fo -> Latn - {0x8DC50000u, 46u}, // fod -> Latn - {0xB5C50000u, 46u}, // fon -> Latn - {0xC5C50000u, 46u}, // for -> Latn - {0x91E50000u, 46u}, // fpe -> Latn - {0xCA050000u, 46u}, // fqs -> Latn - {0x66720000u, 46u}, // fr -> Latn - {0x8A250000u, 46u}, // frc -> Latn - {0xBE250000u, 46u}, // frp -> Latn - {0xC6250000u, 46u}, // frr -> Latn - {0xCA250000u, 46u}, // frs -> Latn + {0x91050000u, 55u}, // fie -> Latn + {0x95050000u, 55u}, // fif -> Latn + {0xAD050000u, 55u}, // fil -> Latn + {0xBD050000u, 55u}, // fip -> Latn + {0xC5050000u, 55u}, // fir -> Latn + {0xCD050000u, 55u}, // fit -> Latn + {0xD9050000u, 55u}, // fiw -> Latn + {0x666A0000u, 55u}, // fj -> Latn + {0xA9450000u, 55u}, // fkk -> Latn + {0xD5450000u, 55u}, // fkv -> Latn + {0x81650000u, 55u}, // fla -> Latn + {0x9D650000u, 55u}, // flh -> Latn + {0xA1650000u, 55u}, // fli -> Latn + {0xAD650000u, 55u}, // fll -> Latn + {0xB5650000u, 55u}, // fln -> Latn + {0xC5650000u, 55u}, // flr -> Latn + {0xE1650000u, 55u}, // fly -> Latn + {0xBD850000u, 55u}, // fmp -> Latn + {0xD1850000u, 21u}, // fmu -> Deva + {0x85A50000u, 55u}, // fnb -> Latn + {0x99A50000u, 55u}, // fng -> Latn + {0xA1A50000u, 55u}, // fni -> Latn + {0x666F0000u, 55u}, // fo -> Latn + {0x8DC50000u, 55u}, // fod -> Latn + {0xA1C50000u, 55u}, // foi -> Latn + {0xB1C50000u, 55u}, // fom -> Latn + {0xB5C50000u, 55u}, // fon -> Latn + {0xC5C50000u, 55u}, // for -> Latn + {0xC9C50000u, 55u}, // fos -> Latn + {0x91E50000u, 55u}, // fpe -> Latn + {0xCA050000u, 55u}, // fqs -> Latn + {0x66720000u, 55u}, // fr -> Latn + {0x8A250000u, 55u}, // frc -> Latn + {0x8E250000u, 55u}, // frd -> Latn + {0xAA250000u, 55u}, // frk -> Latn + {0xB2250000u, 55u}, // frm -> Latn + {0xBA250000u, 55u}, // fro -> Latn + {0xBE250000u, 55u}, // frp -> Latn + {0xC2250000u, 55u}, // frq -> Latn + {0xC6250000u, 55u}, // frr -> Latn + {0xCA250000u, 55u}, // frs -> Latn + {0xCE250000u, 55u}, // frt -> Latn {0x86850000u, 2u}, // fub -> Arab - {0x8E850000u, 46u}, // fud -> Latn - {0x92850000u, 46u}, // fue -> Latn - {0x96850000u, 46u}, // fuf -> Latn - {0x9E850000u, 46u}, // fuh -> Latn - {0xC2850000u, 46u}, // fuq -> Latn - {0xC6850000u, 46u}, // fur -> Latn - {0xD6850000u, 46u}, // fuv -> Latn - {0xE2850000u, 46u}, // fuy -> Latn - {0xC6A50000u, 46u}, // fvr -> Latn - {0x66790000u, 46u}, // fy -> Latn - {0x67610000u, 46u}, // ga -> Latn - {0x80060000u, 46u}, // gaa -> Latn - {0x94060000u, 46u}, // gaf -> Latn - {0x98060000u, 46u}, // gag -> Latn - {0x9C060000u, 46u}, // gah -> Latn - {0xA4060000u, 46u}, // gaj -> Latn - {0xB0060000u, 46u}, // gam -> Latn - {0xB4060000u, 29u}, // gan -> Hans - {0xD8060000u, 46u}, // gaw -> Latn - {0xE0060000u, 46u}, // gay -> Latn - {0x80260000u, 46u}, // gba -> Latn - {0x94260000u, 46u}, // gbf -> Latn - {0xB0260000u, 19u}, // gbm -> Deva - {0xE0260000u, 46u}, // gby -> Latn + {0x8E850000u, 55u}, // fud -> Latn + {0x92850000u, 55u}, // fue -> Latn + {0x96850000u, 55u}, // fuf -> Latn + {0x9E850000u, 55u}, // fuh -> Latn + {0xA2850000u, 55u}, // fui -> Latn + {0xB2850000u, 55u}, // fum -> Latn + {0xB6850000u, 55u}, // fun -> Latn + {0xC2850000u, 55u}, // fuq -> Latn + {0xC6850000u, 55u}, // fur -> Latn + {0xCE850000u, 55u}, // fut -> Latn + {0xD2850000u, 55u}, // fuu -> Latn + {0xD6850000u, 55u}, // fuv -> Latn + {0xE2850000u, 55u}, // fuy -> Latn + {0xC6A50000u, 55u}, // fvr -> Latn + {0x82C50000u, 55u}, // fwa -> Latn + {0x92C50000u, 55u}, // fwe -> Latn + {0x66790000u, 55u}, // fy -> Latn + {0x67610000u, 55u}, // ga -> Latn + {0x80060000u, 55u}, // gaa -> Latn + {0x84060000u, 55u}, // gab -> Latn + {0x88060000u, 55u}, // gac -> Latn + {0x8C060000u, 55u}, // gad -> Latn + {0x90060000u, 55u}, // gae -> Latn + {0x94060000u, 55u}, // gaf -> Latn + {0x98060000u, 55u}, // gag -> Latn + {0x9C060000u, 55u}, // gah -> Latn + {0xA0060000u, 55u}, // gai -> Latn + {0xA4060000u, 55u}, // gaj -> Latn + {0xA8060000u, 55u}, // gak -> Latn + {0xAC060000u, 55u}, // gal -> Latn + {0xB0060000u, 55u}, // gam -> Latn + {0xB4060000u, 35u}, // gan -> Hans + {0xB8060000u, 55u}, // gao -> Latn + {0xBC060000u, 55u}, // gap -> Latn + {0xC0060000u, 80u}, // gaq -> Orya + {0xC4060000u, 55u}, // gar -> Latn + {0xC8060000u, 31u}, // gas -> Gujr + {0xCC060000u, 55u}, // gat -> Latn + {0xD0060000u, 108u}, // gau -> Telu + {0xD8060000u, 55u}, // gaw -> Latn + {0xDC060000u, 55u}, // gax -> Latn + {0xE0060000u, 55u}, // gay -> Latn + {0x80260000u, 55u}, // gba -> Latn + {0x84260000u, 55u}, // gbb -> Latn + {0x8C260000u, 55u}, // gbd -> Latn + {0x90260000u, 55u}, // gbe -> Latn + {0x94260000u, 55u}, // gbf -> Latn + {0x98260000u, 55u}, // gbg -> Latn + {0x9C260000u, 55u}, // gbh -> Latn + {0xA0260000u, 55u}, // gbi -> Latn + {0xA4260000u, 80u}, // gbj -> Orya + {0xA8260000u, 21u}, // gbk -> Deva + {0xAC260000u, 31u}, // gbl -> Gujr + {0xB0260000u, 21u}, // gbm -> Deva + {0xB4260000u, 55u}, // gbn -> Latn + {0xBC260000u, 55u}, // gbp -> Latn + {0xC0260000u, 55u}, // gbq -> Latn + {0xC4260000u, 55u}, // gbr -> Latn + {0xC8260000u, 55u}, // gbs -> Latn + {0xD0260000u, 55u}, // gbu -> Latn + {0xD4260000u, 55u}, // gbv -> Latn + {0xD8260000u, 55u}, // gbw -> Latn + {0xDC260000u, 55u}, // gbx -> Latn + {0xE0260000u, 55u}, // gby -> Latn {0xE4260000u, 2u}, // gbz -> Arab - {0xC4460000u, 46u}, // gcr -> Latn - {0x67640000u, 46u}, // gd -> Latn - {0x90660000u, 46u}, // gde -> Latn - {0xB4660000u, 46u}, // gdn -> Latn - {0xC4660000u, 46u}, // gdr -> Latn - {0x84860000u, 46u}, // geb -> Latn - {0xA4860000u, 46u}, // gej -> Latn - {0xAC860000u, 46u}, // gel -> Latn - {0xE4860000u, 21u}, // gez -> Ethi - {0xA8A60000u, 46u}, // gfk -> Latn - {0xB4C60000u, 19u}, // ggn -> Deva - {0xC8E60000u, 46u}, // ghs -> Latn - {0xAD060000u, 46u}, // gil -> Latn - {0xB1060000u, 46u}, // gim -> Latn + {0x88460000u, 55u}, // gcc -> Latn + {0x8C460000u, 55u}, // gcd -> Latn + {0x94460000u, 55u}, // gcf -> Latn + {0xAC460000u, 55u}, // gcl -> Latn + {0xB4460000u, 55u}, // gcn -> Latn + {0xC4460000u, 55u}, // gcr -> Latn + {0xCC460000u, 55u}, // gct -> Latn + {0x67640000u, 55u}, // gd -> Latn + {0x84660000u, 80u}, // gdb -> Orya + {0x88660000u, 55u}, // gdc -> Latn + {0x8C660000u, 55u}, // gdd -> Latn + {0x90660000u, 55u}, // gde -> Latn + {0x94660000u, 55u}, // gdf -> Latn + {0x98660000u, 55u}, // gdg -> Latn + {0x9C660000u, 55u}, // gdh -> Latn + {0xA0660000u, 55u}, // gdi -> Latn + {0xA4660000u, 55u}, // gdj -> Latn + {0xA8660000u, 55u}, // gdk -> Latn + {0xAC660000u, 55u}, // gdl -> Latn + {0xB0660000u, 55u}, // gdm -> Latn + {0xB4660000u, 55u}, // gdn -> Latn + {0xB8660000u, 20u}, // gdo -> Cyrl + {0xC0660000u, 55u}, // gdq -> Latn + {0xC4660000u, 55u}, // gdr -> Latn + {0xCC660000u, 55u}, // gdt -> Latn + {0xD0660000u, 55u}, // gdu -> Latn + {0xDC660000u, 21u}, // gdx -> Deva + {0x80860000u, 55u}, // gea -> Latn + {0x84860000u, 55u}, // geb -> Latn + {0x88860000u, 55u}, // gec -> Latn + {0x8C860000u, 55u}, // ged -> Latn + {0x94860000u, 55u}, // gef -> Latn + {0x98860000u, 55u}, // geg -> Latn + {0x9C860000u, 55u}, // geh -> Latn + {0xA0860000u, 55u}, // gei -> Latn + {0xA4860000u, 55u}, // gej -> Latn + {0xA8860000u, 55u}, // gek -> Latn + {0xAC860000u, 55u}, // gel -> Latn + {0xC0860000u, 55u}, // geq -> Latn + {0xC8860000u, 55u}, // ges -> Latn + {0xD4860000u, 55u}, // gev -> Latn + {0xD8860000u, 55u}, // gew -> Latn + {0xDC860000u, 55u}, // gex -> Latn + {0xE0860000u, 55u}, // gey -> Latn + {0xE4860000u, 24u}, // gez -> Ethi + {0xA8A60000u, 55u}, // gfk -> Latn + {0x80C60000u, 55u}, // gga -> Latn + {0x84C60000u, 55u}, // ggb -> Latn + {0x8CC60000u, 55u}, // ggd -> Latn + {0x90C60000u, 55u}, // gge -> Latn + {0x98C60000u, 2u}, // ggg -> Arab + {0xA8C60000u, 55u}, // ggk -> Latn + {0xACC60000u, 55u}, // ggl -> Latn + {0xCCC60000u, 55u}, // ggt -> Latn + {0xD0C60000u, 55u}, // ggu -> Latn + {0xD8C60000u, 55u}, // ggw -> Latn + {0x80E60000u, 2u}, // gha -> Arab + {0x88E60000u, 55u}, // ghc -> Latn + {0x90E60000u, 21u}, // ghe -> Deva + {0xA8E60000u, 55u}, // ghk -> Latn + {0xB4E60000u, 55u}, // ghn -> Latn + {0xB8E60000u, 109u}, // gho -> Tfng + {0xC4E60000u, 2u}, // ghr -> Arab + {0xC8E60000u, 55u}, // ghs -> Latn + {0xCCE60000u, 112u}, // ght -> Tibt + {0x81060000u, 55u}, // gia -> Latn + {0x85060000u, 55u}, // gib -> Latn + {0x89060000u, 55u}, // gic -> Latn + {0x8D060000u, 55u}, // gid -> Latn + {0x91060000u, 55u}, // gie -> Latn + {0x99060000u, 2u}, // gig -> Arab + {0x9D060000u, 55u}, // gih -> Latn + {0xAD060000u, 55u}, // gil -> Latn + {0xB1060000u, 55u}, // gim -> Latn + {0xB5060000u, 20u}, // gin -> Cyrl + {0xBD060000u, 55u}, // gip -> Latn + {0xC1060000u, 55u}, // giq -> Latn + {0xC5060000u, 55u}, // gir -> Latn + {0xC9060000u, 55u}, // gis -> Latn + {0xCD060000u, 55u}, // git -> Latn + {0xDD060000u, 55u}, // gix -> Latn + {0xE1060000u, 55u}, // giy -> Latn + {0xE5060000u, 55u}, // giz -> Latn {0xA9260000u, 2u}, // gjk -> Arab - {0xB5260000u, 46u}, // gjn -> Latn + {0xB1260000u, 55u}, // gjm -> Latn + {0xB5260000u, 55u}, // gjn -> Latn + {0xC5260000u, 55u}, // gjr -> Latn {0xD1260000u, 2u}, // gju -> Arab - {0xB5460000u, 46u}, // gkn -> Latn - {0xBD460000u, 46u}, // gkp -> Latn - {0x676C0000u, 46u}, // gl -> Latn + {0x81460000u, 55u}, // gka -> Latn + {0x8D460000u, 55u}, // gkd -> Latn + {0x91460000u, 55u}, // gke -> Latn + {0xB5460000u, 55u}, // gkn -> Latn + {0xB9460000u, 55u}, // gko -> Latn + {0xBD460000u, 55u}, // gkp -> Latn + {0xD1460000u, 55u}, // gku -> Latn + {0x676C0000u, 55u}, // gl -> Latn + {0x85660000u, 55u}, // glb -> Latn + {0x89660000u, 55u}, // glc -> Latn + {0x8D660000u, 20u}, // gld -> Cyrl + {0x9D660000u, 2u}, // glh -> Arab + {0xA5660000u, 55u}, // glj -> Latn {0xA9660000u, 2u}, // glk -> Arab - {0xB1860000u, 46u}, // gmm -> Latn - {0xD5860000u, 21u}, // gmv -> Ethi - {0x676E0000u, 46u}, // gn -> Latn - {0x8DA60000u, 46u}, // gnd -> Latn - {0x99A60000u, 46u}, // gng -> Latn - {0x8DC60000u, 46u}, // god -> Latn - {0x95C60000u, 21u}, // gof -> Ethi - {0xA1C60000u, 46u}, // goi -> Latn - {0xB1C60000u, 19u}, // gom -> Deva - {0xB5C60000u, 90u}, // gon -> Telu - {0xC5C60000u, 46u}, // gor -> Latn - {0xC9C60000u, 46u}, // gos -> Latn - {0xCDC60000u, 25u}, // got -> Goth - {0x86260000u, 46u}, // grb -> Latn - {0x8A260000u, 17u}, // grc -> Cprt - {0xCE260000u, 8u}, // grt -> Beng - {0xDA260000u, 46u}, // grw -> Latn - {0xDA460000u, 46u}, // gsw -> Latn - {0x67750000u, 27u}, // gu -> Gujr - {0x86860000u, 46u}, // gub -> Latn - {0x8A860000u, 46u}, // guc -> Latn - {0x8E860000u, 46u}, // gud -> Latn - {0xC6860000u, 46u}, // gur -> Latn - {0xDA860000u, 46u}, // guw -> Latn - {0xDE860000u, 46u}, // gux -> Latn - {0xE6860000u, 46u}, // guz -> Latn - {0x67760000u, 46u}, // gv -> Latn - {0x96A60000u, 46u}, // gvf -> Latn - {0xC6A60000u, 19u}, // gvr -> Deva - {0xCAA60000u, 46u}, // gvs -> Latn + {0xAD660000u, 55u}, // gll -> Latn + {0xB9660000u, 55u}, // glo -> Latn + {0xC5660000u, 55u}, // glr -> Latn + {0xD1660000u, 55u}, // glu -> Latn + {0xD9660000u, 55u}, // glw -> Latn + {0x81860000u, 55u}, // gma -> Latn + {0x85860000u, 55u}, // gmb -> Latn + {0x8D860000u, 55u}, // gmd -> Latn + {0x99860000u, 55u}, // gmg -> Latn + {0x9D860000u, 55u}, // gmh -> Latn + {0xAD860000u, 53u}, // gml -> Latf + {0xB1860000u, 55u}, // gmm -> Latn + {0xB5860000u, 55u}, // gmn -> Latn + {0xC5860000u, 55u}, // gmr -> Latn + {0xD1860000u, 55u}, // gmu -> Latn + {0xD5860000u, 24u}, // gmv -> Ethi + {0xDD860000u, 55u}, // gmx -> Latn + {0xE1860000u, 58u}, // gmy -> Linb + {0xE5860000u, 55u}, // gmz -> Latn + {0x676E0000u, 55u}, // gn -> Latn + {0x81A60000u, 55u}, // gna -> Latn + {0x85A60000u, 55u}, // gnb -> Latn + {0x89A60000u, 55u}, // gnc -> Latn + {0x8DA60000u, 55u}, // gnd -> Latn + {0x91A60000u, 55u}, // gne -> Latn + {0x99A60000u, 55u}, // gng -> Latn + {0x9DA60000u, 55u}, // gnh -> Latn + {0xA1A60000u, 55u}, // gni -> Latn + {0xA5A60000u, 55u}, // gnj -> Latn + {0xA9A60000u, 55u}, // gnk -> Latn + {0xADA60000u, 55u}, // gnl -> Latn + {0xB1A60000u, 55u}, // gnm -> Latn + {0xB5A60000u, 55u}, // gnn -> Latn + {0xC1A60000u, 55u}, // gnq -> Latn + {0xC5A60000u, 55u}, // gnr -> Latn + {0xCDA60000u, 55u}, // gnt -> Latn + {0xD1A60000u, 55u}, // gnu -> Latn + {0xD9A60000u, 55u}, // gnw -> Latn + {0xE5A60000u, 55u}, // gnz -> Latn + {0x81C60000u, 55u}, // goa -> Latn + {0x85C60000u, 55u}, // gob -> Latn + {0x89C60000u, 55u}, // goc -> Latn + {0x8DC60000u, 55u}, // god -> Latn + {0x91C60000u, 112u}, // goe -> Tibt + {0x95C60000u, 24u}, // gof -> Ethi + {0x99C60000u, 55u}, // gog -> Latn + {0x9DC60000u, 55u}, // goh -> Latn + {0xA1C60000u, 55u}, // goi -> Latn + {0xA5C60000u, 21u}, // goj -> Deva + {0xA9C60000u, 21u}, // gok -> Deva + {0xADC60000u, 55u}, // gol -> Latn + {0xB5C60000u, 21u}, // gon -> Deva + {0xB9C60000u, 55u}, // goo -> Latn + {0xBDC60000u, 55u}, // gop -> Latn + {0xC1C60000u, 55u}, // goq -> Latn + {0xC5C60000u, 55u}, // gor -> Latn + {0xC9C60000u, 55u}, // gos -> Latn + {0xCDC60000u, 28u}, // got -> Goth + {0xD1C60000u, 55u}, // gou -> Latn + {0xD5C60000u, 55u}, // gov -> Latn + {0xD9C60000u, 55u}, // gow -> Latn + {0xDDC60000u, 55u}, // gox -> Latn + {0xE1C60000u, 55u}, // goy -> Latn + {0x81E60000u, 55u}, // gpa -> Latn + {0x91E60000u, 55u}, // gpe -> Latn + {0xB5E60000u, 55u}, // gpn -> Latn + {0x82060000u, 55u}, // gqa -> Latn + {0xB6060000u, 55u}, // gqn -> Latn + {0xC6060000u, 55u}, // gqr -> Latn + {0x82260000u, 21u}, // gra -> Deva + {0x86260000u, 55u}, // grb -> Latn + {0x8A260000u, 19u}, // grc -> Cprt + {0x8E260000u, 55u}, // grd -> Latn + {0x9A260000u, 55u}, // grg -> Latn + {0x9E260000u, 55u}, // grh -> Latn + {0xA2260000u, 55u}, // gri -> Latn + {0xA6260000u, 55u}, // grj -> Latn + {0xB2260000u, 55u}, // grm -> Latn + {0xC2260000u, 55u}, // grq -> Latn + {0xCA260000u, 55u}, // grs -> Latn + {0xCE260000u, 9u}, // grt -> Beng + {0xD2260000u, 24u}, // gru -> Ethi + {0xD6260000u, 55u}, // grv -> Latn + {0xDA260000u, 55u}, // grw -> Latn + {0xDE260000u, 55u}, // grx -> Latn + {0xE2260000u, 55u}, // gry -> Latn + {0xE6260000u, 55u}, // grz -> Latn + {0xAE460000u, 55u}, // gsl -> Latn + {0xB6460000u, 55u}, // gsn -> Latn + {0xBA460000u, 55u}, // gso -> Latn + {0xBE460000u, 55u}, // gsp -> Latn + {0xDA460000u, 55u}, // gsw -> Latn + {0x82660000u, 55u}, // gta -> Latn + {0xD2660000u, 55u}, // gtu -> Latn + {0x67750000u, 31u}, // gu -> Gujr + {0x82860000u, 55u}, // gua -> Latn + {0x86860000u, 55u}, // gub -> Latn + {0x8A860000u, 55u}, // guc -> Latn + {0x8E860000u, 55u}, // gud -> Latn + {0x92860000u, 55u}, // gue -> Latn + {0x96860000u, 55u}, // guf -> Latn + {0x9E860000u, 55u}, // guh -> Latn + {0xA2860000u, 55u}, // gui -> Latn + {0xAA860000u, 55u}, // guk -> Latn + {0xAE860000u, 55u}, // gul -> Latn + {0xB2860000u, 55u}, // gum -> Latn + {0xB6860000u, 55u}, // gun -> Latn + {0xBA860000u, 55u}, // guo -> Latn + {0xBE860000u, 55u}, // gup -> Latn + {0xC2860000u, 55u}, // guq -> Latn + {0xC6860000u, 55u}, // gur -> Latn + {0xCE860000u, 55u}, // gut -> Latn + {0xD2860000u, 55u}, // guu -> Latn + {0xDA860000u, 55u}, // guw -> Latn + {0xDE860000u, 55u}, // gux -> Latn + {0xE6860000u, 55u}, // guz -> Latn + {0x67760000u, 55u}, // gv -> Latn + {0x82A60000u, 55u}, // gva -> Latn + {0x8AA60000u, 55u}, // gvc -> Latn + {0x92A60000u, 55u}, // gve -> Latn + {0x96A60000u, 55u}, // gvf -> Latn + {0xA6A60000u, 55u}, // gvj -> Latn + {0xAEA60000u, 55u}, // gvl -> Latn + {0xB2A60000u, 55u}, // gvm -> Latn + {0xB6A60000u, 55u}, // gvn -> Latn + {0xBAA60000u, 55u}, // gvo -> Latn + {0xBEA60000u, 55u}, // gvp -> Latn + {0xC6A60000u, 21u}, // gvr -> Deva + {0xCAA60000u, 55u}, // gvs -> Latn + {0xE2A60000u, 55u}, // gvy -> Latn + {0x82C60000u, 55u}, // gwa -> Latn + {0x86C60000u, 55u}, // gwb -> Latn {0x8AC60000u, 2u}, // gwc -> Arab - {0xA2C60000u, 46u}, // gwi -> Latn + {0x8EC60000u, 55u}, // gwd -> Latn + {0x92C60000u, 55u}, // gwe -> Latn + {0x96C60000u, 2u}, // gwf -> Arab + {0x9AC60000u, 55u}, // gwg -> Latn + {0xA2C60000u, 55u}, // gwi -> Latn + {0xA6C60000u, 55u}, // gwj -> Latn + {0xB2C60000u, 55u}, // gwm -> Latn + {0xB6C60000u, 55u}, // gwn -> Latn + {0xC6C60000u, 55u}, // gwr -> Latn {0xCEC60000u, 2u}, // gwt -> Arab - {0xA3060000u, 46u}, // gyi -> Latn - {0x68610000u, 46u}, // ha -> Latn + {0xD2C60000u, 55u}, // gwu -> Latn + {0xDAC60000u, 55u}, // gww -> Latn + {0xDEC60000u, 55u}, // gwx -> Latn + {0xDEE60000u, 55u}, // gxx -> Latn + {0x87060000u, 55u}, // gyb -> Latn + {0x8F060000u, 55u}, // gyd -> Latn + {0x93060000u, 55u}, // gye -> Latn + {0x97060000u, 55u}, // gyf -> Latn + {0x9B060000u, 55u}, // gyg -> Latn + {0xA3060000u, 55u}, // gyi -> Latn + {0xAF060000u, 55u}, // gyl -> Latn + {0xB3060000u, 55u}, // gym -> Latn + {0xB7060000u, 55u}, // gyn -> Latn + {0xBB060000u, 21u}, // gyo -> Deva + {0xC7060000u, 55u}, // gyr -> Latn + {0xE3060000u, 55u}, // gyy -> Latn + {0xE7060000u, 55u}, // gyz -> Latn + {0x83260000u, 55u}, // gza -> Latn + {0xA3260000u, 2u}, // gzi -> Arab + {0xB7260000u, 55u}, // gzn -> Latn + {0x68610000u, 55u}, // ha -> Latn {0x6861434Du, 2u}, // ha-CM -> Arab {0x68615344u, 2u}, // ha-SD -> Arab - {0x98070000u, 46u}, // hag -> Latn - {0xA8070000u, 29u}, // hak -> Hans - {0xB0070000u, 46u}, // ham -> Latn - {0xD8070000u, 46u}, // haw -> Latn + {0x80070000u, 55u}, // haa -> Latn + {0x88070000u, 2u}, // hac -> Arab + {0x8C070000u, 55u}, // had -> Latn + {0x90070000u, 55u}, // hae -> Latn + {0x98070000u, 55u}, // hag -> Latn + {0x9C070000u, 55u}, // hah -> Latn + {0xA0070000u, 55u}, // hai -> Latn + {0xA4070000u, 55u}, // haj -> Latn + {0xA8070000u, 35u}, // hak -> Hans + {0xAC070000u, 55u}, // hal -> Latn + {0xB0070000u, 55u}, // ham -> Latn + {0xB4070000u, 55u}, // han -> Latn + {0xB8070000u, 55u}, // hao -> Latn + {0xBC070000u, 55u}, // hap -> Latn + {0xC0070000u, 55u}, // haq -> Latn + {0xC4070000u, 24u}, // har -> Ethi + {0xC8070000u, 55u}, // has -> Latn + {0xD4070000u, 55u}, // hav -> Latn + {0xD8070000u, 55u}, // haw -> Latn + {0xDC070000u, 55u}, // hax -> Latn + {0xE0070000u, 55u}, // hay -> Latn {0xE4070000u, 2u}, // haz -> Arab - {0x84270000u, 46u}, // hbb -> Latn - {0xE0670000u, 21u}, // hdy -> Ethi - {0x68650000u, 31u}, // he -> Hebr - {0xE0E70000u, 46u}, // hhy -> Latn - {0x68690000u, 19u}, // hi -> Deva - {0x81070000u, 46u}, // hia -> Latn - {0x95070000u, 46u}, // hif -> Latn - {0x99070000u, 46u}, // hig -> Latn - {0x9D070000u, 46u}, // hih -> Latn - {0xAD070000u, 46u}, // hil -> Latn - {0x81670000u, 46u}, // hla -> Latn - {0xD1670000u, 32u}, // hlu -> Hluw - {0x8D870000u, 72u}, // hmd -> Plrd - {0xCD870000u, 46u}, // hmt -> Latn + {0x80270000u, 55u}, // hba -> Latn + {0x84270000u, 55u}, // hbb -> Latn + {0xB4270000u, 55u}, // hbn -> Latn + {0xB8270000u, 37u}, // hbo -> Hebr + {0xD0270000u, 55u}, // hbu -> Latn + {0x9C470000u, 55u}, // hch -> Latn + {0xE0670000u, 24u}, // hdy -> Ethi + {0x68650000u, 37u}, // he -> Hebr + {0x8C870000u, 55u}, // hed -> Latn + {0x98870000u, 55u}, // heg -> Latn + {0x9C870000u, 55u}, // heh -> Latn + {0xA0870000u, 55u}, // hei -> Latn + {0xB0870000u, 55u}, // hem -> Latn + {0xB0C70000u, 55u}, // hgm -> Latn + {0xD8C70000u, 55u}, // hgw -> Latn + {0xA0E70000u, 55u}, // hhi -> Latn + {0xC4E70000u, 55u}, // hhr -> Latn + {0xE0E70000u, 55u}, // hhy -> Latn + {0x68690000u, 21u}, // hi -> Deva + {0x81070000u, 55u}, // hia -> Latn + {0x85070000u, 55u}, // hib -> Latn + {0x8D070000u, 55u}, // hid -> Latn + {0x95070000u, 21u}, // hif -> Deva + {0x99070000u, 55u}, // hig -> Latn + {0x9D070000u, 55u}, // hih -> Latn + {0xA1070000u, 102u}, // hii -> Takr + {0xA5070000u, 55u}, // hij -> Latn + {0xA9070000u, 55u}, // hik -> Latn + {0xAD070000u, 55u}, // hil -> Latn + {0xB9070000u, 55u}, // hio -> Latn + {0xC5070000u, 55u}, // hir -> Latn + {0xCD070000u, 119u}, // hit -> Xsux + {0xD9070000u, 55u}, // hiw -> Latn + {0xDD070000u, 55u}, // hix -> Latn + {0xA1270000u, 55u}, // hji -> Latn + {0x81470000u, 55u}, // hka -> Latn + {0x91470000u, 55u}, // hke -> Latn + {0x9D470000u, 2u}, // hkh -> Arab + {0xA9470000u, 55u}, // hkk -> Latn + {0x81670000u, 55u}, // hla -> Latn + {0x85670000u, 21u}, // hlb -> Deva + {0x8D670000u, 55u}, // hld -> Latn + {0xCD670000u, 55u}, // hlt -> Latn + {0xD1670000u, 38u}, // hlu -> Hluw + {0x81870000u, 55u}, // hma -> Latn + {0x85870000u, 55u}, // hmb -> Latn + {0x8D870000u, 86u}, // hmd -> Plrd + {0x95870000u, 55u}, // hmf -> Latn + {0xA5870000u, 10u}, // hmj -> Bopo + {0xB1870000u, 55u}, // hmm -> Latn + {0xB5870000u, 55u}, // hmn -> Latn + {0xBD870000u, 55u}, // hmp -> Latn + {0xC1870000u, 10u}, // hmq -> Bopo + {0xC5870000u, 55u}, // hmr -> Latn + {0xC9870000u, 55u}, // hms -> Latn + {0xCD870000u, 55u}, // hmt -> Latn + {0xD1870000u, 55u}, // hmu -> Latn + {0xD5870000u, 55u}, // hmv -> Latn + {0xD9870000u, 55u}, // hmw -> Latn + {0xE1870000u, 55u}, // hmy -> Latn + {0xE5870000u, 55u}, // hmz -> Latn + {0x81A70000u, 55u}, // hna -> Latn {0x8DA70000u, 2u}, // hnd -> Arab - {0x91A70000u, 19u}, // hne -> Deva - {0xA5A70000u, 33u}, // hnj -> Hmnp - {0xB5A70000u, 46u}, // hnn -> Latn + {0x91A70000u, 21u}, // hne -> Deva + {0x99A70000u, 55u}, // hng -> Latn + {0x9DA70000u, 55u}, // hnh -> Latn + {0xA1A70000u, 55u}, // hni -> Latn + {0xA5A70000u, 39u}, // hnj -> Hmnp + {0xB5A70000u, 55u}, // hnn -> Latn {0xB9A70000u, 2u}, // hno -> Arab - {0x686F0000u, 46u}, // ho -> Latn - {0x89C70000u, 19u}, // hoc -> Deva - {0xA5C70000u, 19u}, // hoj -> Deva - {0xCDC70000u, 46u}, // hot -> Latn - {0x68720000u, 46u}, // hr -> Latn - {0x86470000u, 46u}, // hsb -> Latn - {0xB6470000u, 29u}, // hsn -> Hans - {0x68740000u, 46u}, // ht -> Latn - {0x68750000u, 46u}, // hu -> Latn - {0xA2870000u, 46u}, // hui -> Latn - {0xC6870000u, 46u}, // hur -> Latn + {0xC9A70000u, 55u}, // hns -> Latn + {0x686F0000u, 55u}, // ho -> Latn + {0x81C70000u, 55u}, // hoa -> Latn + {0x85C70000u, 55u}, // hob -> Latn + {0x89C70000u, 21u}, // hoc -> Deva + {0x8DC70000u, 55u}, // hod -> Latn + {0x91C70000u, 55u}, // hoe -> Latn + {0x9DC70000u, 2u}, // hoh -> Arab + {0xA1C70000u, 55u}, // hoi -> Latn + {0xA5C70000u, 21u}, // hoj -> Deva + {0xADC70000u, 55u}, // hol -> Latn + {0xB1C70000u, 55u}, // hom -> Latn + {0xB9C70000u, 55u}, // hoo -> Latn + {0xBDC70000u, 55u}, // hop -> Latn + {0xC5C70000u, 55u}, // hor -> Latn + {0xCDC70000u, 55u}, // hot -> Latn + {0xD5C70000u, 55u}, // hov -> Latn + {0xD9C70000u, 34u}, // how -> Hani + {0xE1C70000u, 21u}, // hoy -> Deva + {0xB9E70000u, 72u}, // hpo -> Mymr + {0x68720000u, 55u}, // hr -> Latn + {0x82270000u, 55u}, // hra -> Latn + {0x8A270000u, 55u}, // hrc -> Latn + {0x92270000u, 55u}, // hre -> Latn + {0xAA270000u, 55u}, // hrk -> Latn + {0xB2270000u, 55u}, // hrm -> Latn + {0xBA270000u, 55u}, // hro -> Latn + {0xBE270000u, 55u}, // hrp -> Latn + {0xCE270000u, 100u}, // hrt -> Syrc + {0xD2270000u, 55u}, // hru -> Latn + {0xDA270000u, 55u}, // hrw -> Latn + {0xDE270000u, 55u}, // hrx -> Latn + {0xE6270000u, 2u}, // hrz -> Arab + {0x86470000u, 55u}, // hsb -> Latn + {0xB6470000u, 35u}, // hsn -> Hans + {0xCA470000u, 2u}, // hss -> Arab + {0x68740000u, 55u}, // ht -> Latn + {0xA2670000u, 55u}, // hti -> Latn + {0xBA670000u, 55u}, // hto -> Latn + {0xCA670000u, 55u}, // hts -> Latn + {0xD2670000u, 55u}, // htu -> Latn + {0xDE670000u, 119u}, // htx -> Xsux + {0x68750000u, 55u}, // hu -> Latn + {0x86870000u, 55u}, // hub -> Latn + {0x8A870000u, 55u}, // huc -> Latn + {0x8E870000u, 55u}, // hud -> Latn + {0x92870000u, 55u}, // hue -> Latn + {0x96870000u, 55u}, // huf -> Latn + {0x9A870000u, 55u}, // hug -> Latn + {0x9E870000u, 55u}, // huh -> Latn + {0xA2870000u, 55u}, // hui -> Latn + {0xAA870000u, 55u}, // huk -> Latn + {0xAE870000u, 55u}, // hul -> Latn + {0xB2870000u, 55u}, // hum -> Latn + {0xBE870000u, 55u}, // hup -> Latn + {0xC6870000u, 55u}, // hur -> Latn + {0xCA870000u, 55u}, // hus -> Latn + {0xCE870000u, 21u}, // hut -> Deva + {0xD2870000u, 55u}, // huu -> Latn + {0xD6870000u, 55u}, // huv -> Latn + {0xDA870000u, 55u}, // huw -> Latn + {0xDE870000u, 55u}, // hux -> Latn + {0xE2870000u, 37u}, // huy -> Hebr + {0xE6870000u, 20u}, // huz -> Cyrl + {0x8AA70000u, 55u}, // hvc -> Latn + {0x92A70000u, 55u}, // hve -> Latn + {0xAAA70000u, 55u}, // hvk -> Latn + {0xB6A70000u, 55u}, // hvn -> Latn + {0xD6A70000u, 55u}, // hvv -> Latn + {0x82C70000u, 55u}, // hwa -> Latn + {0x8AC70000u, 55u}, // hwc -> Latn + {0xBAC70000u, 55u}, // hwo -> Latn {0x68790000u, 4u}, // hy -> Armn - {0x687A0000u, 46u}, // hz -> Latn - {0x69610000u, 46u}, // ia -> Latn - {0xB4080000u, 46u}, // ian -> Latn - {0xC4080000u, 46u}, // iar -> Latn - {0x80280000u, 46u}, // iba -> Latn - {0x84280000u, 46u}, // ibb -> Latn - {0xE0280000u, 46u}, // iby -> Latn - {0x80480000u, 46u}, // ica -> Latn - {0x9C480000u, 46u}, // ich -> Latn - {0x69640000u, 46u}, // id -> Latn - {0x8C680000u, 46u}, // idd -> Latn - {0xA0680000u, 46u}, // idi -> Latn - {0xD0680000u, 46u}, // idu -> Latn - {0x90A80000u, 46u}, // ife -> Latn - {0x69670000u, 46u}, // ig -> Latn - {0x84C80000u, 46u}, // igb -> Latn - {0x90C80000u, 46u}, // ige -> Latn - {0x69690000u, 102u}, // ii -> Yiii - {0xA5280000u, 46u}, // ijj -> Latn - {0x696B0000u, 46u}, // ik -> Latn - {0xA9480000u, 46u}, // ikk -> Latn - {0xD9480000u, 46u}, // ikw -> Latn - {0xDD480000u, 46u}, // ikx -> Latn - {0xB9680000u, 46u}, // ilo -> Latn - {0xB9880000u, 46u}, // imo -> Latn - {0x696E0000u, 46u}, // in -> Latn - {0x9DA80000u, 18u}, // inh -> Cyrl - {0x696F0000u, 46u}, // io -> Latn - {0xD1C80000u, 46u}, // iou -> Latn - {0xA2280000u, 46u}, // iri -> Latn - {0x69730000u, 46u}, // is -> Latn - {0x69740000u, 46u}, // it -> Latn - {0x69750000u, 11u}, // iu -> Cans - {0x69770000u, 31u}, // iw -> Hebr - {0xB2C80000u, 46u}, // iwm -> Latn - {0xCAC80000u, 46u}, // iws -> Latn - {0x9F280000u, 46u}, // izh -> Latn - {0xA3280000u, 46u}, // izi -> Latn - {0x6A610000u, 35u}, // ja -> Jpan - {0x84090000u, 46u}, // jab -> Latn - {0xB0090000u, 46u}, // jam -> Latn - {0xC4090000u, 46u}, // jar -> Latn - {0xB8290000u, 46u}, // jbo -> Latn - {0xD0290000u, 46u}, // jbu -> Latn - {0xB4890000u, 46u}, // jen -> Latn - {0xA8C90000u, 46u}, // jgk -> Latn - {0xB8C90000u, 46u}, // jgo -> Latn - {0x6A690000u, 31u}, // ji -> Hebr - {0x85090000u, 46u}, // jib -> Latn - {0x89890000u, 46u}, // jmc -> Latn - {0xAD890000u, 19u}, // jml -> Deva - {0x82290000u, 46u}, // jra -> Latn - {0xCE890000u, 46u}, // jut -> Latn - {0x6A760000u, 46u}, // jv -> Latn - {0x6A770000u, 46u}, // jw -> Latn - {0x6B610000u, 22u}, // ka -> Geor - {0x800A0000u, 18u}, // kaa -> Cyrl - {0x840A0000u, 46u}, // kab -> Latn - {0x880A0000u, 46u}, // kac -> Latn - {0x8C0A0000u, 46u}, // kad -> Latn - {0xA00A0000u, 46u}, // kai -> Latn - {0xA40A0000u, 46u}, // kaj -> Latn - {0xB00A0000u, 46u}, // kam -> Latn - {0xB80A0000u, 46u}, // kao -> Latn - {0xD80A0000u, 38u}, // kaw -> Kawi - {0x8C2A0000u, 18u}, // kbd -> Cyrl - {0xB02A0000u, 46u}, // kbm -> Latn - {0xBC2A0000u, 46u}, // kbp -> Latn - {0xC02A0000u, 46u}, // kbq -> Latn - {0xDC2A0000u, 46u}, // kbx -> Latn + {0x83070000u, 55u}, // hya -> Latn + {0xDB070000u, 4u}, // hyw -> Armn + {0x687A0000u, 55u}, // hz -> Latn + {0x69610000u, 55u}, // ia -> Latn + {0xA0080000u, 55u}, // iai -> Latn + {0xB4080000u, 55u}, // ian -> Latn + {0xC4080000u, 55u}, // iar -> Latn + {0x80280000u, 55u}, // iba -> Latn + {0x84280000u, 55u}, // ibb -> Latn + {0x8C280000u, 55u}, // ibd -> Latn + {0x90280000u, 55u}, // ibe -> Latn + {0x98280000u, 55u}, // ibg -> Latn + {0x9C280000u, 55u}, // ibh -> Latn + {0xAC280000u, 55u}, // ibl -> Latn + {0xB0280000u, 55u}, // ibm -> Latn + {0xB4280000u, 55u}, // ibn -> Latn + {0xC4280000u, 55u}, // ibr -> Latn + {0xD0280000u, 55u}, // ibu -> Latn + {0xE0280000u, 55u}, // iby -> Latn + {0x80480000u, 55u}, // ica -> Latn + {0x9C480000u, 55u}, // ich -> Latn + {0xC4480000u, 55u}, // icr -> Latn + {0x69640000u, 55u}, // id -> Latn + {0x80680000u, 55u}, // ida -> Latn + {0x84680000u, 55u}, // idb -> Latn + {0x88680000u, 55u}, // idc -> Latn + {0x8C680000u, 55u}, // idd -> Latn + {0x90680000u, 55u}, // ide -> Latn + {0xA0680000u, 55u}, // idi -> Latn + {0xC4680000u, 55u}, // idr -> Latn + {0xC8680000u, 55u}, // ids -> Latn + {0xCC680000u, 55u}, // idt -> Latn + {0xD0680000u, 55u}, // idu -> Latn + {0x69650000u, 55u}, // ie -> Latn + {0x80A80000u, 55u}, // ifa -> Latn + {0x84A80000u, 55u}, // ifb -> Latn + {0x90A80000u, 55u}, // ife -> Latn + {0x94A80000u, 55u}, // iff -> Latn + {0xA8A80000u, 55u}, // ifk -> Latn + {0xB0A80000u, 55u}, // ifm -> Latn + {0xD0A80000u, 55u}, // ifu -> Latn + {0xE0A80000u, 55u}, // ify -> Latn + {0x69670000u, 55u}, // ig -> Latn + {0x84C80000u, 55u}, // igb -> Latn + {0x90C80000u, 55u}, // ige -> Latn + {0x98C80000u, 55u}, // igg -> Latn + {0xACC80000u, 55u}, // igl -> Latn + {0xB0C80000u, 55u}, // igm -> Latn + {0xB4C80000u, 55u}, // ign -> Latn + {0xB8C80000u, 55u}, // igo -> Latn + {0xC8C80000u, 55u}, // igs -> Latn + {0xD8C80000u, 55u}, // igw -> Latn + {0x84E80000u, 55u}, // ihb -> Latn + {0xA0E80000u, 55u}, // ihi -> Latn + {0xBCE80000u, 55u}, // ihp -> Latn + {0xD8E80000u, 55u}, // ihw -> Latn + {0x69690000u, 120u}, // ii -> Yiii + {0xB5080000u, 55u}, // iin -> Latn + {0x89280000u, 55u}, // ijc -> Latn + {0x91280000u, 55u}, // ije -> Latn + {0xA5280000u, 55u}, // ijj -> Latn + {0xB5280000u, 55u}, // ijn -> Latn + {0xC9280000u, 55u}, // ijs -> Latn + {0x696B0000u, 55u}, // ik -> Latn + {0x9D480000u, 55u}, // ikh -> Latn + {0xA1480000u, 55u}, // iki -> Latn + {0xA9480000u, 55u}, // ikk -> Latn + {0xAD480000u, 55u}, // ikl -> Latn + {0xB9480000u, 55u}, // iko -> Latn + {0xBD480000u, 55u}, // ikp -> Latn + {0xC5480000u, 55u}, // ikr -> Latn + {0xCD480000u, 55u}, // ikt -> Latn + {0xD5480000u, 55u}, // ikv -> Latn + {0xD9480000u, 55u}, // ikw -> Latn + {0xDD480000u, 55u}, // ikx -> Latn + {0xE5480000u, 55u}, // ikz -> Latn + {0x81680000u, 55u}, // ila -> Latn + {0x85680000u, 55u}, // ilb -> Latn + {0x99680000u, 55u}, // ilg -> Latn + {0xA1680000u, 55u}, // ili -> Latn + {0xA9680000u, 55u}, // ilk -> Latn + {0xB1680000u, 55u}, // ilm -> Latn + {0xB9680000u, 55u}, // ilo -> Latn + {0xBD680000u, 55u}, // ilp -> Latn + {0xD1680000u, 55u}, // ilu -> Latn + {0xD5680000u, 55u}, // ilv -> Latn + {0xA1880000u, 55u}, // imi -> Latn + {0xAD880000u, 55u}, // iml -> Latn + {0xB5880000u, 55u}, // imn -> Latn + {0xB9880000u, 55u}, // imo -> Latn + {0xC5880000u, 55u}, // imr -> Latn + {0xC9880000u, 55u}, // ims -> Latn + {0xCD880000u, 55u}, // imt -> Latn + {0xE1880000u, 60u}, // imy -> Lyci + {0x696E0000u, 55u}, // in -> Latn + {0x85A80000u, 55u}, // inb -> Latn + {0x99A80000u, 55u}, // ing -> Latn + {0x9DA80000u, 20u}, // inh -> Cyrl + {0xA5A80000u, 55u}, // inj -> Latn + {0xB5A80000u, 55u}, // inn -> Latn + {0xB9A80000u, 55u}, // ino -> Latn + {0xBDA80000u, 55u}, // inp -> Latn + {0xCDA80000u, 72u}, // int -> Mymr + {0x696F0000u, 55u}, // io -> Latn + {0xC5C80000u, 24u}, // ior -> Ethi + {0xD1C80000u, 55u}, // iou -> Latn + {0xD9C80000u, 55u}, // iow -> Latn + {0xA1E80000u, 55u}, // ipi -> Latn + {0xB9E80000u, 55u}, // ipo -> Latn + {0xD2080000u, 55u}, // iqu -> Latn + {0xDA080000u, 55u}, // iqw -> Latn + {0x92280000u, 55u}, // ire -> Latn + {0x9E280000u, 55u}, // irh -> Latn + {0xA2280000u, 55u}, // iri -> Latn + {0xAA280000u, 55u}, // irk -> Latn + {0xB6280000u, 55u}, // irn -> Latn + {0xD2280000u, 105u}, // iru -> Taml + {0xDE280000u, 55u}, // irx -> Latn + {0xE2280000u, 55u}, // iry -> Latn + {0x69730000u, 55u}, // is -> Latn + {0x82480000u, 55u}, // isa -> Latn + {0x8A480000u, 55u}, // isc -> Latn + {0x8E480000u, 55u}, // isd -> Latn + {0x9E480000u, 55u}, // ish -> Latn + {0xA2480000u, 55u}, // isi -> Latn + {0xAA480000u, 2u}, // isk -> Arab + {0xB2480000u, 55u}, // ism -> Latn + {0xB6480000u, 55u}, // isn -> Latn + {0xBA480000u, 55u}, // iso -> Latn + {0xCE480000u, 55u}, // ist -> Latn + {0xD2480000u, 55u}, // isu -> Latn + {0x69740000u, 55u}, // it -> Latn + {0x86680000u, 55u}, // itb -> Latn + {0x8E680000u, 55u}, // itd -> Latn + {0x92680000u, 55u}, // ite -> Latn + {0xA2680000u, 55u}, // iti -> Latn + {0xAA680000u, 37u}, // itk -> Hebr + {0xAE680000u, 20u}, // itl -> Cyrl + {0xB2680000u, 55u}, // itm -> Latn + {0xBA680000u, 55u}, // ito -> Latn + {0xC6680000u, 55u}, // itr -> Latn + {0xCA680000u, 55u}, // its -> Latn + {0xCE680000u, 55u}, // itt -> Latn + {0xD6680000u, 55u}, // itv -> Latn + {0xDA680000u, 55u}, // itw -> Latn + {0xDE680000u, 55u}, // itx -> Latn + {0xE2680000u, 55u}, // ity -> Latn + {0xE6680000u, 55u}, // itz -> Latn + {0x69750000u, 13u}, // iu -> Cans + {0xB2880000u, 55u}, // ium -> Latn + {0x86A80000u, 55u}, // ivb -> Latn + {0xD6A80000u, 55u}, // ivv -> Latn + {0x69770000u, 37u}, // iw -> Hebr + {0xAAC80000u, 55u}, // iwk -> Latn + {0xB2C80000u, 55u}, // iwm -> Latn + {0xBAC80000u, 55u}, // iwo -> Latn + {0xCAC80000u, 55u}, // iws -> Latn + {0x8AE80000u, 55u}, // ixc -> Latn + {0xAEE80000u, 55u}, // ixl -> Latn + {0x83080000u, 55u}, // iya -> Latn + {0xBB080000u, 55u}, // iyo -> Latn + {0xDF080000u, 55u}, // iyx -> Latn + {0x9F280000u, 55u}, // izh -> Latn + {0xB3280000u, 55u}, // izm -> Latn + {0xC7280000u, 55u}, // izr -> Latn + {0xE7280000u, 55u}, // izz -> Latn + {0x6A610000u, 42u}, // ja -> Jpan + {0x80090000u, 55u}, // jaa -> Latn + {0x84090000u, 55u}, // jab -> Latn + {0x88090000u, 55u}, // jac -> Latn + {0x8C090000u, 2u}, // jad -> Arab + {0x90090000u, 55u}, // jae -> Latn + {0x94090000u, 55u}, // jaf -> Latn + {0x9C090000u, 55u}, // jah -> Latn + {0xA4090000u, 55u}, // jaj -> Latn + {0xA8090000u, 55u}, // jak -> Latn + {0xAC090000u, 55u}, // jal -> Latn + {0xB0090000u, 55u}, // jam -> Latn + {0xB4090000u, 55u}, // jan -> Latn + {0xB8090000u, 55u}, // jao -> Latn + {0xC0090000u, 55u}, // jaq -> Latn + {0xC8090000u, 55u}, // jas -> Latn + {0xCC090000u, 2u}, // jat -> Arab + {0xD0090000u, 55u}, // jau -> Latn + {0xDC090000u, 55u}, // jax -> Latn + {0xE0090000u, 55u}, // jay -> Latn + {0xE4090000u, 55u}, // jaz -> Latn + {0x90290000u, 37u}, // jbe -> Hebr + {0xA0290000u, 55u}, // jbi -> Latn + {0xA4290000u, 55u}, // jbj -> Latn + {0xA8290000u, 55u}, // jbk -> Latn + {0xB0290000u, 55u}, // jbm -> Latn + {0xB4290000u, 2u}, // jbn -> Arab + {0xB8290000u, 55u}, // jbo -> Latn + {0xC4290000u, 55u}, // jbr -> Latn + {0xCC290000u, 55u}, // jbt -> Latn + {0xD0290000u, 55u}, // jbu -> Latn + {0xD8290000u, 55u}, // jbw -> Latn + {0xCC490000u, 20u}, // jct -> Cyrl + {0x80690000u, 112u}, // jda -> Tibt + {0x98690000u, 2u}, // jdg -> Arab + {0xCC690000u, 20u}, // jdt -> Cyrl + {0x84890000u, 55u}, // jeb -> Latn + {0x90890000u, 21u}, // jee -> Deva + {0x9C890000u, 55u}, // jeh -> Latn + {0xA0890000u, 55u}, // jei -> Latn + {0xA8890000u, 55u}, // jek -> Latn + {0xAC890000u, 55u}, // jel -> Latn + {0xB4890000u, 55u}, // jen -> Latn + {0xC4890000u, 55u}, // jer -> Latn + {0xCC890000u, 55u}, // jet -> Latn + {0xD0890000u, 55u}, // jeu -> Latn + {0x84C90000u, 55u}, // jgb -> Latn + {0x90C90000u, 25u}, // jge -> Geor + {0xA8C90000u, 55u}, // jgk -> Latn + {0xB8C90000u, 55u}, // jgo -> Latn + {0xA0E90000u, 55u}, // jhi -> Latn + {0x6A690000u, 37u}, // ji -> Hebr + {0x81090000u, 55u}, // jia -> Latn + {0x85090000u, 55u}, // jib -> Latn + {0x89090000u, 55u}, // jic -> Latn + {0x8D090000u, 55u}, // jid -> Latn + {0x91090000u, 55u}, // jie -> Latn + {0x99090000u, 55u}, // jig -> Latn + {0xAD090000u, 55u}, // jil -> Latn + {0xB1090000u, 55u}, // jim -> Latn + {0xCD090000u, 55u}, // jit -> Latn + {0xD1090000u, 55u}, // jiu -> Latn + {0xD5090000u, 55u}, // jiv -> Latn + {0xE1090000u, 55u}, // jiy -> Latn + {0x91290000u, 33u}, // jje -> Hang + {0xC5290000u, 55u}, // jjr -> Latn + {0x81490000u, 55u}, // jka -> Latn + {0xB1490000u, 72u}, // jkm -> Mymr + {0xB9490000u, 55u}, // jko -> Latn + {0xD1490000u, 55u}, // jku -> Latn + {0x91690000u, 55u}, // jle -> Latn + {0x81890000u, 55u}, // jma -> Latn + {0x85890000u, 55u}, // jmb -> Latn + {0x89890000u, 55u}, // jmc -> Latn + {0x8D890000u, 55u}, // jmd -> Latn + {0xA1890000u, 55u}, // jmi -> Latn + {0xAD890000u, 21u}, // jml -> Deva + {0xB5890000u, 55u}, // jmn -> Latn + {0xC5890000u, 55u}, // jmr -> Latn + {0xC9890000u, 55u}, // jms -> Latn + {0xD9890000u, 55u}, // jmw -> Latn + {0xDD890000u, 55u}, // jmx -> Latn + {0x81A90000u, 102u}, // jna -> Takr + {0x8DA90000u, 2u}, // jnd -> Arab + {0x99A90000u, 55u}, // jng -> Latn + {0xA1A90000u, 55u}, // jni -> Latn + {0xA5A90000u, 55u}, // jnj -> Latn + {0xADA90000u, 21u}, // jnl -> Deva + {0xC9A90000u, 21u}, // jns -> Deva + {0x85C90000u, 55u}, // job -> Latn + {0x8DC90000u, 55u}, // jod -> Latn + {0x99C90000u, 2u}, // jog -> Arab + {0xC5C90000u, 55u}, // jor -> Latn + {0xD9C90000u, 55u}, // jow -> Latn + {0x81E90000u, 37u}, // jpa -> Hebr + {0xC5E90000u, 37u}, // jpr -> Hebr + {0xC6090000u, 55u}, // jqr -> Latn + {0x82290000u, 55u}, // jra -> Latn + {0x86290000u, 37u}, // jrb -> Hebr + {0xC6290000u, 55u}, // jrr -> Latn + {0xCE290000u, 55u}, // jrt -> Latn + {0xD2290000u, 55u}, // jru -> Latn + {0x82890000u, 55u}, // jua -> Latn + {0x86890000u, 55u}, // jub -> Latn + {0x8E890000u, 55u}, // jud -> Latn + {0x9E890000u, 55u}, // juh -> Latn + {0xA2890000u, 55u}, // jui -> Latn + {0xAA890000u, 55u}, // juk -> Latn + {0xAE890000u, 21u}, // jul -> Deva + {0xB2890000u, 55u}, // jum -> Latn + {0xB6890000u, 80u}, // jun -> Orya + {0xBA890000u, 55u}, // juo -> Latn + {0xBE890000u, 55u}, // jup -> Latn + {0xC6890000u, 55u}, // jur -> Latn + {0xCE890000u, 55u}, // jut -> Latn + {0xD2890000u, 55u}, // juu -> Latn + {0xDA890000u, 55u}, // juw -> Latn + {0xE2890000u, 80u}, // juy -> Orya + {0x6A760000u, 55u}, // jv -> Latn + {0x8EA90000u, 55u}, // jvd -> Latn + {0xB6A90000u, 55u}, // jvn -> Latn + {0x6A770000u, 55u}, // jw -> Latn + {0xA2C90000u, 55u}, // jwi -> Latn + {0x83090000u, 112u}, // jya -> Tibt + {0x93090000u, 37u}, // jye -> Hebr + {0xE3090000u, 55u}, // jyy -> Latn + {0x6B610000u, 25u}, // ka -> Geor + {0x800A0000u, 20u}, // kaa -> Cyrl + {0x840A0000u, 55u}, // kab -> Latn + {0x880A0000u, 55u}, // kac -> Latn + {0x8C0A0000u, 55u}, // kad -> Latn + {0x980A0000u, 55u}, // kag -> Latn + {0x9C0A0000u, 55u}, // kah -> Latn + {0xA00A0000u, 55u}, // kai -> Latn + {0xA40A0000u, 55u}, // kaj -> Latn + {0xA80A0000u, 55u}, // kak -> Latn + {0xB00A0000u, 55u}, // kam -> Latn + {0xB80A0000u, 55u}, // kao -> Latn + {0xBC0A0000u, 20u}, // kap -> Cyrl + {0xC00A0000u, 55u}, // kaq -> Latn + {0xD40A0000u, 55u}, // kav -> Latn + {0xD80A0000u, 45u}, // kaw -> Kawi + {0xDC0A0000u, 55u}, // kax -> Latn + {0xE00A0000u, 55u}, // kay -> Latn + {0x802A0000u, 55u}, // kba -> Latn + {0x842A0000u, 55u}, // kbb -> Latn + {0x882A0000u, 55u}, // kbc -> Latn + {0x8C2A0000u, 20u}, // kbd -> Cyrl + {0x902A0000u, 55u}, // kbe -> Latn + {0x982A0000u, 112u}, // kbg -> Tibt + {0x9C2A0000u, 55u}, // kbh -> Latn + {0xA02A0000u, 55u}, // kbi -> Latn + {0xA42A0000u, 55u}, // kbj -> Latn + {0xA82A0000u, 55u}, // kbk -> Latn + {0xAC2A0000u, 55u}, // kbl -> Latn + {0xB02A0000u, 55u}, // kbm -> Latn + {0xB42A0000u, 55u}, // kbn -> Latn + {0xB82A0000u, 55u}, // kbo -> Latn + {0xBC2A0000u, 55u}, // kbp -> Latn + {0xC02A0000u, 55u}, // kbq -> Latn + {0xC42A0000u, 55u}, // kbr -> Latn + {0xC82A0000u, 55u}, // kbs -> Latn + {0xCC2A0000u, 55u}, // kbt -> Latn + {0xD02A0000u, 2u}, // kbu -> Arab + {0xD42A0000u, 55u}, // kbv -> Latn + {0xD82A0000u, 55u}, // kbw -> Latn + {0xDC2A0000u, 55u}, // kbx -> Latn {0xE02A0000u, 2u}, // kby -> Arab - {0x984A0000u, 46u}, // kcg -> Latn - {0xA84A0000u, 46u}, // kck -> Latn - {0xAC4A0000u, 46u}, // kcl -> Latn - {0xCC4A0000u, 46u}, // kct -> Latn - {0x906A0000u, 46u}, // kde -> Latn - {0x9C6A0000u, 46u}, // kdh -> Latn - {0xAC6A0000u, 46u}, // kdl -> Latn - {0xCC6A0000u, 93u}, // kdt -> Thai - {0x808A0000u, 46u}, // kea -> Latn - {0xB48A0000u, 46u}, // ken -> Latn - {0xE48A0000u, 46u}, // kez -> Latn - {0xB8AA0000u, 46u}, // kfo -> Latn - {0xC4AA0000u, 19u}, // kfr -> Deva - {0xE0AA0000u, 19u}, // kfy -> Deva - {0x6B670000u, 46u}, // kg -> Latn - {0x90CA0000u, 46u}, // kge -> Latn - {0x94CA0000u, 46u}, // kgf -> Latn - {0xBCCA0000u, 46u}, // kgp -> Latn - {0x80EA0000u, 46u}, // kha -> Latn - {0x84EA0000u, 86u}, // khb -> Talu - {0xB4EA0000u, 19u}, // khn -> Deva - {0xC0EA0000u, 46u}, // khq -> Latn - {0xC8EA0000u, 46u}, // khs -> Latn - {0xCCEA0000u, 59u}, // kht -> Mymr + {0xE42A0000u, 55u}, // kbz -> Latn + {0x804A0000u, 20u}, // kca -> Cyrl + {0x844A0000u, 55u}, // kcb -> Latn + {0x884A0000u, 55u}, // kcc -> Latn + {0x8C4A0000u, 55u}, // kcd -> Latn + {0x904A0000u, 55u}, // kce -> Latn + {0x944A0000u, 55u}, // kcf -> Latn + {0x984A0000u, 55u}, // kcg -> Latn + {0x9C4A0000u, 55u}, // kch -> Latn + {0xA04A0000u, 55u}, // kci -> Latn + {0xA44A0000u, 55u}, // kcj -> Latn + {0xA84A0000u, 55u}, // kck -> Latn + {0xAC4A0000u, 55u}, // kcl -> Latn + {0xB04A0000u, 55u}, // kcm -> Latn + {0xB44A0000u, 55u}, // kcn -> Latn + {0xB84A0000u, 55u}, // kco -> Latn + {0xBC4A0000u, 55u}, // kcp -> Latn + {0xC04A0000u, 55u}, // kcq -> Latn + {0xC84A0000u, 55u}, // kcs -> Latn + {0xCC4A0000u, 55u}, // kct -> Latn + {0xD04A0000u, 55u}, // kcu -> Latn + {0xD44A0000u, 55u}, // kcv -> Latn + {0xD84A0000u, 55u}, // kcw -> Latn + {0xE04A0000u, 2u}, // kcy -> Arab + {0xE44A0000u, 55u}, // kcz -> Latn + {0x806A0000u, 55u}, // kda -> Latn + {0x886A0000u, 55u}, // kdc -> Latn + {0x8C6A0000u, 55u}, // kdd -> Latn + {0x906A0000u, 55u}, // kde -> Latn + {0x946A0000u, 55u}, // kdf -> Latn + {0x986A0000u, 55u}, // kdg -> Latn + {0x9C6A0000u, 55u}, // kdh -> Latn + {0xA06A0000u, 55u}, // kdi -> Latn + {0xA46A0000u, 55u}, // kdj -> Latn + {0xA86A0000u, 55u}, // kdk -> Latn + {0xAC6A0000u, 55u}, // kdl -> Latn + {0xB06A0000u, 55u}, // kdm -> Latn + {0xB46A0000u, 55u}, // kdn -> Latn + {0xBC6A0000u, 55u}, // kdp -> Latn + {0xC06A0000u, 9u}, // kdq -> Beng + {0xC46A0000u, 55u}, // kdr -> Latn + {0xCC6A0000u, 111u}, // kdt -> Thai + {0xD86A0000u, 55u}, // kdw -> Latn + {0xDC6A0000u, 55u}, // kdx -> Latn + {0xE06A0000u, 55u}, // kdy -> Latn + {0xE46A0000u, 55u}, // kdz -> Latn + {0x808A0000u, 55u}, // kea -> Latn + {0x848A0000u, 55u}, // keb -> Latn + {0x888A0000u, 55u}, // kec -> Latn + {0x8C8A0000u, 55u}, // ked -> Latn + {0x908A0000u, 55u}, // kee -> Latn + {0x948A0000u, 55u}, // kef -> Latn + {0x988A0000u, 55u}, // keg -> Latn + {0x9C8A0000u, 55u}, // keh -> Latn + {0xA08A0000u, 55u}, // kei -> Latn + {0xA88A0000u, 55u}, // kek -> Latn + {0xAC8A0000u, 55u}, // kel -> Latn + {0xB08A0000u, 55u}, // kem -> Latn + {0xB48A0000u, 55u}, // ken -> Latn + {0xB88A0000u, 55u}, // keo -> Latn + {0xC48A0000u, 55u}, // ker -> Latn + {0xC88A0000u, 55u}, // kes -> Latn + {0xCC8A0000u, 20u}, // ket -> Cyrl + {0xD08A0000u, 55u}, // keu -> Latn + {0xD48A0000u, 67u}, // kev -> Mlym + {0xD88A0000u, 55u}, // kew -> Latn + {0xDC8A0000u, 21u}, // kex -> Deva + {0xE08A0000u, 108u}, // key -> Telu + {0xE48A0000u, 55u}, // kez -> Latn + {0x80AA0000u, 49u}, // kfa -> Knda + {0x84AA0000u, 21u}, // kfb -> Deva + {0x88AA0000u, 108u}, // kfc -> Telu + {0x8CAA0000u, 49u}, // kfd -> Knda + {0x90AA0000u, 105u}, // kfe -> Taml + {0x94AA0000u, 55u}, // kff -> Latn + {0x98AA0000u, 49u}, // kfg -> Knda + {0x9CAA0000u, 67u}, // kfh -> Mlym + {0xA0AA0000u, 105u}, // kfi -> Taml + {0xA8AA0000u, 21u}, // kfk -> Deva + {0xACAA0000u, 55u}, // kfl -> Latn + {0xB0AA0000u, 2u}, // kfm -> Arab + {0xB4AA0000u, 55u}, // kfn -> Latn + {0xB8AA0000u, 55u}, // kfo -> Latn + {0xBCAA0000u, 21u}, // kfp -> Deva + {0xC0AA0000u, 21u}, // kfq -> Deva + {0xC4AA0000u, 21u}, // kfr -> Deva + {0xC8AA0000u, 21u}, // kfs -> Deva + {0xD0AA0000u, 21u}, // kfu -> Deva + {0xD4AA0000u, 55u}, // kfv -> Latn + {0xD8AA0000u, 55u}, // kfw -> Latn + {0xDCAA0000u, 21u}, // kfx -> Deva + {0xE0AA0000u, 21u}, // kfy -> Deva + {0xE4AA0000u, 55u}, // kfz -> Latn + {0x6B670000u, 55u}, // kg -> Latn + {0x80CA0000u, 55u}, // kga -> Latn + {0x84CA0000u, 55u}, // kgb -> Latn + {0x90CA0000u, 55u}, // kge -> Latn + {0x94CA0000u, 55u}, // kgf -> Latn + {0xA4CA0000u, 21u}, // kgj -> Deva + {0xA8CA0000u, 55u}, // kgk -> Latn + {0xACCA0000u, 55u}, // kgl -> Latn + {0xB8CA0000u, 55u}, // kgo -> Latn + {0xBCCA0000u, 55u}, // kgp -> Latn + {0xC0CA0000u, 55u}, // kgq -> Latn + {0xC4CA0000u, 55u}, // kgr -> Latn + {0xC8CA0000u, 55u}, // kgs -> Latn + {0xCCCA0000u, 55u}, // kgt -> Latn + {0xD0CA0000u, 55u}, // kgu -> Latn + {0xD4CA0000u, 55u}, // kgv -> Latn + {0xD8CA0000u, 55u}, // kgw -> Latn + {0xDCCA0000u, 55u}, // kgx -> Latn + {0xE0CA0000u, 21u}, // kgy -> Deva + {0x80EA0000u, 55u}, // kha -> Latn + {0x84EA0000u, 104u}, // khb -> Talu + {0x88EA0000u, 55u}, // khc -> Latn + {0x8CEA0000u, 55u}, // khd -> Latn + {0x90EA0000u, 55u}, // khe -> Latn + {0x94EA0000u, 111u}, // khf -> Thai + {0x98EA0000u, 112u}, // khg -> Tibt + {0x9CEA0000u, 55u}, // khh -> Latn + {0xA4EA0000u, 55u}, // khj -> Latn + {0xACEA0000u, 55u}, // khl -> Latn + {0xB4EA0000u, 21u}, // khn -> Deva + {0xB8EA0000u, 11u}, // kho -> Brah + {0xBCEA0000u, 55u}, // khp -> Latn + {0xC0EA0000u, 55u}, // khq -> Latn + {0xC4EA0000u, 55u}, // khr -> Latn + {0xC8EA0000u, 55u}, // khs -> Latn + {0xCCEA0000u, 72u}, // kht -> Mymr + {0xD0EA0000u, 55u}, // khu -> Latn + {0xD4EA0000u, 20u}, // khv -> Cyrl {0xD8EA0000u, 2u}, // khw -> Arab - {0xE4EA0000u, 46u}, // khz -> Latn - {0x6B690000u, 46u}, // ki -> Latn - {0xA50A0000u, 46u}, // kij -> Latn - {0xD10A0000u, 46u}, // kiu -> Latn - {0xD90A0000u, 46u}, // kiw -> Latn - {0x6B6A0000u, 46u}, // kj -> Latn - {0x8D2A0000u, 46u}, // kjd -> Latn - {0x992A0000u, 45u}, // kjg -> Laoo - {0xC92A0000u, 46u}, // kjs -> Latn - {0xE12A0000u, 46u}, // kjy -> Latn - {0x6B6B0000u, 18u}, // kk -> Cyrl + {0xDCEA0000u, 55u}, // khx -> Latn + {0xE0EA0000u, 55u}, // khy -> Latn + {0xE4EA0000u, 55u}, // khz -> Latn + {0x6B690000u, 55u}, // ki -> Latn + {0x810A0000u, 55u}, // kia -> Latn + {0x850A0000u, 55u}, // kib -> Latn + {0x890A0000u, 55u}, // kic -> Latn + {0x8D0A0000u, 55u}, // kid -> Latn + {0x910A0000u, 55u}, // kie -> Latn + {0x950A0000u, 21u}, // kif -> Deva + {0x990A0000u, 55u}, // kig -> Latn + {0x9D0A0000u, 55u}, // kih -> Latn + {0xA50A0000u, 55u}, // kij -> Latn + {0xAD0A0000u, 55u}, // kil -> Latn + {0xB10A0000u, 20u}, // kim -> Cyrl + {0xB90A0000u, 55u}, // kio -> Latn + {0xBD0A0000u, 21u}, // kip -> Deva + {0xC10A0000u, 55u}, // kiq -> Latn + {0xC90A0000u, 55u}, // kis -> Latn + {0xCD0A0000u, 55u}, // kit -> Latn + {0xD10A0000u, 55u}, // kiu -> Latn + {0xD50A0000u, 55u}, // kiv -> Latn + {0xD90A0000u, 55u}, // kiw -> Latn + {0xDD0A0000u, 55u}, // kix -> Latn + {0xE10A0000u, 55u}, // kiy -> Latn + {0xE50A0000u, 55u}, // kiz -> Latn + {0x6B6A0000u, 55u}, // kj -> Latn + {0x812A0000u, 55u}, // kja -> Latn + {0x852A0000u, 55u}, // kjb -> Latn + {0x892A0000u, 55u}, // kjc -> Latn + {0x8D2A0000u, 55u}, // kjd -> Latn + {0x912A0000u, 55u}, // kje -> Latn + {0x992A0000u, 52u}, // kjg -> Laoo + {0x9D2A0000u, 20u}, // kjh -> Cyrl + {0xA12A0000u, 55u}, // kji -> Latn + {0xA52A0000u, 55u}, // kjj -> Latn + {0xA92A0000u, 55u}, // kjk -> Latn + {0xAD2A0000u, 21u}, // kjl -> Deva + {0xB12A0000u, 55u}, // kjm -> Latn + {0xB52A0000u, 55u}, // kjn -> Latn + {0xB92A0000u, 21u}, // kjo -> Deva + {0xBD2A0000u, 72u}, // kjp -> Mymr + {0xC12A0000u, 55u}, // kjq -> Latn + {0xC52A0000u, 55u}, // kjr -> Latn + {0xC92A0000u, 55u}, // kjs -> Latn + {0xCD2A0000u, 111u}, // kjt -> Thai + {0xD12A0000u, 55u}, // kju -> Latn + {0xDD2A0000u, 55u}, // kjx -> Latn + {0xE12A0000u, 55u}, // kjy -> Latn + {0xE52A0000u, 112u}, // kjz -> Tibt + {0x6B6B0000u, 20u}, // kk -> Cyrl {0x6B6B4146u, 2u}, // kk-AF -> Arab {0x6B6B434Eu, 2u}, // kk-CN -> Arab {0x6B6B4952u, 2u}, // kk-IR -> Arab {0x6B6B4D4Eu, 2u}, // kk-MN -> Arab - {0x894A0000u, 46u}, // kkc -> Latn - {0xA54A0000u, 46u}, // kkj -> Latn - {0x6B6C0000u, 46u}, // kl -> Latn - {0xB56A0000u, 46u}, // kln -> Latn - {0xC16A0000u, 46u}, // klq -> Latn - {0xCD6A0000u, 46u}, // klt -> Latn - {0xDD6A0000u, 46u}, // klx -> Latn - {0x6B6D0000u, 40u}, // km -> Khmr - {0x858A0000u, 46u}, // kmb -> Latn - {0x9D8A0000u, 46u}, // kmh -> Latn - {0xB98A0000u, 46u}, // kmo -> Latn - {0xC98A0000u, 46u}, // kms -> Latn - {0xD18A0000u, 46u}, // kmu -> Latn - {0xD98A0000u, 46u}, // kmw -> Latn - {0x6B6E0000u, 42u}, // kn -> Knda - {0x95AA0000u, 46u}, // knf -> Latn - {0xBDAA0000u, 46u}, // knp -> Latn - {0x6B6F0000u, 43u}, // ko -> Kore - {0xA1CA0000u, 18u}, // koi -> Cyrl - {0xA9CA0000u, 19u}, // kok -> Deva - {0xADCA0000u, 46u}, // kol -> Latn - {0xC9CA0000u, 46u}, // kos -> Latn - {0xE5CA0000u, 46u}, // koz -> Latn - {0x91EA0000u, 46u}, // kpe -> Latn - {0x95EA0000u, 46u}, // kpf -> Latn - {0xB9EA0000u, 46u}, // kpo -> Latn - {0xC5EA0000u, 46u}, // kpr -> Latn - {0xDDEA0000u, 46u}, // kpx -> Latn - {0x860A0000u, 46u}, // kqb -> Latn - {0x960A0000u, 46u}, // kqf -> Latn - {0xCA0A0000u, 46u}, // kqs -> Latn - {0xE20A0000u, 21u}, // kqy -> Ethi - {0x6B720000u, 46u}, // kr -> Latn - {0x8A2A0000u, 18u}, // krc -> Cyrl - {0xA22A0000u, 46u}, // kri -> Latn - {0xA62A0000u, 46u}, // krj -> Latn - {0xAE2A0000u, 46u}, // krl -> Latn - {0xCA2A0000u, 46u}, // krs -> Latn - {0xD22A0000u, 19u}, // kru -> Deva + {0x814A0000u, 55u}, // kka -> Latn + {0x854A0000u, 55u}, // kkb -> Latn + {0x894A0000u, 55u}, // kkc -> Latn + {0x8D4A0000u, 55u}, // kkd -> Latn + {0x914A0000u, 55u}, // kke -> Latn + {0x954A0000u, 112u}, // kkf -> Tibt + {0x994A0000u, 55u}, // kkg -> Latn + {0x9D4A0000u, 51u}, // kkh -> Lana + {0xA14A0000u, 55u}, // kki -> Latn + {0xA54A0000u, 55u}, // kkj -> Latn + {0xA94A0000u, 55u}, // kkk -> Latn + {0xAD4A0000u, 55u}, // kkl -> Latn + {0xB14A0000u, 55u}, // kkm -> Latn + {0xB94A0000u, 55u}, // kko -> Latn + {0xBD4A0000u, 55u}, // kkp -> Latn + {0xC14A0000u, 55u}, // kkq -> Latn + {0xC54A0000u, 55u}, // kkr -> Latn + {0xC94A0000u, 55u}, // kks -> Latn + {0xCD4A0000u, 21u}, // kkt -> Deva + {0xD14A0000u, 55u}, // kku -> Latn + {0xD54A0000u, 55u}, // kkv -> Latn + {0xD94A0000u, 55u}, // kkw -> Latn + {0xDD4A0000u, 55u}, // kkx -> Latn + {0xE14A0000u, 55u}, // kky -> Latn + {0xE54A0000u, 55u}, // kkz -> Latn + {0x6B6C0000u, 55u}, // kl -> Latn + {0x816A0000u, 55u}, // kla -> Latn + {0x856A0000u, 55u}, // klb -> Latn + {0x896A0000u, 55u}, // klc -> Latn + {0x8D6A0000u, 55u}, // kld -> Latn + {0x916A0000u, 21u}, // kle -> Deva + {0x956A0000u, 55u}, // klf -> Latn + {0x996A0000u, 55u}, // klg -> Latn + {0x9D6A0000u, 55u}, // klh -> Latn + {0xA16A0000u, 55u}, // kli -> Latn + {0xA56A0000u, 2u}, // klj -> Arab + {0xA96A0000u, 55u}, // klk -> Latn + {0xAD6A0000u, 55u}, // kll -> Latn + {0xB16A0000u, 55u}, // klm -> Latn + {0xB56A0000u, 55u}, // kln -> Latn + {0xB96A0000u, 55u}, // klo -> Latn + {0xBD6A0000u, 55u}, // klp -> Latn + {0xC16A0000u, 55u}, // klq -> Latn + {0xC56A0000u, 21u}, // klr -> Deva + {0xC96A0000u, 55u}, // kls -> Latn + {0xCD6A0000u, 55u}, // klt -> Latn + {0xD16A0000u, 55u}, // klu -> Latn + {0xD56A0000u, 55u}, // klv -> Latn + {0xD96A0000u, 55u}, // klw -> Latn + {0xDD6A0000u, 55u}, // klx -> Latn + {0xE16A0000u, 55u}, // kly -> Latn + {0xE56A0000u, 55u}, // klz -> Latn + {0x6B6D0000u, 47u}, // km -> Khmr + {0x818A0000u, 55u}, // kma -> Latn + {0x858A0000u, 55u}, // kmb -> Latn + {0x898A0000u, 55u}, // kmc -> Latn + {0x8D8A0000u, 55u}, // kmd -> Latn + {0x918A0000u, 55u}, // kme -> Latn + {0x958A0000u, 55u}, // kmf -> Latn + {0x998A0000u, 55u}, // kmg -> Latn + {0x9D8A0000u, 55u}, // kmh -> Latn + {0xA18A0000u, 55u}, // kmi -> Latn + {0xA58A0000u, 21u}, // kmj -> Deva + {0xA98A0000u, 55u}, // kmk -> Latn + {0xAD8A0000u, 55u}, // kml -> Latn + {0xB18A0000u, 55u}, // kmm -> Latn + {0xB58A0000u, 55u}, // kmn -> Latn + {0xB98A0000u, 55u}, // kmo -> Latn + {0xBD8A0000u, 55u}, // kmp -> Latn + {0xC18A0000u, 55u}, // kmq -> Latn + {0xC98A0000u, 55u}, // kms -> Latn + {0xCD8A0000u, 55u}, // kmt -> Latn + {0xD18A0000u, 55u}, // kmu -> Latn + {0xD58A0000u, 55u}, // kmv -> Latn + {0xD98A0000u, 55u}, // kmw -> Latn + {0xDD8A0000u, 55u}, // kmx -> Latn + {0xE18A0000u, 55u}, // kmy -> Latn + {0xE58A0000u, 2u}, // kmz -> Arab + {0x6B6E0000u, 49u}, // kn -> Knda + {0x81AA0000u, 55u}, // kna -> Latn + {0x85AA0000u, 55u}, // knb -> Latn + {0x8DAA0000u, 55u}, // knd -> Latn + {0x91AA0000u, 55u}, // kne -> Latn + {0x95AA0000u, 55u}, // knf -> Latn + {0xA1AA0000u, 55u}, // kni -> Latn + {0xA5AA0000u, 55u}, // knj -> Latn + {0xA9AA0000u, 55u}, // knk -> Latn + {0xADAA0000u, 55u}, // knl -> Latn + {0xB1AA0000u, 55u}, // knm -> Latn + {0xB5AA0000u, 21u}, // knn -> Deva + {0xB9AA0000u, 55u}, // kno -> Latn + {0xBDAA0000u, 55u}, // knp -> Latn + {0xC1AA0000u, 55u}, // knq -> Latn + {0xC5AA0000u, 55u}, // knr -> Latn + {0xC9AA0000u, 55u}, // kns -> Latn + {0xCDAA0000u, 55u}, // knt -> Latn + {0xD1AA0000u, 55u}, // knu -> Latn + {0xD5AA0000u, 55u}, // knv -> Latn + {0xD9AA0000u, 55u}, // knw -> Latn + {0xDDAA0000u, 55u}, // knx -> Latn + {0xE1AA0000u, 55u}, // kny -> Latn + {0xE5AA0000u, 55u}, // knz -> Latn + {0x6B6F0000u, 50u}, // ko -> Kore + {0x81CA0000u, 55u}, // koa -> Latn + {0x89CA0000u, 55u}, // koc -> Latn + {0x8DCA0000u, 55u}, // kod -> Latn + {0x91CA0000u, 55u}, // koe -> Latn + {0x95CA0000u, 55u}, // kof -> Latn + {0x99CA0000u, 55u}, // kog -> Latn + {0x9DCA0000u, 55u}, // koh -> Latn + {0xA1CA0000u, 20u}, // koi -> Cyrl + {0xA9CA0000u, 21u}, // kok -> Deva + {0xADCA0000u, 55u}, // kol -> Latn + {0xB9CA0000u, 55u}, // koo -> Latn + {0xBDCA0000u, 55u}, // kop -> Latn + {0xC1CA0000u, 55u}, // koq -> Latn + {0xC9CA0000u, 55u}, // kos -> Latn + {0xCDCA0000u, 55u}, // kot -> Latn + {0xD1CA0000u, 55u}, // kou -> Latn + {0xD5CA0000u, 55u}, // kov -> Latn + {0xD9CA0000u, 55u}, // kow -> Latn + {0xE1CA0000u, 55u}, // koy -> Latn + {0xE5CA0000u, 55u}, // koz -> Latn + {0x81EA0000u, 55u}, // kpa -> Latn + {0x89EA0000u, 55u}, // kpc -> Latn + {0x8DEA0000u, 55u}, // kpd -> Latn + {0x91EA0000u, 55u}, // kpe -> Latn + {0x95EA0000u, 55u}, // kpf -> Latn + {0x99EA0000u, 55u}, // kpg -> Latn + {0x9DEA0000u, 55u}, // kph -> Latn + {0xA1EA0000u, 55u}, // kpi -> Latn + {0xA5EA0000u, 55u}, // kpj -> Latn + {0xA9EA0000u, 55u}, // kpk -> Latn + {0xADEA0000u, 55u}, // kpl -> Latn + {0xB1EA0000u, 55u}, // kpm -> Latn + {0xB5EA0000u, 55u}, // kpn -> Latn + {0xB9EA0000u, 55u}, // kpo -> Latn + {0xC1EA0000u, 55u}, // kpq -> Latn + {0xC5EA0000u, 55u}, // kpr -> Latn + {0xC9EA0000u, 55u}, // kps -> Latn + {0xCDEA0000u, 20u}, // kpt -> Cyrl + {0xD1EA0000u, 55u}, // kpu -> Latn + {0xD9EA0000u, 55u}, // kpw -> Latn + {0xDDEA0000u, 55u}, // kpx -> Latn + {0xE1EA0000u, 20u}, // kpy -> Cyrl + {0xE5EA0000u, 55u}, // kpz -> Latn + {0x820A0000u, 55u}, // kqa -> Latn + {0x860A0000u, 55u}, // kqb -> Latn + {0x8A0A0000u, 55u}, // kqc -> Latn + {0x8E0A0000u, 100u}, // kqd -> Syrc + {0x920A0000u, 55u}, // kqe -> Latn + {0x960A0000u, 55u}, // kqf -> Latn + {0x9A0A0000u, 55u}, // kqg -> Latn + {0x9E0A0000u, 55u}, // kqh -> Latn + {0xA20A0000u, 55u}, // kqi -> Latn + {0xA60A0000u, 55u}, // kqj -> Latn + {0xAA0A0000u, 55u}, // kqk -> Latn + {0xAE0A0000u, 55u}, // kql -> Latn + {0xB20A0000u, 55u}, // kqm -> Latn + {0xB60A0000u, 55u}, // kqn -> Latn + {0xBA0A0000u, 55u}, // kqo -> Latn + {0xBE0A0000u, 55u}, // kqp -> Latn + {0xC20A0000u, 55u}, // kqq -> Latn + {0xC60A0000u, 55u}, // kqr -> Latn + {0xCA0A0000u, 55u}, // kqs -> Latn + {0xCE0A0000u, 55u}, // kqt -> Latn + {0xD20A0000u, 55u}, // kqu -> Latn + {0xD60A0000u, 55u}, // kqv -> Latn + {0xDA0A0000u, 55u}, // kqw -> Latn + {0xDE0A0000u, 55u}, // kqx -> Latn + {0xE20A0000u, 24u}, // kqy -> Ethi + {0xE60A0000u, 55u}, // kqz -> Latn + {0x6B720000u, 55u}, // kr -> Latn + {0x822A0000u, 21u}, // kra -> Deva + {0x862A0000u, 55u}, // krb -> Latn + {0x8A2A0000u, 20u}, // krc -> Cyrl + {0x8E2A0000u, 55u}, // krd -> Latn + {0x922A0000u, 55u}, // kre -> Latn + {0x962A0000u, 55u}, // krf -> Latn + {0x9E2A0000u, 55u}, // krh -> Latn + {0xA22A0000u, 55u}, // kri -> Latn + {0xA62A0000u, 55u}, // krj -> Latn + {0xAA2A0000u, 20u}, // krk -> Cyrl + {0xAE2A0000u, 55u}, // krl -> Latn + {0xB62A0000u, 55u}, // krn -> Latn + {0xBE2A0000u, 55u}, // krp -> Latn + {0xC62A0000u, 47u}, // krr -> Khmr + {0xCA2A0000u, 55u}, // krs -> Latn + {0xCE2A0000u, 55u}, // krt -> Latn + {0xD22A0000u, 21u}, // kru -> Deva + {0xD62A0000u, 47u}, // krv -> Khmr + {0xDA2A0000u, 55u}, // krw -> Latn + {0xDE2A0000u, 55u}, // krx -> Latn + {0xE22A0000u, 55u}, // kry -> Latn + {0xE62A0000u, 55u}, // krz -> Latn {0x6B730000u, 2u}, // ks -> Arab - {0x864A0000u, 46u}, // ksb -> Latn - {0x8E4A0000u, 46u}, // ksd -> Latn - {0x964A0000u, 46u}, // ksf -> Latn - {0x9E4A0000u, 46u}, // ksh -> Latn - {0xA64A0000u, 46u}, // ksj -> Latn - {0xC64A0000u, 46u}, // ksr -> Latn - {0x866A0000u, 21u}, // ktb -> Ethi - {0xB26A0000u, 46u}, // ktm -> Latn - {0xBA6A0000u, 46u}, // kto -> Latn - {0xC66A0000u, 46u}, // ktr -> Latn - {0x6B750000u, 46u}, // ku -> Latn - {0x6B754952u, 2u}, // ku-IR -> Arab + {0x864A0000u, 55u}, // ksb -> Latn + {0x8A4A0000u, 55u}, // ksc -> Latn + {0x8E4A0000u, 55u}, // ksd -> Latn + {0x924A0000u, 55u}, // kse -> Latn + {0x964A0000u, 55u}, // ksf -> Latn + {0x9A4A0000u, 55u}, // ksg -> Latn + {0x9E4A0000u, 55u}, // ksh -> Latn + {0xA24A0000u, 55u}, // ksi -> Latn + {0xA64A0000u, 55u}, // ksj -> Latn + {0xAA4A0000u, 55u}, // ksk -> Latn + {0xAE4A0000u, 55u}, // ksl -> Latn + {0xB24A0000u, 55u}, // ksm -> Latn + {0xB64A0000u, 55u}, // ksn -> Latn + {0xBA4A0000u, 55u}, // kso -> Latn + {0xBE4A0000u, 55u}, // ksp -> Latn + {0xC24A0000u, 55u}, // ksq -> Latn + {0xC64A0000u, 55u}, // ksr -> Latn + {0xCA4A0000u, 55u}, // kss -> Latn + {0xCE4A0000u, 55u}, // kst -> Latn + {0xD24A0000u, 72u}, // ksu -> Mymr + {0xD64A0000u, 55u}, // ksv -> Latn + {0xDA4A0000u, 72u}, // ksw -> Mymr + {0xDE4A0000u, 55u}, // ksx -> Latn + {0xE64A0000u, 21u}, // ksz -> Deva + {0x826A0000u, 55u}, // kta -> Latn + {0x866A0000u, 24u}, // ktb -> Ethi + {0x8A6A0000u, 55u}, // ktc -> Latn + {0x8E6A0000u, 55u}, // ktd -> Latn + {0x926A0000u, 21u}, // kte -> Deva + {0x966A0000u, 55u}, // ktf -> Latn + {0x9A6A0000u, 55u}, // ktg -> Latn + {0x9E6A0000u, 55u}, // kth -> Latn + {0xA26A0000u, 55u}, // kti -> Latn + {0xA66A0000u, 55u}, // ktj -> Latn + {0xAA6A0000u, 55u}, // ktk -> Latn + {0xAE6A0000u, 2u}, // ktl -> Arab + {0xB26A0000u, 55u}, // ktm -> Latn + {0xB66A0000u, 55u}, // ktn -> Latn + {0xBA6A0000u, 55u}, // kto -> Latn + {0xBE6A0000u, 86u}, // ktp -> Plrd + {0xC26A0000u, 55u}, // ktq -> Latn + {0xCA6A0000u, 55u}, // kts -> Latn + {0xCE6A0000u, 55u}, // ktt -> Latn + {0xD26A0000u, 55u}, // ktu -> Latn + {0xD66A0000u, 55u}, // ktv -> Latn + {0xDA6A0000u, 55u}, // ktw -> Latn + {0xDE6A0000u, 55u}, // ktx -> Latn + {0xE26A0000u, 55u}, // kty -> Latn + {0xE66A0000u, 55u}, // ktz -> Latn + {0x6B750000u, 55u}, // ku -> Latn {0x6B754C42u, 2u}, // ku-LB -> Arab - {0x868A0000u, 46u}, // kub -> Latn - {0x8E8A0000u, 46u}, // kud -> Latn - {0x928A0000u, 46u}, // kue -> Latn - {0xA68A0000u, 46u}, // kuj -> Latn - {0xB28A0000u, 18u}, // kum -> Cyrl - {0xB68A0000u, 46u}, // kun -> Latn - {0xBE8A0000u, 46u}, // kup -> Latn - {0xCA8A0000u, 46u}, // kus -> Latn - {0x6B760000u, 18u}, // kv -> Cyrl - {0x9AAA0000u, 46u}, // kvg -> Latn - {0xC6AA0000u, 46u}, // kvr -> Latn + {0x868A0000u, 55u}, // kub -> Latn + {0x8A8A0000u, 55u}, // kuc -> Latn + {0x8E8A0000u, 55u}, // kud -> Latn + {0x928A0000u, 55u}, // kue -> Latn + {0x968A0000u, 52u}, // kuf -> Laoo + {0x9A8A0000u, 55u}, // kug -> Latn + {0x9E8A0000u, 55u}, // kuh -> Latn + {0xA28A0000u, 55u}, // kui -> Latn + {0xA68A0000u, 55u}, // kuj -> Latn + {0xAA8A0000u, 55u}, // kuk -> Latn + {0xAE8A0000u, 55u}, // kul -> Latn + {0xB28A0000u, 20u}, // kum -> Cyrl + {0xB68A0000u, 55u}, // kun -> Latn + {0xBA8A0000u, 55u}, // kuo -> Latn + {0xBE8A0000u, 55u}, // kup -> Latn + {0xC28A0000u, 55u}, // kuq -> Latn + {0xCA8A0000u, 55u}, // kus -> Latn + {0xCE8A0000u, 55u}, // kut -> Latn + {0xD28A0000u, 55u}, // kuu -> Latn + {0xD68A0000u, 55u}, // kuv -> Latn + {0xDA8A0000u, 55u}, // kuw -> Latn + {0xDE8A0000u, 55u}, // kux -> Latn + {0xE28A0000u, 55u}, // kuy -> Latn + {0xE68A0000u, 55u}, // kuz -> Latn + {0x6B760000u, 20u}, // kv -> Cyrl + {0x82AA0000u, 20u}, // kva -> Cyrl + {0x86AA0000u, 55u}, // kvb -> Latn + {0x8AAA0000u, 55u}, // kvc -> Latn + {0x8EAA0000u, 55u}, // kvd -> Latn + {0x92AA0000u, 55u}, // kve -> Latn + {0x96AA0000u, 55u}, // kvf -> Latn + {0x9AAA0000u, 55u}, // kvg -> Latn + {0x9EAA0000u, 55u}, // kvh -> Latn + {0xA2AA0000u, 55u}, // kvi -> Latn + {0xA6AA0000u, 55u}, // kvj -> Latn + {0xAEAA0000u, 55u}, // kvl -> Latn + {0xB2AA0000u, 55u}, // kvm -> Latn + {0xB6AA0000u, 55u}, // kvn -> Latn + {0xBAAA0000u, 55u}, // kvo -> Latn + {0xBEAA0000u, 55u}, // kvp -> Latn + {0xC2AA0000u, 72u}, // kvq -> Mymr + {0xC6AA0000u, 55u}, // kvr -> Latn + {0xCEAA0000u, 72u}, // kvt -> Mymr + {0xD6AA0000u, 55u}, // kvv -> Latn + {0xDAAA0000u, 55u}, // kvw -> Latn {0xDEAA0000u, 2u}, // kvx -> Arab - {0x6B770000u, 46u}, // kw -> Latn - {0xA6CA0000u, 46u}, // kwj -> Latn - {0xAACA0000u, 46u}, // kwk -> Latn - {0xBACA0000u, 46u}, // kwo -> Latn - {0xC2CA0000u, 46u}, // kwq -> Latn - {0x82EA0000u, 46u}, // kxa -> Latn - {0x8AEA0000u, 21u}, // kxc -> Ethi - {0x92EA0000u, 46u}, // kxe -> Latn - {0xAEEA0000u, 19u}, // kxl -> Deva - {0xB2EA0000u, 93u}, // kxm -> Thai + {0xE2AA0000u, 43u}, // kvy -> Kali + {0xE6AA0000u, 55u}, // kvz -> Latn + {0x6B770000u, 55u}, // kw -> Latn + {0x82CA0000u, 55u}, // kwa -> Latn + {0x86CA0000u, 55u}, // kwb -> Latn + {0x8ACA0000u, 55u}, // kwc -> Latn + {0x8ECA0000u, 55u}, // kwd -> Latn + {0x92CA0000u, 55u}, // kwe -> Latn + {0x96CA0000u, 55u}, // kwf -> Latn + {0x9ACA0000u, 55u}, // kwg -> Latn + {0x9ECA0000u, 55u}, // kwh -> Latn + {0xA2CA0000u, 55u}, // kwi -> Latn + {0xA6CA0000u, 55u}, // kwj -> Latn + {0xAACA0000u, 55u}, // kwk -> Latn + {0xAECA0000u, 55u}, // kwl -> Latn + {0xB2CA0000u, 55u}, // kwm -> Latn + {0xB6CA0000u, 55u}, // kwn -> Latn + {0xBACA0000u, 55u}, // kwo -> Latn + {0xBECA0000u, 55u}, // kwp -> Latn + {0xC6CA0000u, 55u}, // kwr -> Latn + {0xCACA0000u, 55u}, // kws -> Latn + {0xCECA0000u, 55u}, // kwt -> Latn + {0xD2CA0000u, 55u}, // kwu -> Latn + {0xD6CA0000u, 55u}, // kwv -> Latn + {0xDACA0000u, 55u}, // kww -> Latn + {0xE2CA0000u, 55u}, // kwy -> Latn + {0xE6CA0000u, 55u}, // kwz -> Latn + {0x82EA0000u, 55u}, // kxa -> Latn + {0x86EA0000u, 55u}, // kxb -> Latn + {0x8AEA0000u, 55u}, // kxc -> Latn + {0x8EEA0000u, 55u}, // kxd -> Latn + {0x96EA0000u, 72u}, // kxf -> Mymr + {0xA2EA0000u, 55u}, // kxi -> Latn + {0xA6EA0000u, 55u}, // kxj -> Latn + {0xAAEA0000u, 72u}, // kxk -> Mymr + {0xB2EA0000u, 111u}, // kxm -> Thai + {0xB6EA0000u, 55u}, // kxn -> Latn + {0xBAEA0000u, 55u}, // kxo -> Latn {0xBEEA0000u, 2u}, // kxp -> Arab - {0xDAEA0000u, 46u}, // kxw -> Latn - {0xE6EA0000u, 46u}, // kxz -> Latn - {0x6B790000u, 18u}, // ky -> Cyrl + {0xC2EA0000u, 55u}, // kxq -> Latn + {0xC6EA0000u, 55u}, // kxr -> Latn + {0xCEEA0000u, 55u}, // kxt -> Latn + {0xD6EA0000u, 55u}, // kxv -> Latn + {0xDAEA0000u, 55u}, // kxw -> Latn + {0xDEEA0000u, 55u}, // kxx -> Latn + {0xE2EA0000u, 55u}, // kxy -> Latn + {0xE6EA0000u, 55u}, // kxz -> Latn + {0x6B790000u, 20u}, // ky -> Cyrl {0x6B79434Eu, 2u}, // ky-CN -> Arab - {0x6B795452u, 46u}, // ky-TR -> Latn - {0x930A0000u, 46u}, // kye -> Latn - {0xDF0A0000u, 46u}, // kyx -> Latn - {0x9F2A0000u, 2u}, // kzh -> Arab - {0xA72A0000u, 46u}, // kzj -> Latn - {0xC72A0000u, 46u}, // kzr -> Latn - {0xCF2A0000u, 46u}, // kzt -> Latn - {0x6C610000u, 46u}, // la -> Latn - {0x840B0000u, 48u}, // lab -> Lina - {0x8C0B0000u, 31u}, // lad -> Hebr - {0x980B0000u, 46u}, // lag -> Latn + {0x6B795452u, 55u}, // ky-TR -> Latn + {0x830A0000u, 55u}, // kya -> Latn + {0x870A0000u, 55u}, // kyb -> Latn + {0x8B0A0000u, 55u}, // kyc -> Latn + {0x8F0A0000u, 55u}, // kyd -> Latn + {0x930A0000u, 55u}, // kye -> Latn + {0x970A0000u, 55u}, // kyf -> Latn + {0x9B0A0000u, 55u}, // kyg -> Latn + {0x9F0A0000u, 55u}, // kyh -> Latn + {0xA30A0000u, 55u}, // kyi -> Latn + {0xA70A0000u, 55u}, // kyj -> Latn + {0xAB0A0000u, 55u}, // kyk -> Latn + {0xAF0A0000u, 55u}, // kyl -> Latn + {0xB30A0000u, 55u}, // kym -> Latn + {0xB70A0000u, 55u}, // kyn -> Latn + {0xBB0A0000u, 55u}, // kyo -> Latn + {0xC30A0000u, 55u}, // kyq -> Latn + {0xC70A0000u, 55u}, // kyr -> Latn + {0xCB0A0000u, 55u}, // kys -> Latn + {0xCF0A0000u, 55u}, // kyt -> Latn + {0xD30A0000u, 43u}, // kyu -> Kali + {0xD70A0000u, 21u}, // kyv -> Deva + {0xDB0A0000u, 21u}, // kyw -> Deva + {0xDF0A0000u, 55u}, // kyx -> Latn + {0xE30A0000u, 55u}, // kyy -> Latn + {0xE70A0000u, 55u}, // kyz -> Latn + {0x832A0000u, 55u}, // kza -> Latn + {0x872A0000u, 55u}, // kzb -> Latn + {0x8B2A0000u, 55u}, // kzc -> Latn + {0x8F2A0000u, 55u}, // kzd -> Latn + {0x932A0000u, 55u}, // kze -> Latn + {0x972A0000u, 55u}, // kzf -> Latn + {0xA32A0000u, 55u}, // kzi -> Latn + {0xAB2A0000u, 55u}, // kzk -> Latn + {0xAF2A0000u, 55u}, // kzl -> Latn + {0xB32A0000u, 55u}, // kzm -> Latn + {0xB72A0000u, 55u}, // kzn -> Latn + {0xBB2A0000u, 55u}, // kzo -> Latn + {0xBF2A0000u, 55u}, // kzp -> Latn + {0xC72A0000u, 55u}, // kzr -> Latn + {0xCB2A0000u, 55u}, // kzs -> Latn + {0xD32A0000u, 55u}, // kzu -> Latn + {0xD72A0000u, 55u}, // kzv -> Latn + {0xDB2A0000u, 55u}, // kzw -> Latn + {0xDF2A0000u, 55u}, // kzx -> Latn + {0xE32A0000u, 55u}, // kzy -> Latn + {0xE72A0000u, 55u}, // kzz -> Latn + {0x6C610000u, 55u}, // la -> Latn + {0x800B0000u, 55u}, // laa -> Latn + {0x840B0000u, 57u}, // lab -> Lina + {0x880B0000u, 55u}, // lac -> Latn + {0x8C0B0000u, 37u}, // lad -> Hebr + {0x900B0000u, 21u}, // lae -> Deva + {0x980B0000u, 55u}, // lag -> Latn {0x9C0B0000u, 2u}, // lah -> Arab - {0xA40B0000u, 46u}, // laj -> Latn - {0xC80B0000u, 46u}, // las -> Latn - {0x6C620000u, 46u}, // lb -> Latn - {0x902B0000u, 18u}, // lbe -> Cyrl - {0xD02B0000u, 46u}, // lbu -> Latn - {0xD82B0000u, 46u}, // lbw -> Latn - {0xB04B0000u, 46u}, // lcm -> Latn - {0xBC4B0000u, 93u}, // lcp -> Thai - {0x846B0000u, 46u}, // ldb -> Latn - {0x8C8B0000u, 46u}, // led -> Latn - {0x908B0000u, 46u}, // lee -> Latn - {0xB08B0000u, 46u}, // lem -> Latn - {0xBC8B0000u, 47u}, // lep -> Lepc - {0xC08B0000u, 46u}, // leq -> Latn - {0xD08B0000u, 46u}, // leu -> Latn - {0xE48B0000u, 18u}, // lez -> Cyrl - {0x6C670000u, 46u}, // lg -> Latn - {0x98CB0000u, 46u}, // lgg -> Latn - {0x6C690000u, 46u}, // li -> Latn - {0x810B0000u, 46u}, // lia -> Latn - {0x8D0B0000u, 46u}, // lid -> Latn - {0x950B0000u, 19u}, // lif -> Deva - {0x990B0000u, 46u}, // lig -> Latn - {0x9D0B0000u, 46u}, // lih -> Latn - {0xA50B0000u, 46u}, // lij -> Latn - {0xAD0B0000u, 46u}, // lil -> Latn - {0xC90B0000u, 49u}, // lis -> Lisu - {0xBD2B0000u, 46u}, // ljp -> Latn + {0xA00B0000u, 55u}, // lai -> Latn + {0xA40B0000u, 55u}, // laj -> Latn + {0xAC0B0000u, 55u}, // lal -> Latn + {0xB00B0000u, 55u}, // lam -> Latn + {0xB40B0000u, 55u}, // lan -> Latn + {0xBC0B0000u, 55u}, // lap -> Latn + {0xC00B0000u, 55u}, // laq -> Latn + {0xC40B0000u, 55u}, // lar -> Latn + {0xC80B0000u, 55u}, // las -> Latn + {0xD00B0000u, 55u}, // lau -> Latn + {0xD80B0000u, 55u}, // law -> Latn + {0xDC0B0000u, 55u}, // lax -> Latn + {0xE40B0000u, 55u}, // laz -> Latn + {0x6C620000u, 55u}, // lb -> Latn + {0x842B0000u, 55u}, // lbb -> Latn + {0x902B0000u, 20u}, // lbe -> Cyrl + {0x942B0000u, 21u}, // lbf -> Deva + {0xA02B0000u, 55u}, // lbi -> Latn + {0xA42B0000u, 112u}, // lbj -> Tibt + {0xAC2B0000u, 55u}, // lbl -> Latn + {0xB02B0000u, 21u}, // lbm -> Deva + {0xB42B0000u, 55u}, // lbn -> Latn + {0xB82B0000u, 52u}, // lbo -> Laoo + {0xC02B0000u, 55u}, // lbq -> Latn + {0xC42B0000u, 21u}, // lbr -> Deva + {0xCC2B0000u, 55u}, // lbt -> Latn + {0xD02B0000u, 55u}, // lbu -> Latn + {0xD42B0000u, 55u}, // lbv -> Latn + {0xD82B0000u, 55u}, // lbw -> Latn + {0xDC2B0000u, 55u}, // lbx -> Latn + {0xE02B0000u, 55u}, // lby -> Latn + {0xE42B0000u, 55u}, // lbz -> Latn + {0x884B0000u, 55u}, // lcc -> Latn + {0x8C4B0000u, 55u}, // lcd -> Latn + {0x904B0000u, 55u}, // lce -> Latn + {0x944B0000u, 55u}, // lcf -> Latn + {0x9C4B0000u, 55u}, // lch -> Latn + {0xAC4B0000u, 55u}, // lcl -> Latn + {0xB04B0000u, 55u}, // lcm -> Latn + {0xBC4B0000u, 111u}, // lcp -> Thai + {0xC04B0000u, 55u}, // lcq -> Latn + {0xC84B0000u, 55u}, // lcs -> Latn + {0x806B0000u, 55u}, // lda -> Latn + {0x846B0000u, 55u}, // ldb -> Latn + {0x8C6B0000u, 55u}, // ldd -> Latn + {0x986B0000u, 55u}, // ldg -> Latn + {0x9C6B0000u, 55u}, // ldh -> Latn + {0xA06B0000u, 55u}, // ldi -> Latn + {0xA46B0000u, 55u}, // ldj -> Latn + {0xA86B0000u, 55u}, // ldk -> Latn + {0xAC6B0000u, 55u}, // ldl -> Latn + {0xB06B0000u, 55u}, // ldm -> Latn + {0xB46B0000u, 55u}, // ldn -> Latn + {0xB86B0000u, 55u}, // ldo -> Latn + {0xBC6B0000u, 55u}, // ldp -> Latn + {0xC06B0000u, 55u}, // ldq -> Latn + {0x808B0000u, 55u}, // lea -> Latn + {0x848B0000u, 55u}, // leb -> Latn + {0x888B0000u, 55u}, // lec -> Latn + {0x8C8B0000u, 55u}, // led -> Latn + {0x908B0000u, 55u}, // lee -> Latn + {0x948B0000u, 55u}, // lef -> Latn + {0x9C8B0000u, 55u}, // leh -> Latn + {0xA08B0000u, 55u}, // lei -> Latn + {0xA48B0000u, 55u}, // lej -> Latn + {0xA88B0000u, 55u}, // lek -> Latn + {0xAC8B0000u, 55u}, // lel -> Latn + {0xB08B0000u, 55u}, // lem -> Latn + {0xB48B0000u, 55u}, // len -> Latn + {0xB88B0000u, 55u}, // leo -> Latn + {0xBC8B0000u, 56u}, // lep -> Lepc + {0xC08B0000u, 55u}, // leq -> Latn + {0xC48B0000u, 55u}, // ler -> Latn + {0xC88B0000u, 55u}, // les -> Latn + {0xCC8B0000u, 55u}, // let -> Latn + {0xD08B0000u, 55u}, // leu -> Latn + {0xD48B0000u, 55u}, // lev -> Latn + {0xD88B0000u, 55u}, // lew -> Latn + {0xDC8B0000u, 55u}, // lex -> Latn + {0xE08B0000u, 55u}, // ley -> Latn + {0xE48B0000u, 20u}, // lez -> Cyrl + {0x80AB0000u, 55u}, // lfa -> Latn + {0xB4AB0000u, 55u}, // lfn -> Latn + {0x6C670000u, 55u}, // lg -> Latn + {0x80CB0000u, 55u}, // lga -> Latn + {0x84CB0000u, 55u}, // lgb -> Latn + {0x98CB0000u, 55u}, // lgg -> Latn + {0x9CCB0000u, 55u}, // lgh -> Latn + {0xA0CB0000u, 55u}, // lgi -> Latn + {0xA8CB0000u, 55u}, // lgk -> Latn + {0xACCB0000u, 55u}, // lgl -> Latn + {0xB0CB0000u, 55u}, // lgm -> Latn + {0xB4CB0000u, 55u}, // lgn -> Latn + {0xB8CB0000u, 55u}, // lgo -> Latn + {0xC0CB0000u, 55u}, // lgq -> Latn + {0xC4CB0000u, 55u}, // lgr -> Latn + {0xCCCB0000u, 55u}, // lgt -> Latn + {0xD0CB0000u, 55u}, // lgu -> Latn + {0xE4CB0000u, 55u}, // lgz -> Latn + {0x80EB0000u, 55u}, // lha -> Latn + {0x9CEB0000u, 55u}, // lhh -> Latn + {0xA0EB0000u, 55u}, // lhi -> Latn + {0xB0EB0000u, 21u}, // lhm -> Deva + {0xB4EB0000u, 55u}, // lhn -> Latn + {0xC8EB0000u, 100u}, // lhs -> Syrc + {0xCCEB0000u, 55u}, // lht -> Latn + {0xD0EB0000u, 55u}, // lhu -> Latn + {0x6C690000u, 55u}, // li -> Latn + {0x810B0000u, 55u}, // lia -> Latn + {0x850B0000u, 55u}, // lib -> Latn + {0x890B0000u, 55u}, // lic -> Latn + {0x8D0B0000u, 55u}, // lid -> Latn + {0x910B0000u, 55u}, // lie -> Latn + {0x950B0000u, 21u}, // lif -> Deva + {0x990B0000u, 55u}, // lig -> Latn + {0x9D0B0000u, 55u}, // lih -> Latn + {0xA50B0000u, 55u}, // lij -> Latn + {0xA90B0000u, 55u}, // lik -> Latn + {0xAD0B0000u, 55u}, // lil -> Latn + {0xB90B0000u, 55u}, // lio -> Latn + {0xBD0B0000u, 55u}, // lip -> Latn + {0xC10B0000u, 55u}, // liq -> Latn + {0xC50B0000u, 55u}, // lir -> Latn + {0xC90B0000u, 59u}, // lis -> Lisu + {0xD10B0000u, 55u}, // liu -> Latn + {0xD50B0000u, 55u}, // liv -> Latn + {0xD90B0000u, 55u}, // liw -> Latn + {0xDD0B0000u, 55u}, // lix -> Latn + {0xE10B0000u, 55u}, // liy -> Latn + {0xE50B0000u, 55u}, // liz -> Latn + {0x812B0000u, 55u}, // lja -> Latn + {0x912B0000u, 55u}, // lje -> Latn + {0xA12B0000u, 55u}, // lji -> Latn + {0xAD2B0000u, 55u}, // ljl -> Latn + {0xBD2B0000u, 55u}, // ljp -> Latn + {0xD92B0000u, 55u}, // ljw -> Latn + {0xDD2B0000u, 55u}, // ljx -> Latn + {0x814B0000u, 55u}, // lka -> Latn + {0x854B0000u, 55u}, // lkb -> Latn + {0x894B0000u, 55u}, // lkc -> Latn + {0x8D4B0000u, 55u}, // lkd -> Latn + {0x914B0000u, 55u}, // lke -> Latn + {0x9D4B0000u, 112u}, // lkh -> Tibt {0xA14B0000u, 2u}, // lki -> Arab - {0xCD4B0000u, 46u}, // lkt -> Latn - {0x916B0000u, 46u}, // lle -> Latn - {0xB56B0000u, 46u}, // lln -> Latn - {0xB58B0000u, 90u}, // lmn -> Telu - {0xB98B0000u, 46u}, // lmo -> Latn - {0xBD8B0000u, 46u}, // lmp -> Latn - {0x6C6E0000u, 46u}, // ln -> Latn - {0xC9AB0000u, 46u}, // lns -> Latn - {0xD1AB0000u, 46u}, // lnu -> Latn - {0x6C6F0000u, 45u}, // lo -> Laoo - {0xA5CB0000u, 46u}, // loj -> Latn - {0xA9CB0000u, 46u}, // lok -> Latn - {0xADCB0000u, 46u}, // lol -> Latn - {0xC5CB0000u, 46u}, // lor -> Latn - {0xC9CB0000u, 46u}, // los -> Latn - {0xE5CB0000u, 46u}, // loz -> Latn + {0xA54B0000u, 55u}, // lkj -> Latn + {0xAD4B0000u, 55u}, // lkl -> Latn + {0xB14B0000u, 55u}, // lkm -> Latn + {0xB54B0000u, 55u}, // lkn -> Latn + {0xB94B0000u, 55u}, // lko -> Latn + {0xC54B0000u, 55u}, // lkr -> Latn + {0xC94B0000u, 55u}, // lks -> Latn + {0xCD4B0000u, 55u}, // lkt -> Latn + {0xD14B0000u, 55u}, // lku -> Latn + {0xE14B0000u, 55u}, // lky -> Latn + {0x816B0000u, 55u}, // lla -> Latn + {0x856B0000u, 55u}, // llb -> Latn + {0x896B0000u, 55u}, // llc -> Latn + {0x8D6B0000u, 55u}, // lld -> Latn + {0x916B0000u, 55u}, // lle -> Latn + {0x956B0000u, 55u}, // llf -> Latn + {0x996B0000u, 55u}, // llg -> Latn + {0xA16B0000u, 55u}, // lli -> Latn + {0xA56B0000u, 55u}, // llj -> Latn + {0xA96B0000u, 55u}, // llk -> Latn + {0xAD6B0000u, 55u}, // lll -> Latn + {0xB16B0000u, 55u}, // llm -> Latn + {0xB56B0000u, 55u}, // lln -> Latn + {0xBD6B0000u, 55u}, // llp -> Latn + {0xC16B0000u, 55u}, // llq -> Latn + {0xD16B0000u, 55u}, // llu -> Latn + {0xDD6B0000u, 55u}, // llx -> Latn + {0x818B0000u, 55u}, // lma -> Latn + {0x858B0000u, 55u}, // lmb -> Latn + {0x898B0000u, 55u}, // lmc -> Latn + {0x8D8B0000u, 55u}, // lmd -> Latn + {0x918B0000u, 55u}, // lme -> Latn + {0x958B0000u, 55u}, // lmf -> Latn + {0x998B0000u, 55u}, // lmg -> Latn + {0x9D8B0000u, 21u}, // lmh -> Deva + {0xA18B0000u, 55u}, // lmi -> Latn + {0xA58B0000u, 55u}, // lmj -> Latn + {0xA98B0000u, 55u}, // lmk -> Latn + {0xAD8B0000u, 55u}, // lml -> Latn + {0xB58B0000u, 108u}, // lmn -> Telu + {0xB98B0000u, 55u}, // lmo -> Latn + {0xBD8B0000u, 55u}, // lmp -> Latn + {0xC18B0000u, 55u}, // lmq -> Latn + {0xC58B0000u, 55u}, // lmr -> Latn + {0xD18B0000u, 55u}, // lmu -> Latn + {0xD58B0000u, 55u}, // lmv -> Latn + {0xD98B0000u, 55u}, // lmw -> Latn + {0xDD8B0000u, 55u}, // lmx -> Latn + {0xE18B0000u, 55u}, // lmy -> Latn + {0x6C6E0000u, 55u}, // ln -> Latn + {0x81AB0000u, 55u}, // lna -> Latn + {0x85AB0000u, 55u}, // lnb -> Latn + {0x8DAB0000u, 55u}, // lnd -> Latn + {0x99AB0000u, 55u}, // lng -> Latn + {0x9DAB0000u, 55u}, // lnh -> Latn + {0xA1AB0000u, 55u}, // lni -> Latn + {0xA5AB0000u, 55u}, // lnj -> Latn + {0xADAB0000u, 55u}, // lnl -> Latn + {0xB1AB0000u, 55u}, // lnm -> Latn + {0xB5AB0000u, 55u}, // lnn -> Latn + {0xC9AB0000u, 55u}, // lns -> Latn + {0xD1AB0000u, 55u}, // lnu -> Latn + {0xD9AB0000u, 55u}, // lnw -> Latn + {0xE5AB0000u, 55u}, // lnz -> Latn + {0x6C6F0000u, 52u}, // lo -> Laoo + {0x81CB0000u, 55u}, // loa -> Latn + {0x85CB0000u, 55u}, // lob -> Latn + {0x89CB0000u, 55u}, // loc -> Latn + {0x91CB0000u, 55u}, // loe -> Latn + {0x99CB0000u, 55u}, // log -> Latn + {0x9DCB0000u, 55u}, // loh -> Latn + {0xA1CB0000u, 55u}, // loi -> Latn + {0xA5CB0000u, 55u}, // loj -> Latn + {0xA9CB0000u, 55u}, // lok -> Latn + {0xADCB0000u, 55u}, // lol -> Latn + {0xB1CB0000u, 55u}, // lom -> Latn + {0xB5CB0000u, 55u}, // lon -> Latn + {0xB9CB0000u, 55u}, // loo -> Latn + {0xBDCB0000u, 55u}, // lop -> Latn + {0xC1CB0000u, 55u}, // loq -> Latn + {0xC5CB0000u, 55u}, // lor -> Latn + {0xC9CB0000u, 55u}, // los -> Latn + {0xCDCB0000u, 55u}, // lot -> Latn + {0xD1CB0000u, 55u}, // lou -> Latn + {0xD9CB0000u, 55u}, // low -> Latn + {0xDDCB0000u, 55u}, // lox -> Latn + {0xE1CB0000u, 21u}, // loy -> Deva + {0xE5CB0000u, 55u}, // loz -> Latn + {0x81EB0000u, 55u}, // lpa -> Latn + {0x91EB0000u, 55u}, // lpe -> Latn + {0xB5EB0000u, 55u}, // lpn -> Latn + {0xB9EB0000u, 86u}, // lpo -> Plrd + {0xDDEB0000u, 55u}, // lpx -> Latn + {0xC60B0000u, 55u}, // lqr -> Latn + {0x822B0000u, 55u}, // lra -> Latn {0x8A2B0000u, 2u}, // lrc -> Arab - {0x6C740000u, 46u}, // lt -> Latn - {0x9A6B0000u, 46u}, // ltg -> Latn - {0x6C750000u, 46u}, // lu -> Latn - {0x828B0000u, 46u}, // lua -> Latn - {0xBA8B0000u, 46u}, // luo -> Latn - {0xE28B0000u, 46u}, // luy -> Latn + {0x9A2B0000u, 55u}, // lrg -> Latn + {0xA22B0000u, 55u}, // lri -> Latn + {0xAA2B0000u, 2u}, // lrk -> Arab + {0xAE2B0000u, 2u}, // lrl -> Arab + {0xB22B0000u, 55u}, // lrm -> Latn + {0xB62B0000u, 55u}, // lrn -> Latn + {0xBA2B0000u, 55u}, // lro -> Latn + {0xCE2B0000u, 55u}, // lrt -> Latn + {0xD62B0000u, 55u}, // lrv -> Latn + {0xE62B0000u, 55u}, // lrz -> Latn + {0x824B0000u, 2u}, // lsa -> Arab + {0x8E4B0000u, 37u}, // lsd -> Hebr + {0x924B0000u, 55u}, // lse -> Latn + {0xA24B0000u, 55u}, // lsi -> Latn + {0xB24B0000u, 55u}, // lsm -> Latn + {0xC64B0000u, 55u}, // lsr -> Latn + {0xCA4B0000u, 2u}, // lss -> Arab + {0x6C740000u, 55u}, // lt -> Latn + {0x8A6B0000u, 36u}, // ltc -> Hant + {0x9A6B0000u, 55u}, // ltg -> Latn + {0x9E6B0000u, 55u}, // lth -> Latn + {0xA26B0000u, 55u}, // lti -> Latn + {0xB66B0000u, 55u}, // ltn -> Latn + {0xBA6B0000u, 55u}, // lto -> Latn + {0xCA6B0000u, 55u}, // lts -> Latn + {0xD26B0000u, 55u}, // ltu -> Latn + {0x6C750000u, 55u}, // lu -> Latn + {0x828B0000u, 55u}, // lua -> Latn + {0x8A8B0000u, 55u}, // luc -> Latn + {0x8E8B0000u, 55u}, // lud -> Latn + {0x928B0000u, 55u}, // lue -> Latn + {0x968B0000u, 55u}, // luf -> Latn + {0xA28B0000u, 55u}, // lui -> Latn + {0xA68B0000u, 55u}, // luj -> Latn + {0xAA8B0000u, 112u}, // luk -> Tibt + {0xAE8B0000u, 55u}, // lul -> Latn + {0xB28B0000u, 55u}, // lum -> Latn + {0xB68B0000u, 55u}, // lun -> Latn + {0xBA8B0000u, 55u}, // luo -> Latn + {0xBE8B0000u, 55u}, // lup -> Latn + {0xC28B0000u, 55u}, // luq -> Latn + {0xC68B0000u, 55u}, // lur -> Latn + {0xCA8B0000u, 55u}, // lus -> Latn + {0xCE8B0000u, 55u}, // lut -> Latn + {0xD28B0000u, 21u}, // luu -> Deva + {0xD68B0000u, 2u}, // luv -> Arab + {0xDA8B0000u, 55u}, // luw -> Latn + {0xE28B0000u, 55u}, // luy -> Latn {0xE68B0000u, 2u}, // luz -> Arab - {0x6C760000u, 46u}, // lv -> Latn - {0xAECB0000u, 93u}, // lwl -> Thai - {0x9F2B0000u, 29u}, // lzh -> Hans - {0xE72B0000u, 46u}, // lzz -> Latn - {0x8C0C0000u, 46u}, // mad -> Latn - {0x940C0000u, 46u}, // maf -> Latn - {0x980C0000u, 19u}, // mag -> Deva - {0xA00C0000u, 19u}, // mai -> Deva - {0xA80C0000u, 46u}, // mak -> Latn - {0xB40C0000u, 46u}, // man -> Latn - {0xB40C474Eu, 61u}, // man-GN -> Nkoo - {0xC80C0000u, 46u}, // mas -> Latn - {0xD80C0000u, 46u}, // maw -> Latn - {0xE40C0000u, 46u}, // maz -> Latn - {0x9C2C0000u, 46u}, // mbh -> Latn - {0xB82C0000u, 46u}, // mbo -> Latn - {0xC02C0000u, 46u}, // mbq -> Latn - {0xD02C0000u, 46u}, // mbu -> Latn - {0xD82C0000u, 46u}, // mbw -> Latn - {0xA04C0000u, 46u}, // mci -> Latn - {0xBC4C0000u, 46u}, // mcp -> Latn - {0xC04C0000u, 46u}, // mcq -> Latn - {0xC44C0000u, 46u}, // mcr -> Latn - {0xD04C0000u, 46u}, // mcu -> Latn - {0x806C0000u, 46u}, // mda -> Latn + {0x6C760000u, 55u}, // lv -> Latn + {0x82AB0000u, 55u}, // lva -> Latn + {0xA2AB0000u, 55u}, // lvi -> Latn + {0xAAAB0000u, 55u}, // lvk -> Latn + {0xAEAB0000u, 55u}, // lvl -> Latn + {0xD2AB0000u, 55u}, // lvu -> Latn + {0x82CB0000u, 55u}, // lwa -> Latn + {0x92CB0000u, 55u}, // lwe -> Latn + {0x9ACB0000u, 55u}, // lwg -> Latn + {0x9ECB0000u, 55u}, // lwh -> Latn + {0xAECB0000u, 111u}, // lwl -> Thai + {0xB2CB0000u, 111u}, // lwm -> Thai + {0xBACB0000u, 55u}, // lwo -> Latn + {0xCECB0000u, 55u}, // lwt -> Latn + {0xDACB0000u, 55u}, // lww -> Latn + {0xB2EB0000u, 55u}, // lxm -> Latn + {0x830B0000u, 112u}, // lya -> Tibt + {0xB70B0000u, 55u}, // lyn -> Latn + {0x9F2B0000u, 35u}, // lzh -> Hans + {0xAF2B0000u, 55u}, // lzl -> Latn + {0xB72B0000u, 55u}, // lzn -> Latn + {0xE72B0000u, 55u}, // lzz -> Latn + {0x800C0000u, 55u}, // maa -> Latn + {0x840C0000u, 55u}, // mab -> Latn + {0x8C0C0000u, 55u}, // mad -> Latn + {0x900C0000u, 55u}, // mae -> Latn + {0x940C0000u, 55u}, // maf -> Latn + {0x980C0000u, 21u}, // mag -> Deva + {0xA00C0000u, 21u}, // mai -> Deva + {0xA40C0000u, 55u}, // maj -> Latn + {0xA80C0000u, 55u}, // mak -> Latn + {0xB00C0000u, 55u}, // mam -> Latn + {0xB40C0000u, 55u}, // man -> Latn + {0xB40C474Eu, 75u}, // man-GN -> Nkoo + {0xC00C0000u, 55u}, // maq -> Latn + {0xC80C0000u, 55u}, // mas -> Latn + {0xCC0C0000u, 55u}, // mat -> Latn + {0xD00C0000u, 55u}, // mau -> Latn + {0xD40C0000u, 55u}, // mav -> Latn + {0xD80C0000u, 55u}, // maw -> Latn + {0xDC0C0000u, 55u}, // max -> Latn + {0xE40C0000u, 55u}, // maz -> Latn + {0x802C0000u, 55u}, // mba -> Latn + {0x842C0000u, 55u}, // mbb -> Latn + {0x882C0000u, 55u}, // mbc -> Latn + {0x8C2C0000u, 55u}, // mbd -> Latn + {0x942C0000u, 55u}, // mbf -> Latn + {0x9C2C0000u, 55u}, // mbh -> Latn + {0xA02C0000u, 55u}, // mbi -> Latn + {0xA42C0000u, 55u}, // mbj -> Latn + {0xA82C0000u, 55u}, // mbk -> Latn + {0xAC2C0000u, 55u}, // mbl -> Latn + {0xB02C0000u, 55u}, // mbm -> Latn + {0xB42C0000u, 55u}, // mbn -> Latn + {0xB82C0000u, 55u}, // mbo -> Latn + {0xBC2C0000u, 55u}, // mbp -> Latn + {0xC02C0000u, 55u}, // mbq -> Latn + {0xC42C0000u, 55u}, // mbr -> Latn + {0xC82C0000u, 55u}, // mbs -> Latn + {0xCC2C0000u, 55u}, // mbt -> Latn + {0xD02C0000u, 55u}, // mbu -> Latn + {0xD42C0000u, 55u}, // mbv -> Latn + {0xD82C0000u, 55u}, // mbw -> Latn + {0xDC2C0000u, 55u}, // mbx -> Latn + {0xE02C0000u, 2u}, // mby -> Arab + {0xE42C0000u, 55u}, // mbz -> Latn + {0x804C0000u, 55u}, // mca -> Latn + {0x844C0000u, 55u}, // mcb -> Latn + {0x884C0000u, 55u}, // mcc -> Latn + {0x8C4C0000u, 55u}, // mcd -> Latn + {0x904C0000u, 55u}, // mce -> Latn + {0x944C0000u, 55u}, // mcf -> Latn + {0x984C0000u, 55u}, // mcg -> Latn + {0x9C4C0000u, 55u}, // mch -> Latn + {0xA04C0000u, 55u}, // mci -> Latn + {0xA44C0000u, 55u}, // mcj -> Latn + {0xA84C0000u, 55u}, // mck -> Latn + {0xAC4C0000u, 55u}, // mcl -> Latn + {0xB04C0000u, 55u}, // mcm -> Latn + {0xB44C0000u, 55u}, // mcn -> Latn + {0xB84C0000u, 55u}, // mco -> Latn + {0xBC4C0000u, 55u}, // mcp -> Latn + {0xC04C0000u, 55u}, // mcq -> Latn + {0xC44C0000u, 55u}, // mcr -> Latn + {0xC84C0000u, 55u}, // mcs -> Latn + {0xCC4C0000u, 55u}, // mct -> Latn + {0xD04C0000u, 55u}, // mcu -> Latn + {0xD44C0000u, 55u}, // mcv -> Latn + {0xD84C0000u, 55u}, // mcw -> Latn + {0xDC4C0000u, 55u}, // mcx -> Latn + {0xE04C0000u, 55u}, // mcy -> Latn + {0xE44C0000u, 55u}, // mcz -> Latn + {0x806C0000u, 55u}, // mda -> Latn + {0x846C0000u, 55u}, // mdb -> Latn + {0x886C0000u, 55u}, // mdc -> Latn + {0x8C6C0000u, 55u}, // mdd -> Latn {0x906C0000u, 2u}, // mde -> Arab - {0x946C0000u, 18u}, // mdf -> Cyrl - {0x9C6C0000u, 46u}, // mdh -> Latn - {0xA46C0000u, 46u}, // mdj -> Latn - {0xC46C0000u, 46u}, // mdr -> Latn - {0xDC6C0000u, 21u}, // mdx -> Ethi - {0x8C8C0000u, 46u}, // med -> Latn - {0x908C0000u, 46u}, // mee -> Latn - {0xA88C0000u, 46u}, // mek -> Latn - {0xB48C0000u, 46u}, // men -> Latn - {0xC48C0000u, 46u}, // mer -> Latn - {0xCC8C0000u, 46u}, // met -> Latn - {0xD08C0000u, 46u}, // meu -> Latn + {0x946C0000u, 20u}, // mdf -> Cyrl + {0x986C0000u, 55u}, // mdg -> Latn + {0x9C6C0000u, 55u}, // mdh -> Latn + {0xA06C0000u, 55u}, // mdi -> Latn + {0xA46C0000u, 55u}, // mdj -> Latn + {0xA86C0000u, 55u}, // mdk -> Latn + {0xB06C0000u, 55u}, // mdm -> Latn + {0xB46C0000u, 55u}, // mdn -> Latn + {0xBC6C0000u, 55u}, // mdp -> Latn + {0xC06C0000u, 55u}, // mdq -> Latn + {0xC46C0000u, 55u}, // mdr -> Latn + {0xC86C0000u, 55u}, // mds -> Latn + {0xCC6C0000u, 55u}, // mdt -> Latn + {0xD06C0000u, 55u}, // mdu -> Latn + {0xD46C0000u, 55u}, // mdv -> Latn + {0xD86C0000u, 55u}, // mdw -> Latn + {0xDC6C0000u, 24u}, // mdx -> Ethi + {0xE06C0000u, 24u}, // mdy -> Ethi + {0xE46C0000u, 55u}, // mdz -> Latn + {0x808C0000u, 55u}, // mea -> Latn + {0x848C0000u, 55u}, // meb -> Latn + {0x888C0000u, 55u}, // mec -> Latn + {0x8C8C0000u, 55u}, // med -> Latn + {0x908C0000u, 55u}, // mee -> Latn + {0x9C8C0000u, 55u}, // meh -> Latn + {0xA48C0000u, 55u}, // mej -> Latn + {0xA88C0000u, 55u}, // mek -> Latn + {0xAC8C0000u, 55u}, // mel -> Latn + {0xB08C0000u, 55u}, // mem -> Latn + {0xB48C0000u, 55u}, // men -> Latn + {0xB88C0000u, 55u}, // meo -> Latn + {0xBC8C0000u, 55u}, // mep -> Latn + {0xC08C0000u, 55u}, // meq -> Latn + {0xC48C0000u, 55u}, // mer -> Latn + {0xC88C0000u, 55u}, // mes -> Latn + {0xCC8C0000u, 55u}, // met -> Latn + {0xD08C0000u, 55u}, // meu -> Latn + {0xD48C0000u, 55u}, // mev -> Latn + {0xD88C0000u, 55u}, // mew -> Latn + {0xE08C0000u, 55u}, // mey -> Latn + {0xE48C0000u, 55u}, // mez -> Latn {0x80AC0000u, 2u}, // mfa -> Arab - {0x90AC0000u, 46u}, // mfe -> Latn - {0xB4AC0000u, 46u}, // mfn -> Latn - {0xB8AC0000u, 46u}, // mfo -> Latn - {0xC0AC0000u, 46u}, // mfq -> Latn - {0x6D670000u, 46u}, // mg -> Latn - {0x9CCC0000u, 46u}, // mgh -> Latn - {0xACCC0000u, 46u}, // mgl -> Latn - {0xB8CC0000u, 46u}, // mgo -> Latn - {0xBCCC0000u, 19u}, // mgp -> Deva - {0xE0CC0000u, 46u}, // mgy -> Latn - {0x6D680000u, 46u}, // mh -> Latn - {0xA0EC0000u, 46u}, // mhi -> Latn - {0xACEC0000u, 46u}, // mhl -> Latn - {0x6D690000u, 46u}, // mi -> Latn - {0x890C0000u, 46u}, // mic -> Latn - {0x950C0000u, 46u}, // mif -> Latn - {0xB50C0000u, 46u}, // min -> Latn - {0xD90C0000u, 46u}, // miw -> Latn - {0x6D6B0000u, 18u}, // mk -> Cyrl + {0x84AC0000u, 55u}, // mfb -> Latn + {0x88AC0000u, 55u}, // mfc -> Latn + {0x8CAC0000u, 55u}, // mfd -> Latn + {0x90AC0000u, 55u}, // mfe -> Latn + {0x94AC0000u, 55u}, // mff -> Latn + {0x98AC0000u, 55u}, // mfg -> Latn + {0x9CAC0000u, 55u}, // mfh -> Latn + {0xA0AC0000u, 2u}, // mfi -> Arab + {0xA4AC0000u, 55u}, // mfj -> Latn + {0xA8AC0000u, 55u}, // mfk -> Latn + {0xACAC0000u, 55u}, // mfl -> Latn + {0xB0AC0000u, 55u}, // mfm -> Latn + {0xB4AC0000u, 55u}, // mfn -> Latn + {0xB8AC0000u, 55u}, // mfo -> Latn + {0xBCAC0000u, 55u}, // mfp -> Latn + {0xC0AC0000u, 55u}, // mfq -> Latn + {0xC4AC0000u, 55u}, // mfr -> Latn + {0xCCAC0000u, 55u}, // mft -> Latn + {0xD0AC0000u, 55u}, // mfu -> Latn + {0xD4AC0000u, 55u}, // mfv -> Latn + {0xD8AC0000u, 55u}, // mfw -> Latn + {0xDCAC0000u, 55u}, // mfx -> Latn + {0xE0AC0000u, 55u}, // mfy -> Latn + {0xE4AC0000u, 55u}, // mfz -> Latn + {0x6D670000u, 55u}, // mg -> Latn + {0x80CC0000u, 54u}, // mga -> Latg + {0x84CC0000u, 55u}, // mgb -> Latn + {0x88CC0000u, 55u}, // mgc -> Latn + {0x8CCC0000u, 55u}, // mgd -> Latn + {0x90CC0000u, 55u}, // mge -> Latn + {0x94CC0000u, 55u}, // mgf -> Latn + {0x98CC0000u, 55u}, // mgg -> Latn + {0x9CCC0000u, 55u}, // mgh -> Latn + {0xA0CC0000u, 55u}, // mgi -> Latn + {0xA4CC0000u, 55u}, // mgj -> Latn + {0xA8CC0000u, 55u}, // mgk -> Latn + {0xACCC0000u, 55u}, // mgl -> Latn + {0xB0CC0000u, 55u}, // mgm -> Latn + {0xB4CC0000u, 55u}, // mgn -> Latn + {0xB8CC0000u, 55u}, // mgo -> Latn + {0xBCCC0000u, 21u}, // mgp -> Deva + {0xC0CC0000u, 55u}, // mgq -> Latn + {0xC4CC0000u, 55u}, // mgr -> Latn + {0xC8CC0000u, 55u}, // mgs -> Latn + {0xCCCC0000u, 55u}, // mgt -> Latn + {0xD0CC0000u, 55u}, // mgu -> Latn + {0xD4CC0000u, 55u}, // mgv -> Latn + {0xD8CC0000u, 55u}, // mgw -> Latn + {0xE0CC0000u, 55u}, // mgy -> Latn + {0xE4CC0000u, 55u}, // mgz -> Latn + {0x6D680000u, 55u}, // mh -> Latn + {0x84EC0000u, 55u}, // mhb -> Latn + {0x88EC0000u, 55u}, // mhc -> Latn + {0x8CEC0000u, 55u}, // mhd -> Latn + {0x90EC0000u, 55u}, // mhe -> Latn + {0x94EC0000u, 55u}, // mhf -> Latn + {0x98EC0000u, 55u}, // mhg -> Latn + {0xA0EC0000u, 55u}, // mhi -> Latn + {0xA4EC0000u, 2u}, // mhj -> Arab + {0xA8EC0000u, 55u}, // mhk -> Latn + {0xACEC0000u, 55u}, // mhl -> Latn + {0xB0EC0000u, 55u}, // mhm -> Latn + {0xB4EC0000u, 55u}, // mhn -> Latn + {0xB8EC0000u, 55u}, // mho -> Latn + {0xBCEC0000u, 55u}, // mhp -> Latn + {0xC0EC0000u, 55u}, // mhq -> Latn + {0xC8EC0000u, 55u}, // mhs -> Latn + {0xCCEC0000u, 55u}, // mht -> Latn + {0xD0EC0000u, 55u}, // mhu -> Latn + {0xD8EC0000u, 55u}, // mhw -> Latn + {0xDCEC0000u, 55u}, // mhx -> Latn + {0xE0EC0000u, 55u}, // mhy -> Latn + {0xE4EC0000u, 55u}, // mhz -> Latn + {0x6D690000u, 55u}, // mi -> Latn + {0x810C0000u, 55u}, // mia -> Latn + {0x850C0000u, 55u}, // mib -> Latn + {0x890C0000u, 55u}, // mic -> Latn + {0x8D0C0000u, 62u}, // mid -> Mand + {0x910C0000u, 55u}, // mie -> Latn + {0x950C0000u, 55u}, // mif -> Latn + {0x990C0000u, 55u}, // mig -> Latn + {0x9D0C0000u, 55u}, // mih -> Latn + {0xA10C0000u, 55u}, // mii -> Latn + {0xA50C0000u, 55u}, // mij -> Latn + {0xA90C0000u, 55u}, // mik -> Latn + {0xAD0C0000u, 55u}, // mil -> Latn + {0xB10C0000u, 55u}, // mim -> Latn + {0xB50C0000u, 55u}, // min -> Latn + {0xB90C0000u, 55u}, // mio -> Latn + {0xBD0C0000u, 55u}, // mip -> Latn + {0xC10C0000u, 55u}, // miq -> Latn + {0xC50C0000u, 55u}, // mir -> Latn + {0xCD0C0000u, 55u}, // mit -> Latn + {0xD10C0000u, 55u}, // miu -> Latn + {0xD90C0000u, 55u}, // miw -> Latn + {0xDD0C0000u, 55u}, // mix -> Latn + {0xE10C0000u, 55u}, // miy -> Latn + {0xE50C0000u, 55u}, // miz -> Latn + {0x852C0000u, 55u}, // mjb -> Latn + {0x892C0000u, 55u}, // mjc -> Latn + {0x8D2C0000u, 55u}, // mjd -> Latn + {0x912C0000u, 55u}, // mje -> Latn + {0x992C0000u, 55u}, // mjg -> Latn + {0x9D2C0000u, 55u}, // mjh -> Latn + {0xA12C0000u, 55u}, // mji -> Latn + {0xA52C0000u, 55u}, // mjj -> Latn + {0xA92C0000u, 55u}, // mjk -> Latn + {0xAD2C0000u, 21u}, // mjl -> Deva + {0xB12C0000u, 55u}, // mjm -> Latn + {0xB52C0000u, 55u}, // mjn -> Latn + {0xC12C0000u, 67u}, // mjq -> Mlym + {0xC52C0000u, 67u}, // mjr -> Mlym + {0xC92C0000u, 55u}, // mjs -> Latn + {0xCD2C0000u, 21u}, // mjt -> Deva + {0xD12C0000u, 108u}, // mju -> Telu + {0xD52C0000u, 67u}, // mjv -> Mlym + {0xD92C0000u, 55u}, // mjw -> Latn + {0xDD2C0000u, 55u}, // mjx -> Latn + {0xE12C0000u, 55u}, // mjy -> Latn + {0xE52C0000u, 21u}, // mjz -> Deva + {0x6D6B0000u, 20u}, // mk -> Cyrl + {0x814C0000u, 55u}, // mka -> Latn + {0x854C0000u, 21u}, // mkb -> Deva + {0x894C0000u, 55u}, // mkc -> Latn + {0x914C0000u, 21u}, // mke -> Deva + {0x954C0000u, 55u}, // mkf -> Latn {0xA14C0000u, 2u}, // mki -> Arab - {0xAD4C0000u, 46u}, // mkl -> Latn - {0xBD4C0000u, 46u}, // mkp -> Latn - {0xD94C0000u, 46u}, // mkw -> Latn - {0x6D6C0000u, 56u}, // ml -> Mlym - {0x916C0000u, 46u}, // mle -> Latn - {0xBD6C0000u, 46u}, // mlp -> Latn - {0xC96C0000u, 46u}, // mls -> Latn - {0xB98C0000u, 46u}, // mmo -> Latn - {0xD18C0000u, 46u}, // mmu -> Latn - {0xDD8C0000u, 46u}, // mmx -> Latn - {0x6D6E0000u, 18u}, // mn -> Cyrl - {0x6D6E434Eu, 57u}, // mn-CN -> Mong - {0x81AC0000u, 46u}, // mna -> Latn - {0x95AC0000u, 46u}, // mnf -> Latn - {0xA1AC0000u, 8u}, // mni -> Beng - {0xD9AC0000u, 59u}, // mnw -> Mymr - {0x6D6F0000u, 46u}, // mo -> Latn - {0x81CC0000u, 46u}, // moa -> Latn - {0x91CC0000u, 46u}, // moe -> Latn - {0x9DCC0000u, 46u}, // moh -> Latn - {0xC9CC0000u, 46u}, // mos -> Latn - {0xDDCC0000u, 46u}, // mox -> Latn - {0xBDEC0000u, 46u}, // mpp -> Latn - {0xC9EC0000u, 46u}, // mps -> Latn - {0xCDEC0000u, 46u}, // mpt -> Latn - {0xDDEC0000u, 46u}, // mpx -> Latn - {0xAE0C0000u, 46u}, // mql -> Latn - {0x6D720000u, 19u}, // mr -> Deva - {0x8E2C0000u, 19u}, // mrd -> Deva - {0xA62C0000u, 18u}, // mrj -> Cyrl - {0xBA2C0000u, 58u}, // mro -> Mroo - {0x6D730000u, 46u}, // ms -> Latn + {0xA54C0000u, 55u}, // mkj -> Latn + {0xA94C0000u, 55u}, // mkk -> Latn + {0xAD4C0000u, 55u}, // mkl -> Latn + {0xB14C0000u, 111u}, // mkm -> Thai + {0xB54C0000u, 55u}, // mkn -> Latn + {0xB94C0000u, 55u}, // mko -> Latn + {0xBD4C0000u, 55u}, // mkp -> Latn + {0xC54C0000u, 55u}, // mkr -> Latn + {0xC94C0000u, 55u}, // mks -> Latn + {0xCD4C0000u, 55u}, // mkt -> Latn + {0xD14C0000u, 55u}, // mku -> Latn + {0xD54C0000u, 55u}, // mkv -> Latn + {0xD94C0000u, 55u}, // mkw -> Latn + {0xDD4C0000u, 55u}, // mkx -> Latn + {0xE14C0000u, 55u}, // mky -> Latn + {0xE54C0000u, 55u}, // mkz -> Latn + {0x6D6C0000u, 67u}, // ml -> Mlym + {0x816C0000u, 55u}, // mla -> Latn + {0x856C0000u, 55u}, // mlb -> Latn + {0x896C0000u, 55u}, // mlc -> Latn + {0x916C0000u, 55u}, // mle -> Latn + {0x956C0000u, 111u}, // mlf -> Thai + {0x9D6C0000u, 55u}, // mlh -> Latn + {0xA16C0000u, 55u}, // mli -> Latn + {0xA56C0000u, 55u}, // mlj -> Latn + {0xA96C0000u, 55u}, // mlk -> Latn + {0xAD6C0000u, 55u}, // mll -> Latn + {0xB56C0000u, 55u}, // mln -> Latn + {0xB96C0000u, 55u}, // mlo -> Latn + {0xBD6C0000u, 55u}, // mlp -> Latn + {0xC16C0000u, 55u}, // mlq -> Latn + {0xC56C0000u, 55u}, // mlr -> Latn + {0xC96C0000u, 55u}, // mls -> Latn + {0xD16C0000u, 55u}, // mlu -> Latn + {0xD56C0000u, 55u}, // mlv -> Latn + {0xD96C0000u, 55u}, // mlw -> Latn + {0xDD6C0000u, 55u}, // mlx -> Latn + {0xE56C0000u, 55u}, // mlz -> Latn + {0x818C0000u, 55u}, // mma -> Latn + {0x858C0000u, 55u}, // mmb -> Latn + {0x898C0000u, 55u}, // mmc -> Latn + {0x8D8C0000u, 55u}, // mmd -> Latn + {0x918C0000u, 55u}, // mme -> Latn + {0x958C0000u, 55u}, // mmf -> Latn + {0x998C0000u, 55u}, // mmg -> Latn + {0x9D8C0000u, 55u}, // mmh -> Latn + {0xA18C0000u, 55u}, // mmi -> Latn + {0xB18C0000u, 55u}, // mmm -> Latn + {0xB58C0000u, 55u}, // mmn -> Latn + {0xB98C0000u, 55u}, // mmo -> Latn + {0xBD8C0000u, 55u}, // mmp -> Latn + {0xC18C0000u, 55u}, // mmq -> Latn + {0xC58C0000u, 55u}, // mmr -> Latn + {0xCD8C0000u, 55u}, // mmt -> Latn + {0xD18C0000u, 55u}, // mmu -> Latn + {0xD58C0000u, 55u}, // mmv -> Latn + {0xD98C0000u, 55u}, // mmw -> Latn + {0xDD8C0000u, 55u}, // mmx -> Latn + {0xE18C0000u, 55u}, // mmy -> Latn + {0xE58C0000u, 55u}, // mmz -> Latn + {0x6D6E0000u, 20u}, // mn -> Cyrl + {0x6D6E434Eu, 69u}, // mn-CN -> Mong + {0x81AC0000u, 55u}, // mna -> Latn + {0x85AC0000u, 55u}, // mnb -> Latn + {0x89AC0000u, 69u}, // mnc -> Mong + {0x8DAC0000u, 55u}, // mnd -> Latn + {0x91AC0000u, 55u}, // mne -> Latn + {0x95AC0000u, 55u}, // mnf -> Latn + {0x99AC0000u, 55u}, // mng -> Latn + {0x9DAC0000u, 55u}, // mnh -> Latn + {0xA1AC0000u, 9u}, // mni -> Beng + {0xA5AC0000u, 2u}, // mnj -> Arab + {0xADAC0000u, 55u}, // mnl -> Latn + {0xB1AC0000u, 55u}, // mnm -> Latn + {0xB5AC0000u, 55u}, // mnn -> Latn + {0xBDAC0000u, 55u}, // mnp -> Latn + {0xC1AC0000u, 55u}, // mnq -> Latn + {0xC5AC0000u, 55u}, // mnr -> Latn + {0xC9AC0000u, 20u}, // mns -> Cyrl + {0xD1AC0000u, 55u}, // mnu -> Latn + {0xD5AC0000u, 55u}, // mnv -> Latn + {0xD9AC0000u, 72u}, // mnw -> Mymr + {0xDDAC0000u, 55u}, // mnx -> Latn + {0xE1AC0000u, 55u}, // mny -> Latn + {0xE5AC0000u, 55u}, // mnz -> Latn + {0x6D6F0000u, 55u}, // mo -> Latn + {0x81CC0000u, 55u}, // moa -> Latn + {0x89CC0000u, 55u}, // moc -> Latn + {0x8DCC0000u, 55u}, // mod -> Latn + {0x91CC0000u, 55u}, // moe -> Latn + {0x99CC0000u, 55u}, // mog -> Latn + {0x9DCC0000u, 55u}, // moh -> Latn + {0xA1CC0000u, 55u}, // moi -> Latn + {0xA5CC0000u, 55u}, // moj -> Latn + {0xA9CC0000u, 55u}, // mok -> Latn + {0xB1CC0000u, 55u}, // mom -> Latn + {0xB9CC0000u, 55u}, // moo -> Latn + {0xBDCC0000u, 55u}, // mop -> Latn + {0xC1CC0000u, 55u}, // moq -> Latn + {0xC5CC0000u, 55u}, // mor -> Latn + {0xC9CC0000u, 55u}, // mos -> Latn + {0xCDCC0000u, 55u}, // mot -> Latn + {0xD1CC0000u, 55u}, // mou -> Latn + {0xD5CC0000u, 55u}, // mov -> Latn + {0xD9CC0000u, 55u}, // mow -> Latn + {0xDDCC0000u, 55u}, // mox -> Latn + {0xE1CC0000u, 55u}, // moy -> Latn + {0xE5CC0000u, 55u}, // moz -> Latn + {0x81EC0000u, 55u}, // mpa -> Latn + {0x85EC0000u, 55u}, // mpb -> Latn + {0x89EC0000u, 55u}, // mpc -> Latn + {0x8DEC0000u, 55u}, // mpd -> Latn + {0x91EC0000u, 55u}, // mpe -> Latn + {0x99EC0000u, 55u}, // mpg -> Latn + {0x9DEC0000u, 55u}, // mph -> Latn + {0xA1EC0000u, 55u}, // mpi -> Latn + {0xA5EC0000u, 55u}, // mpj -> Latn + {0xA9EC0000u, 55u}, // mpk -> Latn + {0xADEC0000u, 55u}, // mpl -> Latn + {0xB1EC0000u, 55u}, // mpm -> Latn + {0xB5EC0000u, 55u}, // mpn -> Latn + {0xB9EC0000u, 55u}, // mpo -> Latn + {0xBDEC0000u, 55u}, // mpp -> Latn + {0xC1EC0000u, 55u}, // mpq -> Latn + {0xC5EC0000u, 55u}, // mpr -> Latn + {0xC9EC0000u, 55u}, // mps -> Latn + {0xCDEC0000u, 55u}, // mpt -> Latn + {0xD1EC0000u, 55u}, // mpu -> Latn + {0xD5EC0000u, 55u}, // mpv -> Latn + {0xD9EC0000u, 55u}, // mpw -> Latn + {0xDDEC0000u, 55u}, // mpx -> Latn + {0xE1EC0000u, 55u}, // mpy -> Latn + {0xE5EC0000u, 111u}, // mpz -> Thai + {0x820C0000u, 55u}, // mqa -> Latn + {0x860C0000u, 55u}, // mqb -> Latn + {0x8A0C0000u, 55u}, // mqc -> Latn + {0x920C0000u, 55u}, // mqe -> Latn + {0x960C0000u, 55u}, // mqf -> Latn + {0x9A0C0000u, 55u}, // mqg -> Latn + {0x9E0C0000u, 55u}, // mqh -> Latn + {0xA20C0000u, 55u}, // mqi -> Latn + {0xA60C0000u, 55u}, // mqj -> Latn + {0xAA0C0000u, 55u}, // mqk -> Latn + {0xAE0C0000u, 55u}, // mql -> Latn + {0xB20C0000u, 55u}, // mqm -> Latn + {0xB60C0000u, 55u}, // mqn -> Latn + {0xBA0C0000u, 55u}, // mqo -> Latn + {0xBE0C0000u, 55u}, // mqp -> Latn + {0xC20C0000u, 55u}, // mqq -> Latn + {0xC60C0000u, 55u}, // mqr -> Latn + {0xCA0C0000u, 55u}, // mqs -> Latn + {0xD20C0000u, 55u}, // mqu -> Latn + {0xD60C0000u, 55u}, // mqv -> Latn + {0xDA0C0000u, 55u}, // mqw -> Latn + {0xDE0C0000u, 55u}, // mqx -> Latn + {0xE20C0000u, 55u}, // mqy -> Latn + {0xE60C0000u, 55u}, // mqz -> Latn + {0x6D720000u, 21u}, // mr -> Deva + {0x822C0000u, 111u}, // mra -> Thai + {0x862C0000u, 55u}, // mrb -> Latn + {0x8A2C0000u, 55u}, // mrc -> Latn + {0x8E2C0000u, 21u}, // mrd -> Deva + {0x962C0000u, 55u}, // mrf -> Latn + {0x9A2C0000u, 55u}, // mrg -> Latn + {0x9E2C0000u, 55u}, // mrh -> Latn + {0xA62C0000u, 20u}, // mrj -> Cyrl + {0xAA2C0000u, 55u}, // mrk -> Latn + {0xAE2C0000u, 55u}, // mrl -> Latn + {0xB22C0000u, 55u}, // mrm -> Latn + {0xB62C0000u, 55u}, // mrn -> Latn + {0xBA2C0000u, 70u}, // mro -> Mroo + {0xBE2C0000u, 55u}, // mrp -> Latn + {0xC22C0000u, 55u}, // mrq -> Latn + {0xC62C0000u, 21u}, // mrr -> Deva + {0xCA2C0000u, 55u}, // mrs -> Latn + {0xCE2C0000u, 55u}, // mrt -> Latn + {0xD22C0000u, 55u}, // mru -> Latn + {0xD62C0000u, 55u}, // mrv -> Latn + {0xDA2C0000u, 55u}, // mrw -> Latn + {0xDE2C0000u, 55u}, // mrx -> Latn + {0xE22C0000u, 55u}, // mry -> Latn + {0xE62C0000u, 55u}, // mrz -> Latn + {0x6D730000u, 55u}, // ms -> Latn {0x6D734343u, 2u}, // ms-CC -> Arab - {0x6D740000u, 46u}, // mt -> Latn - {0x8A6C0000u, 46u}, // mtc -> Latn - {0x966C0000u, 46u}, // mtf -> Latn - {0xA26C0000u, 46u}, // mti -> Latn - {0xC66C0000u, 19u}, // mtr -> Deva - {0x828C0000u, 46u}, // mua -> Latn - {0xC68C0000u, 46u}, // mur -> Latn - {0xCA8C0000u, 46u}, // mus -> Latn - {0x82AC0000u, 46u}, // mva -> Latn - {0xB6AC0000u, 46u}, // mvn -> Latn + {0x864C0000u, 55u}, // msb -> Latn + {0x8A4C0000u, 55u}, // msc -> Latn + {0x924C0000u, 55u}, // mse -> Latn + {0x964C0000u, 55u}, // msf -> Latn + {0x9A4C0000u, 55u}, // msg -> Latn + {0x9E4C0000u, 55u}, // msh -> Latn + {0xA24C0000u, 55u}, // msi -> Latn + {0xA64C0000u, 55u}, // msj -> Latn + {0xAA4C0000u, 55u}, // msk -> Latn + {0xAE4C0000u, 55u}, // msl -> Latn + {0xB24C0000u, 55u}, // msm -> Latn + {0xB64C0000u, 55u}, // msn -> Latn + {0xBA4C0000u, 55u}, // mso -> Latn + {0xBE4C0000u, 55u}, // msp -> Latn + {0xC24C0000u, 55u}, // msq -> Latn + {0xCA4C0000u, 55u}, // mss -> Latn + {0xD24C0000u, 55u}, // msu -> Latn + {0xD64C0000u, 55u}, // msv -> Latn + {0xDA4C0000u, 55u}, // msw -> Latn + {0xDE4C0000u, 55u}, // msx -> Latn + {0xE24C0000u, 55u}, // msy -> Latn + {0xE64C0000u, 55u}, // msz -> Latn + {0x6D740000u, 55u}, // mt -> Latn + {0x826C0000u, 55u}, // mta -> Latn + {0x866C0000u, 55u}, // mtb -> Latn + {0x8A6C0000u, 55u}, // mtc -> Latn + {0x8E6C0000u, 55u}, // mtd -> Latn + {0x926C0000u, 55u}, // mte -> Latn + {0x966C0000u, 55u}, // mtf -> Latn + {0x9A6C0000u, 55u}, // mtg -> Latn + {0x9E6C0000u, 55u}, // mth -> Latn + {0xA26C0000u, 55u}, // mti -> Latn + {0xA66C0000u, 55u}, // mtj -> Latn + {0xAA6C0000u, 55u}, // mtk -> Latn + {0xAE6C0000u, 55u}, // mtl -> Latn + {0xB26C0000u, 20u}, // mtm -> Cyrl + {0xB66C0000u, 55u}, // mtn -> Latn + {0xBA6C0000u, 55u}, // mto -> Latn + {0xBE6C0000u, 55u}, // mtp -> Latn + {0xC26C0000u, 55u}, // mtq -> Latn + {0xC66C0000u, 21u}, // mtr -> Deva + {0xCA6C0000u, 55u}, // mts -> Latn + {0xCE6C0000u, 55u}, // mtt -> Latn + {0xD26C0000u, 55u}, // mtu -> Latn + {0xD66C0000u, 55u}, // mtv -> Latn + {0xDA6C0000u, 55u}, // mtw -> Latn + {0xDE6C0000u, 55u}, // mtx -> Latn + {0xE26C0000u, 55u}, // mty -> Latn + {0x828C0000u, 55u}, // mua -> Latn + {0x868C0000u, 55u}, // mub -> Latn + {0x8A8C0000u, 55u}, // muc -> Latn + {0x8E8C0000u, 20u}, // mud -> Cyrl + {0x928C0000u, 55u}, // mue -> Latn + {0x9A8C0000u, 55u}, // mug -> Latn + {0x9E8C0000u, 55u}, // muh -> Latn + {0xA28C0000u, 55u}, // mui -> Latn + {0xA68C0000u, 55u}, // muj -> Latn + {0xAA8C0000u, 112u}, // muk -> Tibt + {0xB28C0000u, 55u}, // mum -> Latn + {0xBA8C0000u, 55u}, // muo -> Latn + {0xC28C0000u, 55u}, // muq -> Latn + {0xC68C0000u, 55u}, // mur -> Latn + {0xCA8C0000u, 55u}, // mus -> Latn + {0xCE8C0000u, 21u}, // mut -> Deva + {0xD28C0000u, 55u}, // muu -> Latn + {0xD68C0000u, 105u}, // muv -> Taml + {0xDE8C0000u, 55u}, // mux -> Latn + {0xE28C0000u, 55u}, // muy -> Latn + {0xE68C0000u, 24u}, // muz -> Ethi + {0x82AC0000u, 55u}, // mva -> Latn + {0x8EAC0000u, 55u}, // mvd -> Latn + {0x92AC0000u, 2u}, // mve -> Arab + {0x96AC0000u, 69u}, // mvf -> Mong + {0x9AAC0000u, 55u}, // mvg -> Latn + {0x9EAC0000u, 55u}, // mvh -> Latn + {0xAAAC0000u, 55u}, // mvk -> Latn + {0xAEAC0000u, 55u}, // mvl -> Latn + {0xB6AC0000u, 55u}, // mvn -> Latn + {0xBAAC0000u, 55u}, // mvo -> Latn + {0xBEAC0000u, 55u}, // mvp -> Latn + {0xC2AC0000u, 55u}, // mvq -> Latn + {0xC6AC0000u, 55u}, // mvr -> Latn + {0xCAAC0000u, 55u}, // mvs -> Latn + {0xCEAC0000u, 55u}, // mvt -> Latn + {0xD2AC0000u, 55u}, // mvu -> Latn + {0xD6AC0000u, 55u}, // mvv -> Latn + {0xDAAC0000u, 55u}, // mvw -> Latn + {0xDEAC0000u, 55u}, // mvx -> Latn {0xE2AC0000u, 2u}, // mvy -> Arab - {0xAACC0000u, 46u}, // mwk -> Latn - {0xC6CC0000u, 19u}, // mwr -> Deva - {0xD6CC0000u, 46u}, // mwv -> Latn - {0xDACC0000u, 33u}, // mww -> Hmnp - {0x8AEC0000u, 46u}, // mxc -> Latn - {0xB2EC0000u, 46u}, // mxm -> Latn - {0x6D790000u, 59u}, // my -> Mymr - {0xAB0C0000u, 46u}, // myk -> Latn - {0xB30C0000u, 21u}, // mym -> Ethi - {0xD70C0000u, 18u}, // myv -> Cyrl - {0xDB0C0000u, 46u}, // myw -> Latn - {0xDF0C0000u, 46u}, // myx -> Latn - {0xE70C0000u, 52u}, // myz -> Mand - {0xAB2C0000u, 46u}, // mzk -> Latn - {0xB32C0000u, 46u}, // mzm -> Latn + {0xE6AC0000u, 24u}, // mvz -> Ethi + {0x82CC0000u, 55u}, // mwa -> Latn + {0x86CC0000u, 55u}, // mwb -> Latn + {0x8ACC0000u, 55u}, // mwc -> Latn + {0x92CC0000u, 55u}, // mwe -> Latn + {0x96CC0000u, 55u}, // mwf -> Latn + {0x9ACC0000u, 55u}, // mwg -> Latn + {0x9ECC0000u, 55u}, // mwh -> Latn + {0xA2CC0000u, 55u}, // mwi -> Latn + {0xAACC0000u, 55u}, // mwk -> Latn + {0xAECC0000u, 55u}, // mwl -> Latn + {0xB2CC0000u, 55u}, // mwm -> Latn + {0xB6CC0000u, 55u}, // mwn -> Latn + {0xBACC0000u, 55u}, // mwo -> Latn + {0xBECC0000u, 55u}, // mwp -> Latn + {0xC2CC0000u, 55u}, // mwq -> Latn + {0xC6CC0000u, 21u}, // mwr -> Deva + {0xCACC0000u, 55u}, // mws -> Latn + {0xCECC0000u, 72u}, // mwt -> Mymr + {0xD2CC0000u, 55u}, // mwu -> Latn + {0xD6CC0000u, 55u}, // mwv -> Latn + {0xDACC0000u, 39u}, // mww -> Hmnp + {0xE6CC0000u, 55u}, // mwz -> Latn + {0x82EC0000u, 55u}, // mxa -> Latn + {0x86EC0000u, 55u}, // mxb -> Latn + {0x8AEC0000u, 55u}, // mxc -> Latn + {0x8EEC0000u, 55u}, // mxd -> Latn + {0x92EC0000u, 55u}, // mxe -> Latn + {0x96EC0000u, 55u}, // mxf -> Latn + {0x9AEC0000u, 55u}, // mxg -> Latn + {0x9EEC0000u, 55u}, // mxh -> Latn + {0xA2EC0000u, 55u}, // mxi -> Latn + {0xA6EC0000u, 55u}, // mxj -> Latn + {0xAAEC0000u, 55u}, // mxk -> Latn + {0xAEEC0000u, 55u}, // mxl -> Latn + {0xB2EC0000u, 55u}, // mxm -> Latn + {0xB6EC0000u, 55u}, // mxn -> Latn + {0xBAEC0000u, 55u}, // mxo -> Latn + {0xBEEC0000u, 55u}, // mxp -> Latn + {0xC2EC0000u, 55u}, // mxq -> Latn + {0xC6EC0000u, 55u}, // mxr -> Latn + {0xCAEC0000u, 55u}, // mxs -> Latn + {0xCEEC0000u, 55u}, // mxt -> Latn + {0xD2EC0000u, 55u}, // mxu -> Latn + {0xD6EC0000u, 55u}, // mxv -> Latn + {0xDAEC0000u, 55u}, // mxw -> Latn + {0xDEEC0000u, 55u}, // mxx -> Latn + {0xE2EC0000u, 55u}, // mxy -> Latn + {0xE6EC0000u, 55u}, // mxz -> Latn + {0x6D790000u, 72u}, // my -> Mymr + {0x870C0000u, 55u}, // myb -> Latn + {0x8B0C0000u, 55u}, // myc -> Latn + {0x930C0000u, 55u}, // mye -> Latn + {0x970C0000u, 55u}, // myf -> Latn + {0x9B0C0000u, 55u}, // myg -> Latn + {0x9F0C0000u, 55u}, // myh -> Latn + {0xA70C0000u, 55u}, // myj -> Latn + {0xAB0C0000u, 55u}, // myk -> Latn + {0xAF0C0000u, 55u}, // myl -> Latn + {0xB30C0000u, 24u}, // mym -> Ethi + {0xBF0C0000u, 55u}, // myp -> Latn + {0xC70C0000u, 55u}, // myr -> Latn + {0xD30C0000u, 55u}, // myu -> Latn + {0xD70C0000u, 20u}, // myv -> Cyrl + {0xDB0C0000u, 55u}, // myw -> Latn + {0xDF0C0000u, 55u}, // myx -> Latn + {0xE30C0000u, 55u}, // myy -> Latn + {0xE70C0000u, 62u}, // myz -> Mand + {0x832C0000u, 55u}, // mza -> Latn + {0x8F2C0000u, 55u}, // mzd -> Latn + {0x932C0000u, 55u}, // mze -> Latn + {0x9F2C0000u, 55u}, // mzh -> Latn + {0xA32C0000u, 55u}, // mzi -> Latn + {0xA72C0000u, 55u}, // mzj -> Latn + {0xAB2C0000u, 55u}, // mzk -> Latn + {0xAF2C0000u, 55u}, // mzl -> Latn + {0xB32C0000u, 55u}, // mzm -> Latn {0xB72C0000u, 2u}, // mzn -> Arab - {0xBF2C0000u, 46u}, // mzp -> Latn - {0xDB2C0000u, 46u}, // mzw -> Latn - {0xE72C0000u, 46u}, // mzz -> Latn - {0x6E610000u, 46u}, // na -> Latn - {0x880D0000u, 46u}, // nac -> Latn - {0x940D0000u, 46u}, // naf -> Latn - {0xA80D0000u, 46u}, // nak -> Latn - {0xB40D0000u, 29u}, // nan -> Hans - {0xBC0D0000u, 46u}, // nap -> Latn - {0xC00D0000u, 46u}, // naq -> Latn - {0xC80D0000u, 46u}, // nas -> Latn - {0x6E620000u, 46u}, // nb -> Latn - {0x804D0000u, 46u}, // nca -> Latn - {0x904D0000u, 46u}, // nce -> Latn - {0x944D0000u, 46u}, // ncf -> Latn - {0x9C4D0000u, 46u}, // nch -> Latn - {0xB84D0000u, 46u}, // nco -> Latn - {0xD04D0000u, 46u}, // ncu -> Latn - {0x6E640000u, 46u}, // nd -> Latn - {0x886D0000u, 46u}, // ndc -> Latn - {0xC86D0000u, 46u}, // nds -> Latn - {0x6E650000u, 19u}, // ne -> Deva - {0x848D0000u, 46u}, // neb -> Latn - {0xD88D0000u, 19u}, // new -> Deva - {0xDC8D0000u, 46u}, // nex -> Latn - {0xC4AD0000u, 46u}, // nfr -> Latn - {0x6E670000u, 46u}, // ng -> Latn - {0x80CD0000u, 46u}, // nga -> Latn - {0x84CD0000u, 46u}, // ngb -> Latn - {0xACCD0000u, 46u}, // ngl -> Latn - {0x84ED0000u, 46u}, // nhb -> Latn - {0x90ED0000u, 46u}, // nhe -> Latn - {0xD8ED0000u, 46u}, // nhw -> Latn - {0x950D0000u, 46u}, // nif -> Latn - {0xA10D0000u, 46u}, // nii -> Latn - {0xA50D0000u, 46u}, // nij -> Latn - {0xB50D0000u, 46u}, // nin -> Latn - {0xD10D0000u, 46u}, // niu -> Latn - {0xE10D0000u, 46u}, // niy -> Latn - {0xE50D0000u, 46u}, // niz -> Latn - {0xB92D0000u, 46u}, // njo -> Latn - {0x994D0000u, 46u}, // nkg -> Latn - {0xB94D0000u, 46u}, // nko -> Latn - {0x6E6C0000u, 46u}, // nl -> Latn - {0x998D0000u, 46u}, // nmg -> Latn - {0xE58D0000u, 46u}, // nmz -> Latn - {0x6E6E0000u, 46u}, // nn -> Latn - {0x95AD0000u, 46u}, // nnf -> Latn - {0x9DAD0000u, 46u}, // nnh -> Latn - {0xA9AD0000u, 46u}, // nnk -> Latn - {0xB1AD0000u, 46u}, // nnm -> Latn - {0xBDAD0000u, 99u}, // nnp -> Wcho - {0x6E6F0000u, 46u}, // no -> Latn - {0x8DCD0000u, 44u}, // nod -> Lana - {0x91CD0000u, 19u}, // noe -> Deva - {0xB5CD0000u, 75u}, // non -> Runr - {0xBDCD0000u, 46u}, // nop -> Latn - {0xD1CD0000u, 46u}, // nou -> Latn - {0xBA0D0000u, 61u}, // nqo -> Nkoo - {0x6E720000u, 46u}, // nr -> Latn - {0x862D0000u, 46u}, // nrb -> Latn - {0xAA4D0000u, 11u}, // nsk -> Cans - {0xB64D0000u, 46u}, // nsn -> Latn - {0xBA4D0000u, 46u}, // nso -> Latn - {0xCA4D0000u, 46u}, // nss -> Latn - {0xCE4D0000u, 95u}, // nst -> Tnsa - {0xB26D0000u, 46u}, // ntm -> Latn - {0xC66D0000u, 46u}, // ntr -> Latn - {0xA28D0000u, 46u}, // nui -> Latn - {0xBE8D0000u, 46u}, // nup -> Latn - {0xCA8D0000u, 46u}, // nus -> Latn - {0xD68D0000u, 46u}, // nuv -> Latn - {0xDE8D0000u, 46u}, // nux -> Latn - {0x6E760000u, 46u}, // nv -> Latn - {0x86CD0000u, 46u}, // nwb -> Latn - {0xC2ED0000u, 46u}, // nxq -> Latn - {0xC6ED0000u, 46u}, // nxr -> Latn - {0x6E790000u, 46u}, // ny -> Latn - {0xB30D0000u, 46u}, // nym -> Latn - {0xB70D0000u, 46u}, // nyn -> Latn - {0xA32D0000u, 46u}, // nzi -> Latn - {0x6F630000u, 46u}, // oc -> Latn - {0x6F634553u, 46u}, // oc-ES -> Latn - {0x88CE0000u, 46u}, // ogc -> Latn - {0x6F6A0000u, 11u}, // oj -> Cans - {0xC92E0000u, 11u}, // ojs -> Cans - {0x814E0000u, 46u}, // oka -> Latn - {0xC54E0000u, 46u}, // okr -> Latn - {0xD54E0000u, 46u}, // okv -> Latn - {0x6F6D0000u, 46u}, // om -> Latn - {0x99AE0000u, 46u}, // ong -> Latn - {0xB5AE0000u, 46u}, // onn -> Latn - {0xC9AE0000u, 46u}, // ons -> Latn - {0xB1EE0000u, 46u}, // opm -> Latn - {0x6F720000u, 66u}, // or -> Orya - {0xBA2E0000u, 46u}, // oro -> Latn + {0xBB2C0000u, 55u}, // mzo -> Latn + {0xBF2C0000u, 55u}, // mzp -> Latn + {0xC32C0000u, 55u}, // mzq -> Latn + {0xC72C0000u, 55u}, // mzr -> Latn + {0xCF2C0000u, 55u}, // mzt -> Latn + {0xD32C0000u, 55u}, // mzu -> Latn + {0xD72C0000u, 55u}, // mzv -> Latn + {0xDB2C0000u, 55u}, // mzw -> Latn + {0xDF2C0000u, 55u}, // mzx -> Latn + {0xE72C0000u, 55u}, // mzz -> Latn + {0x6E610000u, 55u}, // na -> Latn + {0x800D0000u, 55u}, // naa -> Latn + {0x840D0000u, 55u}, // nab -> Latn + {0x880D0000u, 55u}, // nac -> Latn + {0x900D0000u, 55u}, // nae -> Latn + {0x940D0000u, 55u}, // naf -> Latn + {0x980D0000u, 55u}, // nag -> Latn + {0xA40D0000u, 55u}, // naj -> Latn + {0xA80D0000u, 55u}, // nak -> Latn + {0xAC0D0000u, 55u}, // nal -> Latn + {0xB00D0000u, 55u}, // nam -> Latn + {0xB40D0000u, 35u}, // nan -> Hans + {0xB80D0000u, 21u}, // nao -> Deva + {0xBC0D0000u, 55u}, // nap -> Latn + {0xC00D0000u, 55u}, // naq -> Latn + {0xC40D0000u, 55u}, // nar -> Latn + {0xC80D0000u, 55u}, // nas -> Latn + {0xCC0D0000u, 55u}, // nat -> Latn + {0xD80D0000u, 55u}, // naw -> Latn + {0xDC0D0000u, 55u}, // nax -> Latn + {0xE00D0000u, 55u}, // nay -> Latn + {0xE40D0000u, 55u}, // naz -> Latn + {0x6E620000u, 55u}, // nb -> Latn + {0x802D0000u, 55u}, // nba -> Latn + {0x842D0000u, 55u}, // nbb -> Latn + {0x882D0000u, 55u}, // nbc -> Latn + {0x8C2D0000u, 55u}, // nbd -> Latn + {0x902D0000u, 55u}, // nbe -> Latn + {0x9C2D0000u, 55u}, // nbh -> Latn + {0xA02D0000u, 55u}, // nbi -> Latn + {0xA42D0000u, 55u}, // nbj -> Latn + {0xA82D0000u, 55u}, // nbk -> Latn + {0xB02D0000u, 55u}, // nbm -> Latn + {0xB42D0000u, 55u}, // nbn -> Latn + {0xB82D0000u, 55u}, // nbo -> Latn + {0xBC2D0000u, 55u}, // nbp -> Latn + {0xC02D0000u, 55u}, // nbq -> Latn + {0xC42D0000u, 55u}, // nbr -> Latn + {0xCC2D0000u, 55u}, // nbt -> Latn + {0xD02D0000u, 55u}, // nbu -> Latn + {0xD42D0000u, 55u}, // nbv -> Latn + {0xD82D0000u, 55u}, // nbw -> Latn + {0xE02D0000u, 55u}, // nby -> Latn + {0x804D0000u, 55u}, // nca -> Latn + {0x844D0000u, 55u}, // ncb -> Latn + {0x884D0000u, 55u}, // ncc -> Latn + {0x8C4D0000u, 21u}, // ncd -> Deva + {0x904D0000u, 55u}, // nce -> Latn + {0x944D0000u, 55u}, // ncf -> Latn + {0x984D0000u, 55u}, // ncg -> Latn + {0x9C4D0000u, 55u}, // nch -> Latn + {0xA04D0000u, 55u}, // nci -> Latn + {0xA44D0000u, 55u}, // ncj -> Latn + {0xA84D0000u, 55u}, // nck -> Latn + {0xAC4D0000u, 55u}, // ncl -> Latn + {0xB04D0000u, 55u}, // ncm -> Latn + {0xB44D0000u, 55u}, // ncn -> Latn + {0xB84D0000u, 55u}, // nco -> Latn + {0xC04D0000u, 52u}, // ncq -> Laoo + {0xC44D0000u, 55u}, // ncr -> Latn + {0xCC4D0000u, 55u}, // nct -> Latn + {0xD04D0000u, 55u}, // ncu -> Latn + {0xDC4D0000u, 55u}, // ncx -> Latn + {0xE44D0000u, 55u}, // ncz -> Latn + {0x6E640000u, 55u}, // nd -> Latn + {0x806D0000u, 55u}, // nda -> Latn + {0x846D0000u, 55u}, // ndb -> Latn + {0x886D0000u, 55u}, // ndc -> Latn + {0x8C6D0000u, 55u}, // ndd -> Latn + {0x946D0000u, 20u}, // ndf -> Cyrl + {0x986D0000u, 55u}, // ndg -> Latn + {0x9C6D0000u, 55u}, // ndh -> Latn + {0xA06D0000u, 55u}, // ndi -> Latn + {0xA46D0000u, 55u}, // ndj -> Latn + {0xA86D0000u, 55u}, // ndk -> Latn + {0xAC6D0000u, 55u}, // ndl -> Latn + {0xB06D0000u, 55u}, // ndm -> Latn + {0xB46D0000u, 55u}, // ndn -> Latn + {0xBC6D0000u, 55u}, // ndp -> Latn + {0xC06D0000u, 55u}, // ndq -> Latn + {0xC46D0000u, 55u}, // ndr -> Latn + {0xC86D0000u, 55u}, // nds -> Latn + {0xCC6D0000u, 55u}, // ndt -> Latn + {0xD06D0000u, 55u}, // ndu -> Latn + {0xD46D0000u, 55u}, // ndv -> Latn + {0xD86D0000u, 55u}, // ndw -> Latn + {0xDC6D0000u, 55u}, // ndx -> Latn + {0xE06D0000u, 55u}, // ndy -> Latn + {0xE46D0000u, 55u}, // ndz -> Latn + {0x6E650000u, 21u}, // ne -> Deva + {0x808D0000u, 55u}, // nea -> Latn + {0x848D0000u, 55u}, // neb -> Latn + {0x888D0000u, 55u}, // nec -> Latn + {0x8C8D0000u, 55u}, // ned -> Latn + {0x908D0000u, 55u}, // nee -> Latn + {0x988D0000u, 20u}, // neg -> Cyrl + {0x9C8D0000u, 112u}, // neh -> Tibt + {0xA08D0000u, 119u}, // nei -> Xsux + {0xA48D0000u, 55u}, // nej -> Latn + {0xA88D0000u, 55u}, // nek -> Latn + {0xB08D0000u, 55u}, // nem -> Latn + {0xB48D0000u, 55u}, // nen -> Latn + {0xB88D0000u, 55u}, // neo -> Latn + {0xC08D0000u, 55u}, // neq -> Latn + {0xC48D0000u, 55u}, // ner -> Latn + {0xCC8D0000u, 55u}, // net -> Latn + {0xD08D0000u, 55u}, // neu -> Latn + {0xD88D0000u, 21u}, // new -> Deva + {0xDC8D0000u, 55u}, // nex -> Latn + {0xE08D0000u, 55u}, // ney -> Latn + {0xE48D0000u, 55u}, // nez -> Latn + {0x80AD0000u, 55u}, // nfa -> Latn + {0x8CAD0000u, 55u}, // nfd -> Latn + {0xACAD0000u, 55u}, // nfl -> Latn + {0xC4AD0000u, 55u}, // nfr -> Latn + {0xD0AD0000u, 55u}, // nfu -> Latn + {0x6E670000u, 55u}, // ng -> Latn + {0x80CD0000u, 55u}, // nga -> Latn + {0x84CD0000u, 55u}, // ngb -> Latn + {0x88CD0000u, 55u}, // ngc -> Latn + {0x8CCD0000u, 55u}, // ngd -> Latn + {0x90CD0000u, 55u}, // nge -> Latn + {0x98CD0000u, 55u}, // ngg -> Latn + {0x9CCD0000u, 55u}, // ngh -> Latn + {0xA0CD0000u, 55u}, // ngi -> Latn + {0xA4CD0000u, 55u}, // ngj -> Latn + {0xA8CD0000u, 55u}, // ngk -> Latn + {0xACCD0000u, 55u}, // ngl -> Latn + {0xB0CD0000u, 55u}, // ngm -> Latn + {0xB4CD0000u, 55u}, // ngn -> Latn + {0xBCCD0000u, 55u}, // ngp -> Latn + {0xC0CD0000u, 55u}, // ngq -> Latn + {0xC4CD0000u, 55u}, // ngr -> Latn + {0xC8CD0000u, 55u}, // ngs -> Latn + {0xCCCD0000u, 52u}, // ngt -> Laoo + {0xD0CD0000u, 55u}, // ngu -> Latn + {0xD4CD0000u, 55u}, // ngv -> Latn + {0xD8CD0000u, 55u}, // ngw -> Latn + {0xDCCD0000u, 55u}, // ngx -> Latn + {0xE0CD0000u, 55u}, // ngy -> Latn + {0xE4CD0000u, 55u}, // ngz -> Latn + {0x80ED0000u, 55u}, // nha -> Latn + {0x84ED0000u, 55u}, // nhb -> Latn + {0x88ED0000u, 55u}, // nhc -> Latn + {0x8CED0000u, 55u}, // nhd -> Latn + {0x90ED0000u, 55u}, // nhe -> Latn + {0x94ED0000u, 55u}, // nhf -> Latn + {0x98ED0000u, 55u}, // nhg -> Latn + {0xA0ED0000u, 55u}, // nhi -> Latn + {0xA8ED0000u, 55u}, // nhk -> Latn + {0xB0ED0000u, 55u}, // nhm -> Latn + {0xB4ED0000u, 55u}, // nhn -> Latn + {0xB8ED0000u, 55u}, // nho -> Latn + {0xBCED0000u, 55u}, // nhp -> Latn + {0xC0ED0000u, 55u}, // nhq -> Latn + {0xC4ED0000u, 55u}, // nhr -> Latn + {0xCCED0000u, 55u}, // nht -> Latn + {0xD0ED0000u, 55u}, // nhu -> Latn + {0xD4ED0000u, 55u}, // nhv -> Latn + {0xD8ED0000u, 55u}, // nhw -> Latn + {0xDCED0000u, 55u}, // nhx -> Latn + {0xE0ED0000u, 55u}, // nhy -> Latn + {0xE4ED0000u, 55u}, // nhz -> Latn + {0x810D0000u, 55u}, // nia -> Latn + {0x850D0000u, 55u}, // nib -> Latn + {0x8D0D0000u, 55u}, // nid -> Latn + {0x910D0000u, 55u}, // nie -> Latn + {0x950D0000u, 55u}, // nif -> Latn + {0x990D0000u, 55u}, // nig -> Latn + {0x9D0D0000u, 55u}, // nih -> Latn + {0xA10D0000u, 55u}, // nii -> Latn + {0xA50D0000u, 55u}, // nij -> Latn + {0xAD0D0000u, 55u}, // nil -> Latn + {0xB10D0000u, 55u}, // nim -> Latn + {0xB50D0000u, 55u}, // nin -> Latn + {0xB90D0000u, 20u}, // nio -> Cyrl + {0xC10D0000u, 55u}, // niq -> Latn + {0xC50D0000u, 55u}, // nir -> Latn + {0xC90D0000u, 55u}, // nis -> Latn + {0xCD0D0000u, 108u}, // nit -> Telu + {0xD10D0000u, 55u}, // niu -> Latn + {0xD50D0000u, 20u}, // niv -> Cyrl + {0xD90D0000u, 55u}, // niw -> Latn + {0xDD0D0000u, 55u}, // nix -> Latn + {0xE10D0000u, 55u}, // niy -> Latn + {0xE50D0000u, 55u}, // niz -> Latn + {0x812D0000u, 55u}, // nja -> Latn + {0x852D0000u, 55u}, // njb -> Latn + {0x8D2D0000u, 55u}, // njd -> Latn + {0x9D2D0000u, 55u}, // njh -> Latn + {0xA12D0000u, 55u}, // nji -> Latn + {0xA52D0000u, 55u}, // njj -> Latn + {0xAD2D0000u, 55u}, // njl -> Latn + {0xB12D0000u, 55u}, // njm -> Latn + {0xB52D0000u, 55u}, // njn -> Latn + {0xB92D0000u, 55u}, // njo -> Latn + {0xC52D0000u, 55u}, // njr -> Latn + {0xC92D0000u, 55u}, // njs -> Latn + {0xCD2D0000u, 55u}, // njt -> Latn + {0xD12D0000u, 55u}, // nju -> Latn + {0xDD2D0000u, 55u}, // njx -> Latn + {0xE12D0000u, 55u}, // njy -> Latn + {0xE52D0000u, 55u}, // njz -> Latn + {0x814D0000u, 55u}, // nka -> Latn + {0x854D0000u, 55u}, // nkb -> Latn + {0x894D0000u, 55u}, // nkc -> Latn + {0x8D4D0000u, 55u}, // nkd -> Latn + {0x914D0000u, 55u}, // nke -> Latn + {0x954D0000u, 55u}, // nkf -> Latn + {0x994D0000u, 55u}, // nkg -> Latn + {0x9D4D0000u, 55u}, // nkh -> Latn + {0xA14D0000u, 55u}, // nki -> Latn + {0xA54D0000u, 55u}, // nkj -> Latn + {0xA94D0000u, 55u}, // nkk -> Latn + {0xB14D0000u, 55u}, // nkm -> Latn + {0xB54D0000u, 55u}, // nkn -> Latn + {0xB94D0000u, 55u}, // nko -> Latn + {0xC14D0000u, 55u}, // nkq -> Latn + {0xC54D0000u, 55u}, // nkr -> Latn + {0xC94D0000u, 55u}, // nks -> Latn + {0xCD4D0000u, 55u}, // nkt -> Latn + {0xD14D0000u, 55u}, // nku -> Latn + {0xD54D0000u, 55u}, // nkv -> Latn + {0xD94D0000u, 55u}, // nkw -> Latn + {0xDD4D0000u, 55u}, // nkx -> Latn + {0xE54D0000u, 55u}, // nkz -> Latn + {0x6E6C0000u, 55u}, // nl -> Latn + {0x816D0000u, 55u}, // nla -> Latn + {0x896D0000u, 55u}, // nlc -> Latn + {0x916D0000u, 55u}, // nle -> Latn + {0x996D0000u, 55u}, // nlg -> Latn + {0xA16D0000u, 2u}, // nli -> Arab + {0xA56D0000u, 55u}, // nlj -> Latn + {0xA96D0000u, 55u}, // nlk -> Latn + {0xB16D0000u, 2u}, // nlm -> Arab + {0xB96D0000u, 55u}, // nlo -> Latn + {0xC16D0000u, 55u}, // nlq -> Latn + {0xD16D0000u, 55u}, // nlu -> Latn + {0xD56D0000u, 55u}, // nlv -> Latn + {0xD96D0000u, 55u}, // nlw -> Latn + {0xDD6D0000u, 21u}, // nlx -> Deva + {0xE16D0000u, 55u}, // nly -> Latn + {0xE56D0000u, 55u}, // nlz -> Latn + {0x818D0000u, 55u}, // nma -> Latn + {0x858D0000u, 55u}, // nmb -> Latn + {0x898D0000u, 55u}, // nmc -> Latn + {0x8D8D0000u, 55u}, // nmd -> Latn + {0x918D0000u, 55u}, // nme -> Latn + {0x958D0000u, 55u}, // nmf -> Latn + {0x998D0000u, 55u}, // nmg -> Latn + {0x9D8D0000u, 55u}, // nmh -> Latn + {0xA18D0000u, 55u}, // nmi -> Latn + {0xA58D0000u, 55u}, // nmj -> Latn + {0xA98D0000u, 55u}, // nmk -> Latn + {0xAD8D0000u, 55u}, // nml -> Latn + {0xB18D0000u, 21u}, // nmm -> Deva + {0xB58D0000u, 55u}, // nmn -> Latn + {0xB98D0000u, 55u}, // nmo -> Latn + {0xBD8D0000u, 55u}, // nmp -> Latn + {0xC18D0000u, 55u}, // nmq -> Latn + {0xC58D0000u, 55u}, // nmr -> Latn + {0xC98D0000u, 55u}, // nms -> Latn + {0xCD8D0000u, 55u}, // nmt -> Latn + {0xD18D0000u, 55u}, // nmu -> Latn + {0xD58D0000u, 55u}, // nmv -> Latn + {0xD98D0000u, 55u}, // nmw -> Latn + {0xDD8D0000u, 55u}, // nmx -> Latn + {0xE58D0000u, 55u}, // nmz -> Latn + {0x6E6E0000u, 55u}, // nn -> Latn + {0x81AD0000u, 55u}, // nna -> Latn + {0x85AD0000u, 55u}, // nnb -> Latn + {0x89AD0000u, 55u}, // nnc -> Latn + {0x8DAD0000u, 55u}, // nnd -> Latn + {0x91AD0000u, 55u}, // nne -> Latn + {0x95AD0000u, 55u}, // nnf -> Latn + {0x99AD0000u, 55u}, // nng -> Latn + {0x9DAD0000u, 55u}, // nnh -> Latn + {0xA1AD0000u, 55u}, // nni -> Latn + {0xA5AD0000u, 55u}, // nnj -> Latn + {0xA9AD0000u, 55u}, // nnk -> Latn + {0xADAD0000u, 55u}, // nnl -> Latn + {0xB1AD0000u, 55u}, // nnm -> Latn + {0xB5AD0000u, 55u}, // nnn -> Latn + {0xBDAD0000u, 117u}, // nnp -> Wcho + {0xC1AD0000u, 55u}, // nnq -> Latn + {0xC5AD0000u, 55u}, // nnr -> Latn + {0xCDAD0000u, 55u}, // nnt -> Latn + {0xD1AD0000u, 55u}, // nnu -> Latn + {0xD5AD0000u, 55u}, // nnv -> Latn + {0xD9AD0000u, 55u}, // nnw -> Latn + {0xE1AD0000u, 55u}, // nny -> Latn + {0xE5AD0000u, 55u}, // nnz -> Latn + {0x6E6F0000u, 55u}, // no -> Latn + {0x81CD0000u, 55u}, // noa -> Latn + {0x89CD0000u, 55u}, // noc -> Latn + {0x8DCD0000u, 51u}, // nod -> Lana + {0x91CD0000u, 21u}, // noe -> Deva + {0x95CD0000u, 55u}, // nof -> Latn + {0x99CD0000u, 20u}, // nog -> Cyrl + {0x9DCD0000u, 55u}, // noh -> Latn + {0xA1CD0000u, 21u}, // noi -> Deva + {0xA5CD0000u, 55u}, // noj -> Latn + {0xA9CD0000u, 55u}, // nok -> Latn + {0xB5CD0000u, 90u}, // non -> Runr + {0xBDCD0000u, 55u}, // nop -> Latn + {0xC1CD0000u, 55u}, // noq -> Latn + {0xC9CD0000u, 120u}, // nos -> Yiii + {0xCDCD0000u, 55u}, // not -> Latn + {0xD1CD0000u, 55u}, // nou -> Latn + {0xD5CD0000u, 55u}, // nov -> Latn + {0xD9CD0000u, 55u}, // now -> Latn + {0xE1CD0000u, 55u}, // noy -> Latn + {0x85ED0000u, 112u}, // npb -> Tibt + {0x99ED0000u, 55u}, // npg -> Latn + {0x9DED0000u, 55u}, // nph -> Latn + {0xADED0000u, 55u}, // npl -> Latn + {0xB5ED0000u, 55u}, // npn -> Latn + {0xB9ED0000u, 55u}, // npo -> Latn + {0xC9ED0000u, 55u}, // nps -> Latn + {0xD1ED0000u, 55u}, // npu -> Latn + {0xDDED0000u, 55u}, // npx -> Latn + {0xE1ED0000u, 55u}, // npy -> Latn + {0x9A0D0000u, 55u}, // nqg -> Latn + {0xAA0D0000u, 55u}, // nqk -> Latn + {0xAE0D0000u, 55u}, // nql -> Latn + {0xB20D0000u, 55u}, // nqm -> Latn + {0xB60D0000u, 55u}, // nqn -> Latn + {0xBA0D0000u, 75u}, // nqo -> Nkoo + {0xC20D0000u, 55u}, // nqq -> Latn + {0xCE0D0000u, 55u}, // nqt -> Latn + {0xE20D0000u, 55u}, // nqy -> Latn + {0x6E720000u, 55u}, // nr -> Latn + {0x822D0000u, 55u}, // nra -> Latn + {0x862D0000u, 55u}, // nrb -> Latn + {0x922D0000u, 55u}, // nre -> Latn + {0x962D0000u, 55u}, // nrf -> Latn + {0x9A2D0000u, 55u}, // nrg -> Latn + {0xA22D0000u, 55u}, // nri -> Latn + {0xAA2D0000u, 55u}, // nrk -> Latn + {0xAE2D0000u, 55u}, // nrl -> Latn + {0xB22D0000u, 55u}, // nrm -> Latn + {0xB62D0000u, 90u}, // nrn -> Runr + {0xBE2D0000u, 55u}, // nrp -> Latn + {0xD22D0000u, 55u}, // nru -> Latn + {0xDE2D0000u, 55u}, // nrx -> Latn + {0xE62D0000u, 55u}, // nrz -> Latn + {0x824D0000u, 55u}, // nsa -> Latn + {0x864D0000u, 55u}, // nsb -> Latn + {0x8A4D0000u, 55u}, // nsc -> Latn + {0x8E4D0000u, 120u}, // nsd -> Yiii + {0x924D0000u, 55u}, // nse -> Latn + {0x964D0000u, 120u}, // nsf -> Yiii + {0x9A4D0000u, 55u}, // nsg -> Latn + {0x9E4D0000u, 55u}, // nsh -> Latn + {0xAA4D0000u, 13u}, // nsk -> Cans + {0xB24D0000u, 55u}, // nsm -> Latn + {0xB64D0000u, 55u}, // nsn -> Latn + {0xBA4D0000u, 55u}, // nso -> Latn + {0xC24D0000u, 55u}, // nsq -> Latn + {0xCA4D0000u, 55u}, // nss -> Latn + {0xCE4D0000u, 113u}, // nst -> Tnsa + {0xD24D0000u, 55u}, // nsu -> Latn + {0xD64D0000u, 120u}, // nsv -> Yiii + {0xDA4D0000u, 55u}, // nsw -> Latn + {0xDE4D0000u, 55u}, // nsx -> Latn + {0xE24D0000u, 55u}, // nsy -> Latn + {0xE64D0000u, 55u}, // nsz -> Latn + {0x8E6D0000u, 55u}, // ntd -> Latn + {0x926D0000u, 55u}, // nte -> Latn + {0x9A6D0000u, 55u}, // ntg -> Latn + {0xA26D0000u, 55u}, // nti -> Latn + {0xA66D0000u, 55u}, // ntj -> Latn + {0xAA6D0000u, 55u}, // ntk -> Latn + {0xB26D0000u, 55u}, // ntm -> Latn + {0xBA6D0000u, 55u}, // nto -> Latn + {0xBE6D0000u, 55u}, // ntp -> Latn + {0xC66D0000u, 55u}, // ntr -> Latn + {0xD26D0000u, 55u}, // ntu -> Latn + {0xDE6D0000u, 55u}, // ntx -> Latn + {0xE26D0000u, 120u}, // nty -> Yiii + {0xE66D0000u, 2u}, // ntz -> Arab + {0x828D0000u, 55u}, // nua -> Latn + {0x8A8D0000u, 55u}, // nuc -> Latn + {0x8E8D0000u, 55u}, // nud -> Latn + {0x928D0000u, 55u}, // nue -> Latn + {0x968D0000u, 55u}, // nuf -> Latn + {0x9A8D0000u, 55u}, // nug -> Latn + {0x9E8D0000u, 55u}, // nuh -> Latn + {0xA28D0000u, 55u}, // nui -> Latn + {0xA68D0000u, 55u}, // nuj -> Latn + {0xAA8D0000u, 55u}, // nuk -> Latn + {0xB28D0000u, 55u}, // num -> Latn + {0xB68D0000u, 55u}, // nun -> Latn + {0xBA8D0000u, 55u}, // nuo -> Latn + {0xBE8D0000u, 55u}, // nup -> Latn + {0xC28D0000u, 55u}, // nuq -> Latn + {0xC68D0000u, 55u}, // nur -> Latn + {0xCA8D0000u, 55u}, // nus -> Latn + {0xCE8D0000u, 55u}, // nut -> Latn + {0xD28D0000u, 55u}, // nuu -> Latn + {0xD68D0000u, 55u}, // nuv -> Latn + {0xDA8D0000u, 55u}, // nuw -> Latn + {0xDE8D0000u, 55u}, // nux -> Latn + {0xE28D0000u, 55u}, // nuy -> Latn + {0xE68D0000u, 55u}, // nuz -> Latn + {0x6E760000u, 55u}, // nv -> Latn + {0x9EAD0000u, 55u}, // nvh -> Latn + {0xB2AD0000u, 55u}, // nvm -> Latn + {0xBAAD0000u, 55u}, // nvo -> Latn + {0x86CD0000u, 55u}, // nwb -> Latn + {0x8ACD0000u, 74u}, // nwc -> Newa + {0x92CD0000u, 55u}, // nwe -> Latn + {0x9ACD0000u, 55u}, // nwg -> Latn + {0xA2CD0000u, 55u}, // nwi -> Latn + {0xB2CD0000u, 55u}, // nwm -> Latn + {0xBACD0000u, 55u}, // nwo -> Latn + {0xC6CD0000u, 55u}, // nwr -> Latn + {0xDACD0000u, 55u}, // nww -> Latn + {0xDECD0000u, 21u}, // nwx -> Deva + {0x82ED0000u, 55u}, // nxa -> Latn + {0x8EED0000u, 55u}, // nxd -> Latn + {0x92ED0000u, 55u}, // nxe -> Latn + {0x9AED0000u, 55u}, // nxg -> Latn + {0xA2ED0000u, 55u}, // nxi -> Latn + {0xAEED0000u, 55u}, // nxl -> Latn + {0xB6ED0000u, 55u}, // nxn -> Latn + {0xBAED0000u, 55u}, // nxo -> Latn + {0xC2ED0000u, 55u}, // nxq -> Latn + {0xC6ED0000u, 55u}, // nxr -> Latn + {0xDEED0000u, 55u}, // nxx -> Latn + {0x6E790000u, 55u}, // ny -> Latn + {0x870D0000u, 55u}, // nyb -> Latn + {0x8B0D0000u, 55u}, // nyc -> Latn + {0x8F0D0000u, 55u}, // nyd -> Latn + {0x930D0000u, 55u}, // nye -> Latn + {0x970D0000u, 55u}, // nyf -> Latn + {0x9B0D0000u, 55u}, // nyg -> Latn + {0x9F0D0000u, 55u}, // nyh -> Latn + {0xA30D0000u, 55u}, // nyi -> Latn + {0xA70D0000u, 55u}, // nyj -> Latn + {0xAB0D0000u, 55u}, // nyk -> Latn + {0xAF0D0000u, 111u}, // nyl -> Thai + {0xB30D0000u, 55u}, // nym -> Latn + {0xB70D0000u, 55u}, // nyn -> Latn + {0xBB0D0000u, 55u}, // nyo -> Latn + {0xBF0D0000u, 55u}, // nyp -> Latn + {0xC30D0000u, 2u}, // nyq -> Arab + {0xC70D0000u, 55u}, // nyr -> Latn + {0xCB0D0000u, 55u}, // nys -> Latn + {0xCF0D0000u, 55u}, // nyt -> Latn + {0xD30D0000u, 55u}, // nyu -> Latn + {0xD70D0000u, 55u}, // nyv -> Latn + {0xDB0D0000u, 111u}, // nyw -> Thai + {0xDF0D0000u, 55u}, // nyx -> Latn + {0xE30D0000u, 55u}, // nyy -> Latn + {0x832D0000u, 55u}, // nza -> Latn + {0x872D0000u, 55u}, // nzb -> Latn + {0x8F2D0000u, 55u}, // nzd -> Latn + {0xA32D0000u, 55u}, // nzi -> Latn + {0xAB2D0000u, 55u}, // nzk -> Latn + {0xB32D0000u, 55u}, // nzm -> Latn + {0xC72D0000u, 55u}, // nzr -> Latn + {0xD32D0000u, 55u}, // nzu -> Latn + {0xE32D0000u, 55u}, // nzy -> Latn + {0xE72D0000u, 55u}, // nzz -> Latn + {0x800E0000u, 20u}, // oaa -> Cyrl + {0x880E0000u, 20u}, // oac -> Cyrl + {0xC40E0000u, 100u}, // oar -> Syrc + {0xD40E0000u, 25u}, // oav -> Geor + {0xA02E0000u, 55u}, // obi -> Latn + {0xA82E0000u, 55u}, // obk -> Latn + {0xAC2E0000u, 55u}, // obl -> Latn + {0xB02E0000u, 85u}, // obm -> Phnx + {0xB82E0000u, 55u}, // obo -> Latn + {0xC42E0000u, 72u}, // obr -> Mymr + {0xCC2E0000u, 55u}, // obt -> Latn + {0xD02E0000u, 55u}, // obu -> Latn + {0x6F630000u, 55u}, // oc -> Latn + {0x804E0000u, 55u}, // oca -> Latn + {0xB84E0000u, 55u}, // oco -> Latn + {0xD04E0000u, 55u}, // ocu -> Latn + {0x806E0000u, 55u}, // oda -> Latn + {0xA86E0000u, 2u}, // odk -> Arab + {0xCC6E0000u, 55u}, // odt -> Latn + {0xD06E0000u, 55u}, // odu -> Latn + {0xC8AE0000u, 55u}, // ofs -> Latn + {0xD0AE0000u, 55u}, // ofu -> Latn + {0x84CE0000u, 55u}, // ogb -> Latn + {0x88CE0000u, 55u}, // ogc -> Latn + {0x98CE0000u, 55u}, // ogg -> Latn + {0xB8CE0000u, 55u}, // ogo -> Latn + {0xD0CE0000u, 55u}, // ogu -> Latn + {0xCCEE0000u, 119u}, // oht -> Xsux + {0xD0EE0000u, 55u}, // ohu -> Latn + {0x810E0000u, 55u}, // oia -> Latn + {0x910E0000u, 55u}, // oie -> Latn + {0xB50E0000u, 55u}, // oin -> Latn + {0x6F6A0000u, 13u}, // oj -> Cans + {0x852E0000u, 55u}, // ojb -> Latn + {0x892E0000u, 55u}, // ojc -> Latn + {0xC92E0000u, 13u}, // ojs -> Cans + {0xD52E0000u, 55u}, // ojv -> Latn + {0xD92E0000u, 55u}, // ojw -> Latn + {0x814E0000u, 55u}, // oka -> Latn + {0x854E0000u, 55u}, // okb -> Latn + {0x894E0000u, 55u}, // okc -> Latn + {0x8D4E0000u, 55u}, // okd -> Latn + {0x914E0000u, 55u}, // oke -> Latn + {0x994E0000u, 55u}, // okg -> Latn + {0xA14E0000u, 55u}, // oki -> Latn + {0xA94E0000u, 55u}, // okk -> Latn + {0xB14E0000u, 33u}, // okm -> Hang + {0xB94E0000u, 34u}, // oko -> Hani + {0xC54E0000u, 55u}, // okr -> Latn + {0xC94E0000u, 55u}, // oks -> Latn + {0xD14E0000u, 55u}, // oku -> Latn + {0xD54E0000u, 55u}, // okv -> Latn + {0xDD4E0000u, 55u}, // okx -> Latn + {0xE54E0000u, 47u}, // okz -> Khmr + {0x816E0000u, 21u}, // ola -> Deva + {0x8D6E0000u, 55u}, // old -> Latn + {0x916E0000u, 112u}, // ole -> Tibt + {0xA96E0000u, 55u}, // olk -> Latn + {0xB16E0000u, 55u}, // olm -> Latn + {0xB96E0000u, 55u}, // olo -> Latn + {0xC56E0000u, 55u}, // olr -> Latn + {0xCD6E0000u, 55u}, // olt -> Latn + {0xD16E0000u, 55u}, // olu -> Latn + {0x6F6D0000u, 55u}, // om -> Latn + {0x818E0000u, 55u}, // oma -> Latn + {0x858E0000u, 55u}, // omb -> Latn + {0x898E0000u, 55u}, // omc -> Latn + {0x998E0000u, 55u}, // omg -> Latn + {0xA18E0000u, 55u}, // omi -> Latn + {0xA98E0000u, 20u}, // omk -> Cyrl + {0xAD8E0000u, 55u}, // oml -> Latn + {0xB98E0000u, 55u}, // omo -> Latn + {0xBD8E0000u, 71u}, // omp -> Mtei + {0xC58E0000u, 68u}, // omr -> Modi + {0xCD8E0000u, 55u}, // omt -> Latn + {0xD18E0000u, 55u}, // omu -> Latn + {0xD98E0000u, 55u}, // omw -> Latn + {0xDD8E0000u, 72u}, // omx -> Mymr + {0x81AE0000u, 55u}, // ona -> Latn + {0x91AE0000u, 55u}, // one -> Latn + {0x99AE0000u, 55u}, // ong -> Latn + {0xA1AE0000u, 55u}, // oni -> Latn + {0xA5AE0000u, 55u}, // onj -> Latn + {0xA9AE0000u, 55u}, // onk -> Latn + {0xB5AE0000u, 55u}, // onn -> Latn + {0xB9AE0000u, 55u}, // ono -> Latn + {0xBDAE0000u, 55u}, // onp -> Latn + {0xC5AE0000u, 55u}, // onr -> Latn + {0xC9AE0000u, 55u}, // ons -> Latn + {0xCDAE0000u, 55u}, // ont -> Latn + {0xD1AE0000u, 55u}, // onu -> Latn + {0xDDAE0000u, 55u}, // onx -> Latn + {0x8DCE0000u, 55u}, // ood -> Latn + {0xB5CE0000u, 21u}, // oon -> Deva + {0xC5CE0000u, 55u}, // oor -> Latn + {0x81EE0000u, 55u}, // opa -> Latn + {0xA9EE0000u, 55u}, // opk -> Latn + {0xB1EE0000u, 55u}, // opm -> Latn + {0xB9EE0000u, 55u}, // opo -> Latn + {0xCDEE0000u, 55u}, // opt -> Latn + {0xE1EE0000u, 55u}, // opy -> Latn + {0x6F720000u, 80u}, // or -> Orya + {0x822E0000u, 55u}, // ora -> Latn + {0x8A2E0000u, 55u}, // orc -> Latn + {0x922E0000u, 55u}, // ore -> Latn + {0x9A2E0000u, 55u}, // org -> Latn + {0xB62E0000u, 55u}, // orn -> Latn + {0xBA2E0000u, 55u}, // oro -> Latn + {0xC62E0000u, 55u}, // orr -> Latn + {0xCA2E0000u, 55u}, // ors -> Latn + {0xCE2E0000u, 108u}, // ort -> Telu {0xD22E0000u, 2u}, // oru -> Arab - {0x6F730000u, 18u}, // os -> Cyrl - {0x824E0000u, 67u}, // osa -> Osge + {0xD62E0000u, 20u}, // orv -> Cyrl + {0xDA2E0000u, 55u}, // orw -> Latn + {0xDE2E0000u, 55u}, // orx -> Latn + {0xE62E0000u, 55u}, // orz -> Latn + {0x6F730000u, 20u}, // os -> Cyrl + {0x824E0000u, 81u}, // osa -> Osge + {0x8A4E0000u, 40u}, // osc -> Ital + {0xA24E0000u, 41u}, // osi -> Java + {0xBA4E0000u, 55u}, // oso -> Latn + {0xBE4E0000u, 55u}, // osp -> Latn + {0xCE4E0000u, 55u}, // ost -> Latn + {0xD24E0000u, 55u}, // osu -> Latn + {0xDE4E0000u, 55u}, // osx -> Latn {0x826E0000u, 2u}, // ota -> Arab - {0xAA6E0000u, 65u}, // otk -> Orkh - {0xA28E0000u, 68u}, // oui -> Ougr - {0xB32E0000u, 46u}, // ozm -> Latn - {0x70610000u, 28u}, // pa -> Guru + {0x866E0000u, 112u}, // otb -> Tibt + {0x8E6E0000u, 55u}, // otd -> Latn + {0x926E0000u, 55u}, // ote -> Latn + {0xA26E0000u, 55u}, // oti -> Latn + {0xAA6E0000u, 79u}, // otk -> Orkh + {0xAE6E0000u, 55u}, // otl -> Latn + {0xB26E0000u, 55u}, // otm -> Latn + {0xB66E0000u, 55u}, // otn -> Latn + {0xC26E0000u, 55u}, // otq -> Latn + {0xC66E0000u, 55u}, // otr -> Latn + {0xCA6E0000u, 55u}, // ots -> Latn + {0xCE6E0000u, 55u}, // ott -> Latn + {0xD26E0000u, 55u}, // otu -> Latn + {0xDA6E0000u, 55u}, // otw -> Latn + {0xDE6E0000u, 55u}, // otx -> Latn + {0xE26E0000u, 29u}, // oty -> Gran + {0xE66E0000u, 55u}, // otz -> Latn + {0x868E0000u, 55u}, // oub -> Latn + {0x928E0000u, 55u}, // oue -> Latn + {0xA28E0000u, 82u}, // oui -> Ougr + {0xB28E0000u, 55u}, // oum -> Latn + {0x8EAE0000u, 55u}, // ovd -> Latn + {0xA2CE0000u, 55u}, // owi -> Latn + {0xAECE0000u, 55u}, // owl -> Latn + {0x8F0E0000u, 55u}, // oyd -> Latn + {0xB30E0000u, 55u}, // oym -> Latn + {0xE30E0000u, 55u}, // oyy -> Latn + {0xB32E0000u, 55u}, // ozm -> Latn + {0x70610000u, 32u}, // pa -> Guru {0x7061504Bu, 2u}, // pa-PK -> Arab - {0x980F0000u, 46u}, // pag -> Latn - {0xAC0F0000u, 70u}, // pal -> Phli - {0xB00F0000u, 46u}, // pam -> Latn - {0xBC0F0000u, 46u}, // pap -> Latn - {0xD00F0000u, 46u}, // pau -> Latn - {0xA02F0000u, 46u}, // pbi -> Latn - {0x8C4F0000u, 46u}, // pcd -> Latn - {0xB04F0000u, 46u}, // pcm -> Latn - {0x886F0000u, 46u}, // pdc -> Latn - {0xCC6F0000u, 46u}, // pdt -> Latn - {0x8C8F0000u, 46u}, // ped -> Latn - {0xB88F0000u, 100u}, // peo -> Xpeo - {0xDC8F0000u, 46u}, // pex -> Latn - {0xACAF0000u, 46u}, // pfl -> Latn + {0x840F0000u, 55u}, // pab -> Latn + {0x880F0000u, 55u}, // pac -> Latn + {0x8C0F0000u, 55u}, // pad -> Latn + {0x900F0000u, 55u}, // pae -> Latn + {0x940F0000u, 55u}, // paf -> Latn + {0x980F0000u, 55u}, // pag -> Latn + {0x9C0F0000u, 55u}, // pah -> Latn + {0xA00F0000u, 55u}, // pai -> Latn + {0xA80F0000u, 55u}, // pak -> Latn + {0xAC0F0000u, 84u}, // pal -> Phli + {0xB00F0000u, 55u}, // pam -> Latn + {0xB80F0000u, 55u}, // pao -> Latn + {0xBC0F0000u, 55u}, // pap -> Latn + {0xC00F0000u, 20u}, // paq -> Cyrl + {0xC40F0000u, 55u}, // par -> Latn + {0xC80F0000u, 55u}, // pas -> Latn + {0xD00F0000u, 55u}, // pau -> Latn + {0xD40F0000u, 55u}, // pav -> Latn + {0xD80F0000u, 55u}, // paw -> Latn + {0xDC0F0000u, 55u}, // pax -> Latn + {0xE00F0000u, 55u}, // pay -> Latn + {0xE40F0000u, 55u}, // paz -> Latn + {0x842F0000u, 55u}, // pbb -> Latn + {0x882F0000u, 55u}, // pbc -> Latn + {0x902F0000u, 55u}, // pbe -> Latn + {0x942F0000u, 55u}, // pbf -> Latn + {0x982F0000u, 55u}, // pbg -> Latn + {0x9C2F0000u, 55u}, // pbh -> Latn + {0xA02F0000u, 55u}, // pbi -> Latn + {0xAC2F0000u, 55u}, // pbl -> Latn + {0xB02F0000u, 55u}, // pbm -> Latn + {0xB42F0000u, 55u}, // pbn -> Latn + {0xB82F0000u, 55u}, // pbo -> Latn + {0xBC2F0000u, 55u}, // pbp -> Latn + {0xC42F0000u, 55u}, // pbr -> Latn + {0xC82F0000u, 55u}, // pbs -> Latn + {0xCC2F0000u, 2u}, // pbt -> Arab + {0xD42F0000u, 55u}, // pbv -> Latn + {0xE02F0000u, 55u}, // pby -> Latn + {0x804F0000u, 55u}, // pca -> Latn + {0x844F0000u, 47u}, // pcb -> Khmr + {0x884F0000u, 55u}, // pcc -> Latn + {0x8C4F0000u, 55u}, // pcd -> Latn + {0x904F0000u, 72u}, // pce -> Mymr + {0x944F0000u, 67u}, // pcf -> Mlym + {0x984F0000u, 67u}, // pcg -> Mlym + {0x9C4F0000u, 21u}, // pch -> Deva + {0xA04F0000u, 21u}, // pci -> Deva + {0xA44F0000u, 108u}, // pcj -> Telu + {0xA84F0000u, 55u}, // pck -> Latn + {0xB04F0000u, 55u}, // pcm -> Latn + {0xB44F0000u, 55u}, // pcn -> Latn + {0xBC4F0000u, 55u}, // pcp -> Latn + {0xD84F0000u, 55u}, // pcw -> Latn + {0x806F0000u, 55u}, // pda -> Latn + {0x886F0000u, 55u}, // pdc -> Latn + {0xB46F0000u, 55u}, // pdn -> Latn + {0xB86F0000u, 55u}, // pdo -> Latn + {0xCC6F0000u, 55u}, // pdt -> Latn + {0xD06F0000u, 55u}, // pdu -> Latn + {0x808F0000u, 55u}, // pea -> Latn + {0x848F0000u, 55u}, // peb -> Latn + {0x8C8F0000u, 55u}, // ped -> Latn + {0x908F0000u, 55u}, // pee -> Latn + {0x988F0000u, 80u}, // peg -> Orya + {0xA08F0000u, 55u}, // pei -> Latn + {0xA88F0000u, 55u}, // pek -> Latn + {0xAC8F0000u, 55u}, // pel -> Latn + {0xB08F0000u, 55u}, // pem -> Latn + {0xB88F0000u, 118u}, // peo -> Xpeo + {0xBC8F0000u, 55u}, // pep -> Latn + {0xC08F0000u, 55u}, // peq -> Latn + {0xD48F0000u, 55u}, // pev -> Latn + {0xDC8F0000u, 55u}, // pex -> Latn + {0xE08F0000u, 55u}, // pey -> Latn + {0xE48F0000u, 55u}, // pez -> Latn + {0x80AF0000u, 55u}, // pfa -> Latn + {0x90AF0000u, 55u}, // pfe -> Latn + {0xACAF0000u, 55u}, // pfl -> Latn + {0x80CF0000u, 55u}, // pga -> Latn + {0x8CCF0000u, 46u}, // pgd -> Khar + {0x98CF0000u, 21u}, // pgg -> Deva + {0xA0CF0000u, 55u}, // pgi -> Latn + {0xA8CF0000u, 55u}, // pgk -> Latn + {0xACCF0000u, 77u}, // pgl -> Ogam + {0xB4CF0000u, 40u}, // pgn -> Ital + {0xC8CF0000u, 55u}, // pgs -> Latn + {0xD0CF0000u, 55u}, // pgu -> Latn + {0x8CEF0000u, 21u}, // phd -> Deva + {0x98EF0000u, 55u}, // phg -> Latn + {0x9CEF0000u, 55u}, // phh -> Latn + {0xA8EF0000u, 72u}, // phk -> Mymr {0xACEF0000u, 2u}, // phl -> Arab - {0xB4EF0000u, 71u}, // phn -> Phnx - {0xAD0F0000u, 46u}, // pil -> Latn - {0xBD0F0000u, 46u}, // pip -> Latn - {0xC90F0000u, 46u}, // pis -> Latn - {0x814F0000u, 9u}, // pka -> Brah - {0xB94F0000u, 46u}, // pko -> Latn - {0x706C0000u, 46u}, // pl -> Latn - {0x816F0000u, 46u}, // pla -> Latn - {0xC98F0000u, 46u}, // pms -> Latn - {0x99AF0000u, 46u}, // png -> Latn - {0xB5AF0000u, 46u}, // pnn -> Latn - {0xCDAF0000u, 26u}, // pnt -> Grek - {0xB5CF0000u, 46u}, // pon -> Latn - {0x81EF0000u, 19u}, // ppa -> Deva - {0xB9EF0000u, 46u}, // ppo -> Latn - {0xB20F0000u, 46u}, // pqm -> Latn - {0x822F0000u, 39u}, // pra -> Khar + {0xB0EF0000u, 55u}, // phm -> Latn + {0xB4EF0000u, 85u}, // phn -> Phnx + {0xB8EF0000u, 52u}, // pho -> Laoo + {0xC4EF0000u, 2u}, // phr -> Arab + {0xCCEF0000u, 111u}, // pht -> Thai + {0xD0EF0000u, 111u}, // phu -> Thai + {0xD4EF0000u, 2u}, // phv -> Arab + {0xD8EF0000u, 21u}, // phw -> Deva + {0x70690000u, 95u}, // pi -> Sinh + {0x810F0000u, 55u}, // pia -> Latn + {0x850F0000u, 55u}, // pib -> Latn + {0x890F0000u, 55u}, // pic -> Latn + {0x8D0F0000u, 55u}, // pid -> Latn + {0x950F0000u, 55u}, // pif -> Latn + {0x990F0000u, 55u}, // pig -> Latn + {0x9D0F0000u, 55u}, // pih -> Latn + {0xA50F0000u, 55u}, // pij -> Latn + {0xAD0F0000u, 55u}, // pil -> Latn + {0xB10F0000u, 55u}, // pim -> Latn + {0xB50F0000u, 55u}, // pin -> Latn + {0xB90F0000u, 55u}, // pio -> Latn + {0xBD0F0000u, 55u}, // pip -> Latn + {0xC50F0000u, 55u}, // pir -> Latn + {0xC90F0000u, 55u}, // pis -> Latn + {0xCD0F0000u, 55u}, // pit -> Latn + {0xD10F0000u, 55u}, // piu -> Latn + {0xD50F0000u, 55u}, // piv -> Latn + {0xD90F0000u, 55u}, // piw -> Latn + {0xDD0F0000u, 55u}, // pix -> Latn + {0xE10F0000u, 55u}, // piy -> Latn + {0xE50F0000u, 55u}, // piz -> Latn + {0xCD2F0000u, 55u}, // pjt -> Latn + {0x814F0000u, 11u}, // pka -> Brah + {0x854F0000u, 55u}, // pkb -> Latn + {0x994F0000u, 55u}, // pkg -> Latn + {0x9D4F0000u, 55u}, // pkh -> Latn + {0xB54F0000u, 55u}, // pkn -> Latn + {0xB94F0000u, 55u}, // pko -> Latn + {0xBD4F0000u, 55u}, // pkp -> Latn + {0xC54F0000u, 67u}, // pkr -> Mlym + {0xD14F0000u, 55u}, // pku -> Latn + {0x706C0000u, 55u}, // pl -> Latn + {0x816F0000u, 55u}, // pla -> Latn + {0x856F0000u, 55u}, // plb -> Latn + {0x896F0000u, 55u}, // plc -> Latn + {0x8D6F0000u, 55u}, // pld -> Latn + {0x916F0000u, 55u}, // ple -> Latn + {0x996F0000u, 55u}, // plg -> Latn + {0x9D6F0000u, 55u}, // plh -> Latn + {0xA96F0000u, 2u}, // plk -> Arab + {0xAD6F0000u, 72u}, // pll -> Mymr + {0xB56F0000u, 55u}, // pln -> Latn + {0xB96F0000u, 55u}, // plo -> Latn + {0xC56F0000u, 55u}, // plr -> Latn + {0xC96F0000u, 55u}, // pls -> Latn + {0xD16F0000u, 55u}, // plu -> Latn + {0xD56F0000u, 55u}, // plv -> Latn + {0xD96F0000u, 55u}, // plw -> Latn + {0xE56F0000u, 55u}, // plz -> Latn + {0x818F0000u, 55u}, // pma -> Latn + {0x858F0000u, 55u}, // pmb -> Latn + {0x8D8F0000u, 55u}, // pmd -> Latn + {0x918F0000u, 55u}, // pme -> Latn + {0x958F0000u, 55u}, // pmf -> Latn + {0x9D8F0000u, 11u}, // pmh -> Brah + {0xA18F0000u, 55u}, // pmi -> Latn + {0xA58F0000u, 55u}, // pmj -> Latn + {0xAD8F0000u, 55u}, // pml -> Latn + {0xB18F0000u, 55u}, // pmm -> Latn + {0xB58F0000u, 55u}, // pmn -> Latn + {0xB98F0000u, 55u}, // pmo -> Latn + {0xC18F0000u, 55u}, // pmq -> Latn + {0xC58F0000u, 55u}, // pmr -> Latn + {0xC98F0000u, 55u}, // pms -> Latn + {0xCD8F0000u, 55u}, // pmt -> Latn + {0xD98F0000u, 55u}, // pmw -> Latn + {0xDD8F0000u, 55u}, // pmx -> Latn + {0xE18F0000u, 55u}, // pmy -> Latn + {0xE58F0000u, 55u}, // pmz -> Latn + {0x81AF0000u, 55u}, // pna -> Latn + {0x89AF0000u, 55u}, // pnc -> Latn + {0x8DAF0000u, 55u}, // pnd -> Latn + {0x91AF0000u, 55u}, // pne -> Latn + {0x99AF0000u, 55u}, // png -> Latn + {0x9DAF0000u, 55u}, // pnh -> Latn + {0xA1AF0000u, 55u}, // pni -> Latn + {0xA5AF0000u, 55u}, // pnj -> Latn + {0xA9AF0000u, 55u}, // pnk -> Latn + {0xADAF0000u, 55u}, // pnl -> Latn + {0xB1AF0000u, 55u}, // pnm -> Latn + {0xB5AF0000u, 55u}, // pnn -> Latn + {0xB9AF0000u, 55u}, // pno -> Latn + {0xBDAF0000u, 55u}, // pnp -> Latn + {0xC1AF0000u, 55u}, // pnq -> Latn + {0xC5AF0000u, 55u}, // pnr -> Latn + {0xC9AF0000u, 55u}, // pns -> Latn + {0xCDAF0000u, 30u}, // pnt -> Grek + {0xD5AF0000u, 55u}, // pnv -> Latn + {0xD9AF0000u, 55u}, // pnw -> Latn + {0xE1AF0000u, 55u}, // pny -> Latn + {0xE5AF0000u, 55u}, // pnz -> Latn + {0x89CF0000u, 55u}, // poc -> Latn + {0x91CF0000u, 55u}, // poe -> Latn + {0x95CF0000u, 55u}, // pof -> Latn + {0x99CF0000u, 55u}, // pog -> Latn + {0x9DCF0000u, 55u}, // poh -> Latn + {0xA1CF0000u, 55u}, // poi -> Latn + {0xA9CF0000u, 55u}, // pok -> Latn + {0xB1CF0000u, 55u}, // pom -> Latn + {0xB5CF0000u, 55u}, // pon -> Latn + {0xB9CF0000u, 55u}, // poo -> Latn + {0xBDCF0000u, 55u}, // pop -> Latn + {0xC1CF0000u, 55u}, // poq -> Latn + {0xC9CF0000u, 55u}, // pos -> Latn + {0xCDCF0000u, 55u}, // pot -> Latn + {0xD5CF0000u, 55u}, // pov -> Latn + {0xD9CF0000u, 55u}, // pow -> Latn + {0xE1CF0000u, 55u}, // poy -> Latn + {0x91EF0000u, 55u}, // ppe -> Latn + {0xA1EF0000u, 55u}, // ppi -> Latn + {0xA9EF0000u, 55u}, // ppk -> Latn + {0xADEF0000u, 55u}, // ppl -> Latn + {0xB1EF0000u, 55u}, // ppm -> Latn + {0xB5EF0000u, 55u}, // ppn -> Latn + {0xB9EF0000u, 55u}, // ppo -> Latn + {0xBDEF0000u, 55u}, // ppp -> Latn + {0xC1EF0000u, 55u}, // ppq -> Latn + {0xC9EF0000u, 55u}, // pps -> Latn + {0xCDEF0000u, 55u}, // ppt -> Latn + {0x820F0000u, 55u}, // pqa -> Latn + {0xB20F0000u, 55u}, // pqm -> Latn + {0x822F0000u, 46u}, // pra -> Khar + {0x8A2F0000u, 2u}, // prc -> Arab {0x8E2F0000u, 2u}, // prd -> Arab - {0x9A2F0000u, 46u}, // prg -> Latn + {0x922F0000u, 55u}, // pre -> Latn + {0x962F0000u, 55u}, // prf -> Latn + {0x9A2F0000u, 55u}, // prg -> Latn + {0x9E2F0000u, 55u}, // prh -> Latn + {0xA22F0000u, 55u}, // pri -> Latn + {0xAA2F0000u, 55u}, // prk -> Latn + {0xB22F0000u, 55u}, // prm -> Latn + {0xBA2F0000u, 55u}, // pro -> Latn + {0xC22F0000u, 55u}, // prq -> Latn + {0xC62F0000u, 55u}, // prr -> Latn + {0xCE2F0000u, 111u}, // prt -> Thai + {0xD22F0000u, 55u}, // pru -> Latn + {0xDA2F0000u, 55u}, // prw -> Latn + {0xDE2F0000u, 2u}, // prx -> Arab {0x70730000u, 2u}, // ps -> Arab - {0xCA4F0000u, 46u}, // pss -> Latn - {0x70740000u, 46u}, // pt -> Latn - {0xBE6F0000u, 46u}, // ptp -> Latn - {0xD28F0000u, 46u}, // puu -> Latn - {0x82CF0000u, 46u}, // pwa -> Latn - {0x71750000u, 46u}, // qu -> Latn - {0x8A900000u, 46u}, // quc -> Latn - {0x9A900000u, 46u}, // qug -> Latn - {0xA0110000u, 46u}, // rai -> Latn - {0xA4110000u, 19u}, // raj -> Deva - {0xB8110000u, 46u}, // rao -> Latn - {0x94510000u, 46u}, // rcf -> Latn - {0xA4910000u, 46u}, // rej -> Latn - {0xAC910000u, 46u}, // rel -> Latn - {0xC8910000u, 46u}, // res -> Latn - {0xB4D10000u, 46u}, // rgn -> Latn - {0x98F10000u, 74u}, // rhg -> Rohg - {0x81110000u, 46u}, // ria -> Latn - {0x95110000u, 91u}, // rif -> Tfng - {0x95114E4Cu, 46u}, // rif-NL -> Latn - {0xC9310000u, 19u}, // rjs -> Deva - {0xCD510000u, 8u}, // rkt -> Beng - {0x726D0000u, 46u}, // rm -> Latn - {0x95910000u, 46u}, // rmf -> Latn - {0xB9910000u, 46u}, // rmo -> Latn + {0x824F0000u, 55u}, // psa -> Latn + {0x924F0000u, 55u}, // pse -> Latn + {0x9E4F0000u, 2u}, // psh -> Arab + {0xA24F0000u, 2u}, // psi -> Arab + {0xB24F0000u, 55u}, // psm -> Latn + {0xB64F0000u, 55u}, // psn -> Latn + {0xC24F0000u, 55u}, // psq -> Latn + {0xCA4F0000u, 55u}, // pss -> Latn + {0xCE4F0000u, 2u}, // pst -> Arab + {0xD24F0000u, 11u}, // psu -> Brah + {0xDA4F0000u, 55u}, // psw -> Latn + {0x70740000u, 55u}, // pt -> Latn + {0x826F0000u, 55u}, // pta -> Latn + {0x9E6F0000u, 55u}, // pth -> Latn + {0xA26F0000u, 55u}, // pti -> Latn + {0xB66F0000u, 55u}, // ptn -> Latn + {0xBA6F0000u, 55u}, // pto -> Latn + {0xBE6F0000u, 55u}, // ptp -> Latn + {0xC66F0000u, 55u}, // ptr -> Latn + {0xCE6F0000u, 55u}, // ptt -> Latn + {0xD26F0000u, 55u}, // ptu -> Latn + {0xD66F0000u, 55u}, // ptv -> Latn + {0x828F0000u, 55u}, // pua -> Latn + {0x868F0000u, 55u}, // pub -> Latn + {0x8A8F0000u, 55u}, // puc -> Latn + {0x8E8F0000u, 55u}, // pud -> Latn + {0x928F0000u, 55u}, // pue -> Latn + {0x968F0000u, 55u}, // puf -> Latn + {0x9A8F0000u, 55u}, // pug -> Latn + {0xA28F0000u, 55u}, // pui -> Latn + {0xA68F0000u, 55u}, // puj -> Latn + {0xB28F0000u, 21u}, // pum -> Deva + {0xBA8F0000u, 55u}, // puo -> Latn + {0xBE8F0000u, 55u}, // pup -> Latn + {0xC28F0000u, 55u}, // puq -> Latn + {0xC68F0000u, 55u}, // pur -> Latn + {0xCE8F0000u, 55u}, // put -> Latn + {0xD28F0000u, 55u}, // puu -> Latn + {0xDA8F0000u, 55u}, // puw -> Latn + {0xDE8F0000u, 55u}, // pux -> Latn + {0xE28F0000u, 55u}, // puy -> Latn + {0x82CF0000u, 55u}, // pwa -> Latn + {0x86CF0000u, 55u}, // pwb -> Latn + {0x9ACF0000u, 55u}, // pwg -> Latn + {0xB2CF0000u, 55u}, // pwm -> Latn + {0xB6CF0000u, 55u}, // pwn -> Latn + {0xBACF0000u, 72u}, // pwo -> Mymr + {0xC6CF0000u, 21u}, // pwr -> Deva + {0xDACF0000u, 111u}, // pww -> Thai + {0xB2EF0000u, 55u}, // pxm -> Latn + {0x930F0000u, 55u}, // pye -> Latn + {0xB30F0000u, 55u}, // pym -> Latn + {0xB70F0000u, 55u}, // pyn -> Latn + {0xD30F0000u, 55u}, // pyu -> Latn + {0xDF0F0000u, 72u}, // pyx -> Mymr + {0xE30F0000u, 55u}, // pyy -> Latn + {0x932F0000u, 55u}, // pze -> Latn + {0x9F2F0000u, 55u}, // pzh -> Latn + {0xB72F0000u, 55u}, // pzn -> Latn + {0x71750000u, 55u}, // qu -> Latn + {0x82900000u, 55u}, // qua -> Latn + {0x86900000u, 55u}, // qub -> Latn + {0x8A900000u, 55u}, // quc -> Latn + {0x8E900000u, 55u}, // qud -> Latn + {0x96900000u, 55u}, // quf -> Latn + {0x9A900000u, 55u}, // qug -> Latn + {0xA2900000u, 55u}, // qui -> Latn + {0xAA900000u, 55u}, // quk -> Latn + {0xAE900000u, 55u}, // qul -> Latn + {0xB2900000u, 55u}, // qum -> Latn + {0xB6900000u, 55u}, // qun -> Latn + {0xBE900000u, 55u}, // qup -> Latn + {0xC2900000u, 55u}, // quq -> Latn + {0xC6900000u, 55u}, // qur -> Latn + {0xCA900000u, 55u}, // qus -> Latn + {0xD6900000u, 55u}, // quv -> Latn + {0xDA900000u, 55u}, // quw -> Latn + {0xDE900000u, 55u}, // qux -> Latn + {0xE2900000u, 55u}, // quy -> Latn + {0x82B00000u, 55u}, // qva -> Latn + {0x8AB00000u, 55u}, // qvc -> Latn + {0x92B00000u, 55u}, // qve -> Latn + {0x9EB00000u, 55u}, // qvh -> Latn + {0xA2B00000u, 55u}, // qvi -> Latn + {0xA6B00000u, 55u}, // qvj -> Latn + {0xAEB00000u, 55u}, // qvl -> Latn + {0xB2B00000u, 55u}, // qvm -> Latn + {0xB6B00000u, 55u}, // qvn -> Latn + {0xBAB00000u, 55u}, // qvo -> Latn + {0xBEB00000u, 55u}, // qvp -> Latn + {0xCAB00000u, 55u}, // qvs -> Latn + {0xDAB00000u, 55u}, // qvw -> Latn + {0xE6B00000u, 55u}, // qvz -> Latn + {0x82D00000u, 55u}, // qwa -> Latn + {0x8AD00000u, 55u}, // qwc -> Latn + {0x9ED00000u, 55u}, // qwh -> Latn + {0xB2D00000u, 55u}, // qwm -> Latn + {0xCAD00000u, 55u}, // qws -> Latn + {0xCED00000u, 55u}, // qwt -> Latn + {0x82F00000u, 55u}, // qxa -> Latn + {0x8AF00000u, 55u}, // qxc -> Latn + {0x9EF00000u, 55u}, // qxh -> Latn + {0xAEF00000u, 55u}, // qxl -> Latn + {0xB6F00000u, 55u}, // qxn -> Latn + {0xBAF00000u, 55u}, // qxo -> Latn + {0xBEF00000u, 55u}, // qxp -> Latn + {0xC2F00000u, 2u}, // qxq -> Arab + {0xC6F00000u, 55u}, // qxr -> Latn + {0xCEF00000u, 55u}, // qxt -> Latn + {0xD2F00000u, 55u}, // qxu -> Latn + {0xDAF00000u, 55u}, // qxw -> Latn + {0x83100000u, 55u}, // qya -> Latn + {0xBF100000u, 55u}, // qyp -> Latn + {0x80110000u, 21u}, // raa -> Deva + {0x84110000u, 21u}, // rab -> Deva + {0x88110000u, 55u}, // rac -> Latn + {0x8C110000u, 55u}, // rad -> Latn + {0x94110000u, 21u}, // raf -> Deva + {0x98110000u, 55u}, // rag -> Latn + {0x9C110000u, 9u}, // rah -> Beng + {0xA0110000u, 55u}, // rai -> Latn + {0xA4110000u, 21u}, // raj -> Deva + {0xA8110000u, 55u}, // rak -> Latn + {0xB0110000u, 55u}, // ram -> Latn + {0xB4110000u, 55u}, // ran -> Latn + {0xB8110000u, 55u}, // rao -> Latn + {0xBC110000u, 55u}, // rap -> Latn + {0xC4110000u, 55u}, // rar -> Latn + {0xD4110000u, 21u}, // rav -> Deva + {0xD8110000u, 55u}, // raw -> Latn + {0xDC110000u, 55u}, // rax -> Latn + {0xE0110000u, 55u}, // ray -> Latn + {0xE4110000u, 55u}, // raz -> Latn + {0x84310000u, 72u}, // rbb -> Mymr + {0xA8310000u, 55u}, // rbk -> Latn + {0xAC310000u, 55u}, // rbl -> Latn + {0xBC310000u, 55u}, // rbp -> Latn + {0x94510000u, 55u}, // rcf -> Latn + {0x84710000u, 2u}, // rdb -> Arab + {0x80910000u, 55u}, // rea -> Latn + {0x84910000u, 55u}, // reb -> Latn + {0x90910000u, 55u}, // ree -> Latn + {0x98910000u, 55u}, // reg -> Latn + {0xA0910000u, 80u}, // rei -> Orya + {0xA4910000u, 55u}, // rej -> Latn + {0xAC910000u, 55u}, // rel -> Latn + {0xB0910000u, 55u}, // rem -> Latn + {0xB4910000u, 55u}, // ren -> Latn + {0xC8910000u, 55u}, // res -> Latn + {0xCC910000u, 55u}, // ret -> Latn + {0xE0910000u, 55u}, // rey -> Latn + {0x80D10000u, 55u}, // rga -> Latn + {0xB4D10000u, 55u}, // rgn -> Latn + {0xC4D10000u, 55u}, // rgr -> Latn + {0xC8D10000u, 55u}, // rgs -> Latn + {0xD0D10000u, 55u}, // rgu -> Latn + {0x98F10000u, 89u}, // rhg -> Rohg + {0xBCF10000u, 55u}, // rhp -> Latn + {0x81110000u, 55u}, // ria -> Latn + {0x95110000u, 55u}, // rif -> Latn + {0xAD110000u, 55u}, // ril -> Latn + {0xB1110000u, 55u}, // rim -> Latn + {0xB5110000u, 55u}, // rin -> Latn + {0xC5110000u, 55u}, // rir -> Latn + {0xCD110000u, 55u}, // rit -> Latn + {0xD1110000u, 55u}, // riu -> Latn + {0x99310000u, 55u}, // rjg -> Latn + {0xA1310000u, 21u}, // rji -> Deva + {0xC9310000u, 21u}, // rjs -> Deva + {0x81510000u, 47u}, // rka -> Khmr + {0x85510000u, 55u}, // rkb -> Latn + {0x9D510000u, 55u}, // rkh -> Latn + {0xA1510000u, 72u}, // rki -> Mymr + {0xB1510000u, 55u}, // rkm -> Latn + {0xCD510000u, 9u}, // rkt -> Beng + {0xD9510000u, 55u}, // rkw -> Latn + {0x726D0000u, 55u}, // rm -> Latn + {0x81910000u, 55u}, // rma -> Latn + {0x85910000u, 55u}, // rmb -> Latn + {0x89910000u, 55u}, // rmc -> Latn + {0x8D910000u, 55u}, // rmd -> Latn + {0x91910000u, 55u}, // rme -> Latn + {0x95910000u, 55u}, // rmf -> Latn + {0x99910000u, 55u}, // rmg -> Latn + {0x9D910000u, 55u}, // rmh -> Latn + {0xA1910000u, 4u}, // rmi -> Armn + {0xA9910000u, 55u}, // rmk -> Latn + {0xAD910000u, 55u}, // rml -> Latn + {0xB1910000u, 55u}, // rmm -> Latn + {0xB5910000u, 55u}, // rmn -> Latn + {0xB9910000u, 55u}, // rmo -> Latn + {0xBD910000u, 55u}, // rmp -> Latn + {0xC1910000u, 55u}, // rmq -> Latn {0xCD910000u, 2u}, // rmt -> Arab - {0xD1910000u, 46u}, // rmu -> Latn - {0x726E0000u, 46u}, // rn -> Latn - {0x81B10000u, 46u}, // rna -> Latn - {0x99B10000u, 46u}, // rng -> Latn - {0x726F0000u, 46u}, // ro -> Latn - {0x85D10000u, 46u}, // rob -> Latn - {0x95D10000u, 46u}, // rof -> Latn - {0xB9D10000u, 46u}, // roo -> Latn - {0xBA310000u, 46u}, // rro -> Latn - {0xB2710000u, 46u}, // rtm -> Latn - {0x72750000u, 18u}, // ru -> Cyrl - {0x92910000u, 18u}, // rue -> Cyrl - {0x9A910000u, 46u}, // rug -> Latn - {0x72770000u, 46u}, // rw -> Latn - {0xAAD10000u, 46u}, // rwk -> Latn - {0xBAD10000u, 46u}, // rwo -> Latn - {0xD3110000u, 37u}, // ryu -> Kana - {0x73610000u, 19u}, // sa -> Deva - {0x94120000u, 46u}, // saf -> Latn - {0x9C120000u, 18u}, // sah -> Cyrl - {0xC0120000u, 46u}, // saq -> Latn - {0xC8120000u, 46u}, // sas -> Latn - {0xCC120000u, 64u}, // sat -> Olck - {0xD4120000u, 46u}, // sav -> Latn - {0xE4120000u, 78u}, // saz -> Saur - {0x80320000u, 46u}, // sba -> Latn - {0x90320000u, 46u}, // sbe -> Latn - {0xBC320000u, 46u}, // sbp -> Latn - {0x73630000u, 46u}, // sc -> Latn - {0xA8520000u, 19u}, // sck -> Deva + {0xD1910000u, 55u}, // rmu -> Latn + {0xD9910000u, 55u}, // rmw -> Latn + {0xDD910000u, 55u}, // rmx -> Latn + {0xE5910000u, 72u}, // rmz -> Mymr + {0x726E0000u, 55u}, // rn -> Latn + {0x8DB10000u, 55u}, // rnd -> Latn + {0x99B10000u, 55u}, // rng -> Latn + {0xADB10000u, 55u}, // rnl -> Latn + {0xB5B10000u, 55u}, // rnn -> Latn + {0xC5B10000u, 55u}, // rnr -> Latn + {0xD9B10000u, 55u}, // rnw -> Latn + {0x726F0000u, 55u}, // ro -> Latn + {0x85D10000u, 55u}, // rob -> Latn + {0x89D10000u, 55u}, // roc -> Latn + {0x8DD10000u, 55u}, // rod -> Latn + {0x91D10000u, 55u}, // roe -> Latn + {0x95D10000u, 55u}, // rof -> Latn + {0x99D10000u, 55u}, // rog -> Latn + {0xADD10000u, 55u}, // rol -> Latn + {0xB1D10000u, 55u}, // rom -> Latn + {0xB9D10000u, 55u}, // roo -> Latn + {0xBDD10000u, 55u}, // rop -> Latn + {0xC5D10000u, 55u}, // ror -> Latn + {0xD1D10000u, 55u}, // rou -> Latn + {0xD9D10000u, 55u}, // row -> Latn + {0xB5F10000u, 55u}, // rpn -> Latn + {0xCDF10000u, 55u}, // rpt -> Latn + {0xA2310000u, 55u}, // rri -> Latn + {0xB2310000u, 55u}, // rrm -> Latn + {0xBA310000u, 55u}, // rro -> Latn + {0xCE310000u, 55u}, // rrt -> Latn + {0xAA510000u, 20u}, // rsk -> Cyrl + {0xDA510000u, 55u}, // rsw -> Latn + {0x8A710000u, 55u}, // rtc -> Latn + {0x9E710000u, 55u}, // rth -> Latn + {0xB2710000u, 55u}, // rtm -> Latn + {0xDA710000u, 21u}, // rtw -> Deva + {0x72750000u, 20u}, // ru -> Cyrl + {0x86910000u, 55u}, // rub -> Latn + {0x8A910000u, 55u}, // ruc -> Latn + {0x92910000u, 20u}, // rue -> Cyrl + {0x96910000u, 55u}, // ruf -> Latn + {0x9A910000u, 55u}, // rug -> Latn + {0xA2910000u, 55u}, // rui -> Latn + {0xAA910000u, 55u}, // ruk -> Latn + {0xBA910000u, 55u}, // ruo -> Latn + {0xBE910000u, 55u}, // rup -> Latn + {0xC2910000u, 55u}, // ruq -> Latn + {0xCE910000u, 20u}, // rut -> Cyrl + {0xD2910000u, 55u}, // ruu -> Latn + {0xE2910000u, 55u}, // ruy -> Latn + {0xE6910000u, 55u}, // ruz -> Latn + {0x72770000u, 55u}, // rw -> Latn + {0x82D10000u, 55u}, // rwa -> Latn + {0xAAD10000u, 55u}, // rwk -> Latn + {0xAED10000u, 55u}, // rwl -> Latn + {0xB2D10000u, 55u}, // rwm -> Latn + {0xBAD10000u, 55u}, // rwo -> Latn + {0xC6D10000u, 21u}, // rwr -> Deva + {0x8EF10000u, 55u}, // rxd -> Latn + {0xDAF10000u, 55u}, // rxw -> Latn + {0xD3110000u, 44u}, // ryu -> Kana + {0x73610000u, 21u}, // sa -> Deva + {0x80120000u, 55u}, // saa -> Latn + {0x84120000u, 55u}, // sab -> Latn + {0x88120000u, 55u}, // sac -> Latn + {0x8C120000u, 55u}, // sad -> Latn + {0x90120000u, 55u}, // sae -> Latn + {0x94120000u, 55u}, // saf -> Latn + {0x9C120000u, 20u}, // sah -> Cyrl + {0xA4120000u, 55u}, // saj -> Latn + {0xA8120000u, 55u}, // sak -> Latn + {0xB0120000u, 91u}, // sam -> Samr + {0xB8120000u, 55u}, // sao -> Latn + {0xC0120000u, 55u}, // saq -> Latn + {0xC4120000u, 55u}, // sar -> Latn + {0xC8120000u, 55u}, // sas -> Latn + {0xCC120000u, 78u}, // sat -> Olck + {0xD0120000u, 55u}, // sau -> Latn + {0xD4120000u, 55u}, // sav -> Latn + {0xD8120000u, 55u}, // saw -> Latn + {0xDC120000u, 55u}, // sax -> Latn + {0xE0120000u, 55u}, // say -> Latn + {0xE4120000u, 93u}, // saz -> Saur + {0x80320000u, 55u}, // sba -> Latn + {0x84320000u, 55u}, // sbb -> Latn + {0x88320000u, 55u}, // sbc -> Latn + {0x8C320000u, 55u}, // sbd -> Latn + {0x90320000u, 55u}, // sbe -> Latn + {0x98320000u, 55u}, // sbg -> Latn + {0x9C320000u, 55u}, // sbh -> Latn + {0xA0320000u, 55u}, // sbi -> Latn + {0xA4320000u, 55u}, // sbj -> Latn + {0xA8320000u, 55u}, // sbk -> Latn + {0xAC320000u, 55u}, // sbl -> Latn + {0xB0320000u, 55u}, // sbm -> Latn + {0xB4320000u, 2u}, // sbn -> Arab + {0xB8320000u, 55u}, // sbo -> Latn + {0xBC320000u, 55u}, // sbp -> Latn + {0xC0320000u, 55u}, // sbq -> Latn + {0xC4320000u, 55u}, // sbr -> Latn + {0xC8320000u, 55u}, // sbs -> Latn + {0xCC320000u, 55u}, // sbt -> Latn + {0xD0320000u, 112u}, // sbu -> Tibt + {0xD4320000u, 55u}, // sbv -> Latn + {0xD8320000u, 55u}, // sbw -> Latn + {0xDC320000u, 55u}, // sbx -> Latn + {0xE0320000u, 55u}, // sby -> Latn + {0xE4320000u, 55u}, // sbz -> Latn + {0x73630000u, 55u}, // sc -> Latn + {0x84520000u, 55u}, // scb -> Latn + {0x90520000u, 55u}, // sce -> Latn + {0x94520000u, 55u}, // scf -> Latn + {0x98520000u, 55u}, // scg -> Latn + {0x9C520000u, 55u}, // sch -> Latn + {0xA0520000u, 55u}, // sci -> Latn + {0xA8520000u, 21u}, // sck -> Deva {0xAC520000u, 2u}, // scl -> Arab - {0xB4520000u, 46u}, // scn -> Latn - {0xB8520000u, 46u}, // sco -> Latn + {0xB4520000u, 55u}, // scn -> Latn + {0xB8520000u, 55u}, // sco -> Latn + {0xBC520000u, 21u}, // scp -> Deva + {0xC8520000u, 55u}, // scs -> Latn + {0xCC520000u, 52u}, // sct -> Laoo + {0xD0520000u, 102u}, // scu -> Takr + {0xD4520000u, 55u}, // scv -> Latn + {0xD8520000u, 55u}, // scw -> Latn + {0xDC520000u, 30u}, // scx -> Grek {0x73640000u, 2u}, // sd -> Arab - {0x7364494Eu, 19u}, // sd-IN -> Deva - {0x88720000u, 46u}, // sdc -> Latn + {0x7364494Eu, 21u}, // sd-IN -> Deva + {0x80720000u, 55u}, // sda -> Latn + {0x84720000u, 2u}, // sdb -> Arab + {0x88720000u, 55u}, // sdc -> Latn + {0x90720000u, 55u}, // sde -> Latn + {0x94720000u, 2u}, // sdf -> Arab + {0x98720000u, 2u}, // sdg -> Arab {0x9C720000u, 2u}, // sdh -> Arab - {0x73650000u, 46u}, // se -> Latn - {0x94920000u, 46u}, // sef -> Latn - {0x9C920000u, 46u}, // seh -> Latn - {0xA0920000u, 46u}, // sei -> Latn - {0xC8920000u, 46u}, // ses -> Latn - {0x73670000u, 46u}, // sg -> Latn - {0x80D20000u, 63u}, // sga -> Ogam - {0xC8D20000u, 46u}, // sgs -> Latn - {0xD8D20000u, 21u}, // sgw -> Ethi - {0xE4D20000u, 46u}, // sgz -> Latn - {0x73680000u, 46u}, // sh -> Latn - {0xA0F20000u, 91u}, // shi -> Tfng - {0xA8F20000u, 46u}, // shk -> Latn - {0xB4F20000u, 59u}, // shn -> Mymr + {0xA4720000u, 55u}, // sdj -> Latn + {0xA8720000u, 55u}, // sdk -> Latn + {0xB4720000u, 55u}, // sdn -> Latn + {0xB8720000u, 55u}, // sdo -> Latn + {0xC0720000u, 55u}, // sdq -> Latn + {0xC4720000u, 9u}, // sdr -> Beng + {0xC8720000u, 2u}, // sds -> Arab + {0xD0720000u, 55u}, // sdu -> Latn + {0xDC720000u, 55u}, // sdx -> Latn + {0x73650000u, 55u}, // se -> Latn + {0x80920000u, 55u}, // sea -> Latn + {0x84920000u, 55u}, // seb -> Latn + {0x88920000u, 55u}, // sec -> Latn + {0x8C920000u, 55u}, // sed -> Latn + {0x90920000u, 55u}, // see -> Latn + {0x94920000u, 55u}, // sef -> Latn + {0x98920000u, 55u}, // seg -> Latn + {0x9C920000u, 55u}, // seh -> Latn + {0xA0920000u, 55u}, // sei -> Latn + {0xA4920000u, 55u}, // sej -> Latn + {0xA8920000u, 55u}, // sek -> Latn + {0xAC920000u, 20u}, // sel -> Cyrl + {0xB4920000u, 55u}, // sen -> Latn + {0xB8920000u, 55u}, // seo -> Latn + {0xBC920000u, 55u}, // sep -> Latn + {0xC0920000u, 55u}, // seq -> Latn + {0xC4920000u, 55u}, // ser -> Latn + {0xC8920000u, 55u}, // ses -> Latn + {0xCC920000u, 55u}, // set -> Latn + {0xD0920000u, 55u}, // seu -> Latn + {0xD4920000u, 55u}, // sev -> Latn + {0xD8920000u, 55u}, // sew -> Latn + {0xE0920000u, 55u}, // sey -> Latn + {0xE4920000u, 55u}, // sez -> Latn + {0x90B20000u, 55u}, // sfe -> Latn + {0xB0B20000u, 86u}, // sfm -> Plrd + {0xD8B20000u, 55u}, // sfw -> Latn + {0x73670000u, 55u}, // sg -> Latn + {0x80D20000u, 77u}, // sga -> Ogam + {0x84D20000u, 55u}, // sgb -> Latn + {0x88D20000u, 55u}, // sgc -> Latn + {0x8CD20000u, 55u}, // sgd -> Latn + {0x90D20000u, 55u}, // sge -> Latn + {0x9CD20000u, 20u}, // sgh -> Cyrl + {0xA0D20000u, 55u}, // sgi -> Latn + {0xA4D20000u, 21u}, // sgj -> Deva + {0xB0D20000u, 55u}, // sgm -> Latn + {0xBCD20000u, 55u}, // sgp -> Latn + {0xC4D20000u, 2u}, // sgr -> Arab + {0xC8D20000u, 55u}, // sgs -> Latn + {0xCCD20000u, 112u}, // sgt -> Tibt + {0xD0D20000u, 55u}, // sgu -> Latn + {0xD8D20000u, 24u}, // sgw -> Ethi + {0xE0D20000u, 2u}, // sgy -> Arab + {0xE4D20000u, 55u}, // sgz -> Latn + {0x80F20000u, 55u}, // sha -> Latn + {0x84F20000u, 55u}, // shb -> Latn + {0x88F20000u, 55u}, // shc -> Latn + {0x8CF20000u, 2u}, // shd -> Arab + {0x90F20000u, 55u}, // she -> Latn + {0x98F20000u, 55u}, // shg -> Latn + {0x9CF20000u, 55u}, // shh -> Latn + {0xA0F20000u, 109u}, // shi -> Tfng + {0xA4F20000u, 55u}, // shj -> Latn + {0xA8F20000u, 55u}, // shk -> Latn + {0xB0F20000u, 2u}, // shm -> Arab + {0xB4F20000u, 72u}, // shn -> Mymr + {0xB8F20000u, 55u}, // sho -> Latn + {0xBCF20000u, 55u}, // shp -> Latn + {0xC0F20000u, 55u}, // shq -> Latn + {0xC4F20000u, 55u}, // shr -> Latn + {0xC8F20000u, 55u}, // shs -> Latn + {0xCCF20000u, 55u}, // sht -> Latn {0xD0F20000u, 2u}, // shu -> Arab - {0x73690000u, 80u}, // si -> Sinh - {0x8D120000u, 46u}, // sid -> Latn - {0x99120000u, 46u}, // sig -> Latn - {0xAD120000u, 46u}, // sil -> Latn - {0xB1120000u, 46u}, // sim -> Latn - {0xC5320000u, 46u}, // sjr -> Latn - {0x736B0000u, 46u}, // sk -> Latn - {0x89520000u, 46u}, // skc -> Latn + {0xD4F20000u, 2u}, // shv -> Arab + {0xD8F20000u, 55u}, // shw -> Latn + {0xE0F20000u, 55u}, // shy -> Latn + {0xE4F20000u, 55u}, // shz -> Latn + {0x73690000u, 95u}, // si -> Sinh + {0x81120000u, 20u}, // sia -> Cyrl + {0x85120000u, 55u}, // sib -> Latn + {0x8D120000u, 55u}, // sid -> Latn + {0x91120000u, 55u}, // sie -> Latn + {0x95120000u, 55u}, // sif -> Latn + {0x99120000u, 55u}, // sig -> Latn + {0x9D120000u, 55u}, // sih -> Latn + {0xA1120000u, 55u}, // sii -> Latn + {0xA5120000u, 55u}, // sij -> Latn + {0xA9120000u, 55u}, // sik -> Latn + {0xAD120000u, 55u}, // sil -> Latn + {0xB1120000u, 55u}, // sim -> Latn + {0xBD120000u, 112u}, // sip -> Tibt + {0xC1120000u, 55u}, // siq -> Latn + {0xC5120000u, 55u}, // sir -> Latn + {0xC9120000u, 55u}, // sis -> Latn + {0xD1120000u, 55u}, // siu -> Latn + {0xD5120000u, 55u}, // siv -> Latn + {0xD9120000u, 55u}, // siw -> Latn + {0xDD120000u, 55u}, // six -> Latn + {0xE1120000u, 2u}, // siy -> Arab + {0xE5120000u, 2u}, // siz -> Arab + {0x81320000u, 55u}, // sja -> Latn + {0x85320000u, 55u}, // sjb -> Latn + {0x8D320000u, 20u}, // sjd -> Cyrl + {0x91320000u, 55u}, // sje -> Latn + {0x99320000u, 55u}, // sjg -> Latn + {0xAD320000u, 55u}, // sjl -> Latn + {0xB1320000u, 55u}, // sjm -> Latn + {0xBD320000u, 21u}, // sjp -> Deva + {0xC5320000u, 55u}, // sjr -> Latn + {0xCD320000u, 20u}, // sjt -> Cyrl + {0xD1320000u, 55u}, // sju -> Latn + {0xD9320000u, 55u}, // sjw -> Latn + {0x736B0000u, 55u}, // sk -> Latn + {0x81520000u, 55u}, // ska -> Latn + {0x85520000u, 111u}, // skb -> Thai + {0x89520000u, 55u}, // skc -> Latn + {0x8D520000u, 55u}, // skd -> Latn + {0x91520000u, 55u}, // ske -> Latn + {0x95520000u, 55u}, // skf -> Latn + {0x99520000u, 55u}, // skg -> Latn + {0x9D520000u, 55u}, // skh -> Latn + {0xA1520000u, 55u}, // ski -> Latn + {0xA5520000u, 21u}, // skj -> Deva + {0xB1520000u, 55u}, // skm -> Latn + {0xB5520000u, 55u}, // skn -> Latn + {0xB9520000u, 55u}, // sko -> Latn + {0xBD520000u, 55u}, // skp -> Latn + {0xC1520000u, 55u}, // skq -> Latn {0xC5520000u, 2u}, // skr -> Arab - {0xC9520000u, 46u}, // sks -> Latn - {0x736C0000u, 46u}, // sl -> Latn - {0x8D720000u, 46u}, // sld -> Latn - {0xA1720000u, 46u}, // sli -> Latn - {0xAD720000u, 46u}, // sll -> Latn - {0xE1720000u, 46u}, // sly -> Latn - {0x736D0000u, 46u}, // sm -> Latn - {0x81920000u, 46u}, // sma -> Latn - {0x8D920000u, 46u}, // smd -> Latn - {0xA5920000u, 46u}, // smj -> Latn - {0xB5920000u, 46u}, // smn -> Latn - {0xBD920000u, 76u}, // smp -> Samr - {0xC1920000u, 46u}, // smq -> Latn - {0xC9920000u, 46u}, // sms -> Latn - {0x736E0000u, 46u}, // sn -> Latn - {0x85B20000u, 46u}, // snb -> Latn - {0x89B20000u, 46u}, // snc -> Latn - {0xA9B20000u, 46u}, // snk -> Latn - {0xBDB20000u, 46u}, // snp -> Latn - {0xDDB20000u, 46u}, // snx -> Latn - {0xE1B20000u, 46u}, // sny -> Latn - {0x736F0000u, 46u}, // so -> Latn - {0x99D20000u, 81u}, // sog -> Sogd - {0xA9D20000u, 46u}, // sok -> Latn - {0xC1D20000u, 46u}, // soq -> Latn - {0xD1D20000u, 93u}, // sou -> Thai - {0xE1D20000u, 46u}, // soy -> Latn - {0x8DF20000u, 46u}, // spd -> Latn - {0xADF20000u, 46u}, // spl -> Latn - {0xC9F20000u, 46u}, // sps -> Latn - {0x73710000u, 46u}, // sq -> Latn - {0x73720000u, 18u}, // sr -> Cyrl - {0x73724D45u, 46u}, // sr-ME -> Latn - {0x7372524Fu, 46u}, // sr-RO -> Latn - {0x73725255u, 46u}, // sr-RU -> Latn - {0x73725452u, 46u}, // sr-TR -> Latn - {0x86320000u, 82u}, // srb -> Sora - {0xB6320000u, 46u}, // srn -> Latn - {0xC6320000u, 46u}, // srr -> Latn - {0xDE320000u, 19u}, // srx -> Deva - {0x73730000u, 46u}, // ss -> Latn - {0x8E520000u, 46u}, // ssd -> Latn - {0x9A520000u, 46u}, // ssg -> Latn - {0xE2520000u, 46u}, // ssy -> Latn - {0x73740000u, 46u}, // st -> Latn - {0xAA720000u, 46u}, // stk -> Latn - {0xC2720000u, 46u}, // stq -> Latn - {0x73750000u, 46u}, // su -> Latn - {0x82920000u, 46u}, // sua -> Latn - {0x92920000u, 46u}, // sue -> Latn - {0xAA920000u, 46u}, // suk -> Latn - {0xC6920000u, 46u}, // sur -> Latn - {0xCA920000u, 46u}, // sus -> Latn - {0x73760000u, 46u}, // sv -> Latn - {0x73770000u, 46u}, // sw -> Latn + {0xC9520000u, 55u}, // sks -> Latn + {0xCD520000u, 55u}, // skt -> Latn + {0xD1520000u, 55u}, // sku -> Latn + {0xD5520000u, 55u}, // skv -> Latn + {0xD9520000u, 55u}, // skw -> Latn + {0xDD520000u, 55u}, // skx -> Latn + {0xE1520000u, 55u}, // sky -> Latn + {0xE5520000u, 55u}, // skz -> Latn + {0x736C0000u, 55u}, // sl -> Latn + {0x89720000u, 55u}, // slc -> Latn + {0x8D720000u, 55u}, // sld -> Latn + {0x99720000u, 55u}, // slg -> Latn + {0x9D720000u, 55u}, // slh -> Latn + {0xA1720000u, 55u}, // sli -> Latn + {0xA5720000u, 55u}, // slj -> Latn + {0xAD720000u, 55u}, // sll -> Latn + {0xB1720000u, 55u}, // slm -> Latn + {0xB5720000u, 55u}, // sln -> Latn + {0xBD720000u, 55u}, // slp -> Latn + {0xC5720000u, 55u}, // slr -> Latn + {0xD1720000u, 55u}, // slu -> Latn + {0xD9720000u, 55u}, // slw -> Latn + {0xDD720000u, 55u}, // slx -> Latn + {0xE1720000u, 55u}, // sly -> Latn + {0xE5720000u, 55u}, // slz -> Latn + {0x736D0000u, 55u}, // sm -> Latn + {0x81920000u, 55u}, // sma -> Latn + {0x85920000u, 55u}, // smb -> Latn + {0x89920000u, 55u}, // smc -> Latn + {0x95920000u, 55u}, // smf -> Latn + {0x99920000u, 55u}, // smg -> Latn + {0x9D920000u, 120u}, // smh -> Yiii + {0xA5920000u, 55u}, // smj -> Latn + {0xA9920000u, 55u}, // smk -> Latn + {0xAD920000u, 55u}, // sml -> Latn + {0xB5920000u, 55u}, // smn -> Latn + {0xBD920000u, 91u}, // smp -> Samr + {0xC1920000u, 55u}, // smq -> Latn + {0xC5920000u, 55u}, // smr -> Latn + {0xC9920000u, 55u}, // sms -> Latn + {0xCD920000u, 55u}, // smt -> Latn + {0xD1920000u, 47u}, // smu -> Khmr + {0xD9920000u, 55u}, // smw -> Latn + {0xDD920000u, 55u}, // smx -> Latn + {0xE1920000u, 2u}, // smy -> Arab + {0xE5920000u, 55u}, // smz -> Latn + {0x736E0000u, 55u}, // sn -> Latn + {0x89B20000u, 55u}, // snc -> Latn + {0x91B20000u, 55u}, // sne -> Latn + {0x95B20000u, 55u}, // snf -> Latn + {0x99B20000u, 55u}, // sng -> Latn + {0xA1B20000u, 55u}, // sni -> Latn + {0xA5B20000u, 55u}, // snj -> Latn + {0xA9B20000u, 55u}, // snk -> Latn + {0xADB20000u, 55u}, // snl -> Latn + {0xB1B20000u, 55u}, // snm -> Latn + {0xB5B20000u, 55u}, // snn -> Latn + {0xB9B20000u, 55u}, // sno -> Latn + {0xBDB20000u, 55u}, // snp -> Latn + {0xC1B20000u, 55u}, // snq -> Latn + {0xC5B20000u, 55u}, // snr -> Latn + {0xC9B20000u, 55u}, // sns -> Latn + {0xD1B20000u, 55u}, // snu -> Latn + {0xD5B20000u, 55u}, // snv -> Latn + {0xD9B20000u, 55u}, // snw -> Latn + {0xDDB20000u, 55u}, // snx -> Latn + {0xE1B20000u, 55u}, // sny -> Latn + {0xE5B20000u, 55u}, // snz -> Latn + {0x736F0000u, 55u}, // so -> Latn + {0x81D20000u, 107u}, // soa -> Tavt + {0x85D20000u, 55u}, // sob -> Latn + {0x89D20000u, 55u}, // soc -> Latn + {0x8DD20000u, 55u}, // sod -> Latn + {0x91D20000u, 55u}, // soe -> Latn + {0x99D20000u, 96u}, // sog -> Sogd + {0xA1D20000u, 21u}, // soi -> Deva + {0xA9D20000u, 55u}, // sok -> Latn + {0xADD20000u, 55u}, // sol -> Latn + {0xB9D20000u, 55u}, // soo -> Latn + {0xBDD20000u, 55u}, // sop -> Latn + {0xC1D20000u, 55u}, // soq -> Latn + {0xC5D20000u, 55u}, // sor -> Latn + {0xC9D20000u, 55u}, // sos -> Latn + {0xD1D20000u, 111u}, // sou -> Thai + {0xD5D20000u, 55u}, // sov -> Latn + {0xD9D20000u, 55u}, // sow -> Latn + {0xDDD20000u, 55u}, // sox -> Latn + {0xE1D20000u, 55u}, // soy -> Latn + {0xE5D20000u, 55u}, // soz -> Latn + {0x85F20000u, 55u}, // spb -> Latn + {0x89F20000u, 55u}, // spc -> Latn + {0x8DF20000u, 55u}, // spd -> Latn + {0x91F20000u, 55u}, // spe -> Latn + {0x99F20000u, 55u}, // spg -> Latn + {0xA1F20000u, 55u}, // spi -> Latn + {0xA9F20000u, 55u}, // spk -> Latn + {0xADF20000u, 55u}, // spl -> Latn + {0xB1F20000u, 55u}, // spm -> Latn + {0xB5F20000u, 55u}, // spn -> Latn + {0xB9F20000u, 55u}, // spo -> Latn + {0xBDF20000u, 55u}, // spp -> Latn + {0xC1F20000u, 55u}, // spq -> Latn + {0xC5F20000u, 55u}, // spr -> Latn + {0xC9F20000u, 55u}, // sps -> Latn + {0xCDF20000u, 112u}, // spt -> Tibt + {0xD5F20000u, 80u}, // spv -> Orya + {0x73710000u, 55u}, // sq -> Latn + {0x82120000u, 55u}, // sqa -> Latn + {0x9E120000u, 55u}, // sqh -> Latn + {0xB2120000u, 55u}, // sqm -> Latn + {0xBA120000u, 2u}, // sqo -> Arab + {0xC2120000u, 52u}, // sqq -> Laoo + {0xCE120000u, 2u}, // sqt -> Arab + {0xD2120000u, 55u}, // squ -> Latn + {0x73720000u, 20u}, // sr -> Cyrl + {0x73724D45u, 55u}, // sr-ME -> Latn + {0x7372524Fu, 55u}, // sr-RO -> Latn + {0x73725255u, 55u}, // sr-RU -> Latn + {0x73725452u, 55u}, // sr-TR -> Latn + {0x82320000u, 55u}, // sra -> Latn + {0x86320000u, 97u}, // srb -> Sora + {0x92320000u, 55u}, // sre -> Latn + {0x96320000u, 55u}, // srf -> Latn + {0x9A320000u, 55u}, // srg -> Latn + {0x9E320000u, 2u}, // srh -> Arab + {0xA2320000u, 55u}, // sri -> Latn + {0xAA320000u, 55u}, // srk -> Latn + {0xAE320000u, 55u}, // srl -> Latn + {0xB2320000u, 55u}, // srm -> Latn + {0xB6320000u, 55u}, // srn -> Latn + {0xBA320000u, 55u}, // sro -> Latn + {0xC2320000u, 55u}, // srq -> Latn + {0xC6320000u, 55u}, // srr -> Latn + {0xCA320000u, 55u}, // srs -> Latn + {0xCE320000u, 55u}, // srt -> Latn + {0xD2320000u, 55u}, // sru -> Latn + {0xD6320000u, 55u}, // srv -> Latn + {0xDA320000u, 55u}, // srw -> Latn + {0xDE320000u, 21u}, // srx -> Deva + {0xE2320000u, 55u}, // sry -> Latn + {0xE6320000u, 2u}, // srz -> Arab + {0x73730000u, 55u}, // ss -> Latn + {0x86520000u, 55u}, // ssb -> Latn + {0x8A520000u, 55u}, // ssc -> Latn + {0x8E520000u, 55u}, // ssd -> Latn + {0x92520000u, 55u}, // sse -> Latn + {0x96520000u, 55u}, // ssf -> Latn + {0x9A520000u, 55u}, // ssg -> Latn + {0x9E520000u, 2u}, // ssh -> Arab + {0xA6520000u, 55u}, // ssj -> Latn + {0xAE520000u, 55u}, // ssl -> Latn + {0xB2520000u, 55u}, // ssm -> Latn + {0xB6520000u, 55u}, // ssn -> Latn + {0xBA520000u, 55u}, // sso -> Latn + {0xC2520000u, 55u}, // ssq -> Latn + {0xCA520000u, 52u}, // sss -> Laoo + {0xCE520000u, 55u}, // sst -> Latn + {0xD2520000u, 55u}, // ssu -> Latn + {0xD6520000u, 55u}, // ssv -> Latn + {0xDE520000u, 55u}, // ssx -> Latn + {0xE2520000u, 55u}, // ssy -> Latn + {0xE6520000u, 55u}, // ssz -> Latn + {0x73740000u, 55u}, // st -> Latn + {0x82720000u, 55u}, // sta -> Latn + {0x86720000u, 55u}, // stb -> Latn + {0x92720000u, 55u}, // ste -> Latn + {0x96720000u, 55u}, // stf -> Latn + {0x9A720000u, 55u}, // stg -> Latn + {0x9E720000u, 55u}, // sth -> Latn + {0xA2720000u, 55u}, // sti -> Latn + {0xA6720000u, 55u}, // stj -> Latn + {0xAA720000u, 55u}, // stk -> Latn + {0xAE720000u, 55u}, // stl -> Latn + {0xB2720000u, 55u}, // stm -> Latn + {0xB6720000u, 55u}, // stn -> Latn + {0xBA720000u, 55u}, // sto -> Latn + {0xBE720000u, 55u}, // stp -> Latn + {0xC2720000u, 55u}, // stq -> Latn + {0xC6720000u, 55u}, // str -> Latn + {0xCA720000u, 2u}, // sts -> Arab + {0xCE720000u, 55u}, // stt -> Latn + {0xD6720000u, 24u}, // stv -> Ethi + {0xDA720000u, 55u}, // stw -> Latn + {0xE2720000u, 20u}, // sty -> Cyrl + {0x73750000u, 55u}, // su -> Latn + {0x82920000u, 55u}, // sua -> Latn + {0x86920000u, 55u}, // sub -> Latn + {0x8A920000u, 55u}, // suc -> Latn + {0x92920000u, 55u}, // sue -> Latn + {0x9A920000u, 55u}, // sug -> Latn + {0xA2920000u, 55u}, // sui -> Latn + {0xA6920000u, 55u}, // suj -> Latn + {0xAA920000u, 55u}, // suk -> Latn + {0xBA920000u, 55u}, // suo -> Latn + {0xC2920000u, 55u}, // suq -> Latn + {0xC6920000u, 55u}, // sur -> Latn + {0xCA920000u, 55u}, // sus -> Latn + {0xCE920000u, 55u}, // sut -> Latn + {0xD6920000u, 55u}, // suv -> Latn + {0xDA920000u, 55u}, // suw -> Latn + {0xE2920000u, 55u}, // suy -> Latn + {0xE6920000u, 99u}, // suz -> Sunu + {0x73760000u, 55u}, // sv -> Latn + {0x82B20000u, 25u}, // sva -> Geor + {0x86B20000u, 55u}, // svb -> Latn + {0x8AB20000u, 55u}, // svc -> Latn + {0x92B20000u, 55u}, // sve -> Latn + {0xB2B20000u, 55u}, // svm -> Latn + {0xCAB20000u, 55u}, // svs -> Latn + {0x73770000u, 55u}, // sw -> Latn {0x86D20000u, 2u}, // swb -> Arab - {0x8AD20000u, 46u}, // swc -> Latn - {0x9AD20000u, 46u}, // swg -> Latn - {0xBED20000u, 46u}, // swp -> Latn - {0xD6D20000u, 19u}, // swv -> Deva - {0xB6F20000u, 46u}, // sxn -> Latn - {0xDAF20000u, 46u}, // sxw -> Latn - {0xAF120000u, 8u}, // syl -> Beng - {0xC7120000u, 84u}, // syr -> Syrc - {0xAF320000u, 46u}, // szl -> Latn - {0x74610000u, 87u}, // ta -> Taml - {0xA4130000u, 19u}, // taj -> Deva - {0xAC130000u, 46u}, // tal -> Latn - {0xB4130000u, 46u}, // tan -> Latn - {0xC0130000u, 46u}, // taq -> Latn - {0x88330000u, 46u}, // tbc -> Latn - {0x8C330000u, 46u}, // tbd -> Latn - {0x94330000u, 46u}, // tbf -> Latn - {0x98330000u, 46u}, // tbg -> Latn - {0xB8330000u, 46u}, // tbo -> Latn - {0xD8330000u, 46u}, // tbw -> Latn - {0xE4330000u, 46u}, // tbz -> Latn - {0xA0530000u, 46u}, // tci -> Latn - {0xE0530000u, 42u}, // tcy -> Knda - {0x8C730000u, 85u}, // tdd -> Tale - {0x98730000u, 19u}, // tdg -> Deva - {0x9C730000u, 19u}, // tdh -> Deva - {0xD0730000u, 46u}, // tdu -> Latn - {0x74650000u, 90u}, // te -> Telu - {0x8C930000u, 46u}, // ted -> Latn - {0xB0930000u, 46u}, // tem -> Latn - {0xB8930000u, 46u}, // teo -> Latn - {0xCC930000u, 46u}, // tet -> Latn - {0xA0B30000u, 46u}, // tfi -> Latn - {0x74670000u, 18u}, // tg -> Cyrl + {0x96D20000u, 55u}, // swf -> Latn + {0x9AD20000u, 55u}, // swg -> Latn + {0xA2D20000u, 34u}, // swi -> Hani + {0xA6D20000u, 55u}, // swj -> Latn + {0xAAD20000u, 55u}, // swk -> Latn + {0xB2D20000u, 55u}, // swm -> Latn + {0xBAD20000u, 55u}, // swo -> Latn + {0xBED20000u, 55u}, // swp -> Latn + {0xC2D20000u, 55u}, // swq -> Latn + {0xC6D20000u, 55u}, // swr -> Latn + {0xCAD20000u, 55u}, // sws -> Latn + {0xCED20000u, 55u}, // swt -> Latn + {0xD2D20000u, 55u}, // swu -> Latn + {0xD6D20000u, 21u}, // swv -> Deva + {0xDAD20000u, 55u}, // sww -> Latn + {0xDED20000u, 55u}, // swx -> Latn + {0xE2D20000u, 55u}, // swy -> Latn + {0x86F20000u, 55u}, // sxb -> Latn + {0x92F20000u, 55u}, // sxe -> Latn + {0xB6F20000u, 55u}, // sxn -> Latn + {0xC6F20000u, 55u}, // sxr -> Latn + {0xCAF20000u, 55u}, // sxs -> Latn + {0xD2F20000u, 90u}, // sxu -> Runr + {0xDAF20000u, 55u}, // sxw -> Latn + {0x83120000u, 55u}, // sya -> Latn + {0x87120000u, 55u}, // syb -> Latn + {0x8B120000u, 100u}, // syc -> Syrc + {0xA3120000u, 55u}, // syi -> Latn + {0xAB120000u, 55u}, // syk -> Latn + {0xAF120000u, 9u}, // syl -> Beng + {0xB3120000u, 55u}, // sym -> Latn + {0xB7120000u, 100u}, // syn -> Syrc + {0xBB120000u, 55u}, // syo -> Latn + {0xC7120000u, 100u}, // syr -> Syrc + {0xCB120000u, 55u}, // sys -> Latn + {0xDB120000u, 21u}, // syw -> Deva + {0xDF120000u, 55u}, // syx -> Latn + {0x83320000u, 55u}, // sza -> Latn + {0x87320000u, 55u}, // szb -> Latn + {0x8B320000u, 55u}, // szc -> Latn + {0x9B320000u, 55u}, // szg -> Latn + {0xAF320000u, 55u}, // szl -> Latn + {0xB7320000u, 55u}, // szn -> Latn + {0xBF320000u, 55u}, // szp -> Latn + {0xD7320000u, 55u}, // szv -> Latn + {0xDB320000u, 55u}, // szw -> Latn + {0xE3320000u, 55u}, // szy -> Latn + {0x74610000u, 105u}, // ta -> Taml + {0x80130000u, 55u}, // taa -> Latn + {0x84130000u, 20u}, // tab -> Cyrl + {0x88130000u, 55u}, // tac -> Latn + {0x8C130000u, 55u}, // tad -> Latn + {0x90130000u, 55u}, // tae -> Latn + {0x94130000u, 55u}, // taf -> Latn + {0x98130000u, 55u}, // tag -> Latn + {0xA4130000u, 21u}, // taj -> Deva + {0xA8130000u, 55u}, // tak -> Latn + {0xAC130000u, 55u}, // tal -> Latn + {0xB4130000u, 55u}, // tan -> Latn + {0xB8130000u, 55u}, // tao -> Latn + {0xBC130000u, 55u}, // tap -> Latn + {0xC0130000u, 55u}, // taq -> Latn + {0xC4130000u, 55u}, // tar -> Latn + {0xC8130000u, 55u}, // tas -> Latn + {0xD0130000u, 55u}, // tau -> Latn + {0xD4130000u, 55u}, // tav -> Latn + {0xD8130000u, 55u}, // taw -> Latn + {0xDC130000u, 55u}, // tax -> Latn + {0xE0130000u, 55u}, // tay -> Latn + {0xE4130000u, 55u}, // taz -> Latn + {0x80330000u, 55u}, // tba -> Latn + {0x88330000u, 55u}, // tbc -> Latn + {0x8C330000u, 55u}, // tbd -> Latn + {0x90330000u, 55u}, // tbe -> Latn + {0x94330000u, 55u}, // tbf -> Latn + {0x98330000u, 55u}, // tbg -> Latn + {0x9C330000u, 55u}, // tbh -> Latn + {0xA0330000u, 55u}, // tbi -> Latn + {0xA4330000u, 55u}, // tbj -> Latn + {0xA8330000u, 101u}, // tbk -> Tagb + {0xAC330000u, 55u}, // tbl -> Latn + {0xB0330000u, 55u}, // tbm -> Latn + {0xB4330000u, 55u}, // tbn -> Latn + {0xB8330000u, 55u}, // tbo -> Latn + {0xBC330000u, 55u}, // tbp -> Latn + {0xC8330000u, 55u}, // tbs -> Latn + {0xCC330000u, 55u}, // tbt -> Latn + {0xD0330000u, 55u}, // tbu -> Latn + {0xD4330000u, 55u}, // tbv -> Latn + {0xD8330000u, 55u}, // tbw -> Latn + {0xDC330000u, 55u}, // tbx -> Latn + {0xE0330000u, 55u}, // tby -> Latn + {0xE4330000u, 55u}, // tbz -> Latn + {0x80530000u, 55u}, // tca -> Latn + {0x84530000u, 55u}, // tcb -> Latn + {0x88530000u, 55u}, // tcc -> Latn + {0x8C530000u, 55u}, // tcd -> Latn + {0x90530000u, 55u}, // tce -> Latn + {0x94530000u, 55u}, // tcf -> Latn + {0x98530000u, 55u}, // tcg -> Latn + {0x9C530000u, 55u}, // tch -> Latn + {0xA0530000u, 55u}, // tci -> Latn + {0xA8530000u, 55u}, // tck -> Latn + {0xB0530000u, 55u}, // tcm -> Latn + {0xB4530000u, 112u}, // tcn -> Tibt + {0xB8530000u, 72u}, // tco -> Mymr + {0xBC530000u, 55u}, // tcp -> Latn + {0xC0530000u, 55u}, // tcq -> Latn + {0xC8530000u, 55u}, // tcs -> Latn + {0xD0530000u, 55u}, // tcu -> Latn + {0xD8530000u, 55u}, // tcw -> Latn + {0xDC530000u, 105u}, // tcx -> Taml + {0xE0530000u, 49u}, // tcy -> Knda + {0xE4530000u, 55u}, // tcz -> Latn + {0x80730000u, 109u}, // tda -> Tfng + {0x84730000u, 21u}, // tdb -> Deva + {0x88730000u, 55u}, // tdc -> Latn + {0x8C730000u, 103u}, // tdd -> Tale + {0x90730000u, 55u}, // tde -> Latn + {0x98730000u, 21u}, // tdg -> Deva + {0x9C730000u, 21u}, // tdh -> Deva + {0xA0730000u, 55u}, // tdi -> Latn + {0xA4730000u, 55u}, // tdj -> Latn + {0xA8730000u, 55u}, // tdk -> Latn + {0xAC730000u, 55u}, // tdl -> Latn + {0xB0730000u, 55u}, // tdm -> Latn + {0xB4730000u, 55u}, // tdn -> Latn + {0xB8730000u, 55u}, // tdo -> Latn + {0xC0730000u, 55u}, // tdq -> Latn + {0xC4730000u, 55u}, // tdr -> Latn + {0xC8730000u, 55u}, // tds -> Latn + {0xCC730000u, 55u}, // tdt -> Latn + {0xD4730000u, 55u}, // tdv -> Latn + {0xDC730000u, 55u}, // tdx -> Latn + {0xE0730000u, 55u}, // tdy -> Latn + {0x74650000u, 108u}, // te -> Telu + {0x80930000u, 55u}, // tea -> Latn + {0x84930000u, 55u}, // teb -> Latn + {0x88930000u, 55u}, // tec -> Latn + {0x8C930000u, 55u}, // ted -> Latn + {0x90930000u, 55u}, // tee -> Latn + {0x98930000u, 55u}, // teg -> Latn + {0x9C930000u, 55u}, // teh -> Latn + {0xA0930000u, 55u}, // tei -> Latn + {0xA8930000u, 55u}, // tek -> Latn + {0xB0930000u, 55u}, // tem -> Latn + {0xB4930000u, 55u}, // ten -> Latn + {0xB8930000u, 55u}, // teo -> Latn + {0xBC930000u, 55u}, // tep -> Latn + {0xC0930000u, 55u}, // teq -> Latn + {0xC4930000u, 55u}, // ter -> Latn + {0xC8930000u, 41u}, // tes -> Java + {0xCC930000u, 55u}, // tet -> Latn + {0xD0930000u, 55u}, // teu -> Latn + {0xD4930000u, 55u}, // tev -> Latn + {0xD8930000u, 55u}, // tew -> Latn + {0xDC930000u, 55u}, // tex -> Latn + {0xE0930000u, 55u}, // tey -> Latn + {0xE4930000u, 55u}, // tez -> Latn + {0xA0B30000u, 55u}, // tfi -> Latn + {0xB4B30000u, 55u}, // tfn -> Latn + {0xB8B30000u, 55u}, // tfo -> Latn + {0xC4B30000u, 55u}, // tfr -> Latn + {0xCCB30000u, 55u}, // tft -> Latn + {0x74670000u, 20u}, // tg -> Cyrl {0x7467504Bu, 2u}, // tg-PK -> Arab - {0x88D30000u, 46u}, // tgc -> Latn - {0xB8D30000u, 46u}, // tgo -> Latn - {0xD0D30000u, 46u}, // tgu -> Latn - {0x74680000u, 93u}, // th -> Thai - {0xACF30000u, 19u}, // thl -> Deva - {0xC0F30000u, 19u}, // thq -> Deva - {0xC4F30000u, 19u}, // thr -> Deva - {0x74690000u, 21u}, // ti -> Ethi - {0x95130000u, 46u}, // tif -> Latn - {0x99130000u, 21u}, // tig -> Ethi - {0xA9130000u, 46u}, // tik -> Latn - {0xB1130000u, 46u}, // tim -> Latn - {0xB9130000u, 46u}, // tio -> Latn - {0xD5130000u, 46u}, // tiv -> Latn - {0x746B0000u, 46u}, // tk -> Latn - {0xAD530000u, 46u}, // tkl -> Latn - {0xC5530000u, 46u}, // tkr -> Latn - {0xCD530000u, 19u}, // tkt -> Deva - {0x746C0000u, 46u}, // tl -> Latn - {0x95730000u, 46u}, // tlf -> Latn - {0xDD730000u, 46u}, // tlx -> Latn - {0xE1730000u, 46u}, // tly -> Latn - {0x9D930000u, 46u}, // tmh -> Latn - {0xE1930000u, 46u}, // tmy -> Latn - {0x746E0000u, 46u}, // tn -> Latn - {0x9DB30000u, 46u}, // tnh -> Latn - {0x746F0000u, 46u}, // to -> Latn - {0x95D30000u, 46u}, // tof -> Latn - {0x99D30000u, 46u}, // tog -> Latn - {0xA9D30000u, 46u}, // tok -> Latn - {0xC1D30000u, 46u}, // toq -> Latn - {0xA1F30000u, 46u}, // tpi -> Latn - {0xB1F30000u, 46u}, // tpm -> Latn - {0xE5F30000u, 46u}, // tpz -> Latn - {0xBA130000u, 46u}, // tqo -> Latn - {0x74720000u, 46u}, // tr -> Latn - {0xD2330000u, 46u}, // tru -> Latn - {0xD6330000u, 46u}, // trv -> Latn + {0x80D30000u, 55u}, // tga -> Latn + {0x84D30000u, 55u}, // tgb -> Latn + {0x88D30000u, 55u}, // tgc -> Latn + {0x8CD30000u, 55u}, // tgd -> Latn + {0x90D30000u, 21u}, // tge -> Deva + {0x94D30000u, 112u}, // tgf -> Tibt + {0x9CD30000u, 55u}, // tgh -> Latn + {0xA0D30000u, 55u}, // tgi -> Latn + {0xA4D30000u, 55u}, // tgj -> Latn + {0xB4D30000u, 55u}, // tgn -> Latn + {0xB8D30000u, 55u}, // tgo -> Latn + {0xBCD30000u, 55u}, // tgp -> Latn + {0xC0D30000u, 55u}, // tgq -> Latn + {0xC8D30000u, 55u}, // tgs -> Latn + {0xCCD30000u, 55u}, // tgt -> Latn + {0xD0D30000u, 55u}, // tgu -> Latn + {0xD4D30000u, 55u}, // tgv -> Latn + {0xD8D30000u, 55u}, // tgw -> Latn + {0xDCD30000u, 55u}, // tgx -> Latn + {0xE0D30000u, 55u}, // tgy -> Latn + {0xE4D30000u, 55u}, // tgz -> Latn + {0x74680000u, 111u}, // th -> Thai + {0x8CF30000u, 55u}, // thd -> Latn + {0x90F30000u, 21u}, // the -> Deva + {0x94F30000u, 21u}, // thf -> Deva + {0x9CF30000u, 55u}, // thh -> Latn + {0xA0F30000u, 103u}, // thi -> Tale + {0xA8F30000u, 55u}, // thk -> Latn + {0xACF30000u, 21u}, // thl -> Deva + {0xB0F30000u, 111u}, // thm -> Thai + {0xBCF30000u, 55u}, // thp -> Latn + {0xC0F30000u, 21u}, // thq -> Deva + {0xC4F30000u, 21u}, // thr -> Deva + {0xC8F30000u, 21u}, // ths -> Deva + {0xCCF30000u, 55u}, // tht -> Latn + {0xD0F30000u, 55u}, // thu -> Latn + {0xD4F30000u, 55u}, // thv -> Latn + {0xE0F30000u, 55u}, // thy -> Latn + {0xE4F30000u, 55u}, // thz -> Latn + {0x74690000u, 24u}, // ti -> Ethi + {0x89130000u, 55u}, // tic -> Latn + {0x95130000u, 55u}, // tif -> Latn + {0x99130000u, 24u}, // tig -> Ethi + {0x9D130000u, 55u}, // tih -> Latn + {0xA1130000u, 55u}, // tii -> Latn + {0xA5130000u, 21u}, // tij -> Deva + {0xA9130000u, 55u}, // tik -> Latn + {0xAD130000u, 55u}, // til -> Latn + {0xB1130000u, 55u}, // tim -> Latn + {0xB5130000u, 20u}, // tin -> Cyrl + {0xB9130000u, 55u}, // tio -> Latn + {0xBD130000u, 55u}, // tip -> Latn + {0xC1130000u, 55u}, // tiq -> Latn + {0xC9130000u, 55u}, // tis -> Latn + {0xCD130000u, 55u}, // tit -> Latn + {0xD1130000u, 55u}, // tiu -> Latn + {0xD5130000u, 55u}, // tiv -> Latn + {0xD9130000u, 55u}, // tiw -> Latn + {0xDD130000u, 55u}, // tix -> Latn + {0xE1130000u, 55u}, // tiy -> Latn + {0x81330000u, 55u}, // tja -> Latn + {0x99330000u, 55u}, // tjg -> Latn + {0xA1330000u, 55u}, // tji -> Latn + {0xA5330000u, 55u}, // tjj -> Latn + {0xAD330000u, 72u}, // tjl -> Mymr + {0xB5330000u, 55u}, // tjn -> Latn + {0xB9330000u, 2u}, // tjo -> Arab + {0xBD330000u, 55u}, // tjp -> Latn + {0xC9330000u, 55u}, // tjs -> Latn + {0xD1330000u, 55u}, // tju -> Latn + {0xD9330000u, 55u}, // tjw -> Latn + {0x746B0000u, 55u}, // tk -> Latn + {0x81530000u, 55u}, // tka -> Latn + {0x85530000u, 21u}, // tkb -> Deva + {0x8D530000u, 55u}, // tkd -> Latn + {0x91530000u, 55u}, // tke -> Latn + {0x95530000u, 55u}, // tkf -> Latn + {0x99530000u, 55u}, // tkg -> Latn + {0xAD530000u, 55u}, // tkl -> Latn + {0xBD530000u, 55u}, // tkp -> Latn + {0xC1530000u, 55u}, // tkq -> Latn + {0xC5530000u, 55u}, // tkr -> Latn + {0xC9530000u, 2u}, // tks -> Arab + {0xCD530000u, 21u}, // tkt -> Deva + {0xD1530000u, 55u}, // tku -> Latn + {0xD5530000u, 55u}, // tkv -> Latn + {0xD9530000u, 55u}, // tkw -> Latn + {0xDD530000u, 55u}, // tkx -> Latn + {0xE5530000u, 55u}, // tkz -> Latn + {0x746C0000u, 55u}, // tl -> Latn + {0x81730000u, 55u}, // tla -> Latn + {0x85730000u, 55u}, // tlb -> Latn + {0x89730000u, 55u}, // tlc -> Latn + {0x8D730000u, 55u}, // tld -> Latn + {0x95730000u, 55u}, // tlf -> Latn + {0x99730000u, 55u}, // tlg -> Latn + {0xA1730000u, 55u}, // tli -> Latn + {0xA5730000u, 55u}, // tlj -> Latn + {0xA9730000u, 55u}, // tlk -> Latn + {0xAD730000u, 55u}, // tll -> Latn + {0xB1730000u, 55u}, // tlm -> Latn + {0xB5730000u, 55u}, // tln -> Latn + {0xBD730000u, 55u}, // tlp -> Latn + {0xC1730000u, 55u}, // tlq -> Latn + {0xC5730000u, 55u}, // tlr -> Latn + {0xC9730000u, 55u}, // tls -> Latn + {0xCD730000u, 55u}, // tlt -> Latn + {0xD1730000u, 55u}, // tlu -> Latn + {0xD5730000u, 55u}, // tlv -> Latn + {0xDD730000u, 55u}, // tlx -> Latn + {0xE1730000u, 55u}, // tly -> Latn + {0x81930000u, 55u}, // tma -> Latn + {0x85930000u, 55u}, // tmb -> Latn + {0x89930000u, 55u}, // tmc -> Latn + {0x8D930000u, 55u}, // tmd -> Latn + {0x91930000u, 55u}, // tme -> Latn + {0x95930000u, 55u}, // tmf -> Latn + {0x99930000u, 55u}, // tmg -> Latn + {0x9D930000u, 55u}, // tmh -> Latn + {0xA1930000u, 55u}, // tmi -> Latn + {0xA5930000u, 55u}, // tmj -> Latn + {0xAD930000u, 55u}, // tml -> Latn + {0xB1930000u, 55u}, // tmm -> Latn + {0xB5930000u, 55u}, // tmn -> Latn + {0xB9930000u, 55u}, // tmo -> Latn + {0xC1930000u, 55u}, // tmq -> Latn + {0xC5930000u, 100u}, // tmr -> Syrc + {0xCD930000u, 55u}, // tmt -> Latn + {0xD1930000u, 55u}, // tmu -> Latn + {0xD5930000u, 55u}, // tmv -> Latn + {0xD9930000u, 55u}, // tmw -> Latn + {0xE1930000u, 55u}, // tmy -> Latn + {0xE5930000u, 55u}, // tmz -> Latn + {0x746E0000u, 55u}, // tn -> Latn + {0x81B30000u, 55u}, // tna -> Latn + {0x85B30000u, 55u}, // tnb -> Latn + {0x89B30000u, 55u}, // tnc -> Latn + {0x8DB30000u, 55u}, // tnd -> Latn + {0x99B30000u, 55u}, // tng -> Latn + {0x9DB30000u, 55u}, // tnh -> Latn + {0xA1B30000u, 55u}, // tni -> Latn + {0xA9B30000u, 55u}, // tnk -> Latn + {0xADB30000u, 55u}, // tnl -> Latn + {0xB1B30000u, 55u}, // tnm -> Latn + {0xB5B30000u, 55u}, // tnn -> Latn + {0xB9B30000u, 55u}, // tno -> Latn + {0xBDB30000u, 55u}, // tnp -> Latn + {0xC1B30000u, 55u}, // tnq -> Latn + {0xC5B30000u, 55u}, // tnr -> Latn + {0xC9B30000u, 55u}, // tns -> Latn + {0xCDB30000u, 55u}, // tnt -> Latn + {0xD5B30000u, 12u}, // tnv -> Cakm + {0xD9B30000u, 55u}, // tnw -> Latn + {0xDDB30000u, 55u}, // tnx -> Latn + {0xE1B30000u, 55u}, // tny -> Latn + {0x746F0000u, 55u}, // to -> Latn + {0x85D30000u, 55u}, // tob -> Latn + {0x89D30000u, 55u}, // toc -> Latn + {0x8DD30000u, 55u}, // tod -> Latn + {0x95D30000u, 55u}, // tof -> Latn + {0x99D30000u, 55u}, // tog -> Latn + {0x9DD30000u, 55u}, // toh -> Latn + {0xA1D30000u, 55u}, // toi -> Latn + {0xA5D30000u, 55u}, // toj -> Latn + {0xA9D30000u, 55u}, // tok -> Latn + {0xADD30000u, 55u}, // tol -> Latn + {0xB1D30000u, 55u}, // tom -> Latn + {0xB9D30000u, 55u}, // too -> Latn + {0xBDD30000u, 55u}, // top -> Latn + {0xC1D30000u, 55u}, // toq -> Latn + {0xC5D30000u, 55u}, // tor -> Latn + {0xC9D30000u, 55u}, // tos -> Latn + {0xD1D30000u, 55u}, // tou -> Latn + {0xD5D30000u, 2u}, // tov -> Arab + {0xD9D30000u, 55u}, // tow -> Latn + {0xDDD30000u, 55u}, // tox -> Latn + {0xE1D30000u, 55u}, // toy -> Latn + {0xE5D30000u, 55u}, // toz -> Latn + {0x81F30000u, 55u}, // tpa -> Latn + {0x89F30000u, 55u}, // tpc -> Latn + {0x91F30000u, 55u}, // tpe -> Latn + {0x95F30000u, 55u}, // tpf -> Latn + {0x99F30000u, 55u}, // tpg -> Latn + {0xA1F30000u, 55u}, // tpi -> Latn + {0xA5F30000u, 55u}, // tpj -> Latn + {0xA9F30000u, 55u}, // tpk -> Latn + {0xADF30000u, 55u}, // tpl -> Latn + {0xB1F30000u, 55u}, // tpm -> Latn + {0xB5F30000u, 55u}, // tpn -> Latn + {0xBDF30000u, 55u}, // tpp -> Latn + {0xC5F30000u, 55u}, // tpr -> Latn + {0xCDF30000u, 55u}, // tpt -> Latn + {0xD1F30000u, 47u}, // tpu -> Khmr + {0xD5F30000u, 55u}, // tpv -> Latn + {0xDDF30000u, 55u}, // tpx -> Latn + {0xE1F30000u, 55u}, // tpy -> Latn + {0xE5F30000u, 55u}, // tpz -> Latn + {0x86130000u, 55u}, // tqb -> Latn + {0xAE130000u, 55u}, // tql -> Latn + {0xB2130000u, 55u}, // tqm -> Latn + {0xB6130000u, 55u}, // tqn -> Latn + {0xBA130000u, 55u}, // tqo -> Latn + {0xBE130000u, 55u}, // tqp -> Latn + {0xCE130000u, 55u}, // tqt -> Latn + {0xD2130000u, 55u}, // tqu -> Latn + {0xDA130000u, 55u}, // tqw -> Latn + {0x74720000u, 55u}, // tr -> Latn + {0x82330000u, 2u}, // tra -> Arab + {0x86330000u, 55u}, // trb -> Latn + {0x8A330000u, 55u}, // trc -> Latn + {0x92330000u, 55u}, // tre -> Latn + {0x96330000u, 55u}, // trf -> Latn + {0x9A330000u, 37u}, // trg -> Hebr + {0x9E330000u, 55u}, // trh -> Latn + {0xA2330000u, 55u}, // tri -> Latn + {0xA6330000u, 55u}, // trj -> Latn + {0xAE330000u, 55u}, // trl -> Latn + {0xB2330000u, 2u}, // trm -> Arab + {0xB6330000u, 55u}, // trn -> Latn + {0xBA330000u, 55u}, // tro -> Latn + {0xBE330000u, 55u}, // trp -> Latn + {0xC2330000u, 55u}, // trq -> Latn + {0xC6330000u, 55u}, // trr -> Latn + {0xCA330000u, 55u}, // trs -> Latn + {0xCE330000u, 55u}, // trt -> Latn + {0xD2330000u, 55u}, // tru -> Latn + {0xD6330000u, 55u}, // trv -> Latn {0xDA330000u, 2u}, // trw -> Arab - {0x74730000u, 46u}, // ts -> Latn - {0x8E530000u, 26u}, // tsd -> Grek - {0x96530000u, 19u}, // tsf -> Deva - {0x9A530000u, 46u}, // tsg -> Latn - {0xA6530000u, 94u}, // tsj -> Tibt - {0xDA530000u, 46u}, // tsw -> Latn - {0x74740000u, 18u}, // tt -> Cyrl - {0x8E730000u, 46u}, // ttd -> Latn - {0x92730000u, 46u}, // tte -> Latn - {0xA6730000u, 46u}, // ttj -> Latn - {0xC6730000u, 46u}, // ttr -> Latn - {0xCA730000u, 93u}, // tts -> Thai - {0xCE730000u, 46u}, // ttt -> Latn - {0x9E930000u, 46u}, // tuh -> Latn - {0xAE930000u, 46u}, // tul -> Latn - {0xB2930000u, 46u}, // tum -> Latn - {0xC2930000u, 46u}, // tuq -> Latn - {0x8EB30000u, 46u}, // tvd -> Latn - {0xAEB30000u, 46u}, // tvl -> Latn - {0xD2B30000u, 46u}, // tvu -> Latn - {0x9ED30000u, 46u}, // twh -> Latn - {0xC2D30000u, 46u}, // twq -> Latn - {0x9AF30000u, 88u}, // txg -> Tang - {0xBAF30000u, 96u}, // txo -> Toto - {0x74790000u, 46u}, // ty -> Latn - {0x83130000u, 46u}, // tya -> Latn - {0xD7130000u, 18u}, // tyv -> Cyrl - {0xB3330000u, 46u}, // tzm -> Latn - {0xD0340000u, 46u}, // ubu -> Latn - {0xA0740000u, 0u}, // udi -> Aghb - {0xB0740000u, 18u}, // udm -> Cyrl + {0xDE330000u, 55u}, // trx -> Latn + {0xE2330000u, 55u}, // try -> Latn + {0xE6330000u, 55u}, // trz -> Latn + {0x74730000u, 55u}, // ts -> Latn + {0x82530000u, 55u}, // tsa -> Latn + {0x86530000u, 55u}, // tsb -> Latn + {0x8A530000u, 55u}, // tsc -> Latn + {0x8E530000u, 30u}, // tsd -> Grek + {0x9A530000u, 55u}, // tsg -> Latn + {0x9E530000u, 55u}, // tsh -> Latn + {0xA2530000u, 55u}, // tsi -> Latn + {0xA6530000u, 112u}, // tsj -> Tibt + {0xAE530000u, 55u}, // tsl -> Latn + {0xBE530000u, 55u}, // tsp -> Latn + {0xC6530000u, 55u}, // tsr -> Latn + {0xCE530000u, 55u}, // tst -> Latn + {0xD2530000u, 55u}, // tsu -> Latn + {0xD6530000u, 55u}, // tsv -> Latn + {0xDA530000u, 55u}, // tsw -> Latn + {0xDE530000u, 55u}, // tsx -> Latn + {0xE6530000u, 55u}, // tsz -> Latn + {0x74740000u, 20u}, // tt -> Cyrl + {0x86730000u, 55u}, // ttb -> Latn + {0x8A730000u, 55u}, // ttc -> Latn + {0x8E730000u, 55u}, // ttd -> Latn + {0x92730000u, 55u}, // tte -> Latn + {0x96730000u, 55u}, // ttf -> Latn + {0x9E730000u, 52u}, // tth -> Laoo + {0xA2730000u, 55u}, // tti -> Latn + {0xA6730000u, 55u}, // ttj -> Latn + {0xAA730000u, 55u}, // ttk -> Latn + {0xAE730000u, 55u}, // ttl -> Latn + {0xB2730000u, 55u}, // ttm -> Latn + {0xB6730000u, 55u}, // ttn -> Latn + {0xBA730000u, 52u}, // tto -> Laoo + {0xBE730000u, 55u}, // ttp -> Latn + {0xC6730000u, 55u}, // ttr -> Latn + {0xCA730000u, 111u}, // tts -> Thai + {0xCE730000u, 55u}, // ttt -> Latn + {0xD2730000u, 55u}, // ttu -> Latn + {0xD6730000u, 55u}, // ttv -> Latn + {0xDA730000u, 55u}, // ttw -> Latn + {0xE2730000u, 55u}, // tty -> Latn + {0xE6730000u, 21u}, // ttz -> Deva + {0x82930000u, 55u}, // tua -> Latn + {0x86930000u, 55u}, // tub -> Latn + {0x8A930000u, 55u}, // tuc -> Latn + {0x8E930000u, 55u}, // tud -> Latn + {0x92930000u, 55u}, // tue -> Latn + {0x96930000u, 55u}, // tuf -> Latn + {0x9A930000u, 55u}, // tug -> Latn + {0x9E930000u, 55u}, // tuh -> Latn + {0xA2930000u, 55u}, // tui -> Latn + {0xA6930000u, 55u}, // tuj -> Latn + {0xAE930000u, 55u}, // tul -> Latn + {0xB2930000u, 55u}, // tum -> Latn + {0xB6930000u, 55u}, // tun -> Latn + {0xBA930000u, 55u}, // tuo -> Latn + {0xC2930000u, 55u}, // tuq -> Latn + {0xCA930000u, 55u}, // tus -> Latn + {0xD2930000u, 55u}, // tuu -> Latn + {0xD6930000u, 55u}, // tuv -> Latn + {0xDE930000u, 55u}, // tux -> Latn + {0xE2930000u, 55u}, // tuy -> Latn + {0xE6930000u, 55u}, // tuz -> Latn + {0x82B30000u, 55u}, // tva -> Latn + {0x8EB30000u, 55u}, // tvd -> Latn + {0x92B30000u, 55u}, // tve -> Latn + {0xA2B30000u, 55u}, // tvi -> Latn + {0xAAB30000u, 55u}, // tvk -> Latn + {0xAEB30000u, 55u}, // tvl -> Latn + {0xB2B30000u, 55u}, // tvm -> Latn + {0xB6B30000u, 72u}, // tvn -> Mymr + {0xBAB30000u, 55u}, // tvo -> Latn + {0xCAB30000u, 55u}, // tvs -> Latn + {0xCEB30000u, 55u}, // tvt -> Latn + {0xD2B30000u, 55u}, // tvu -> Latn + {0xDAB30000u, 55u}, // tvw -> Latn + {0xDEB30000u, 55u}, // tvx -> Latn + {0x82D30000u, 55u}, // twa -> Latn + {0x86D30000u, 55u}, // twb -> Latn + {0x8ED30000u, 55u}, // twd -> Latn + {0x92D30000u, 55u}, // twe -> Latn + {0x96D30000u, 55u}, // twf -> Latn + {0x9AD30000u, 55u}, // twg -> Latn + {0x9ED30000u, 55u}, // twh -> Latn + {0xAED30000u, 55u}, // twl -> Latn + {0xB2D30000u, 21u}, // twm -> Deva + {0xB6D30000u, 55u}, // twn -> Latn + {0xBAD30000u, 55u}, // two -> Latn + {0xBED30000u, 55u}, // twp -> Latn + {0xC2D30000u, 55u}, // twq -> Latn + {0xC6D30000u, 55u}, // twr -> Latn + {0xCED30000u, 55u}, // twt -> Latn + {0xD2D30000u, 55u}, // twu -> Latn + {0xDAD30000u, 55u}, // tww -> Latn + {0xDED30000u, 55u}, // twx -> Latn + {0xE2D30000u, 55u}, // twy -> Latn + {0x82F30000u, 55u}, // txa -> Latn + {0x92F30000u, 55u}, // txe -> Latn + {0x9AF30000u, 106u}, // txg -> Tang + {0xA2F30000u, 55u}, // txi -> Latn + {0xA6F30000u, 55u}, // txj -> Latn + {0xB2F30000u, 55u}, // txm -> Latn + {0xB6F30000u, 55u}, // txn -> Latn + {0xBAF30000u, 114u}, // txo -> Toto + {0xC2F30000u, 55u}, // txq -> Latn + {0xCAF30000u, 55u}, // txs -> Latn + {0xCEF30000u, 55u}, // txt -> Latn + {0xD2F30000u, 55u}, // txu -> Latn + {0xDEF30000u, 55u}, // txx -> Latn + {0xE2F30000u, 55u}, // txy -> Latn + {0x74790000u, 55u}, // ty -> Latn + {0x83130000u, 55u}, // tya -> Latn + {0x93130000u, 55u}, // tye -> Latn + {0x9F130000u, 55u}, // tyh -> Latn + {0xA3130000u, 55u}, // tyi -> Latn + {0xA7130000u, 55u}, // tyj -> Latn + {0xAF130000u, 55u}, // tyl -> Latn + {0xB7130000u, 55u}, // tyn -> Latn + {0xBF130000u, 55u}, // typ -> Latn + {0xC7130000u, 107u}, // tyr -> Tavt + {0xCB130000u, 55u}, // tys -> Latn + {0xCF130000u, 55u}, // tyt -> Latn + {0xD3130000u, 55u}, // tyu -> Latn + {0xD7130000u, 20u}, // tyv -> Cyrl + {0xDF130000u, 55u}, // tyx -> Latn + {0xE3130000u, 55u}, // tyy -> Latn + {0xE7130000u, 55u}, // tyz -> Latn + {0x9F330000u, 55u}, // tzh -> Latn + {0xA7330000u, 55u}, // tzj -> Latn + {0xAF330000u, 55u}, // tzl -> Latn + {0xB3330000u, 55u}, // tzm -> Latn + {0xB7330000u, 55u}, // tzn -> Latn + {0xBB330000u, 55u}, // tzo -> Latn + {0xDF330000u, 55u}, // tzx -> Latn + {0xB0140000u, 55u}, // uam -> Latn + {0xC4140000u, 55u}, // uar -> Latn + {0x80340000u, 55u}, // uba -> Latn + {0xA0340000u, 55u}, // ubi -> Latn + {0xAC340000u, 55u}, // ubl -> Latn + {0xC4340000u, 55u}, // ubr -> Latn + {0xD0340000u, 55u}, // ubu -> Latn + {0xE0340000u, 55u}, // uby -> Latn + {0x80740000u, 55u}, // uda -> Latn + {0x90740000u, 20u}, // ude -> Cyrl + {0x98740000u, 67u}, // udg -> Mlym + {0xA0740000u, 20u}, // udi -> Cyrl + {0xA4740000u, 55u}, // udj -> Latn + {0xAC740000u, 55u}, // udl -> Latn + {0xB0740000u, 20u}, // udm -> Cyrl + {0xD0740000u, 55u}, // udu -> Latn + {0xC8940000u, 55u}, // ues -> Latn + {0xA0B40000u, 55u}, // ufi -> Latn {0x75670000u, 2u}, // ug -> Arab - {0x75674B5Au, 18u}, // ug-KZ -> Cyrl - {0x75674D4Eu, 18u}, // ug-MN -> Cyrl - {0x80D40000u, 97u}, // uga -> Ugar - {0x756B0000u, 18u}, // uk -> Cyrl - {0xA1740000u, 46u}, // uli -> Latn - {0x85940000u, 46u}, // umb -> Latn - {0xC5B40000u, 8u}, // unr -> Beng - {0xC5B44E50u, 19u}, // unr-NP -> Deva - {0xDDB40000u, 8u}, // unx -> Beng - {0xA9D40000u, 46u}, // uok -> Latn + {0x75674B5Au, 20u}, // ug-KZ -> Cyrl + {0x75674D4Eu, 20u}, // ug-MN -> Cyrl + {0x80D40000u, 115u}, // uga -> Ugar + {0x84D40000u, 55u}, // ugb -> Latn + {0x90D40000u, 55u}, // uge -> Latn + {0x9CD40000u, 20u}, // ugh -> Cyrl + {0xB8D40000u, 111u}, // ugo -> Thai + {0x80F40000u, 55u}, // uha -> Latn + {0xB4F40000u, 55u}, // uhn -> Latn + {0xC9140000u, 55u}, // uis -> Latn + {0xD5140000u, 55u}, // uiv -> Latn + {0xA1340000u, 55u}, // uji -> Latn + {0x756B0000u, 20u}, // uk -> Cyrl + {0x81540000u, 55u}, // uka -> Latn + {0x99540000u, 55u}, // ukg -> Latn + {0x9D540000u, 55u}, // ukh -> Latn + {0xA1540000u, 80u}, // uki -> Orya + {0xA9540000u, 55u}, // ukk -> Latn + {0xBD540000u, 55u}, // ukp -> Latn + {0xC1540000u, 55u}, // ukq -> Latn + {0xD1540000u, 55u}, // uku -> Latn + {0xD5540000u, 55u}, // ukv -> Latn + {0xD9540000u, 55u}, // ukw -> Latn + {0xE1540000u, 55u}, // uky -> Latn + {0x81740000u, 55u}, // ula -> Latn + {0x85740000u, 55u}, // ulb -> Latn + {0x89740000u, 20u}, // ulc -> Cyrl + {0x91740000u, 55u}, // ule -> Latn + {0x95740000u, 55u}, // ulf -> Latn + {0xA1740000u, 55u}, // uli -> Latn + {0xA9740000u, 55u}, // ulk -> Latn + {0xB1740000u, 55u}, // ulm -> Latn + {0xB5740000u, 55u}, // uln -> Latn + {0xD1740000u, 55u}, // ulu -> Latn + {0xD9740000u, 55u}, // ulw -> Latn + {0xE1740000u, 55u}, // uly -> Latn + {0x81940000u, 55u}, // uma -> Latn + {0x85940000u, 55u}, // umb -> Latn + {0x8D940000u, 55u}, // umd -> Latn + {0x99940000u, 55u}, // umg -> Latn + {0xA1940000u, 55u}, // umi -> Latn + {0xB1940000u, 55u}, // umm -> Latn + {0xB5940000u, 55u}, // umn -> Latn + {0xB9940000u, 55u}, // umo -> Latn + {0xBD940000u, 55u}, // ump -> Latn + {0xC5940000u, 55u}, // umr -> Latn + {0xC9940000u, 55u}, // ums -> Latn + {0x81B40000u, 55u}, // una -> Latn + {0x91B40000u, 55u}, // une -> Latn + {0x99B40000u, 55u}, // ung -> Latn + {0xA1B40000u, 55u}, // uni -> Latn + {0xA9B40000u, 55u}, // unk -> Latn + {0xB1B40000u, 55u}, // unm -> Latn + {0xB5B40000u, 55u}, // unn -> Latn + {0xC5B40000u, 9u}, // unr -> Beng + {0xC5B44E50u, 21u}, // unr-NP -> Deva + {0xD1B40000u, 55u}, // unu -> Latn + {0xDDB40000u, 9u}, // unx -> Beng + {0xE5B40000u, 55u}, // unz -> Latn + {0xB5D40000u, 55u}, // uon -> Latn + {0xA1F40000u, 55u}, // upi -> Latn + {0xD5F40000u, 55u}, // upv -> Latn {0x75720000u, 2u}, // ur -> Arab - {0xA2340000u, 46u}, // uri -> Latn - {0xCE340000u, 46u}, // urt -> Latn - {0xDA340000u, 46u}, // urw -> Latn - {0x82540000u, 46u}, // usa -> Latn - {0x9E740000u, 46u}, // uth -> Latn - {0xC6740000u, 46u}, // utr -> Latn - {0x9EB40000u, 46u}, // uvh -> Latn - {0xAEB40000u, 46u}, // uvl -> Latn - {0x757A0000u, 46u}, // uz -> Latn + {0x82340000u, 55u}, // ura -> Latn + {0x86340000u, 55u}, // urb -> Latn + {0x8A340000u, 55u}, // urc -> Latn + {0x92340000u, 55u}, // ure -> Latn + {0x96340000u, 55u}, // urf -> Latn + {0x9A340000u, 55u}, // urg -> Latn + {0x9E340000u, 55u}, // urh -> Latn + {0xA2340000u, 55u}, // uri -> Latn + {0xAA340000u, 111u}, // urk -> Thai + {0xB2340000u, 55u}, // urm -> Latn + {0xB6340000u, 55u}, // urn -> Latn + {0xBA340000u, 55u}, // uro -> Latn + {0xBE340000u, 55u}, // urp -> Latn + {0xC6340000u, 55u}, // urr -> Latn + {0xCE340000u, 55u}, // urt -> Latn + {0xD2340000u, 55u}, // uru -> Latn + {0xD6340000u, 55u}, // urv -> Latn + {0xDA340000u, 55u}, // urw -> Latn + {0xDE340000u, 55u}, // urx -> Latn + {0xE2340000u, 55u}, // ury -> Latn + {0xE6340000u, 55u}, // urz -> Latn + {0x82540000u, 55u}, // usa -> Latn + {0x9E540000u, 2u}, // ush -> Arab + {0xA2540000u, 55u}, // usi -> Latn + {0xAA540000u, 55u}, // usk -> Latn + {0xBE540000u, 55u}, // usp -> Latn + {0xCA540000u, 55u}, // uss -> Latn + {0xD2540000u, 55u}, // usu -> Latn + {0x82740000u, 55u}, // uta -> Latn + {0x92740000u, 55u}, // ute -> Latn + {0x9E740000u, 55u}, // uth -> Latn + {0xBE740000u, 55u}, // utp -> Latn + {0xC6740000u, 55u}, // utr -> Latn + {0xD2740000u, 55u}, // utu -> Latn + {0xB2940000u, 30u}, // uum -> Grek + {0xC6940000u, 55u}, // uur -> Latn + {0x92B40000u, 55u}, // uve -> Latn + {0x9EB40000u, 55u}, // uvh -> Latn + {0xAEB40000u, 55u}, // uvl -> Latn + {0x82D40000u, 55u}, // uwa -> Latn + {0x83140000u, 55u}, // uya -> Latn + {0x757A0000u, 55u}, // uz -> Latn {0x757A4146u, 2u}, // uz-AF -> Arab - {0x757A434Eu, 18u}, // uz-CN -> Cyrl - {0x98150000u, 46u}, // vag -> Latn - {0xA0150000u, 98u}, // vai -> Vaii - {0xB4150000u, 46u}, // van -> Latn - {0x76650000u, 46u}, // ve -> Latn - {0x88950000u, 46u}, // vec -> Latn - {0xBC950000u, 46u}, // vep -> Latn - {0x76690000u, 46u}, // vi -> Latn - {0x89150000u, 46u}, // vic -> Latn - {0xD5150000u, 46u}, // viv -> Latn - {0xC9750000u, 46u}, // vls -> Latn - {0x95950000u, 46u}, // vmf -> Latn - {0xD9950000u, 46u}, // vmw -> Latn - {0x766F0000u, 46u}, // vo -> Latn - {0xCDD50000u, 46u}, // vot -> Latn - {0xBA350000u, 46u}, // vro -> Latn - {0xB6950000u, 46u}, // vun -> Latn - {0xCE950000u, 46u}, // vut -> Latn - {0x77610000u, 46u}, // wa -> Latn - {0x90160000u, 46u}, // wae -> Latn - {0xA4160000u, 46u}, // waj -> Latn - {0xAC160000u, 21u}, // wal -> Ethi - {0xB4160000u, 46u}, // wan -> Latn - {0xC4160000u, 46u}, // war -> Latn - {0xBC360000u, 46u}, // wbp -> Latn - {0xC0360000u, 90u}, // wbq -> Telu - {0xC4360000u, 19u}, // wbr -> Deva - {0xA0560000u, 46u}, // wci -> Latn - {0xC4960000u, 46u}, // wer -> Latn - {0xA0D60000u, 46u}, // wgi -> Latn - {0x98F60000u, 46u}, // whg -> Latn - {0x85160000u, 46u}, // wib -> Latn - {0xD1160000u, 46u}, // wiu -> Latn - {0xD5160000u, 46u}, // wiv -> Latn - {0x81360000u, 46u}, // wja -> Latn - {0xA1360000u, 46u}, // wji -> Latn - {0xC9760000u, 46u}, // wls -> Latn - {0xB9960000u, 46u}, // wmo -> Latn - {0x89B60000u, 46u}, // wnc -> Latn + {0x757A434Eu, 20u}, // uz-CN -> Cyrl + {0xCB340000u, 2u}, // uzs -> Arab + {0x80150000u, 105u}, // vaa -> Taml + {0x90150000u, 55u}, // vae -> Latn + {0x94150000u, 2u}, // vaf -> Arab + {0x98150000u, 55u}, // vag -> Latn + {0x9C150000u, 21u}, // vah -> Deva + {0xA0150000u, 116u}, // vai -> Vaii + {0xA4150000u, 55u}, // vaj -> Latn + {0xAC150000u, 55u}, // val -> Latn + {0xB0150000u, 55u}, // vam -> Latn + {0xB4150000u, 55u}, // van -> Latn + {0xB8150000u, 55u}, // vao -> Latn + {0xBC150000u, 55u}, // vap -> Latn + {0xC4150000u, 55u}, // var -> Latn + {0xC8150000u, 21u}, // vas -> Deva + {0xD0150000u, 55u}, // vau -> Latn + {0xD4150000u, 21u}, // vav -> Deva + {0xE0150000u, 21u}, // vay -> Deva + {0x84350000u, 55u}, // vbb -> Latn + {0xA8350000u, 55u}, // vbk -> Latn + {0x76650000u, 55u}, // ve -> Latn + {0x88950000u, 55u}, // vec -> Latn + {0xB0950000u, 55u}, // vem -> Latn + {0xB8950000u, 55u}, // veo -> Latn + {0xBC950000u, 55u}, // vep -> Latn + {0xC4950000u, 55u}, // ver -> Latn + {0xC4D50000u, 2u}, // vgr -> Arab + {0x76690000u, 55u}, // vi -> Latn + {0x89150000u, 55u}, // vic -> Latn + {0x8D150000u, 55u}, // vid -> Latn + {0x95150000u, 55u}, // vif -> Latn + {0x99150000u, 55u}, // vig -> Latn + {0xAD150000u, 55u}, // vil -> Latn + {0xB5150000u, 55u}, // vin -> Latn + {0xCD150000u, 55u}, // vit -> Latn + {0xD5150000u, 55u}, // viv -> Latn + {0xA9350000u, 21u}, // vjk -> Deva + {0x81550000u, 55u}, // vka -> Latn + {0xA5550000u, 55u}, // vkj -> Latn + {0xA9550000u, 55u}, // vkk -> Latn + {0xAD550000u, 55u}, // vkl -> Latn + {0xB1550000u, 55u}, // vkm -> Latn + {0xB5550000u, 55u}, // vkn -> Latn + {0xB9550000u, 55u}, // vko -> Latn + {0xBD550000u, 55u}, // vkp -> Latn + {0xCD550000u, 55u}, // vkt -> Latn + {0xD1550000u, 55u}, // vku -> Latn + {0xE5550000u, 55u}, // vkz -> Latn + {0xBD750000u, 55u}, // vlp -> Latn + {0xC9750000u, 55u}, // vls -> Latn + {0x81950000u, 55u}, // vma -> Latn + {0x85950000u, 55u}, // vmb -> Latn + {0x89950000u, 55u}, // vmc -> Latn + {0x8D950000u, 49u}, // vmd -> Knda + {0x91950000u, 55u}, // vme -> Latn + {0x95950000u, 55u}, // vmf -> Latn + {0x99950000u, 55u}, // vmg -> Latn + {0x9D950000u, 2u}, // vmh -> Arab + {0xA1950000u, 55u}, // vmi -> Latn + {0xA5950000u, 55u}, // vmj -> Latn + {0xA9950000u, 55u}, // vmk -> Latn + {0xAD950000u, 55u}, // vml -> Latn + {0xB1950000u, 55u}, // vmm -> Latn + {0xBD950000u, 55u}, // vmp -> Latn + {0xC1950000u, 55u}, // vmq -> Latn + {0xC5950000u, 55u}, // vmr -> Latn + {0xC9950000u, 55u}, // vms -> Latn + {0xD1950000u, 55u}, // vmu -> Latn + {0xD9950000u, 55u}, // vmw -> Latn + {0xDD950000u, 55u}, // vmx -> Latn + {0xE1950000u, 55u}, // vmy -> Latn + {0xE5950000u, 55u}, // vmz -> Latn + {0xA9B50000u, 55u}, // vnk -> Latn + {0xB1B50000u, 55u}, // vnm -> Latn + {0xBDB50000u, 55u}, // vnp -> Latn + {0x766F0000u, 55u}, // vo -> Latn + {0xC5D50000u, 55u}, // vor -> Latn + {0xCDD50000u, 55u}, // vot -> Latn + {0x82350000u, 55u}, // vra -> Latn + {0xBA350000u, 55u}, // vro -> Latn + {0xCA350000u, 55u}, // vrs -> Latn + {0xCE350000u, 55u}, // vrt -> Latn + {0xBA750000u, 55u}, // vto -> Latn + {0xB2950000u, 55u}, // vum -> Latn + {0xB6950000u, 55u}, // vun -> Latn + {0xCE950000u, 55u}, // vut -> Latn + {0x82D50000u, 55u}, // vwa -> Latn + {0x77610000u, 55u}, // wa -> Latn + {0x80160000u, 55u}, // waa -> Latn + {0x84160000u, 55u}, // wab -> Latn + {0x88160000u, 55u}, // wac -> Latn + {0x8C160000u, 55u}, // wad -> Latn + {0x90160000u, 55u}, // wae -> Latn + {0x94160000u, 55u}, // waf -> Latn + {0x98160000u, 55u}, // wag -> Latn + {0x9C160000u, 55u}, // wah -> Latn + {0xA0160000u, 55u}, // wai -> Latn + {0xA4160000u, 55u}, // waj -> Latn + {0xAC160000u, 24u}, // wal -> Ethi + {0xB0160000u, 55u}, // wam -> Latn + {0xB4160000u, 55u}, // wan -> Latn + {0xBC160000u, 55u}, // wap -> Latn + {0xC0160000u, 55u}, // waq -> Latn + {0xC4160000u, 55u}, // war -> Latn + {0xC8160000u, 55u}, // was -> Latn + {0xCC160000u, 55u}, // wat -> Latn + {0xD0160000u, 55u}, // wau -> Latn + {0xD4160000u, 55u}, // wav -> Latn + {0xD8160000u, 55u}, // waw -> Latn + {0xDC160000u, 55u}, // wax -> Latn + {0xE0160000u, 55u}, // way -> Latn + {0xE4160000u, 55u}, // waz -> Latn + {0x80360000u, 55u}, // wba -> Latn + {0x84360000u, 55u}, // wbb -> Latn + {0x90360000u, 55u}, // wbe -> Latn + {0x94360000u, 55u}, // wbf -> Latn + {0x9C360000u, 55u}, // wbh -> Latn + {0xA0360000u, 55u}, // wbi -> Latn + {0xA4360000u, 55u}, // wbj -> Latn + {0xA8360000u, 2u}, // wbk -> Arab + {0xAC360000u, 55u}, // wbl -> Latn + {0xB0360000u, 55u}, // wbm -> Latn + {0xBC360000u, 55u}, // wbp -> Latn + {0xC0360000u, 108u}, // wbq -> Telu + {0xC4360000u, 21u}, // wbr -> Deva + {0xCC360000u, 55u}, // wbt -> Latn + {0xD4360000u, 55u}, // wbv -> Latn + {0xD8360000u, 55u}, // wbw -> Latn + {0x80560000u, 55u}, // wca -> Latn + {0xA0560000u, 55u}, // wci -> Latn + {0x8C760000u, 55u}, // wdd -> Latn + {0x98760000u, 55u}, // wdg -> Latn + {0xA4760000u, 55u}, // wdj -> Latn + {0xA8760000u, 55u}, // wdk -> Latn + {0xCC760000u, 55u}, // wdt -> Latn + {0xD0760000u, 55u}, // wdu -> Latn + {0xE0760000u, 55u}, // wdy -> Latn + {0x88960000u, 55u}, // wec -> Latn + {0x8C960000u, 55u}, // wed -> Latn + {0x98960000u, 55u}, // weg -> Latn + {0x9C960000u, 55u}, // weh -> Latn + {0xA0960000u, 55u}, // wei -> Latn + {0xB0960000u, 55u}, // wem -> Latn + {0xB8960000u, 55u}, // weo -> Latn + {0xBC960000u, 55u}, // wep -> Latn + {0xC4960000u, 55u}, // wer -> Latn + {0xC8960000u, 55u}, // wes -> Latn + {0xCC960000u, 55u}, // wet -> Latn + {0xD0960000u, 55u}, // weu -> Latn + {0xD8960000u, 55u}, // wew -> Latn + {0x98B60000u, 55u}, // wfg -> Latn + {0x80D60000u, 55u}, // wga -> Latn + {0x84D60000u, 55u}, // wgb -> Latn + {0x98D60000u, 55u}, // wgg -> Latn + {0xA0D60000u, 55u}, // wgi -> Latn + {0xB8D60000u, 55u}, // wgo -> Latn + {0xD0D60000u, 55u}, // wgu -> Latn + {0xE0D60000u, 55u}, // wgy -> Latn + {0x80F60000u, 55u}, // wha -> Latn + {0x98F60000u, 55u}, // whg -> Latn + {0xA8F60000u, 55u}, // whk -> Latn + {0xD0F60000u, 55u}, // whu -> Latn + {0x85160000u, 55u}, // wib -> Latn + {0x89160000u, 55u}, // wic -> Latn + {0x91160000u, 55u}, // wie -> Latn + {0x95160000u, 55u}, // wif -> Latn + {0x99160000u, 55u}, // wig -> Latn + {0x9D160000u, 55u}, // wih -> Latn + {0xA1160000u, 55u}, // wii -> Latn + {0xA5160000u, 55u}, // wij -> Latn + {0xA9160000u, 55u}, // wik -> Latn + {0xAD160000u, 55u}, // wil -> Latn + {0xB1160000u, 55u}, // wim -> Latn + {0xB5160000u, 55u}, // win -> Latn + {0xC5160000u, 55u}, // wir -> Latn + {0xD1160000u, 55u}, // wiu -> Latn + {0xD5160000u, 55u}, // wiv -> Latn + {0xE1160000u, 55u}, // wiy -> Latn + {0x81360000u, 55u}, // wja -> Latn + {0xA1360000u, 55u}, // wji -> Latn + {0x81560000u, 55u}, // wka -> Latn + {0x8D560000u, 55u}, // wkd -> Latn + {0xC5560000u, 55u}, // wkr -> Latn + {0xD9560000u, 55u}, // wkw -> Latn + {0xE1560000u, 55u}, // wky -> Latn + {0x81760000u, 55u}, // wla -> Latn + {0x91760000u, 24u}, // wle -> Ethi + {0x99760000u, 55u}, // wlg -> Latn + {0x9D760000u, 55u}, // wlh -> Latn + {0xA1760000u, 55u}, // wli -> Latn + {0xB1760000u, 55u}, // wlm -> Latn + {0xB9760000u, 2u}, // wlo -> Arab + {0xC5760000u, 55u}, // wlr -> Latn + {0xC9760000u, 55u}, // wls -> Latn + {0xD1760000u, 55u}, // wlu -> Latn + {0xD5760000u, 55u}, // wlv -> Latn + {0xD9760000u, 55u}, // wlw -> Latn + {0xDD760000u, 55u}, // wlx -> Latn + {0x81960000u, 55u}, // wma -> Latn + {0x85960000u, 55u}, // wmb -> Latn + {0x89960000u, 55u}, // wmc -> Latn + {0x8D960000u, 55u}, // wmd -> Latn + {0x91960000u, 21u}, // wme -> Deva + {0x9D960000u, 55u}, // wmh -> Latn + {0xA1960000u, 55u}, // wmi -> Latn + {0xB1960000u, 55u}, // wmm -> Latn + {0xB5960000u, 55u}, // wmn -> Latn + {0xB9960000u, 55u}, // wmo -> Latn + {0xC9960000u, 55u}, // wms -> Latn + {0xCD960000u, 55u}, // wmt -> Latn + {0xD9960000u, 55u}, // wmw -> Latn + {0xDD960000u, 55u}, // wmx -> Latn + {0x85B60000u, 55u}, // wnb -> Latn + {0x89B60000u, 55u}, // wnc -> Latn + {0x8DB60000u, 55u}, // wnd -> Latn + {0x91B60000u, 2u}, // wne -> Arab + {0x99B60000u, 55u}, // wng -> Latn {0xA1B60000u, 2u}, // wni -> Arab - {0xD1B60000u, 46u}, // wnu -> Latn - {0x776F0000u, 46u}, // wo -> Latn - {0x85D60000u, 46u}, // wob -> Latn - {0xC9D60000u, 46u}, // wos -> Latn - {0xCA360000u, 46u}, // wrs -> Latn - {0x9A560000u, 23u}, // wsg -> Gong - {0xAA560000u, 46u}, // wsk -> Latn - {0xB2760000u, 19u}, // wtm -> Deva - {0xD2960000u, 29u}, // wuu -> Hans - {0xD6960000u, 46u}, // wuv -> Latn - {0x82D60000u, 46u}, // wwa -> Latn - {0xD4170000u, 46u}, // xav -> Latn - {0xA0370000u, 46u}, // xbi -> Latn - {0xB8570000u, 15u}, // xco -> Chrs - {0xC4570000u, 12u}, // xcr -> Cari - {0xC8970000u, 46u}, // xes -> Latn - {0x78680000u, 46u}, // xh -> Latn - {0x81770000u, 46u}, // xla -> Latn - {0x89770000u, 50u}, // xlc -> Lyci - {0x8D770000u, 51u}, // xld -> Lydi - {0x95970000u, 22u}, // xmf -> Geor - {0xB5970000u, 53u}, // xmn -> Mani - {0xC5970000u, 55u}, // xmr -> Merc - {0x81B70000u, 60u}, // xna -> Narb - {0xC5B70000u, 19u}, // xnr -> Deva - {0x99D70000u, 46u}, // xog -> Latn - {0xB5D70000u, 46u}, // xon -> Latn - {0xC5F70000u, 73u}, // xpr -> Prti - {0x86370000u, 46u}, // xrb -> Latn - {0x82570000u, 77u}, // xsa -> Sarb - {0xA2570000u, 46u}, // xsi -> Latn - {0xB2570000u, 46u}, // xsm -> Latn - {0xC6570000u, 19u}, // xsr -> Deva - {0x92D70000u, 46u}, // xwe -> Latn - {0xB0180000u, 46u}, // yam -> Latn - {0xB8180000u, 46u}, // yao -> Latn - {0xBC180000u, 46u}, // yap -> Latn - {0xC8180000u, 46u}, // yas -> Latn - {0xCC180000u, 46u}, // yat -> Latn - {0xD4180000u, 46u}, // yav -> Latn - {0xE0180000u, 46u}, // yay -> Latn - {0xE4180000u, 46u}, // yaz -> Latn - {0x80380000u, 46u}, // yba -> Latn - {0x84380000u, 46u}, // ybb -> Latn - {0xE0380000u, 46u}, // yby -> Latn - {0xC4980000u, 46u}, // yer -> Latn - {0xC4D80000u, 46u}, // ygr -> Latn - {0xD8D80000u, 46u}, // ygw -> Latn - {0x79690000u, 31u}, // yi -> Hebr - {0xB9580000u, 46u}, // yko -> Latn - {0x91780000u, 46u}, // yle -> Latn - {0x99780000u, 46u}, // ylg -> Latn - {0xAD780000u, 46u}, // yll -> Latn - {0xAD980000u, 46u}, // yml -> Latn - {0x796F0000u, 46u}, // yo -> Latn - {0xB5D80000u, 46u}, // yon -> Latn - {0x86380000u, 46u}, // yrb -> Latn - {0x92380000u, 46u}, // yre -> Latn - {0xAE380000u, 46u}, // yrl -> Latn - {0xCA580000u, 46u}, // yss -> Latn - {0x82980000u, 46u}, // yua -> Latn - {0x92980000u, 30u}, // yue -> Hant - {0x9298434Eu, 29u}, // yue-CN -> Hans - {0xA6980000u, 46u}, // yuj -> Latn - {0xCE980000u, 46u}, // yut -> Latn - {0xDA980000u, 46u}, // yuw -> Latn - {0x7A610000u, 46u}, // za -> Latn - {0x98190000u, 46u}, // zag -> Latn + {0xA9B60000u, 55u}, // wnk -> Latn + {0xB1B60000u, 55u}, // wnm -> Latn + {0xB5B60000u, 55u}, // wnn -> Latn + {0xB9B60000u, 55u}, // wno -> Latn + {0xBDB60000u, 55u}, // wnp -> Latn + {0xD1B60000u, 55u}, // wnu -> Latn + {0xD9B60000u, 55u}, // wnw -> Latn + {0xE1B60000u, 55u}, // wny -> Latn + {0x776F0000u, 55u}, // wo -> Latn + {0x81D60000u, 55u}, // woa -> Latn + {0x85D60000u, 55u}, // wob -> Latn + {0x89D60000u, 55u}, // woc -> Latn + {0x8DD60000u, 55u}, // wod -> Latn + {0x91D60000u, 55u}, // woe -> Latn + {0x95D60000u, 55u}, // wof -> Latn + {0x99D60000u, 55u}, // wog -> Latn + {0xA1D60000u, 55u}, // woi -> Latn + {0xA9D60000u, 55u}, // wok -> Latn + {0xB1D60000u, 55u}, // wom -> Latn + {0xB5D60000u, 55u}, // won -> Latn + {0xB9D60000u, 55u}, // woo -> Latn + {0xC5D60000u, 55u}, // wor -> Latn + {0xC9D60000u, 55u}, // wos -> Latn + {0xD9D60000u, 55u}, // wow -> Latn + {0x89F60000u, 55u}, // wpc -> Latn + {0x86360000u, 55u}, // wrb -> Latn + {0x9A360000u, 55u}, // wrg -> Latn + {0x9E360000u, 55u}, // wrh -> Latn + {0xA2360000u, 55u}, // wri -> Latn + {0xAA360000u, 55u}, // wrk -> Latn + {0xAE360000u, 55u}, // wrl -> Latn + {0xB2360000u, 55u}, // wrm -> Latn + {0xBA360000u, 55u}, // wro -> Latn + {0xBE360000u, 55u}, // wrp -> Latn + {0xC6360000u, 55u}, // wrr -> Latn + {0xCA360000u, 55u}, // wrs -> Latn + {0xD2360000u, 55u}, // wru -> Latn + {0xD6360000u, 55u}, // wrv -> Latn + {0xDA360000u, 55u}, // wrw -> Latn + {0xDE360000u, 55u}, // wrx -> Latn + {0xE6360000u, 55u}, // wrz -> Latn + {0x82560000u, 55u}, // wsa -> Latn + {0x9A560000u, 26u}, // wsg -> Gong + {0xA2560000u, 55u}, // wsi -> Latn + {0xAA560000u, 55u}, // wsk -> Latn + {0xC6560000u, 55u}, // wsr -> Latn + {0xCA560000u, 55u}, // wss -> Latn + {0xD2560000u, 55u}, // wsu -> Latn + {0xD6560000u, 2u}, // wsv -> Arab + {0x86760000u, 55u}, // wtb -> Latn + {0x96760000u, 55u}, // wtf -> Latn + {0x9E760000u, 55u}, // wth -> Latn + {0xA2760000u, 55u}, // wti -> Latn + {0xAA760000u, 55u}, // wtk -> Latn + {0xB2760000u, 21u}, // wtm -> Deva + {0xDA760000u, 55u}, // wtw -> Latn + {0x82960000u, 55u}, // wua -> Latn + {0x86960000u, 55u}, // wub -> Latn + {0x8E960000u, 55u}, // wud -> Latn + {0xAE960000u, 55u}, // wul -> Latn + {0xB2960000u, 55u}, // wum -> Latn + {0xB6960000u, 55u}, // wun -> Latn + {0xC6960000u, 55u}, // wur -> Latn + {0xCE960000u, 55u}, // wut -> Latn + {0xD2960000u, 35u}, // wuu -> Hans + {0xD6960000u, 55u}, // wuv -> Latn + {0xDE960000u, 55u}, // wux -> Latn + {0xE2960000u, 55u}, // wuy -> Latn + {0x82D60000u, 55u}, // wwa -> Latn + {0x86D60000u, 55u}, // wwb -> Latn + {0xBAD60000u, 55u}, // wwo -> Latn + {0xC6D60000u, 55u}, // wwr -> Latn + {0xDAD60000u, 55u}, // www -> Latn + {0xDAF60000u, 55u}, // wxw -> Latn + {0x87160000u, 55u}, // wyb -> Latn + {0xA3160000u, 55u}, // wyi -> Latn + {0xB3160000u, 55u}, // wym -> Latn + {0xB7160000u, 55u}, // wyn -> Latn + {0xC7160000u, 55u}, // wyr -> Latn + {0xE3160000u, 55u}, // wyy -> Latn + {0x80170000u, 55u}, // xaa -> Latn + {0x84170000u, 55u}, // xab -> Latn + {0x98170000u, 0u}, // xag -> Aghb + {0xA0170000u, 55u}, // xai -> Latn + {0xA4170000u, 55u}, // xaj -> Latn + {0xA8170000u, 55u}, // xak -> Latn + {0xAC170000u, 20u}, // xal -> Cyrl + {0xB0170000u, 55u}, // xam -> Latn + {0xB4170000u, 24u}, // xan -> Ethi + {0xB8170000u, 55u}, // xao -> Latn + {0xC4170000u, 55u}, // xar -> Latn + {0xC8170000u, 20u}, // xas -> Cyrl + {0xCC170000u, 55u}, // xat -> Latn + {0xD0170000u, 55u}, // xau -> Latn + {0xD4170000u, 55u}, // xav -> Latn + {0xD8170000u, 55u}, // xaw -> Latn + {0xE0170000u, 55u}, // xay -> Latn + {0x84370000u, 55u}, // xbb -> Latn + {0x8C370000u, 55u}, // xbd -> Latn + {0x90370000u, 55u}, // xbe -> Latn + {0x98370000u, 55u}, // xbg -> Latn + {0xA0370000u, 55u}, // xbi -> Latn + {0xA4370000u, 55u}, // xbj -> Latn + {0xB0370000u, 55u}, // xbm -> Latn + {0xB4370000u, 55u}, // xbn -> Latn + {0xBC370000u, 55u}, // xbp -> Latn + {0xC4370000u, 55u}, // xbr -> Latn + {0xD8370000u, 55u}, // xbw -> Latn + {0xE0370000u, 55u}, // xby -> Latn + {0x9C570000u, 55u}, // xch -> Latn + {0xB8570000u, 17u}, // xco -> Chrs + {0xC4570000u, 14u}, // xcr -> Cari + {0x80770000u, 55u}, // xda -> Latn + {0xA8770000u, 55u}, // xdk -> Latn + {0xB8770000u, 55u}, // xdo -> Latn + {0xC0770000u, 20u}, // xdq -> Cyrl + {0xE0770000u, 55u}, // xdy -> Latn + {0x8C970000u, 55u}, // xed -> Latn + {0x98970000u, 55u}, // xeg -> Latn + {0xB0970000u, 55u}, // xem -> Latn + {0xC4970000u, 55u}, // xer -> Latn + {0xC8970000u, 55u}, // xes -> Latn + {0xCC970000u, 55u}, // xet -> Latn + {0xD0970000u, 55u}, // xeu -> Latn + {0x84D70000u, 55u}, // xgb -> Latn + {0x8CD70000u, 55u}, // xgd -> Latn + {0x98D70000u, 55u}, // xgg -> Latn + {0xA0D70000u, 55u}, // xgi -> Latn + {0xB0D70000u, 55u}, // xgm -> Latn + {0xD0D70000u, 55u}, // xgu -> Latn + {0xD8D70000u, 55u}, // xgw -> Latn + {0x78680000u, 55u}, // xh -> Latn + {0x90F70000u, 2u}, // xhe -> Arab + {0xB0F70000u, 47u}, // xhm -> Khmr + {0xD4F70000u, 55u}, // xhv -> Latn + {0xA1170000u, 55u}, // xii -> Latn + {0xB5170000u, 55u}, // xin -> Latn + {0xC5170000u, 55u}, // xir -> Latn + {0xC9170000u, 80u}, // xis -> Orya + {0xE1170000u, 55u}, // xiy -> Latn + {0x85370000u, 55u}, // xjb -> Latn + {0xCD370000u, 55u}, // xjt -> Latn + {0x81570000u, 2u}, // xka -> Arab + {0x85570000u, 55u}, // xkb -> Latn + {0x89570000u, 2u}, // xkc -> Arab + {0x8D570000u, 55u}, // xkd -> Latn + {0x91570000u, 55u}, // xke -> Latn + {0x95570000u, 112u}, // xkf -> Tibt + {0x99570000u, 55u}, // xkg -> Latn + {0xA5570000u, 2u}, // xkj -> Arab + {0xAD570000u, 55u}, // xkl -> Latn + {0xB5570000u, 55u}, // xkn -> Latn + {0xBD570000u, 2u}, // xkp -> Arab + {0xC1570000u, 55u}, // xkq -> Latn + {0xC5570000u, 55u}, // xkr -> Latn + {0xC9570000u, 55u}, // xks -> Latn + {0xCD570000u, 55u}, // xkt -> Latn + {0xD1570000u, 55u}, // xku -> Latn + {0xD5570000u, 55u}, // xkv -> Latn + {0xD9570000u, 55u}, // xkw -> Latn + {0xDD570000u, 55u}, // xkx -> Latn + {0xE1570000u, 55u}, // xky -> Latn + {0xE5570000u, 55u}, // xkz -> Latn + {0x81770000u, 55u}, // xla -> Latn + {0x89770000u, 60u}, // xlc -> Lyci + {0x8D770000u, 61u}, // xld -> Lydi + {0xE1770000u, 23u}, // xly -> Elym + {0x81970000u, 55u}, // xma -> Latn + {0x85970000u, 55u}, // xmb -> Latn + {0x89970000u, 55u}, // xmc -> Latn + {0x8D970000u, 55u}, // xmd -> Latn + {0x95970000u, 25u}, // xmf -> Geor + {0x99970000u, 55u}, // xmg -> Latn + {0x9D970000u, 55u}, // xmh -> Latn + {0xA5970000u, 55u}, // xmj -> Latn + {0xB1970000u, 55u}, // xmm -> Latn + {0xB5970000u, 63u}, // xmn -> Mani + {0xB9970000u, 55u}, // xmo -> Latn + {0xBD970000u, 55u}, // xmp -> Latn + {0xC1970000u, 55u}, // xmq -> Latn + {0xC5970000u, 66u}, // xmr -> Merc + {0xCD970000u, 55u}, // xmt -> Latn + {0xD1970000u, 55u}, // xmu -> Latn + {0xD5970000u, 55u}, // xmv -> Latn + {0xD9970000u, 55u}, // xmw -> Latn + {0xDD970000u, 55u}, // xmx -> Latn + {0xE1970000u, 55u}, // xmy -> Latn + {0xE5970000u, 55u}, // xmz -> Latn + {0x81B70000u, 73u}, // xna -> Narb + {0x85B70000u, 55u}, // xnb -> Latn + {0xA1B70000u, 55u}, // xni -> Latn + {0xA5B70000u, 55u}, // xnj -> Latn + {0xA9B70000u, 55u}, // xnk -> Latn + {0xB1B70000u, 55u}, // xnm -> Latn + {0xB5B70000u, 55u}, // xnn -> Latn + {0xC1B70000u, 55u}, // xnq -> Latn + {0xC5B70000u, 21u}, // xnr -> Deva + {0xCDB70000u, 55u}, // xnt -> Latn + {0xD1B70000u, 55u}, // xnu -> Latn + {0xE1B70000u, 55u}, // xny -> Latn + {0xE5B70000u, 55u}, // xnz -> Latn + {0x89D70000u, 55u}, // xoc -> Latn + {0x8DD70000u, 55u}, // xod -> Latn + {0x99D70000u, 55u}, // xog -> Latn + {0xA1D70000u, 55u}, // xoi -> Latn + {0xA9D70000u, 55u}, // xok -> Latn + {0xB1D70000u, 55u}, // xom -> Latn + {0xB5D70000u, 55u}, // xon -> Latn + {0xB9D70000u, 55u}, // xoo -> Latn + {0xBDD70000u, 55u}, // xop -> Latn + {0xC5D70000u, 55u}, // xor -> Latn + {0xD9D70000u, 55u}, // xow -> Latn + {0x81F70000u, 55u}, // xpa -> Latn + {0x85F70000u, 55u}, // xpb -> Latn + {0x8DF70000u, 55u}, // xpd -> Latn + {0x95F70000u, 55u}, // xpf -> Latn + {0x99F70000u, 30u}, // xpg -> Grek + {0x9DF70000u, 55u}, // xph -> Latn + {0xA1F70000u, 77u}, // xpi -> Ogam + {0xA5F70000u, 55u}, // xpj -> Latn + {0xA9F70000u, 55u}, // xpk -> Latn + {0xADF70000u, 55u}, // xpl -> Latn + {0xB1F70000u, 20u}, // xpm -> Cyrl + {0xB5F70000u, 55u}, // xpn -> Latn + {0xB9F70000u, 55u}, // xpo -> Latn + {0xC1F70000u, 55u}, // xpq -> Latn + {0xC5F70000u, 87u}, // xpr -> Prti + {0xCDF70000u, 55u}, // xpt -> Latn + {0xD5F70000u, 55u}, // xpv -> Latn + {0xD9F70000u, 55u}, // xpw -> Latn + {0xDDF70000u, 55u}, // xpx -> Latn + {0xE5F70000u, 55u}, // xpz -> Latn + {0x82370000u, 55u}, // xra -> Latn + {0x86370000u, 55u}, // xrb -> Latn + {0x8E370000u, 55u}, // xrd -> Latn + {0x92370000u, 55u}, // xre -> Latn + {0x9A370000u, 55u}, // xrg -> Latn + {0xA2370000u, 55u}, // xri -> Latn + {0xB2370000u, 20u}, // xrm -> Cyrl + {0xB6370000u, 20u}, // xrn -> Cyrl + {0xC6370000u, 55u}, // xrr -> Latn + {0xD2370000u, 55u}, // xru -> Latn + {0xDA370000u, 55u}, // xrw -> Latn + {0x82570000u, 92u}, // xsa -> Sarb + {0x86570000u, 55u}, // xsb -> Latn + {0x92570000u, 55u}, // xse -> Latn + {0x9E570000u, 55u}, // xsh -> Latn + {0xA2570000u, 55u}, // xsi -> Latn + {0xB2570000u, 55u}, // xsm -> Latn + {0xB6570000u, 55u}, // xsn -> Latn + {0xBE570000u, 55u}, // xsp -> Latn + {0xC2570000u, 55u}, // xsq -> Latn + {0xC6570000u, 21u}, // xsr -> Deva + {0xD2570000u, 55u}, // xsu -> Latn + {0xE2570000u, 55u}, // xsy -> Latn + {0x82770000u, 55u}, // xta -> Latn + {0x86770000u, 55u}, // xtb -> Latn + {0x8A770000u, 55u}, // xtc -> Latn + {0x8E770000u, 55u}, // xtd -> Latn + {0x92770000u, 55u}, // xte -> Latn + {0x9E770000u, 55u}, // xth -> Latn + {0xA2770000u, 55u}, // xti -> Latn + {0xA6770000u, 55u}, // xtj -> Latn + {0xAE770000u, 55u}, // xtl -> Latn + {0xB2770000u, 55u}, // xtm -> Latn + {0xB6770000u, 55u}, // xtn -> Latn + {0xBE770000u, 55u}, // xtp -> Latn + {0xC2770000u, 11u}, // xtq -> Brah + {0xCA770000u, 55u}, // xts -> Latn + {0xCE770000u, 55u}, // xtt -> Latn + {0xD2770000u, 55u}, // xtu -> Latn + {0xD6770000u, 55u}, // xtv -> Latn + {0xDA770000u, 55u}, // xtw -> Latn + {0xE2770000u, 55u}, // xty -> Latn + {0x86970000u, 105u}, // xub -> Taml + {0x8E970000u, 55u}, // xud -> Latn + {0xA6970000u, 105u}, // xuj -> Taml + {0xAE970000u, 55u}, // xul -> Latn + {0xB2970000u, 55u}, // xum -> Latn + {0xB6970000u, 55u}, // xun -> Latn + {0xBA970000u, 55u}, // xuo -> Latn + {0xCE970000u, 55u}, // xut -> Latn + {0xD2970000u, 55u}, // xuu -> Latn + {0x92B70000u, 40u}, // xve -> Ital + {0xA2B70000u, 2u}, // xvi -> Arab + {0xB6B70000u, 55u}, // xvn -> Latn + {0xBAB70000u, 55u}, // xvo -> Latn + {0xCAB70000u, 55u}, // xvs -> Latn + {0x82D70000u, 55u}, // xwa -> Latn + {0x8ED70000u, 55u}, // xwd -> Latn + {0x92D70000u, 55u}, // xwe -> Latn + {0xA6D70000u, 55u}, // xwj -> Latn + {0xAAD70000u, 55u}, // xwk -> Latn + {0xAED70000u, 55u}, // xwl -> Latn + {0xBAD70000u, 20u}, // xwo -> Cyrl + {0xC6D70000u, 55u}, // xwr -> Latn + {0xCED70000u, 55u}, // xwt -> Latn + {0xDAD70000u, 55u}, // xww -> Latn + {0x86F70000u, 55u}, // xxb -> Latn + {0xAAF70000u, 55u}, // xxk -> Latn + {0xB2F70000u, 55u}, // xxm -> Latn + {0xC6F70000u, 55u}, // xxr -> Latn + {0xCEF70000u, 55u}, // xxt -> Latn + {0x83170000u, 55u}, // xya -> Latn + {0x87170000u, 55u}, // xyb -> Latn + {0xA7170000u, 55u}, // xyj -> Latn + {0xAB170000u, 55u}, // xyk -> Latn + {0xAF170000u, 55u}, // xyl -> Latn + {0xCF170000u, 55u}, // xyt -> Latn + {0xE3170000u, 55u}, // xyy -> Latn + {0x9F370000u, 64u}, // xzh -> Marc + {0xBF370000u, 55u}, // xzp -> Latn + {0x80180000u, 55u}, // yaa -> Latn + {0x84180000u, 55u}, // yab -> Latn + {0x88180000u, 55u}, // yac -> Latn + {0x8C180000u, 55u}, // yad -> Latn + {0x90180000u, 55u}, // yae -> Latn + {0x94180000u, 55u}, // yaf -> Latn + {0x98180000u, 55u}, // yag -> Latn + {0x9C180000u, 55u}, // yah -> Latn + {0xA0180000u, 20u}, // yai -> Cyrl + {0xA4180000u, 55u}, // yaj -> Latn + {0xA8180000u, 55u}, // yak -> Latn + {0xAC180000u, 55u}, // yal -> Latn + {0xB0180000u, 55u}, // yam -> Latn + {0xB4180000u, 55u}, // yan -> Latn + {0xB8180000u, 55u}, // yao -> Latn + {0xBC180000u, 55u}, // yap -> Latn + {0xC0180000u, 55u}, // yaq -> Latn + {0xC4180000u, 55u}, // yar -> Latn + {0xC8180000u, 55u}, // yas -> Latn + {0xCC180000u, 55u}, // yat -> Latn + {0xD0180000u, 55u}, // yau -> Latn + {0xD4180000u, 55u}, // yav -> Latn + {0xD8180000u, 55u}, // yaw -> Latn + {0xDC180000u, 55u}, // yax -> Latn + {0xE0180000u, 55u}, // yay -> Latn + {0xE4180000u, 55u}, // yaz -> Latn + {0x80380000u, 55u}, // yba -> Latn + {0x84380000u, 55u}, // ybb -> Latn + {0x90380000u, 55u}, // ybe -> Latn + {0x9C380000u, 21u}, // ybh -> Deva + {0xA0380000u, 21u}, // ybi -> Deva + {0xA4380000u, 55u}, // ybj -> Latn + {0xAC380000u, 55u}, // ybl -> Latn + {0xB0380000u, 55u}, // ybm -> Latn + {0xB4380000u, 55u}, // ybn -> Latn + {0xB8380000u, 55u}, // ybo -> Latn + {0xDC380000u, 55u}, // ybx -> Latn + {0xE0380000u, 55u}, // yby -> Latn + {0xAC580000u, 55u}, // ycl -> Latn + {0xB4580000u, 55u}, // ycn -> Latn + {0xC4580000u, 55u}, // ycr -> Latn + {0x80780000u, 55u}, // yda -> Latn + {0x90780000u, 55u}, // yde -> Latn + {0x98780000u, 2u}, // ydg -> Arab + {0xA8780000u, 55u}, // ydk -> Latn + {0x80980000u, 67u}, // yea -> Mlym + {0x88980000u, 55u}, // yec -> Latn + {0x90980000u, 55u}, // yee -> Latn + {0xA0980000u, 55u}, // yei -> Latn + {0xA4980000u, 30u}, // yej -> Grek + {0xAC980000u, 55u}, // yel -> Latn + {0xC4980000u, 55u}, // yer -> Latn + {0xC8980000u, 55u}, // yes -> Latn + {0xCC980000u, 55u}, // yet -> Latn + {0xD0980000u, 108u}, // yeu -> Telu + {0xD4980000u, 55u}, // yev -> Latn + {0xE0980000u, 55u}, // yey -> Latn + {0x80D80000u, 55u}, // yga -> Latn + {0xA0D80000u, 55u}, // ygi -> Latn + {0xACD80000u, 55u}, // ygl -> Latn + {0xB0D80000u, 55u}, // ygm -> Latn + {0xBCD80000u, 86u}, // ygp -> Plrd + {0xC4D80000u, 55u}, // ygr -> Latn + {0xD0D80000u, 55u}, // ygu -> Latn + {0xD8D80000u, 55u}, // ygw -> Latn + {0x8CF80000u, 37u}, // yhd -> Hebr + {0x79690000u, 37u}, // yi -> Hebr + {0x81180000u, 55u}, // yia -> Latn + {0x99180000u, 120u}, // yig -> Yiii + {0x9D180000u, 37u}, // yih -> Hebr + {0xA1180000u, 55u}, // yii -> Latn + {0xA5180000u, 55u}, // yij -> Latn + {0xAD180000u, 55u}, // yil -> Latn + {0xB1180000u, 55u}, // yim -> Latn + {0xC5180000u, 55u}, // yir -> Latn + {0xC9180000u, 55u}, // yis -> Latn + {0xD5180000u, 120u}, // yiv -> Yiii + {0x81580000u, 55u}, // yka -> Latn + {0x99580000u, 20u}, // ykg -> Cyrl + {0x9D580000u, 20u}, // ykh -> Cyrl + {0xA1580000u, 55u}, // yki -> Latn + {0xA9580000u, 55u}, // ykk -> Latn + {0xB1580000u, 55u}, // ykm -> Latn + {0xB9580000u, 55u}, // yko -> Latn + {0xC5580000u, 55u}, // ykr -> Latn + {0xE1580000u, 55u}, // yky -> Latn + {0x81780000u, 55u}, // yla -> Latn + {0x85780000u, 55u}, // ylb -> Latn + {0x91780000u, 55u}, // yle -> Latn + {0x99780000u, 55u}, // ylg -> Latn + {0xA1780000u, 55u}, // yli -> Latn + {0xAD780000u, 55u}, // yll -> Latn + {0xC5780000u, 55u}, // ylr -> Latn + {0xD1780000u, 55u}, // ylu -> Latn + {0xE1780000u, 55u}, // yly -> Latn + {0x85980000u, 55u}, // ymb -> Latn + {0x91980000u, 55u}, // yme -> Latn + {0x99980000u, 55u}, // ymg -> Latn + {0xA9980000u, 55u}, // ymk -> Latn + {0xAD980000u, 55u}, // yml -> Latn + {0xB1980000u, 55u}, // ymm -> Latn + {0xB5980000u, 55u}, // ymn -> Latn + {0xB9980000u, 55u}, // ymo -> Latn + {0xBD980000u, 55u}, // ymp -> Latn + {0x81B80000u, 86u}, // yna -> Plrd + {0x8DB80000u, 55u}, // ynd -> Latn + {0x99B80000u, 55u}, // yng -> Latn + {0xA9B80000u, 20u}, // ynk -> Cyrl + {0xADB80000u, 55u}, // ynl -> Latn + {0xC1B80000u, 55u}, // ynq -> Latn + {0xC9B80000u, 55u}, // yns -> Latn + {0xD1B80000u, 55u}, // ynu -> Latn + {0x796F0000u, 55u}, // yo -> Latn + {0x85D80000u, 55u}, // yob -> Latn + {0x99D80000u, 55u}, // yog -> Latn + {0xA1D80000u, 42u}, // yoi -> Jpan + {0xA9D80000u, 55u}, // yok -> Latn + {0xADD80000u, 55u}, // yol -> Latn + {0xB1D80000u, 55u}, // yom -> Latn + {0xB5D80000u, 55u}, // yon -> Latn + {0xCDD80000u, 55u}, // yot -> Latn + {0xE1D80000u, 111u}, // yoy -> Thai + {0x82380000u, 55u}, // yra -> Latn + {0x86380000u, 55u}, // yrb -> Latn + {0x92380000u, 55u}, // yre -> Latn + {0xAA380000u, 20u}, // yrk -> Cyrl + {0xAE380000u, 55u}, // yrl -> Latn + {0xB2380000u, 55u}, // yrm -> Latn + {0xBA380000u, 55u}, // yro -> Latn + {0xCA380000u, 55u}, // yrs -> Latn + {0xDA380000u, 55u}, // yrw -> Latn + {0xE2380000u, 55u}, // yry -> Latn + {0x8E580000u, 120u}, // ysd -> Yiii + {0xB6580000u, 120u}, // ysn -> Yiii + {0xBE580000u, 120u}, // ysp -> Yiii + {0xC6580000u, 20u}, // ysr -> Cyrl + {0xCA580000u, 55u}, // yss -> Latn + {0xE2580000u, 86u}, // ysy -> Plrd + {0xDA780000u, 55u}, // ytw -> Latn + {0xE2780000u, 55u}, // yty -> Latn + {0x82980000u, 55u}, // yua -> Latn + {0x86980000u, 55u}, // yub -> Latn + {0x8A980000u, 55u}, // yuc -> Latn + {0x8E980000u, 37u}, // yud -> Hebr + {0x92980000u, 36u}, // yue -> Hant + {0x9298434Eu, 35u}, // yue-CN -> Hans + {0x96980000u, 55u}, // yuf -> Latn + {0x9A980000u, 20u}, // yug -> Cyrl + {0xA2980000u, 55u}, // yui -> Latn + {0xA6980000u, 55u}, // yuj -> Latn + {0xAE980000u, 55u}, // yul -> Latn + {0xB2980000u, 55u}, // yum -> Latn + {0xB6980000u, 55u}, // yun -> Latn + {0xBE980000u, 55u}, // yup -> Latn + {0xC2980000u, 55u}, // yuq -> Latn + {0xC6980000u, 55u}, // yur -> Latn + {0xCE980000u, 55u}, // yut -> Latn + {0xDA980000u, 55u}, // yuw -> Latn + {0xDE980000u, 20u}, // yux -> Cyrl + {0xE6980000u, 55u}, // yuz -> Latn + {0x82B80000u, 55u}, // yva -> Latn + {0xCEB80000u, 55u}, // yvt -> Latn + {0x82D80000u, 55u}, // ywa -> Latn + {0x9AD80000u, 55u}, // ywg -> Latn + {0xB6D80000u, 55u}, // ywn -> Latn + {0xC2D80000u, 86u}, // ywq -> Plrd + {0xC6D80000u, 55u}, // ywr -> Latn + {0xD2D80000u, 86u}, // ywu -> Plrd + {0xDAD80000u, 55u}, // yww -> Latn + {0x82F80000u, 55u}, // yxa -> Latn + {0x9AF80000u, 55u}, // yxg -> Latn + {0xAEF80000u, 55u}, // yxl -> Latn + {0xB2F80000u, 55u}, // yxm -> Latn + {0xD2F80000u, 55u}, // yxu -> Latn + {0xE2F80000u, 55u}, // yxy -> Latn + {0xC7180000u, 55u}, // yyr -> Latn + {0xD3180000u, 55u}, // yyu -> Latn + {0x7A610000u, 55u}, // za -> Latn + {0x80190000u, 55u}, // zaa -> Latn + {0x84190000u, 55u}, // zab -> Latn + {0x88190000u, 55u}, // zac -> Latn + {0x8C190000u, 55u}, // zad -> Latn + {0x90190000u, 55u}, // zae -> Latn + {0x94190000u, 55u}, // zaf -> Latn + {0x98190000u, 55u}, // zag -> Latn + {0x9C190000u, 55u}, // zah -> Latn + {0xA4190000u, 55u}, // zaj -> Latn + {0xA8190000u, 55u}, // zak -> Latn + {0xB0190000u, 55u}, // zam -> Latn + {0xB8190000u, 55u}, // zao -> Latn + {0xBC190000u, 55u}, // zap -> Latn + {0xC0190000u, 55u}, // zaq -> Latn + {0xC4190000u, 55u}, // zar -> Latn + {0xC8190000u, 55u}, // zas -> Latn + {0xCC190000u, 55u}, // zat -> Latn + {0xD0190000u, 112u}, // zau -> Tibt + {0xD4190000u, 55u}, // zav -> Latn + {0xD8190000u, 55u}, // zaw -> Latn + {0xDC190000u, 55u}, // zax -> Latn + {0xE0190000u, 55u}, // zay -> Latn + {0xE4190000u, 55u}, // zaz -> Latn + {0x80390000u, 2u}, // zba -> Arab + {0x88390000u, 55u}, // zbc -> Latn + {0x90390000u, 55u}, // zbe -> Latn + {0xCC390000u, 55u}, // zbt -> Latn + {0xD0390000u, 55u}, // zbu -> Latn + {0xD8390000u, 55u}, // zbw -> Latn + {0x80590000u, 55u}, // zca -> Latn + {0x9C590000u, 34u}, // zch -> Hani {0xA4790000u, 2u}, // zdj -> Arab - {0x80990000u, 46u}, // zea -> Latn - {0x9CD90000u, 91u}, // zgh -> Tfng - {0x7A680000u, 29u}, // zh -> Hans - {0x7A684155u, 30u}, // zh-AU -> Hant - {0x7A68424Eu, 30u}, // zh-BN -> Hant - {0x7A684742u, 30u}, // zh-GB -> Hant - {0x7A684746u, 30u}, // zh-GF -> Hant - {0x7A68484Bu, 30u}, // zh-HK -> Hant - {0x7A684944u, 30u}, // zh-ID -> Hant - {0x7A684D4Fu, 30u}, // zh-MO -> Hant - {0x7A685041u, 30u}, // zh-PA -> Hant - {0x7A685046u, 30u}, // zh-PF -> Hant - {0x7A685048u, 30u}, // zh-PH -> Hant - {0x7A685352u, 30u}, // zh-SR -> Hant - {0x7A685448u, 30u}, // zh-TH -> Hant - {0x7A685457u, 30u}, // zh-TW -> Hant - {0x7A685553u, 30u}, // zh-US -> Hant - {0x7A68564Eu, 30u}, // zh-VN -> Hant - {0xDCF90000u, 62u}, // zhx -> Nshu - {0x81190000u, 46u}, // zia -> Latn - {0xCD590000u, 41u}, // zkt -> Kits - {0xB1790000u, 46u}, // zlm -> Latn - {0xA1990000u, 46u}, // zmi -> Latn - {0x91B90000u, 46u}, // zne -> Latn - {0x7A750000u, 46u}, // zu -> Latn - {0x83390000u, 46u}, // zza -> Latn + {0x80990000u, 55u}, // zea -> Latn + {0x98990000u, 55u}, // zeg -> Latn + {0x9C990000u, 34u}, // zeh -> Hani + {0xB0990000u, 55u}, // zem -> Latn + {0xB4990000u, 109u}, // zen -> Tfng + {0x80D90000u, 55u}, // zga -> Latn + {0x84D90000u, 34u}, // zgb -> Hani + {0x9CD90000u, 109u}, // zgh -> Tfng + {0xB0D90000u, 34u}, // zgm -> Hani + {0xB4D90000u, 34u}, // zgn -> Hani + {0xC4D90000u, 55u}, // zgr -> Latn + {0x7A680000u, 35u}, // zh -> Hans + {0x7A684155u, 36u}, // zh-AU -> Hant + {0x7A68424Eu, 36u}, // zh-BN -> Hant + {0x7A684742u, 36u}, // zh-GB -> Hant + {0x7A684746u, 36u}, // zh-GF -> Hant + {0x7A68484Bu, 36u}, // zh-HK -> Hant + {0x7A684944u, 36u}, // zh-ID -> Hant + {0x7A684D4Fu, 36u}, // zh-MO -> Hant + {0x7A685041u, 36u}, // zh-PA -> Hant + {0x7A685046u, 36u}, // zh-PF -> Hant + {0x7A685048u, 36u}, // zh-PH -> Hant + {0x7A685352u, 36u}, // zh-SR -> Hant + {0x7A685448u, 36u}, // zh-TH -> Hant + {0x7A685457u, 36u}, // zh-TW -> Hant + {0x7A685553u, 36u}, // zh-US -> Hant + {0x7A68564Eu, 36u}, // zh-VN -> Hant + {0x8CF90000u, 34u}, // zhd -> Hani + {0xA0F90000u, 55u}, // zhi -> Latn + {0xB4F90000u, 55u}, // zhn -> Latn + {0xD8F90000u, 55u}, // zhw -> Latn + {0xDCF90000u, 76u}, // zhx -> Nshu + {0x81190000u, 55u}, // zia -> Latn + {0xA9190000u, 55u}, // zik -> Latn + {0xAD190000u, 55u}, // zil -> Latn + {0xB1190000u, 55u}, // zim -> Latn + {0xB5190000u, 55u}, // zin -> Latn + {0xD9190000u, 55u}, // ziw -> Latn + {0xE5190000u, 55u}, // ziz -> Latn + {0x81590000u, 55u}, // zka -> Latn + {0x8D590000u, 55u}, // zkd -> Latn + {0xB9590000u, 20u}, // zko -> Cyrl + {0xBD590000u, 55u}, // zkp -> Latn + {0xCD590000u, 48u}, // zkt -> Kits + {0xD1590000u, 55u}, // zku -> Latn + {0xE5590000u, 20u}, // zkz -> Cyrl + {0x81790000u, 55u}, // zla -> Latn + {0xA5790000u, 34u}, // zlj -> Hani + {0xB1790000u, 55u}, // zlm -> Latn + {0xB5790000u, 34u}, // zln -> Hani + {0xC1790000u, 34u}, // zlq -> Hani + {0xD1790000u, 55u}, // zlu -> Latn + {0x81990000u, 55u}, // zma -> Latn + {0x85990000u, 55u}, // zmb -> Latn + {0x89990000u, 55u}, // zmc -> Latn + {0x8D990000u, 55u}, // zmd -> Latn + {0x91990000u, 55u}, // zme -> Latn + {0x95990000u, 55u}, // zmf -> Latn + {0x99990000u, 55u}, // zmg -> Latn + {0x9D990000u, 55u}, // zmh -> Latn + {0xA1990000u, 55u}, // zmi -> Latn + {0xA5990000u, 55u}, // zmj -> Latn + {0xA9990000u, 55u}, // zmk -> Latn + {0xAD990000u, 55u}, // zml -> Latn + {0xB1990000u, 55u}, // zmm -> Latn + {0xB5990000u, 55u}, // zmn -> Latn + {0xB9990000u, 55u}, // zmo -> Latn + {0xBD990000u, 55u}, // zmp -> Latn + {0xC1990000u, 55u}, // zmq -> Latn + {0xC5990000u, 55u}, // zmr -> Latn + {0xC9990000u, 55u}, // zms -> Latn + {0xCD990000u, 55u}, // zmt -> Latn + {0xD1990000u, 55u}, // zmu -> Latn + {0xD5990000u, 55u}, // zmv -> Latn + {0xD9990000u, 55u}, // zmw -> Latn + {0xDD990000u, 55u}, // zmx -> Latn + {0xE1990000u, 55u}, // zmy -> Latn + {0xE5990000u, 55u}, // zmz -> Latn + {0x81B90000u, 55u}, // zna -> Latn + {0x91B90000u, 55u}, // zne -> Latn + {0x99B90000u, 55u}, // zng -> Latn + {0xA9B90000u, 55u}, // znk -> Latn + {0xC9B90000u, 55u}, // zns -> Latn + {0x89D90000u, 55u}, // zoc -> Latn + {0x9DD90000u, 55u}, // zoh -> Latn + {0xB1D90000u, 55u}, // zom -> Latn + {0xB9D90000u, 55u}, // zoo -> Latn + {0xC1D90000u, 55u}, // zoq -> Latn + {0xC5D90000u, 55u}, // zor -> Latn + {0xC9D90000u, 55u}, // zos -> Latn + {0x81F90000u, 55u}, // zpa -> Latn + {0x85F90000u, 55u}, // zpb -> Latn + {0x89F90000u, 55u}, // zpc -> Latn + {0x8DF90000u, 55u}, // zpd -> Latn + {0x91F90000u, 55u}, // zpe -> Latn + {0x95F90000u, 55u}, // zpf -> Latn + {0x99F90000u, 55u}, // zpg -> Latn + {0x9DF90000u, 55u}, // zph -> Latn + {0xA1F90000u, 55u}, // zpi -> Latn + {0xA5F90000u, 55u}, // zpj -> Latn + {0xA9F90000u, 55u}, // zpk -> Latn + {0xADF90000u, 55u}, // zpl -> Latn + {0xB1F90000u, 55u}, // zpm -> Latn + {0xB5F90000u, 55u}, // zpn -> Latn + {0xB9F90000u, 55u}, // zpo -> Latn + {0xBDF90000u, 55u}, // zpp -> Latn + {0xC1F90000u, 55u}, // zpq -> Latn + {0xC5F90000u, 55u}, // zpr -> Latn + {0xC9F90000u, 55u}, // zps -> Latn + {0xCDF90000u, 55u}, // zpt -> Latn + {0xD1F90000u, 55u}, // zpu -> Latn + {0xD5F90000u, 55u}, // zpv -> Latn + {0xD9F90000u, 55u}, // zpw -> Latn + {0xDDF90000u, 55u}, // zpx -> Latn + {0xE1F90000u, 55u}, // zpy -> Latn + {0xE5F90000u, 55u}, // zpz -> Latn + {0x92190000u, 34u}, // zqe -> Hani + {0x9A390000u, 80u}, // zrg -> Orya + {0xB6390000u, 55u}, // zrn -> Latn + {0xBA390000u, 55u}, // zro -> Latn + {0xBE390000u, 37u}, // zrp -> Hebr + {0xCA390000u, 55u}, // zrs -> Latn + {0x82590000u, 55u}, // zsa -> Latn + {0xC6590000u, 55u}, // zsr -> Latn + {0xD2590000u, 55u}, // zsu -> Latn + {0x92790000u, 55u}, // zte -> Latn + {0x9A790000u, 55u}, // ztg -> Latn + {0xAE790000u, 55u}, // ztl -> Latn + {0xB2790000u, 55u}, // ztm -> Latn + {0xB6790000u, 55u}, // ztn -> Latn + {0xBE790000u, 55u}, // ztp -> Latn + {0xC2790000u, 55u}, // ztq -> Latn + {0xCA790000u, 55u}, // zts -> Latn + {0xCE790000u, 55u}, // ztt -> Latn + {0xD2790000u, 55u}, // ztu -> Latn + {0xDE790000u, 55u}, // ztx -> Latn + {0xE2790000u, 55u}, // zty -> Latn + {0x7A750000u, 55u}, // zu -> Latn + {0x9E990000u, 55u}, // zuh -> Latn + {0xB2990000u, 2u}, // zum -> Arab + {0xB6990000u, 55u}, // zun -> Latn + {0xE2990000u, 55u}, // zuy -> Latn + {0x82D90000u, 24u}, // zwa -> Ethi + {0x9B190000u, 34u}, // zyg -> Hani + {0xA7190000u, 55u}, // zyj -> Latn + {0xB7190000u, 34u}, // zyn -> Hani + {0xBF190000u, 55u}, // zyp -> Latn + {0x83390000u, 55u}, // zza -> Latn + {0xA7390000u, 34u}, // zzj -> Hani }); std::unordered_set<uint64_t> REPRESENTATIVE_LOCALES({ 0x616145544C61746ELLU, // aa_Latn_ET + 0x80004E474C61746ELLU, // aaa_Latn_NG + 0x84004E474C61746ELLU, // aab_Latn_NG + 0x880050474C61746ELLU, // aac_Latn_PG + 0x8C0050474C61746ELLU, // aad_Latn_PG + 0x900049544C61746ELLU, // aae_Latn_IT + 0x9400494E4D6C796DLLU, // aaf_Mlym_IN + 0x980050474C61746ELLU, // aag_Latn_PG + 0x9C0050474C61746ELLU, // aah_Latn_PG + 0xA00050474C61746ELLU, // aai_Latn_PG + 0xA80050474C61746ELLU, // aak_Latn_PG + 0xAC00434D4C61746ELLU, // aal_Latn_CM + 0xB40042524C61746ELLU, // aan_Latn_BR + 0xB800445A41726162LLU, // aao_Arab_DZ + 0xBC0042524C61746ELLU, // aap_Latn_BR + 0xC00055534C61746ELLU, // aaq_Latn_US + 0xC800545A4C61746ELLU, // aas_Latn_TZ + 0xCC0047524772656BLLU, // aat_Grek_GR + 0xD00050474C61746ELLU, // aau_Latn_PG + 0xD80050474C61746ELLU, // aaw_Latn_PG + 0xDC0049444C61746ELLU, // aax_Latn_ID + 0xE40049444C61746ELLU, // aaz_Latn_ID 0x616247454379726CLLU, // ab_Cyrl_GE + 0x802043494C61746ELLU, // aba_Latn_CI + 0x8420434D4C61746ELLU, // abb_Latn_CM + 0x882050484C61746ELLU, // abc_Latn_PH + 0x8C2050484C61746ELLU, // abd_Latn_PH + 0x902043414C61746ELLU, // abe_Latn_CA + 0x94204D594C61746ELLU, // abf_Latn_MY + 0x982050474C61746ELLU, // abg_Latn_PG + 0x9C20544A41726162LLU, // abh_Arab_TJ + 0xA02043494C61746ELLU, // abi_Latn_CI + 0xAC204944526A6E67LLU, // abl_Rjng_ID + 0xB0204E474C61746ELLU, // abm_Latn_NG + 0xB4204E474C61746ELLU, // abn_Latn_NG + 0xB8204E474C61746ELLU, // abo_Latn_NG + 0xBC2050484C61746ELLU, // abp_Latn_PH 0xC42047484C61746ELLU, // abr_Latn_GH + 0xC82049444C61746ELLU, // abs_Latn_ID + 0xCC2050474C61746ELLU, // abt_Latn_PG + 0xD02043494C61746ELLU, // abu_Latn_CI + 0xD420424841726162LLU, // abv_Arab_BH + 0xD82050474C61746ELLU, // abw_Latn_PG + 0xDC2050484C61746ELLU, // abx_Latn_PH + 0xE02050474C61746ELLU, // aby_Latn_PG + 0xE42049444C61746ELLU, // abz_Latn_ID + 0x8040434F4C61746ELLU, // aca_Latn_CO + 0x84404E474C61746ELLU, // acb_Latn_NG + 0x8C4047484C61746ELLU, // acd_Latn_GH 0x904049444C61746ELLU, // ace_Latn_ID + 0x94404C434C61746ELLU, // acf_Latn_LC 0x9C4055474C61746ELLU, // ach_Latn_UG + 0xB040495141726162LLU, // acm_Arab_IQ + 0xB440434E4C61746ELLU, // acn_Latn_CN + 0xBC404E474C61746ELLU, // acp_Latn_NG + 0xC040594541726162LLU, // acq_Arab_YE + 0xC44047544C61746ELLU, // acr_Latn_GT + 0xC84042524C61746ELLU, // acs_Latn_BR + 0xCC404E4C4C61746ELLU, // act_Latn_NL + 0xD04045434C61746ELLU, // acu_Latn_EC + 0xD44055534C61746ELLU, // acv_Latn_US + 0xD840534141726162LLU, // acw_Arab_SA + 0xDC404F4D41726162LLU, // acx_Arab_OM + 0xE04043594C61746ELLU, // acy_Latn_CY + 0xE44053444C61746ELLU, // acz_Latn_SD 0x806047484C61746ELLU, // ada_Latn_GH - 0xBC60425454696274LLU, // adp_Tibt_BT + 0x8460544C4C61746ELLU, // adb_Latn_TL + 0x8C60434D4C61746ELLU, // add_Latn_CM + 0x906054474C61746ELLU, // ade_Latn_TG + 0x94604F4D41726162LLU, // adf_Arab_OM + 0x986041554C61746ELLU, // adg_Latn_AU + 0x9C6055474C61746ELLU, // adh_Latn_UG + 0xA060494E4C61746ELLU, // adi_Latn_IN + 0xA46043494C61746ELLU, // adj_Latn_CI + 0xAC60494E4C61746ELLU, // adl_Latn_IN + 0xB46049444C61746ELLU, // adn_Latn_ID + 0xB86050474C61746ELLU, // ado_Latn_PG + 0xC06047484C61746ELLU, // adq_Latn_GH + 0xC46049444C61746ELLU, // adr_Latn_ID + 0xCC6041554C61746ELLU, // adt_Latn_AU + 0xD0604E474C61746ELLU, // adu_Latn_NG + 0xD86042524C61746ELLU, // adw_Latn_BR + 0xDC60434E54696274LLU, // adx_Tibt_CN 0xE06052554379726CLLU, // ady_Cyrl_RU + 0xE46050474C61746ELLU, // adz_Latn_PG 0x6165495241767374LLU, // ae_Avst_IR + 0x808041554C61746ELLU, // aea_Latn_AU 0x8480544E41726162LLU, // aeb_Arab_TN + 0x8880454741726162LLU, // aec_Arab_EG + 0x9080414641726162LLU, // aee_Arab_AF + 0xA8804E434C61746ELLU, // aek_Latn_NC + 0xAC80434D4C61746ELLU, // ael_Latn_CM + 0xB080564E4C61746ELLU, // aem_Latn_VN + 0xC080504B41726162LLU, // aeq_Arab_PK + 0xC48041554C61746ELLU, // aer_Latn_AU + 0xD080434E4C61746ELLU, // aeu_Latn_CN + 0xD88050474C61746ELLU, // aew_Latn_PG + 0xE08050474C61746ELLU, // aey_Latn_PG + 0xE48050474C61746ELLU, // aez_Latn_PG 0x61665A414C61746ELLU, // af_Latn_ZA + 0x84A04B5741726162LLU, // afb_Arab_KW + 0x8CA050474C61746ELLU, // afd_Latn_PG + 0x90A04E474C61746ELLU, // afe_Latn_NG + 0x9CA047484C61746ELLU, // afh_Latn_GH + 0xA0A050474C61746ELLU, // afi_Latn_PG + 0xA8A050474C61746ELLU, // afk_Latn_PG + 0xB4A04E474C61746ELLU, // afn_Latn_NG + 0xB8A04E474C61746ELLU, // afo_Latn_NG + 0xBCA050474C61746ELLU, // afp_Latn_PG + 0xC8A04D584C61746ELLU, // afs_Latn_MX + 0xD0A047484C61746ELLU, // afu_Latn_GH + 0xE4A049444C61746ELLU, // afz_Latn_ID + 0x80C050454C61746ELLU, // aga_Latn_PE + 0x84C04E474C61746ELLU, // agb_Latn_NG + 0x88C04E474C61746ELLU, // agc_Latn_NG + 0x8CC050474C61746ELLU, // agd_Latn_PG + 0x90C050474C61746ELLU, // age_Latn_PG + 0x94C049444C61746ELLU, // agf_Latn_ID + 0x98C050474C61746ELLU, // agg_Latn_PG + 0x9CC043444C61746ELLU, // agh_Latn_CD + 0xA0C0494E44657661LLU, // agi_Deva_IN + 0xA4C0455445746869LLU, // agj_Ethi_ET + 0xA8C050484C61746ELLU, // agk_Latn_PH + 0xACC050474C61746ELLU, // agl_Latn_PG + 0xB0C050474C61746ELLU, // agm_Latn_PG + 0xB4C050484C61746ELLU, // agn_Latn_PH + 0xB8C050474C61746ELLU, // ago_Latn_PG 0xC0C0434D4C61746ELLU, // agq_Latn_CM + 0xC4C050454C61746ELLU, // agr_Latn_PE + 0xC8C0434D4C61746ELLU, // ags_Latn_CM + 0xCCC050484C61746ELLU, // agt_Latn_PH + 0xD0C047544C61746ELLU, // agu_Latn_GT + 0xD4C050484C61746ELLU, // agv_Latn_PH + 0xD8C053424C61746ELLU, // agw_Latn_SB + 0xDCC052554379726CLLU, // agx_Cyrl_RU + 0xE0C050484C61746ELLU, // agy_Latn_PH + 0xE4C050484C61746ELLU, // agz_Latn_PH + 0x80E047484C61746ELLU, // aha_Latn_GH + 0x84E056554C61746ELLU, // ahb_Latn_VU + 0x98E0455445746869LLU, // ahg_Ethi_ET + 0x9CE049444C61746ELLU, // ahh_Latn_ID + 0xA0E043494C61746ELLU, // ahi_Latn_CI + 0xA8E04D4D4C61746ELLU, // ahk_Latn_MM + 0xACE054474C61746ELLU, // ahl_Latn_TG + 0xB0E043494C61746ELLU, // ahm_Latn_CI + 0xB4E04E474C61746ELLU, // ahn_Latn_NG 0xB8E0494E41686F6DLLU, // aho_Ahom_IN - 0xCD20544E41726162LLU, // ajt_Arab_TN + 0xBCE043494C61746ELLU, // ahp_Latn_CI + 0xC4E0494E44657661LLU, // ahr_Deva_IN + 0xC8E04E474C61746ELLU, // ahs_Latn_NG + 0xCCE055534C61746ELLU, // aht_Latn_US + 0x810053424C61746ELLU, // aia_Latn_SB + 0x8500434E41726162LLU, // aib_Arab_CN + 0x890050474C61746ELLU, // aic_Latn_PG + 0x8D0041554C61746ELLU, // aid_Latn_AU + 0x910050474C61746ELLU, // aie_Latn_PG + 0x950050474C61746ELLU, // aif_Latn_PG + 0x990041474C61746ELLU, // aig_Latn_AG + 0xA100495153797263LLU, // aii_Syrc_IQ + 0xA500494C48656272LLU, // aij_Hebr_IL + 0xA9004E474C61746ELLU, // aik_Latn_NG + 0xAD0050474C61746ELLU, // ail_Latn_PG + 0xB100494E4C61746ELLU, // aim_Latn_IN + 0xB5004A504B616E61LLU, // ain_Kana_JP + 0xB900494E4D796D72LLU, // aio_Mymr_IN + 0xBD0049444C61746ELLU, // aip_Latn_ID + 0xC100414641726162LLU, // aiq_Arab_AF + 0xC50049444C61746ELLU, // air_Latn_ID + 0xCD0042524C61746ELLU, // ait_Latn_BR + 0xD90045544C61746ELLU, // aiw_Latn_ET + 0xDD0050474C61746ELLU, // aix_Latn_PG + 0xE10043464C61746ELLU, // aiy_Latn_CF + 0x812053534C61746ELLU, // aja_Latn_SS + 0x9920424A4C61746ELLU, // ajg_Latn_BJ + 0xA1204E434C61746ELLU, // aji_Latn_NC + 0xB52041554C61746ELLU, // ajn_Latn_AU + 0xD9204E474C61746ELLU, // ajw_Latn_NG + 0xE520494E4C61746ELLU, // ajz_Latn_IN 0x616B47484C61746ELLU, // ak_Latn_GH + 0x854049444C61746ELLU, // akb_Latn_ID + 0x894049444C61746ELLU, // akc_Latn_ID + 0x8D404E474C61746ELLU, // akd_Latn_NG + 0x914047594C61746ELLU, // ake_Latn_GY + 0x95404E474C61746ELLU, // akf_Latn_NG + 0x994049444C61746ELLU, // akg_Latn_ID + 0x9D4050474C61746ELLU, // akh_Latn_PG + 0xA14050474C61746ELLU, // aki_Latn_PG 0xA940495158737578LLU, // akk_Xsux_IQ + 0xAD4050484C61746ELLU, // akl_Latn_PH + 0xB94053524C61746ELLU, // ako_Latn_SR + 0xBD4047484C61746ELLU, // akp_Latn_GH + 0xC14050474C61746ELLU, // akq_Latn_PG + 0xC54056554C61746ELLU, // akr_Latn_VU + 0xC94054474C61746ELLU, // aks_Latn_TG + 0xCD4050474C61746ELLU, // akt_Latn_PG + 0xD140434D4C61746ELLU, // aku_Latn_CM + 0xD54052554379726CLLU, // akv_Cyrl_RU + 0xD94043474C61746ELLU, // akw_Latn_CG + 0xE54055534C61746ELLU, // akz_Latn_US + 0x81604E474C61746ELLU, // ala_Latn_NG + 0x8960434C4C61746ELLU, // alc_Latn_CL + 0x8D6043494C61746ELLU, // ald_Latn_CI + 0x916055534C61746ELLU, // ale_Latn_US + 0x95604E474C61746ELLU, // alf_Latn_NG + 0x9D6041554C61746ELLU, // alh_Latn_AU + 0xA16050474C61746ELLU, // ali_Latn_PG + 0xA56050484C61746ELLU, // alj_Latn_PH + 0xA9604C414C616F6FLLU, // alk_Laoo_LA + 0xAD60494E4D6C796DLLU, // all_Mlym_IN + 0xB16056554C61746ELLU, // alm_Latn_VU 0xB560584B4C61746ELLU, // aln_Latn_XK + 0xB96049444C61746ELLU, // alo_Latn_ID + 0xBD6049444C61746ELLU, // alp_Latn_ID + 0xC16043414C61746ELLU, // alq_Latn_CA + 0xC56052554379726CLLU, // alr_Cyrl_RU 0xCD6052554379726CLLU, // alt_Cyrl_RU + 0xD16053424C61746ELLU, // alu_Latn_SB + 0xD960455445746869LLU, // alw_Ethi_ET + 0xDD6050474C61746ELLU, // alx_Latn_PG + 0xE16041554C61746ELLU, // aly_Latn_AU + 0xE56043444C61746ELLU, // alz_Latn_CD 0x616D455445746869LLU, // am_Ethi_ET + 0x818042524C61746ELLU, // ama_Latn_BR + 0x85804E474C61746ELLU, // amb_Latn_NG + 0x898050454C61746ELLU, // amc_Latn_PE + 0x918050454C61746ELLU, // ame_Latn_PE + 0x958045544C61746ELLU, // amf_Latn_ET + 0x998041554C61746ELLU, // amg_Latn_AU + 0xA18054574C61746ELLU, // ami_Latn_TW + 0xA58054444C61746ELLU, // amj_Latn_TD + 0xA98049444C61746ELLU, // amk_Latn_ID + 0xB18050474C61746ELLU, // amm_Latn_PG + 0xB58050474C61746ELLU, // amn_Latn_PG 0xB9804E474C61746ELLU, // amo_Latn_NG + 0xBD8050474C61746ELLU, // amp_Latn_PG + 0xC18049444C61746ELLU, // amq_Latn_ID + 0xC58050454C61746ELLU, // amr_Latn_PE + 0xC9804A504A70616ELLU, // ams_Jpan_JP + 0xCD8050474C61746ELLU, // amt_Latn_PG + 0xD1804D584C61746ELLU, // amu_Latn_MX + 0xD58049444C61746ELLU, // amv_Latn_ID + 0xD980535953797263LLU, // amw_Syrc_SY + 0xDD8041554C61746ELLU, // amx_Latn_AU + 0xE18041554C61746ELLU, // amy_Latn_AU + 0xE58041554C61746ELLU, // amz_Latn_AU 0x616E45534C61746ELLU, // an_Latn_ES + 0x81A0434F4C61746ELLU, // ana_Latn_CO + 0x85A050454C61746ELLU, // anb_Latn_PE + 0x89A04E474C61746ELLU, // anc_Latn_NG + 0x8DA049444C61746ELLU, // and_Latn_ID + 0x91A04E434C61746ELLU, // ane_Latn_NC + 0x95A047484C61746ELLU, // anf_Latn_GH + 0x99A047424C61746ELLU, // ang_Latn_GB + 0x9DA050474C61746ELLU, // anh_Latn_PG + 0xA1A052554379726CLLU, // ani_Cyrl_RU + 0xA5A050474C61746ELLU, // anj_Latn_PG + 0xA9A04E474C61746ELLU, // ank_Latn_NG + 0xADA04D4D4C61746ELLU, // anl_Latn_MM + 0xB1A0494E4C61746ELLU, // anm_Latn_IN 0xB5A04E474C61746ELLU, // ann_Latn_NG + 0xB9A0434F4C61746ELLU, // ano_Latn_CO + 0xBDA0494E44657661LLU, // anp_Deva_IN + 0xC1A0494E44657661LLU, // anq_Deva_IN + 0xC5A0494E44657661LLU, // anr_Deva_IN + 0xC9A0434F4C61746ELLU, // ans_Latn_CO + 0xCDA041554C61746ELLU, // ant_Latn_AU + 0xD1A0455445746869LLU, // anu_Ethi_ET + 0xD5A0434D4C61746ELLU, // anv_Latn_CM + 0xD9A04E474C61746ELLU, // anw_Latn_NG + 0xDDA050474C61746ELLU, // anx_Latn_PG + 0xE1A043494C61746ELLU, // any_Latn_CI + 0xE5A050474C61746ELLU, // anz_Latn_PG + 0x81C053544C61746ELLU, // aoa_Latn_ST + 0x85C050474C61746ELLU, // aob_Latn_PG + 0x89C056454C61746ELLU, // aoc_Latn_VE + 0x8DC050474C61746ELLU, // aod_Latn_PG + 0x91C050474C61746ELLU, // aoe_Latn_PG + 0x95C050474C61746ELLU, // aof_Latn_PG + 0x99C050474C61746ELLU, // aog_Latn_PG + 0xA1C041554C61746ELLU, // aoi_Latn_AU + 0xA5C050474C61746ELLU, // aoj_Latn_PG + 0xA9C04E434C61746ELLU, // aok_Latn_NC + 0xADC049444C61746ELLU, // aol_Latn_ID + 0xB1C050474C61746ELLU, // aom_Latn_PG + 0xB5C050474C61746ELLU, // aon_Latn_PG + 0xC5C056554C61746ELLU, // aor_Latn_VU + 0xC9C049444C61746ELLU, // aos_Latn_ID + 0xCDC0424442656E67LLU, // aot_Beng_BD + 0xDDC047594C61746ELLU, // aox_Latn_GY 0xE5C049444C61746ELLU, // aoz_Latn_ID + 0x85E053424C61746ELLU, // apb_Latn_SB + 0x89E0535941726162LLU, // apc_Arab_SY 0x8DE0544741726162LLU, // apd_Arab_TG + 0x91E050474C61746ELLU, // ape_Latn_PG + 0x95E050484C61746ELLU, // apf_Latn_PH + 0x99E049444C61746ELLU, // apg_Latn_ID + 0x9DE04E5044657661LLU, // aph_Deva_NP + 0xA1E042524C61746ELLU, // api_Latn_BR + 0xA5E055534C61746ELLU, // apj_Latn_US + 0xA9E055534C61746ELLU, // apk_Latn_US + 0xADE055534C61746ELLU, // apl_Latn_US + 0xB1E055534C61746ELLU, // apm_Latn_US + 0xB5E042524C61746ELLU, // apn_Latn_BR + 0xB9E050474C61746ELLU, // apo_Latn_PG + 0xBDE056554C61746ELLU, // app_Latn_VU + 0xC5E050474C61746ELLU, // apr_Latn_PG + 0xC9E050474C61746ELLU, // aps_Latn_PG + 0xCDE0494E4C61746ELLU, // apt_Latn_IN + 0xD1E042524C61746ELLU, // apu_Latn_BR + 0xD5E042524C61746ELLU, // apv_Latn_BR + 0xD9E055534C61746ELLU, // apw_Latn_US + 0xDDE049444C61746ELLU, // apx_Latn_ID + 0xE1E042524C61746ELLU, // apy_Latn_BR + 0xE5E050474C61746ELLU, // apz_Latn_PG + 0x8A0052554379726CLLU, // aqc_Cyrl_RU + 0x8E004D4C4C61746ELLU, // aqd_Latn_ML + 0x9A004E474C61746ELLU, // aqg_Latn_NG + 0xAA004E474C61746ELLU, // aqk_Latn_NG + 0xB20049444C61746ELLU, // aqm_Latn_ID + 0xB60050484C61746ELLU, // aqn_Latn_PH + 0xC6004E434C61746ELLU, // aqr_Latn_NC + 0xCE0050594C61746ELLU, // aqt_Latn_PY + 0xE60042524C61746ELLU, // aqz_Latn_BR 0x6172454741726162LLU, // ar_Arab_EG 0x8A20495241726D69LLU, // arc_Armi_IR + 0x8A20495148617472LLU, // arc_Hatr_IQ 0x8A204A4F4E626174LLU, // arc_Nbat_JO 0x8A20535950616C6DLLU, // arc_Palm_SY + 0x8E2041554C61746ELLU, // ard_Latn_AU + 0x922041554C61746ELLU, // are_Latn_AU + 0x9E20434F4C61746ELLU, // arh_Latn_CO + 0xA22055534C61746ELLU, // ari_Latn_US + 0xA62042524C61746ELLU, // arj_Latn_BR + 0xAA2042524C61746ELLU, // ark_Latn_BR + 0xAE2050454C61746ELLU, // arl_Latn_PE 0xB620434C4C61746ELLU, // arn_Latn_CL 0xBA20424F4C61746ELLU, // aro_Latn_BO + 0xBE2055534C61746ELLU, // arp_Latn_US 0xC220445A41726162LLU, // arq_Arab_DZ + 0xC62042524C61746ELLU, // arr_Latn_BR 0xCA20534141726162LLU, // ars_Arab_SA + 0xD22042524C61746ELLU, // aru_Latn_BR + 0xDA2053524C61746ELLU, // arw_Latn_SR + 0xDE2042524C61746ELLU, // arx_Latn_BR 0xE2204D4141726162LLU, // ary_Arab_MA 0xE620454741726162LLU, // arz_Arab_EG 0x6173494E42656E67LLU, // as_Beng_IN 0x8240545A4C61746ELLU, // asa_Latn_TZ + 0x864043414C61746ELLU, // asb_Latn_CA + 0x8A4049444C61746ELLU, // asc_Latn_ID 0x9240555353676E77LLU, // ase_Sgnw_US + 0x9A404E474C61746ELLU, // asg_Latn_NG + 0x9E4050454C61746ELLU, // ash_Latn_PE + 0xA24049444C61746ELLU, // asi_Latn_ID + 0xA640434D4C61746ELLU, // asj_Latn_CM + 0xAA40414641726162LLU, // ask_Arab_AF + 0xAE4049444C61746ELLU, // asl_Latn_ID + 0xB64042524C61746ELLU, // asn_Latn_BR + 0xBA4050474C61746ELLU, // aso_Latn_PG + 0xC640494E44657661LLU, // asr_Deva_IN + 0xCA40434D4C61746ELLU, // ass_Latn_CM 0xCE4045534C61746ELLU, // ast_Latn_ES + 0xD24042524C61746ELLU, // asu_Latn_BR + 0xD64043444C61746ELLU, // asv_Latn_CD + 0xDE4050474C61746ELLU, // asx_Latn_PG + 0xE24049444C61746ELLU, // asy_Latn_ID + 0xE64049444C61746ELLU, // asz_Latn_ID + 0x826050474C61746ELLU, // ata_Latn_PG + 0x8660434E4C61746ELLU, // atb_Latn_CN + 0x8A6050454C61746ELLU, // atc_Latn_PE + 0x8E6050484C61746ELLU, // atd_Latn_PH + 0x926050474C61746ELLU, // ate_Latn_PG + 0x9A604E474C61746ELLU, // atg_Latn_NG + 0xA26043494C61746ELLU, // ati_Latn_CI 0xA66043414C61746ELLU, // atj_Latn_CA + 0xAA6050484C61746ELLU, // atk_Latn_PH + 0xAE6050484C61746ELLU, // atl_Latn_PH + 0xB26050484C61746ELLU, // atm_Latn_PH + 0xB660495241726162LLU, // atn_Arab_IR + 0xBA60434D4C61746ELLU, // ato_Latn_CM + 0xBE6050484C61746ELLU, // atp_Latn_PH + 0xC26049444C61746ELLU, // atq_Latn_ID + 0xC66042524C61746ELLU, // atr_Latn_BR + 0xCA6055534C61746ELLU, // ats_Latn_US + 0xCE6050484C61746ELLU, // att_Latn_PH + 0xD26053534C61746ELLU, // atu_Latn_SS + 0xD66052554379726CLLU, // atv_Cyrl_RU + 0xDA6055534C61746ELLU, // atw_Latn_US + 0xDE6042524C61746ELLU, // atx_Latn_BR + 0xE26056554C61746ELLU, // aty_Latn_VU + 0xE66050484C61746ELLU, // atz_Latn_PH + 0x828053424C61746ELLU, // aua_Latn_SB + 0x8A8045434C61746ELLU, // auc_Latn_EC + 0x8E8053424C61746ELLU, // aud_Latn_SB + 0x9A80424A4C61746ELLU, // aug_Latn_BJ + 0x9E805A4D4C61746ELLU, // auh_Latn_ZM + 0xA28050474C61746ELLU, // aui_Latn_PG + 0xA6804C5941726162LLU, // auj_Arab_LY + 0xAA8050474C61746ELLU, // auk_Latn_PG + 0xAE8056554C61746ELLU, // aul_Latn_VU + 0xB2804E474C61746ELLU, // aum_Latn_NG + 0xB68050474C61746ELLU, // aun_Latn_PG + 0xBA804E474C61746ELLU, // auo_Latn_NG + 0xBE8050474C61746ELLU, // aup_Latn_PG + 0xC28049444C61746ELLU, // auq_Latn_ID + 0xC68050474C61746ELLU, // aur_Latn_PG + 0xCE8050464C61746ELLU, // aut_Latn_PF + 0xD28049444C61746ELLU, // auu_Latn_ID + 0xDA8049444C61746ELLU, // auw_Latn_ID + 0xE28050474C61746ELLU, // auy_Latn_PG + 0xE680555A41726162LLU, // auz_Arab_UZ 0x617652554379726CLLU, // av_Cyrl_RU + 0x86A050474C61746ELLU, // avb_Latn_PG + 0x8EA0495241726162LLU, // avd_Arab_IR + 0xA2A043494C61746ELLU, // avi_Latn_CI + 0xAEA0454741726162LLU, // avl_Arab_EG + 0xB2A041554C61746ELLU, // avm_Latn_AU + 0xB6A047484C61746ELLU, // avn_Latn_GH + 0xBAA042524C61746ELLU, // avo_Latn_BR + 0xCAA050454C61746ELLU, // avs_Latn_PE + 0xCEA050474C61746ELLU, // avt_Latn_PG + 0xD2A053534C61746ELLU, // avu_Latn_SS + 0xD6A042524C61746ELLU, // avv_Latn_BR 0x82C0494E44657661LLU, // awa_Deva_IN + 0x86C050474C61746ELLU, // awb_Latn_PG + 0x8AC04E474C61746ELLU, // awc_Latn_NG + 0x92C042524C61746ELLU, // awe_Latn_BR + 0x9AC041554C61746ELLU, // awg_Latn_AU + 0x9EC049444C61746ELLU, // awh_Latn_ID + 0xA2C050474C61746ELLU, // awi_Latn_PG + 0xAAC041554C61746ELLU, // awk_Latn_AU + 0xB2C050474C61746ELLU, // awm_Latn_PG + 0xB6C0455445746869LLU, // awn_Ethi_ET + 0xBAC04E474C61746ELLU, // awo_Latn_NG + 0xC6C049444C61746ELLU, // awr_Latn_ID + 0xCAC049444C61746ELLU, // aws_Latn_ID + 0xCEC042524C61746ELLU, // awt_Latn_BR + 0xD2C049444C61746ELLU, // awu_Latn_ID + 0xD6C049444C61746ELLU, // awv_Latn_ID + 0xDAC050474C61746ELLU, // aww_Latn_PG + 0xDEC050474C61746ELLU, // awx_Latn_PG + 0xE2C049444C61746ELLU, // awy_Latn_ID + 0x86E041524C61746ELLU, // axb_Latn_AR + 0x92E041554C61746ELLU, // axe_Latn_AU + 0x9AE042524C61746ELLU, // axg_Latn_BR + 0xAAE043464C61746ELLU, // axk_Latn_CF + 0xAEE041554C61746ELLU, // axl_Latn_AU + 0xB2E0414D41726D6ELLU, // axm_Armn_AM + 0xDEE04E434C61746ELLU, // axx_Latn_NC 0x6179424F4C61746ELLU, // ay_Latn_BO + 0x830050474C61746ELLU, // aya_Latn_PG + 0x8700424A4C61746ELLU, // ayb_Latn_BJ + 0x8B0050454C61746ELLU, // ayc_Latn_PE + 0x8F0041554C61746ELLU, // ayd_Latn_AU + 0x93004E474C61746ELLU, // aye_Latn_NG + 0x9B0054474C61746ELLU, // ayg_Latn_TG + 0x9F00594541726162LLU, // ayh_Arab_YE + 0xA3004E474C61746ELLU, // ayi_Latn_NG + 0xAB004E474C61746ELLU, // ayk_Latn_NG + 0xAF004C5941726162LLU, // ayl_Arab_LY + 0xB700594541726162LLU, // ayn_Arab_YE + 0xBB0050594C61746ELLU, // ayo_Latn_PY + 0xBF00495141726162LLU, // ayp_Arab_IQ + 0xC30050474C61746ELLU, // ayq_Latn_PG + 0xCB0050484C61746ELLU, // ays_Latn_PH + 0xCF0050484C61746ELLU, // ayt_Latn_PH + 0xD3004E474C61746ELLU, // ayu_Latn_NG + 0xE70049444C61746ELLU, // ayz_Latn_ID 0x617A495241726162LLU, // az_Arab_IR 0x617A415A4C61746ELLU, // az_Latn_AZ + 0x8720495241726162LLU, // azb_Arab_IR + 0x8F204D584C61746ELLU, // azd_Latn_MX + 0x9B204D584C61746ELLU, // azg_Latn_MX + 0xB3204D584C61746ELLU, // azm_Latn_MX + 0xB7204D584C61746ELLU, // azn_Latn_MX + 0xBB20434D4C61746ELLU, // azo_Latn_CM + 0xCF2050484C61746ELLU, // azt_Latn_PH + 0xE7204D584C61746ELLU, // azz_Latn_MX 0x626152554379726CLLU, // ba_Cyrl_RU + 0x800153424C61746ELLU, // baa_Latn_SB + 0x840147574C61746ELLU, // bab_Latn_GW + 0x880149444C61746ELLU, // bac_Latn_ID + 0x900156454C61746ELLU, // bae_Latn_VE + 0x9401434D4C61746ELLU, // baf_Latn_CM + 0x9801434D4C61746ELLU, // bag_Latn_CM + 0x9C0142534C61746ELLU, // bah_Latn_BS + 0xA40149444C61746ELLU, // baj_Latn_ID 0xAC01504B41726162LLU, // bal_Arab_PK 0xB40149444C61746ELLU, // ban_Latn_ID + 0xB801434F4C61746ELLU, // bao_Latn_CO 0xBC014E5044657661LLU, // bap_Deva_NP + 0xBC01494E4B726169LLU, // bap_Krai_IN 0xC40141544C61746ELLU, // bar_Latn_AT 0xC801434D4C61746ELLU, // bas_Latn_CM + 0xD0014E474C61746ELLU, // bau_Latn_NG + 0xD401434D4C61746ELLU, // bav_Latn_CM + 0xD801434D4C61746ELLU, // baw_Latn_CM 0xDC01434D42616D75LLU, // bax_Bamu_CM + 0xE00149444C61746ELLU, // bay_Latn_ID + 0x8021424A4C61746ELLU, // bba_Latn_BJ + 0x842150474C61746ELLU, // bbb_Latn_PG 0x882149444C61746ELLU, // bbc_Latn_ID + 0x8C2150474C61746ELLU, // bbd_Latn_PG + 0x902143444C61746ELLU, // bbe_Latn_CD + 0x942150474C61746ELLU, // bbf_Latn_PG + 0x982147414C61746ELLU, // bbg_Latn_GA + 0xA021434D4C61746ELLU, // bbi_Latn_CM 0xA421434D4C61746ELLU, // bbj_Latn_CM + 0xA821434D4C61746ELLU, // bbk_Latn_CM + 0xAC21474547656F72LLU, // bbl_Geor_GE + 0xB02143444C61746ELLU, // bbm_Latn_CD + 0xB42150474C61746ELLU, // bbn_Latn_PG + 0xB82142464C61746ELLU, // bbo_Latn_BF + 0xBC2143464C61746ELLU, // bbp_Latn_CF + 0xC021434D4C61746ELLU, // bbq_Latn_CM + 0xC42150474C61746ELLU, // bbr_Latn_PG + 0xC8214E474C61746ELLU, // bbs_Latn_NG + 0xCC214E474C61746ELLU, // bbt_Latn_NG + 0xD0214E474C61746ELLU, // bbu_Latn_NG + 0xD42150474C61746ELLU, // bbv_Latn_PG + 0xD821434D4C61746ELLU, // bbw_Latn_CM + 0xDC21434D4C61746ELLU, // bbx_Latn_CM + 0xE021434D4C61746ELLU, // bby_Latn_CM + 0x8041434E4C61746ELLU, // bca_Latn_CN + 0x8441534E4C61746ELLU, // bcb_Latn_SN + 0x8C4149444C61746ELLU, // bcd_Latn_ID + 0x9041434D4C61746ELLU, // bce_Latn_CM + 0x944150474C61746ELLU, // bcf_Latn_PG + 0x9841474E4C61746ELLU, // bcg_Latn_GN + 0x9C4150474C61746ELLU, // bch_Latn_PG 0xA04143494C61746ELLU, // bci_Latn_CI + 0xA44141554C61746ELLU, // bcj_Latn_AU + 0xA84141554C61746ELLU, // bck_Latn_AU + 0xB04150474C61746ELLU, // bcm_Latn_PG + 0xB4414E474C61746ELLU, // bcn_Latn_NG + 0xB84150474C61746ELLU, // bco_Latn_PG + 0xBC4143444C61746ELLU, // bcp_Latn_CD + 0xC041455445746869LLU, // bcq_Ethi_ET + 0xC44143414C61746ELLU, // bcr_Latn_CA + 0xC8414E474C61746ELLU, // bcs_Latn_NG + 0xCC4143444C61746ELLU, // bct_Latn_CD + 0xD04150474C61746ELLU, // bcu_Latn_PG + 0xD4414E474C61746ELLU, // bcv_Latn_NG + 0xD841434D4C61746ELLU, // bcw_Latn_CM + 0xE0414E474C61746ELLU, // bcy_Latn_NG + 0xE441534E4C61746ELLU, // bcz_Latn_SN + 0x8061534E4C61746ELLU, // bda_Latn_SN + 0x846149444C61746ELLU, // bdb_Latn_ID + 0x8861434F4C61746ELLU, // bdc_Latn_CO + 0x8C6150474C61746ELLU, // bdd_Latn_PG + 0x90614E474C61746ELLU, // bde_Latn_NG + 0x946150474C61746ELLU, // bdf_Latn_PG + 0x98614D594C61746ELLU, // bdg_Latn_MY + 0x9C6153534C61746ELLU, // bdh_Latn_SS + 0xA06153444C61746ELLU, // bdi_Latn_SD + 0xA46153534C61746ELLU, // bdj_Latn_SS + 0xA861415A4C61746ELLU, // bdk_Latn_AZ + 0xAC6149444C61746ELLU, // bdl_Latn_ID + 0xB06154444C61746ELLU, // bdm_Latn_TD + 0xB461434D4C61746ELLU, // bdn_Latn_CM + 0xB86154444C61746ELLU, // bdo_Latn_TD + 0xBC61545A4C61746ELLU, // bdp_Latn_TZ + 0xC061564E4C61746ELLU, // bdq_Latn_VN + 0xC4614D594C61746ELLU, // bdr_Latn_MY + 0xC861545A4C61746ELLU, // bds_Latn_TZ + 0xCC6143464C61746ELLU, // bdt_Latn_CF + 0xD061434D4C61746ELLU, // bdu_Latn_CM + 0xD461494E4F727961LLU, // bdv_Orya_IN + 0xD86149444C61746ELLU, // bdw_Latn_ID + 0xDC6149444C61746ELLU, // bdx_Latn_ID + 0xE06141554C61746ELLU, // bdy_Latn_AU + 0xE461504B41726162LLU, // bdz_Arab_PK 0x626542594379726CLLU, // be_Cyrl_BY + 0x808143414C61746ELLU, // bea_Latn_CA + 0x8481434D4C61746ELLU, // beb_Latn_CM + 0x8881434D4C61746ELLU, // bec_Latn_CM + 0x8C8149444C61746ELLU, // bed_Latn_ID + 0x9081494E44657661LLU, // bee_Deva_IN + 0x948150474C61746ELLU, // bef_Latn_PG + 0x9C81424A4C61746ELLU, // beh_Latn_BJ + 0xA08149444C61746ELLU, // bei_Latn_ID 0xA481534441726162LLU, // bej_Arab_SD + 0xA88150474C61746ELLU, // bek_Latn_PG 0xB0815A4D4C61746ELLU, // bem_Latn_ZM + 0xB88150474C61746ELLU, // beo_Latn_PG + 0xBC8149444C61746ELLU, // bep_Latn_ID + 0xC08143474C61746ELLU, // beq_Latn_CG + 0xC88154444C61746ELLU, // bes_Latn_TD + 0xCC8143494C61746ELLU, // bet_Latn_CI + 0xD08149444C61746ELLU, // beu_Latn_ID + 0xD48143494C61746ELLU, // bev_Latn_CI 0xD88149444C61746ELLU, // bew_Latn_ID + 0xDC8153534C61746ELLU, // bex_Latn_SS + 0xE08150474C61746ELLU, // bey_Latn_PG 0xE481545A4C61746ELLU, // bez_Latn_TZ + 0x80A153534C61746ELLU, // bfa_Latn_SS + 0x84A1494E44657661LLU, // bfb_Deva_IN + 0x88A1434E4C61746ELLU, // bfc_Latn_CN 0x8CA1434D4C61746ELLU, // bfd_Latn_CM + 0x90A149444C61746ELLU, // bfe_Latn_ID + 0x94A143464C61746ELLU, // bff_Latn_CF + 0x98A149444C61746ELLU, // bfg_Latn_ID + 0x9CA150474C61746ELLU, // bfh_Latn_PG + 0xA4A1434D4C61746ELLU, // bfj_Latn_CM + 0xACA143464C61746ELLU, // bfl_Latn_CF + 0xB0A1434D4C61746ELLU, // bfm_Latn_CM + 0xB4A1544C4C61746ELLU, // bfn_Latn_TL + 0xB8A142464C61746ELLU, // bfo_Latn_BF + 0xBCA1434D4C61746ELLU, // bfp_Latn_CM 0xC0A1494E54616D6CLLU, // bfq_Taml_IN + 0xC8A1434E4C61746ELLU, // bfs_Latn_CN 0xCCA1504B41726162LLU, // bft_Arab_PK + 0xD0A1494E54696274LLU, // bfu_Tibt_IN + 0xD8A1494E4F727961LLU, // bfw_Orya_IN + 0xDCA150484C61746ELLU, // bfx_Latn_PH 0xE0A1494E44657661LLU, // bfy_Deva_IN + 0xE4A1494E44657661LLU, // bfz_Deva_IN 0x626742474379726CLLU, // bg_Cyrl_BG + 0x80C14E474C61746ELLU, // bga_Latn_NG + 0x84C149444C61746ELLU, // bgb_Latn_ID 0x88C1494E44657661LLU, // bgc_Deva_IN + 0x8CC1494E44657661LLU, // bgd_Deva_IN + 0x94C1434D4C61746ELLU, // bgf_Latn_CM + 0x98C1494E4C61746ELLU, // bgg_Latn_IN + 0xA0C150484C61746ELLU, // bgi_Latn_PH + 0xA4C1434D4C61746ELLU, // bgj_Latn_CM 0xB4C1504B41726162LLU, // bgn_Arab_PK + 0xB8C1474E4C61746ELLU, // bgo_Latn_GN + 0xBCC1504B41726162LLU, // bgp_Arab_PK + 0xC0C1494E44657661LLU, // bgq_Deva_IN + 0xC4C1494E4C61746ELLU, // bgr_Latn_IN + 0xC8C150484C61746ELLU, // bgs_Latn_PH + 0xCCC153424C61746ELLU, // bgt_Latn_SB + 0xD0C14E474C61746ELLU, // bgu_Latn_NG + 0xD4C149444C61746ELLU, // bgv_Latn_ID + 0xD8C1494E44657661LLU, // bgw_Deva_IN 0xDCC154524772656BLLU, // bgx_Grek_TR + 0xE0C149444C61746ELLU, // bgy_Latn_ID + 0xE4C149444C61746ELLU, // bgz_Latn_ID + 0x80E1494E44657661LLU, // bha_Deva_IN 0x84E1494E44657661LLU, // bhb_Deva_IN + 0x88E149444C61746ELLU, // bhc_Latn_ID + 0x8CE1494E44657661LLU, // bhd_Deva_IN + 0x90E1504B41726162LLU, // bhe_Arab_PK + 0x94E150474C61746ELLU, // bhf_Latn_PG + 0x98E150474C61746ELLU, // bhg_Latn_PG + 0x9CE1494C4379726CLLU, // bhh_Cyrl_IL 0xA0E1494E44657661LLU, // bhi_Deva_IN + 0xA4E14E5044657661LLU, // bhj_Deva_NP + 0xACE150474C61746ELLU, // bhl_Latn_PG + 0xB0E14F4D41726162LLU, // bhm_Arab_OM + 0xB4E1474553797263LLU, // bhn_Syrc_GE 0xB8E1494E44657661LLU, // bho_Deva_IN + 0xBCE149444C61746ELLU, // bhp_Latn_ID + 0xC0E149444C61746ELLU, // bhq_Latn_ID + 0xC4E14D474C61746ELLU, // bhr_Latn_MG + 0xC8E1434D4C61746ELLU, // bhs_Latn_CM + 0xCCE1494E44657661LLU, // bht_Deva_IN + 0xD0E1494E44657661LLU, // bhu_Deva_IN + 0xD4E149444C61746ELLU, // bhv_Latn_ID + 0xD8E149444C61746ELLU, // bhw_Latn_ID + 0xE0E143444C61746ELLU, // bhy_Latn_CD + 0xE4E149444C61746ELLU, // bhz_Latn_ID 0x626956554C61746ELLU, // bi_Latn_VU + 0x810141554C61746ELLU, // bia_Latn_AU + 0x850142464C61746ELLU, // bib_Latn_BF + 0x8D0154444C61746ELLU, // bid_Latn_TD + 0x910150474C61746ELLU, // bie_Latn_PG + 0x950147574C61746ELLU, // bif_Latn_GW + 0x990150474C61746ELLU, // big_Latn_PG 0xA90150484C61746ELLU, // bik_Latn_PH + 0xAD014E474C61746ELLU, // bil_Latn_NG + 0xB10147484C61746ELLU, // bim_Latn_GH 0xB5014E474C61746ELLU, // bin_Latn_NG + 0xB90150474C61746ELLU, // bio_Latn_PG + 0xBD0143444C61746ELLU, // bip_Latn_CD + 0xC10150474C61746ELLU, // biq_Latn_PG + 0xC50150474C61746ELLU, // bir_Latn_PG + 0xCD0150474C61746ELLU, // bit_Latn_PG + 0xD101494E4C61746ELLU, // biu_Latn_IN + 0xD50147484C61746ELLU, // biv_Latn_GH + 0xD901434D4C61746ELLU, // biw_Latn_CM + 0xE101494E44657661LLU, // biy_Deva_IN + 0xE50143444C61746ELLU, // biz_Latn_CD + 0x812143444C61746ELLU, // bja_Latn_CD + 0x852141554C61746ELLU, // bjb_Latn_AU + 0x892150474C61746ELLU, // bjc_Latn_PG + 0x9521494C53797263LLU, // bjf_Syrc_IL + 0x992147574C61746ELLU, // bjg_Latn_GW + 0x9D2150474C61746ELLU, // bjh_Latn_PG + 0xA12145544C61746ELLU, // bji_Latn_ET 0xA521494E44657661LLU, // bjj_Deva_IN + 0xA92150474C61746ELLU, // bjk_Latn_PG + 0xAD2150474C61746ELLU, // bjl_Latn_PG + 0xB121495141726162LLU, // bjm_Arab_IQ 0xB52149444C61746ELLU, // bjn_Latn_ID + 0xB92143464C61746ELLU, // bjo_Latn_CF + 0xBD2150474C61746ELLU, // bjp_Latn_PG + 0xC52150474C61746ELLU, // bjr_Latn_PG + 0xC92142424C61746ELLU, // bjs_Latn_BB 0xCD21534E4C61746ELLU, // bjt_Latn_SN + 0xD121434D4C61746ELLU, // bju_Latn_CM + 0xD52154444C61746ELLU, // bjv_Latn_TD + 0xD92143494C61746ELLU, // bjw_Latn_CI + 0xDD2150484C61746ELLU, // bjx_Latn_PH + 0xE12141554C61746ELLU, // bjy_Latn_AU + 0xE52150474C61746ELLU, // bjz_Latn_PG + 0x81414E474C61746ELLU, // bka_Latn_NG + 0x8941434D4C61746ELLU, // bkc_Latn_CM + 0x8D4150484C61746ELLU, // bkd_Latn_PH + 0x954143444C61746ELLU, // bkf_Latn_CD + 0x994143464C61746ELLU, // bkg_Latn_CF + 0x9D41434D4C61746ELLU, // bkh_Latn_CM + 0xA14156554C61746ELLU, // bki_Latn_VU + 0xA54143464C61746ELLU, // bkj_Latn_CF + 0xA941494E54696274LLU, // bkk_Tibt_IN + 0xAD4149444C61746ELLU, // bkl_Latn_ID 0xB141434D4C61746ELLU, // bkm_Latn_CM + 0xB54149444C61746ELLU, // bkn_Latn_ID + 0xB941434D4C61746ELLU, // bko_Latn_CM + 0xBD4143444C61746ELLU, // bkp_Latn_CD + 0xC14142524C61746ELLU, // bkq_Latn_BR + 0xC54149444C61746ELLU, // bkr_Latn_ID + 0xC94150484C61746ELLU, // bks_Latn_PH + 0xCD4143444C61746ELLU, // bkt_Latn_CD 0xD14150484C61746ELLU, // bku_Latn_PH + 0xD5414E474C61746ELLU, // bkv_Latn_NG + 0xD94143474C61746ELLU, // bkw_Latn_CG + 0xDD41544C4C61746ELLU, // bkx_Latn_TL + 0xE1414E474C61746ELLU, // bky_Latn_NG + 0xE54149444C61746ELLU, // bkz_Latn_ID 0x816143414C61746ELLU, // bla_Latn_CA - 0x99614D594C61746ELLU, // blg_Latn_MY + 0x856153424C61746ELLU, // blb_Latn_SB + 0x896143414C61746ELLU, // blc_Latn_CA + 0x8D6149444C61746ELLU, // bld_Latn_ID + 0x916147574C61746ELLU, // ble_Latn_GW + 0x956149444C61746ELLU, // blf_Latn_ID + 0x9D614C524C61746ELLU, // blh_Latn_LR + 0xA16143444C61746ELLU, // bli_Latn_CD + 0xA56149444C61746ELLU, // blj_Latn_ID + 0xA9614D4D4D796D72LLU, // blk_Mymr_MM + 0xB16153534C61746ELLU, // blm_Latn_SS + 0xB56150484C61746ELLU, // bln_Latn_PH + 0xB961424A4C61746ELLU, // blo_Latn_BJ + 0xBD6153424C61746ELLU, // blp_Latn_SB + 0xC16150474C61746ELLU, // blq_Latn_PG + 0xC561434E4C61746ELLU, // blr_Latn_CN + 0xC96149444C61746ELLU, // bls_Latn_ID 0xCD61564E54617674LLU, // blt_Tavt_VN + 0xD561414F4C61746ELLU, // blv_Latn_AO + 0xD96150484C61746ELLU, // blw_Latn_PH + 0xDD6150484C61746ELLU, // blx_Latn_PH + 0xE161424A4C61746ELLU, // bly_Latn_BJ + 0xE56149444C61746ELLU, // blz_Latn_ID 0x626D4D4C4C61746ELLU, // bm_Latn_ML + 0x81814E474C61746ELLU, // bma_Latn_NG + 0x858143444C61746ELLU, // bmb_Latn_CD + 0x898150474C61746ELLU, // bmc_Latn_PG + 0x8D81474E4C61746ELLU, // bmd_Latn_GN + 0x918143464C61746ELLU, // bme_Latn_CF + 0x9581534C4C61746ELLU, // bmf_Latn_SL + 0x998143444C61746ELLU, // bmg_Latn_CD + 0x9D8150474C61746ELLU, // bmh_Latn_PG + 0xA18154444C61746ELLU, // bmi_Latn_TD + 0xA5814E5044657661LLU, // bmj_Deva_NP + 0xA98150474C61746ELLU, // bmk_Latn_PG + 0xAD8143444C61746ELLU, // bml_Latn_CD + 0xB1814D474C61746ELLU, // bmm_Latn_MG + 0xB58150474C61746ELLU, // bmn_Latn_PG + 0xB981434D4C61746ELLU, // bmo_Latn_CM + 0xBD8150474C61746ELLU, // bmp_Latn_PG 0xC1814D4C4C61746ELLU, // bmq_Latn_ML + 0xC581434F4C61746ELLU, // bmr_Latn_CO + 0xC9814E454C61746ELLU, // bms_Latn_NE + 0xD18150474C61746ELLU, // bmu_Latn_PG + 0xD581434D4C61746ELLU, // bmv_Latn_CM + 0xD98143474C61746ELLU, // bmw_Latn_CG + 0xDD8150474C61746ELLU, // bmx_Latn_PG + 0xE58150474C61746ELLU, // bmz_Latn_PG 0x626E424442656E67LLU, // bn_Beng_BD + 0x81A149444C61746ELLU, // bna_Latn_ID + 0x85A14D594C61746ELLU, // bnb_Latn_MY + 0x89A150484C61746ELLU, // bnc_Latn_PH + 0x8DA149444C61746ELLU, // bnd_Latn_ID + 0x91A149444C61746ELLU, // bne_Latn_ID + 0x95A149444C61746ELLU, // bnf_Latn_ID + 0x99A147514C61746ELLU, // bng_Latn_GQ + 0xA1A143444C61746ELLU, // bni_Latn_CD + 0xA5A150484C61746ELLU, // bnj_Latn_PH + 0xA9A156554C61746ELLU, // bnk_Latn_VU + 0xB1A147514C61746ELLU, // bnm_Latn_GQ + 0xB5A154574C61746ELLU, // bnn_Latn_TW + 0xB9A150484C61746ELLU, // bno_Latn_PH + 0xBDA150474C61746ELLU, // bnp_Latn_PG + 0xC1A149444C61746ELLU, // bnq_Latn_ID + 0xC5A156554C61746ELLU, // bnr_Latn_VU + 0xC9A1494E44657661LLU, // bns_Deva_IN + 0xD1A149444C61746ELLU, // bnu_Latn_ID + 0xD5A149444C61746ELLU, // bnv_Latn_ID + 0xD9A150474C61746ELLU, // bnw_Latn_PG + 0xDDA143444C61746ELLU, // bnx_Latn_CD + 0xE1A14D594C61746ELLU, // bny_Latn_MY + 0xE5A1434D4C61746ELLU, // bnz_Latn_CM 0x626F434E54696274LLU, // bo_Tibt_CN + 0x81C150454C61746ELLU, // boa_Latn_PE + 0x85C14B454C61746ELLU, // bob_Latn_KE + 0x91C1434D4C61746ELLU, // boe_Latn_CM + 0x95C142464C61746ELLU, // bof_Latn_BF + 0x9DC143444C61746ELLU, // boh_Latn_CD + 0xA5C150474C61746ELLU, // boj_Latn_PG + 0xA9C143474C61746ELLU, // bok_Latn_CG + 0xADC14E474C61746ELLU, // bol_Latn_NG + 0xB1C14E474C61746ELLU, // bom_Latn_NG + 0xB5C150474C61746ELLU, // bon_Latn_PG + 0xB9C14D4C4C61746ELLU, // boo_Latn_ML + 0xBDC150474C61746ELLU, // bop_Latn_PG + 0xC1C150474C61746ELLU, // boq_Latn_PG + 0xC5C142524C61746ELLU, // bor_Latn_BR + 0xCDC153534C61746ELLU, // bot_Latn_SS + 0xD1C1545A4C61746ELLU, // bou_Latn_TZ + 0xD5C147484C61746ELLU, // bov_Latn_GH + 0xD9C150474C61746ELLU, // bow_Latn_PG + 0xDDC142464C61746ELLU, // box_Latn_BF + 0xE1C143464C61746ELLU, // boy_Latn_CF + 0xE5C14D4C4C61746ELLU, // boz_Latn_ML + 0x81E156554C61746ELLU, // bpa_Latn_VU + 0x89E1434D4C61746ELLU, // bpc_Latn_CM + 0x8DE143464C61746ELLU, // bpd_Latn_CF + 0x91E150474C61746ELLU, // bpe_Latn_PG + 0x99E149444C61746ELLU, // bpg_Latn_ID + 0x9DE152554379726CLLU, // bph_Cyrl_RU + 0xA1E150474C61746ELLU, // bpi_Latn_PG + 0xA5E143444C61746ELLU, // bpj_Latn_CD + 0xA9E14E434C61746ELLU, // bpk_Latn_NC + 0xADE141554C61746ELLU, // bpl_Latn_AU + 0xB1E150474C61746ELLU, // bpm_Latn_PG + 0xB9E149444C61746ELLU, // bpo_Latn_ID + 0xBDE149444C61746ELLU, // bpp_Latn_ID + 0xC1E149444C61746ELLU, // bpq_Latn_ID + 0xC5E150484C61746ELLU, // bpr_Latn_PH + 0xC9E150484C61746ELLU, // bps_Latn_PH + 0xCDE141554C61746ELLU, // bpt_Latn_AU + 0xD1E150474C61746ELLU, // bpu_Latn_PG + 0xD5E149444C61746ELLU, // bpv_Latn_ID + 0xD9E150474C61746ELLU, // bpw_Latn_PG + 0xDDE1494E44657661LLU, // bpx_Deva_IN 0xE1E1494E42656E67LLU, // bpy_Beng_IN + 0xE5E149444C61746ELLU, // bpz_Latn_ID + 0x8201424A4C61746ELLU, // bqa_Latn_BJ + 0x860149444C61746ELLU, // bqb_Latn_ID + 0x8A01424A4C61746ELLU, // bqc_Latn_BJ + 0x8E01434D4C61746ELLU, // bqd_Latn_CM + 0x9601474E4C61746ELLU, // bqf_Latn_GN + 0x9A0154474C61746ELLU, // bqg_Latn_TG 0xA201495241726162LLU, // bqi_Arab_IR + 0xA601534E4C61746ELLU, // bqj_Latn_SN + 0xAA0143464C61746ELLU, // bqk_Latn_CF + 0xAE0150474C61746ELLU, // bql_Latn_PG + 0xB201434D4C61746ELLU, // bqm_Latn_CM + 0xBA01434D4C61746ELLU, // bqo_Latn_CM + 0xBE014E474C61746ELLU, // bqp_Latn_NG + 0xC20149444C61746ELLU, // bqq_Latn_ID + 0xC60149444C61746ELLU, // bqr_Latn_ID + 0xCA0150474C61746ELLU, // bqs_Latn_PG + 0xCE01434D4C61746ELLU, // bqt_Latn_CM + 0xD20143444C61746ELLU, // bqu_Latn_CD 0xD60143494C61746ELLU, // bqv_Latn_CI + 0xDA014E474C61746ELLU, // bqw_Latn_NG + 0xDE014E474C61746ELLU, // bqx_Latn_NG + 0xE601434D4C61746ELLU, // bqz_Latn_CM 0x627246524C61746ELLU, // br_Latn_FR 0x8221494E44657661LLU, // bra_Deva_IN + 0x86214B484B686D72LLU, // brb_Khmr_KH + 0x8A2147594C61746ELLU, // brc_Latn_GY + 0x8E214E5044657661LLU, // brd_Deva_NP + 0x962143444C61746ELLU, // brf_Latn_CD + 0x9A21424F4C61746ELLU, // brg_Latn_BO 0x9E21504B41726162LLU, // brh_Arab_PK + 0xA221434D4C61746ELLU, // bri_Latn_CM + 0xA62156554C61746ELLU, // brj_Latn_VU + 0xAA21534441726162LLU, // brk_Arab_SD + 0xAE2142574C61746ELLU, // brl_Latn_BW + 0xB22143444C61746ELLU, // brm_Latn_CD + 0xB62143524C61746ELLU, // brn_Latn_CR + 0xBA21425454696274LLU, // bro_Tibt_BT + 0xBE2149444C61746ELLU, // brp_Latn_ID + 0xC22150474C61746ELLU, // brq_Latn_PG + 0xC62153424C61746ELLU, // brr_Latn_SB + 0xCA2149444C61746ELLU, // brs_Latn_ID + 0xCE214E474C61746ELLU, // brt_Latn_NG + 0xD221564E4C61746ELLU, // bru_Latn_VN + 0xD6214C414C616F6FLLU, // brv_Laoo_LA + 0xDA21494E4B6E6461LLU, // brw_Knda_IN 0xDE21494E44657661LLU, // brx_Deva_IN + 0xE22150474C61746ELLU, // bry_Latn_PG + 0xE62150474C61746ELLU, // brz_Latn_PG 0x627342414C61746ELLU, // bs_Latn_BA + 0x824149444C61746ELLU, // bsa_Latn_ID + 0x8641424E4C61746ELLU, // bsb_Latn_BN + 0x8A41534E4C61746ELLU, // bsc_Latn_SN + 0x9241434D4C61746ELLU, // bse_Latn_CM + 0x96414E474C61746ELLU, // bsf_Latn_NG + 0x9E41414641726162LLU, // bsh_Arab_AF + 0xA241434D4C61746ELLU, // bsi_Latn_CM + 0xA6414E474C61746ELLU, // bsj_Latn_NG + 0xAA41504B41726162LLU, // bsk_Arab_PK + 0xAE414E474C61746ELLU, // bsl_Latn_NG + 0xB24149444C61746ELLU, // bsm_Latn_ID + 0xB641434F4C61746ELLU, // bsn_Latn_CO + 0xBA4154444C61746ELLU, // bso_Latn_TD + 0xBE41474E4C61746ELLU, // bsp_Latn_GN 0xC2414C5242617373LLU, // bsq_Bass_LR + 0xC6414E474C61746ELLU, // bsr_Latn_NG 0xCA41434D4C61746ELLU, // bss_Latn_CM + 0xCE41455445746869LLU, // bst_Ethi_ET + 0xD24149444C61746ELLU, // bsu_Latn_ID + 0xD641474E4C61746ELLU, // bsv_Latn_GN + 0xDA4145544C61746ELLU, // bsw_Latn_ET + 0xDE414E474C61746ELLU, // bsx_Latn_NG + 0xE2414D594C61746ELLU, // bsy_Latn_MY + 0x82614E474C61746ELLU, // bta_Latn_NG + 0x8A61434D4C61746ELLU, // btc_Latn_CM + 0x8E6149444261746BLLU, // btd_Batk_ID + 0x92614E474C61746ELLU, // bte_Latn_NG + 0x966154444C61746ELLU, // btf_Latn_TD + 0x9A6143494C61746ELLU, // btg_Latn_CI + 0x9E614D594C61746ELLU, // bth_Latn_MY + 0xA26149444C61746ELLU, // bti_Latn_ID + 0xA66149444C61746ELLU, // btj_Latn_ID + 0xB26149444261746BLLU, // btm_Batk_ID + 0xB66150484C61746ELLU, // btn_Latn_PH 0xBA6150484C61746ELLU, // bto_Latn_PH + 0xBE6150474C61746ELLU, // btp_Latn_PG + 0xC2614D594C61746ELLU, // btq_Latn_MY + 0xC66156554C61746ELLU, // btr_Latn_VU + 0xCA6149444C61746ELLU, // bts_Latn_ID + 0xCE614E474C61746ELLU, // btt_Latn_NG + 0xD2614E474C61746ELLU, // btu_Latn_NG 0xD661504B44657661LLU, // btv_Deva_PK + 0xDA6150484C61746ELLU, // btw_Latn_PH + 0xDE6149444C61746ELLU, // btx_Latn_ID + 0xE26149444C61746ELLU, // bty_Latn_ID + 0xE66149444C61746ELLU, // btz_Latn_ID 0x828152554379726CLLU, // bua_Cyrl_RU + 0x868154444C61746ELLU, // bub_Latn_TD 0x8A8159544C61746ELLU, // buc_Latn_YT + 0x8E8154474C61746ELLU, // bud_Latn_TG + 0x928143414C61746ELLU, // bue_Latn_CA + 0x968143444C61746ELLU, // buf_Latn_CD 0x9A8149444C61746ELLU, // bug_Latn_ID + 0x9E81434E4C61746ELLU, // buh_Latn_CN + 0xA28143474C61746ELLU, // bui_Latn_CG + 0xA6814E474C61746ELLU, // buj_Latn_NG + 0xAA8150474C61746ELLU, // buk_Latn_PG 0xB281434D4C61746ELLU, // bum_Latn_CM + 0xB681534C4C61746ELLU, // bun_Latn_SL + 0xBA8150474C61746ELLU, // buo_Latn_PG + 0xBE8149444C61746ELLU, // bup_Latn_ID + 0xC28150474C61746ELLU, // buq_Latn_PG + 0xCA814E474C61746ELLU, // bus_Latn_NG + 0xCE8150474C61746ELLU, // but_Latn_PG + 0xD28143444C61746ELLU, // buu_Latn_CD + 0xD68150474C61746ELLU, // buv_Latn_PG + 0xDA8147414C61746ELLU, // buw_Latn_GA + 0xDE814E474C61746ELLU, // bux_Latn_NG + 0xE281534C4C61746ELLU, // buy_Latn_SL + 0xE6814E474C61746ELLU, // buz_Latn_NG + 0x82A154444C61746ELLU, // bva_Latn_TD 0x86A147514C61746ELLU, // bvb_Latn_GQ + 0x8AA153424C61746ELLU, // bvc_Latn_SB + 0x8EA153424C61746ELLU, // bvd_Latn_SB + 0x92A149444C61746ELLU, // bve_Latn_ID + 0x96A154444C61746ELLU, // bvf_Latn_TD + 0x9AA1434D4C61746ELLU, // bvg_Latn_CM + 0x9EA14E474C61746ELLU, // bvh_Latn_NG + 0xA2A153534C61746ELLU, // bvi_Latn_SS + 0xA6A14E474C61746ELLU, // bvj_Latn_NG + 0xAAA149444C61746ELLU, // bvk_Latn_ID + 0xB2A1434D4C61746ELLU, // bvm_Latn_CM + 0xB6A150474C61746ELLU, // bvn_Latn_PG + 0xBAA154444C61746ELLU, // bvo_Latn_TD + 0xC2A143464C61746ELLU, // bvq_Latn_CF + 0xC6A141554C61746ELLU, // bvr_Latn_AU + 0xCEA149444C61746ELLU, // bvt_Latn_ID + 0xD2A149444C61746ELLU, // bvu_Latn_ID + 0xD6A156454C61746ELLU, // bvv_Latn_VE + 0xDAA14E474C61746ELLU, // bvw_Latn_NG + 0xDEA143474C61746ELLU, // bvx_Latn_CG + 0xE2A150484C61746ELLU, // bvy_Latn_PH + 0xE6A149444C61746ELLU, // bvz_Latn_ID + 0x82C14E434C61746ELLU, // bwa_Latn_NC + 0x86C1464A4C61746ELLU, // bwb_Latn_FJ + 0x8AC15A4D4C61746ELLU, // bwc_Latn_ZM + 0x8EC150474C61746ELLU, // bwd_Latn_PG + 0x92C14D4D4D796D72LLU, // bwe_Mymr_MM + 0x96C150474C61746ELLU, // bwf_Latn_PG + 0x9AC14D5A4C61746ELLU, // bwg_Latn_MZ + 0x9EC1434D4C61746ELLU, // bwh_Latn_CM + 0xA2C156454C61746ELLU, // bwi_Latn_VE + 0xA6C142464C61746ELLU, // bwj_Latn_BF + 0xAAC150474C61746ELLU, // bwk_Latn_PG + 0xAEC143444C61746ELLU, // bwl_Latn_CD + 0xB2C150474C61746ELLU, // bwm_Latn_PG + 0xBAC145544C61746ELLU, // bwo_Latn_ET + 0xBEC149444C61746ELLU, // bwp_Latn_ID + 0xC2C142464C61746ELLU, // bwq_Latn_BF + 0xC6C14E474C61746ELLU, // bwr_Latn_NG + 0xCAC143444C61746ELLU, // bws_Latn_CD + 0xCEC1434D4C61746ELLU, // bwt_Latn_CM + 0xD2C147484C61746ELLU, // bwu_Latn_GH + 0xDAC143444C61746ELLU, // bww_Latn_CD + 0xDEC1434E4C61746ELLU, // bwx_Latn_CN + 0xE2C142464C61746ELLU, // bwy_Latn_BF + 0xE6C143474C61746ELLU, // bwz_Latn_CG + 0x82E153424C61746ELLU, // bxa_Latn_SB + 0x86E153534C61746ELLU, // bxb_Latn_SS + 0x8AE147514C61746ELLU, // bxc_Latn_GQ + 0x96E150474C61746ELLU, // bxf_Latn_PG + 0x9AE143444C61746ELLU, // bxg_Latn_CD + 0x9EE150474C61746ELLU, // bxh_Latn_PG + 0xA2E141554C61746ELLU, // bxi_Latn_AU + 0xA6E141554C61746ELLU, // bxj_Latn_AU + 0xAEE142464C61746ELLU, // bxl_Latn_BF + 0xB2E14D4E4379726CLLU, // bxm_Cyrl_MN + 0xB6E141554C61746ELLU, // bxn_Latn_AU + 0xBAE14E474C61746ELLU, // bxo_Latn_NG + 0xBEE1434D4C61746ELLU, // bxp_Latn_CM + 0xC2E14E474C61746ELLU, // bxq_Latn_NG + 0xCAE1434D4C61746ELLU, // bxs_Latn_CM + 0xD2E1434E4D6F6E67LLU, // bxu_Mong_CN + 0xD6E154444C61746ELLU, // bxv_Latn_TD + 0xDAE14D4C4C61746ELLU, // bxw_Latn_ML + 0xE6E150474C61746ELLU, // bxz_Latn_PG + 0x830150484C61746ELLU, // bya_Latn_PH + 0x8701434D4C61746ELLU, // byb_Latn_CM + 0x8B014E474C61746ELLU, // byc_Latn_NG + 0x8F0149444C61746ELLU, // byd_Latn_ID + 0x930150474C61746ELLU, // bye_Latn_PG + 0x97014E474C61746ELLU, // byf_Latn_NG + 0x9F014E5044657661LLU, // byh_Deva_NP + 0xA30143444C61746ELLU, // byi_Latn_CD + 0xA7014E474C61746ELLU, // byj_Latn_NG + 0xAB01434E4C61746ELLU, // byk_Latn_CN + 0xAF0149444C61746ELLU, // byl_Latn_ID + 0xB30141554C61746ELLU, // bym_Latn_AU 0xB701455245746869LLU, // byn_Ethi_ER + 0xBF014E474C61746ELLU, // byp_Latn_NG + 0xC70150474C61746ELLU, // byr_Latn_PG + 0xCB014E474C61746ELLU, // bys_Latn_NG 0xD701434D4C61746ELLU, // byv_Latn_CM + 0xDB014E5044657661LLU, // byw_Deva_NP + 0xDF0150474C61746ELLU, // byx_Latn_PG + 0xE70150474C61746ELLU, // byz_Latn_PG + 0x83214C524C61746ELLU, // bza_Latn_LR + 0x872149444C61746ELLU, // bzb_Latn_ID + 0x8B214D474C61746ELLU, // bzc_Latn_MG + 0x8F2143524C61746ELLU, // bzd_Latn_CR 0x93214D4C4C61746ELLU, // bze_Latn_ML + 0x972150474C61746ELLU, // bzf_Latn_PG + 0x9F2150474C61746ELLU, // bzh_Latn_PG + 0xA321544854686169LLU, // bzi_Thai_TH + 0xA721425A4C61746ELLU, // bzj_Latn_BZ + 0xAB214E494C61746ELLU, // bzk_Latn_NI + 0xAF2149444C61746ELLU, // bzl_Latn_ID + 0xB32143444C61746ELLU, // bzm_Latn_CD + 0xB72149444C61746ELLU, // bzn_Latn_ID + 0xBB2143444C61746ELLU, // bzo_Latn_CD + 0xBF2149444C61746ELLU, // bzp_Latn_ID + 0xC32149444C61746ELLU, // bzq_Latn_ID + 0xC72141554C61746ELLU, // bzr_Latn_AU + 0xD32149444C61746ELLU, // bzu_Latn_ID + 0xD721434D4C61746ELLU, // bzv_Latn_CM + 0xDB214E474C61746ELLU, // bzw_Latn_NG + 0xDF214D4C4C61746ELLU, // bzx_Latn_ML + 0xE3214E474C61746ELLU, // bzy_Latn_NG + 0xE7214E474C61746ELLU, // bzz_Latn_NG 0x636145534C61746ELLU, // ca_Latn_ES + 0x800247544C61746ELLU, // caa_Latn_GT + 0x8402484E4C61746ELLU, // cab_Latn_HN + 0x880247544C61746ELLU, // cac_Latn_GT 0x8C0255534C61746ELLU, // cad_Latn_US + 0x9002534E4C61746ELLU, // cae_Latn_SN + 0x940243414C61746ELLU, // caf_Latn_CA + 0x980250594C61746ELLU, // cag_Latn_PY + 0x9C0250454C61746ELLU, // cah_Latn_PE + 0xA402424F4C61746ELLU, // caj_Latn_BO + 0xA80247544C61746ELLU, // cak_Latn_GT + 0xAC024D504C61746ELLU, // cal_Latn_MP + 0xB0024E434C61746ELLU, // cam_Latn_NC + 0xB40250474C61746ELLU, // can_Latn_PG + 0xB802424F4C61746ELLU, // cao_Latn_BO + 0xBC02424F4C61746ELLU, // cap_Latn_BO + 0xC002494E4C61746ELLU, // caq_Latn_IN + 0xC40256454C61746ELLU, // car_Latn_VE + 0xC802424F4C61746ELLU, // cas_Latn_BO + 0xD402424F4C61746ELLU, // cav_Latn_BO + 0xD802424F4C61746ELLU, // caw_Latn_BO + 0xDC02424F4C61746ELLU, // cax_Latn_BO + 0xE00243414C61746ELLU, // cay_Latn_CA + 0xE402424F4C61746ELLU, // caz_Latn_BO + 0x8422434F4C61746ELLU, // cbb_Latn_CO + 0x8822434F4C61746ELLU, // cbc_Latn_CO + 0x8C22434F4C61746ELLU, // cbd_Latn_CO + 0x9822434F4C61746ELLU, // cbg_Latn_CO + 0xA02245434C61746ELLU, // cbi_Latn_EC + 0xA422424A4C61746ELLU, // cbj_Latn_BJ + 0xA82250484C61746ELLU, // cbk_Latn_PH + 0xAC224D4D4C61746ELLU, // cbl_Latn_MM + 0xB422544854686169LLU, // cbn_Thai_TH + 0xB8224E474C61746ELLU, // cbo_Latn_NG + 0xC0224E474C61746ELLU, // cbq_Latn_NG + 0xC42250454C61746ELLU, // cbr_Latn_PE + 0xC82250454C61746ELLU, // cbs_Latn_PE + 0xCC2250454C61746ELLU, // cbt_Latn_PE + 0xD02250454C61746ELLU, // cbu_Latn_PE + 0xD422434F4C61746ELLU, // cbv_Latn_CO + 0xD82250484C61746ELLU, // cbw_Latn_PH + 0xE022434F4C61746ELLU, // cby_Latn_CO + 0x884250454C61746ELLU, // ccc_Latn_PE + 0x8C4242524C61746ELLU, // ccd_Latn_BR + 0x90424D5A4C61746ELLU, // cce_Latn_MZ + 0x98424E474C61746ELLU, // ccg_Latn_NG 0x9C424E474C61746ELLU, // cch_Latn_NG + 0xA44247574C61746ELLU, // ccj_Latn_GW + 0xAC42545A4C61746ELLU, // ccl_Latn_TZ + 0xB0424D594C61746ELLU, // ccm_Latn_MY + 0xB8424D584C61746ELLU, // cco_Latn_MX 0xBC42424443616B6DLLU, // ccp_Cakm_BD + 0xC44253564C61746ELLU, // ccr_Latn_SV + 0x9062494E54656C75LLU, // cde_Telu_IN + 0x9462494E4C61746ELLU, // cdf_Latn_IN + 0x9C62494E44657661LLU, // cdh_Deva_IN + 0xA062494E47756A72LLU, // cdi_Gujr_IN + 0xA462494E44657661LLU, // cdj_Deva_IN + 0xB0624E5044657661LLU, // cdm_Deva_NP + 0xB862434E48616E73LLU, // cdo_Hans_CN + 0xC4624E474C61746ELLU, // cdr_Latn_NG + 0xE462494E42656E67LLU, // cdz_Beng_IN 0x636552554379726CLLU, // ce_Cyrl_RU + 0x808255534C61746ELLU, // cea_Latn_US 0x848250484C61746ELLU, // ceb_Latn_PH + 0x988250594C61746ELLU, // ceg_Latn_PY + 0xA8824D4D4C61746ELLU, // cek_Latn_MM + 0xB4824E474C61746ELLU, // cen_Latn_NG + 0xCC824E474C61746ELLU, // cet_Latn_NG + 0xE0824D4D4C61746ELLU, // cey_Latn_MM + 0x80A24E474C61746ELLU, // cfa_Latn_NG + 0x8CA24E474C61746ELLU, // cfd_Latn_NG + 0x98A24E474C61746ELLU, // cfg_Latn_NG + 0xB0A24D4D4C61746ELLU, // cfm_Latn_MM + 0x80C250474C61746ELLU, // cga_Latn_PG + 0x88C250484C61746ELLU, // cgc_Latn_PH 0x98C255474C61746ELLU, // cgg_Latn_UG + 0xA8C2425454696274LLU, // cgk_Tibt_BT 0x636847554C61746ELLU, // ch_Latn_GU + 0x84E2434F4C61746ELLU, // chb_Latn_CO + 0x8CE24D584C61746ELLU, // chd_Latn_MX + 0x94E24D584C61746ELLU, // chf_Latn_MX + 0x98E2544D41726162LLU, // chg_Arab_TM + 0x9CE255534C61746ELLU, // chh_Latn_US + 0xA4E24D584C61746ELLU, // chj_Latn_MX 0xA8E2464D4C61746ELLU, // chk_Latn_FM + 0xACE255534C61746ELLU, // chl_Latn_US 0xB0E252554379726CLLU, // chm_Cyrl_RU + 0xB4E255534C61746ELLU, // chn_Latn_US 0xB8E255534C61746ELLU, // cho_Latn_US 0xBCE243414C61746ELLU, // chp_Latn_CA + 0xC0E24D584C61746ELLU, // chq_Latn_MX 0xC4E2555343686572LLU, // chr_Cher_US + 0xCCE250454C61746ELLU, // cht_Latn_PE + 0xD8E24D5A4C61746ELLU, // chw_Latn_MZ + 0xDCE24E5044657661LLU, // chx_Deva_NP + 0xE0E255534C61746ELLU, // chy_Latn_US + 0xE4E24D584C61746ELLU, // chz_Latn_MX + 0x810249444C61746ELLU, // cia_Latn_ID + 0x8502424A4C61746ELLU, // cib_Latn_BJ 0x890255534C61746ELLU, // cic_Latn_US + 0x91024E474C61746ELLU, // cie_Latn_NG + 0x9D02494E44657661LLU, // cih_Deva_IN + 0xB10249544C61746ELLU, // cim_Latn_IT + 0xB50242524C61746ELLU, // cin_Latn_BR + 0xBD024D584C61746ELLU, // cip_Latn_MX + 0xC5024E434C61746ELLU, // cir_Latn_NC + 0xD90255534C61746ELLU, // ciw_Latn_US + 0xE10256454C61746ELLU, // ciy_Latn_VE 0x81224B4841726162LLU, // cja_Arab_KH + 0x9122564E4C61746ELLU, // cje_Latn_VN + 0x9D2255534C61746ELLU, // cjh_Latn_US + 0xA12252554379726CLLU, // cji_Cyrl_RU + 0xA922414F4C61746ELLU, // cjk_Latn_AO 0xB122564E4368616DLLU, // cjm_Cham_VN + 0xB52250474C61746ELLU, // cjn_Latn_PG + 0xB92250454C61746ELLU, // cjo_Latn_PE + 0xBD2243524C61746ELLU, // cjp_Latn_CR + 0xC92252554C61746ELLU, // cjs_Latn_RU + 0xD52250474C61746ELLU, // cjv_Latn_PG + 0xE122434E48616E73LLU, // cjy_Hans_CN 0x8542495141726162LLU, // ckb_Arab_IQ + 0xAD424E474C61746ELLU, // ckl_Latn_NG + 0xB14248524C61746ELLU, // ckm_Latn_HR + 0xB5424D4D4C61746ELLU, // ckn_Latn_MM + 0xB94247484C61746ELLU, // cko_Latn_GH + 0xC14254444C61746ELLU, // ckq_Latn_TD + 0xC54250474C61746ELLU, // ckr_Latn_PG + 0xC9424E434C61746ELLU, // cks_Latn_NC + 0xCD4252554379726CLLU, // ckt_Cyrl_RU + 0xD14255534C61746ELLU, // cku_Latn_US + 0xD54254574C61746ELLU, // ckv_Latn_TW + 0xDD42434D4C61746ELLU, // ckx_Latn_CM + 0xE1424E474C61746ELLU, // cky_Latn_NG + 0xE54247544C61746ELLU, // ckz_Latn_GT + 0x81624E474C61746ELLU, // cla_Latn_NG 0x896243414C61746ELLU, // clc_Latn_CA + 0x91624D584C61746ELLU, // cle_Latn_MX + 0x9D62504B41726162LLU, // clh_Arab_PK + 0xA16247484C61746ELLU, // cli_Latn_GH + 0xA5624D4D4C61746ELLU, // clj_Latn_MM + 0xA962494E4C61746ELLU, // clk_Latn_IN + 0xAD6247484C61746ELLU, // cll_Latn_GH + 0xB16255534C61746ELLU, // clm_Latn_US + 0xB9624D584C61746ELLU, // clo_Latn_MX + 0xCD624D4D4C61746ELLU, // clt_Latn_MM + 0xD16250484C61746ELLU, // clu_Latn_PH + 0xD96252554379726CLLU, // clw_Cyrl_RU + 0xE1624D584C61746ELLU, // cly_Latn_MX + 0x8182564E4C61746ELLU, // cma_Latn_VN + 0x918242464C61746ELLU, // cme_Latn_BF 0x99824D4E536F796FLLU, // cmg_Soyo_MN + 0xA182434F4C61746ELLU, // cmi_Latn_CO + 0xAD8249444C61746ELLU, // cml_Latn_ID + 0xB982564E4C61746ELLU, // cmo_Latn_VN + 0xC5824D4D4C61746ELLU, // cmr_Latn_MM + 0xC98249544C61746ELLU, // cms_Latn_IT + 0xCD825A414C61746ELLU, // cmt_Latn_ZA + 0x81A2494E54696274LLU, // cna_Tibt_IN + 0x85A24D4D4C61746ELLU, // cnb_Latn_MM + 0x89A2564E4C61746ELLU, // cnc_Latn_VN + 0x99A2434E4C61746ELLU, // cng_Latn_CN + 0x9DA24D4D4C61746ELLU, // cnh_Latn_MM + 0xA1A250454C61746ELLU, // cni_Latn_PE + 0xA9A24D4D4C61746ELLU, // cnk_Latn_MM + 0xADA24D584C61746ELLU, // cnl_Latn_MX + 0xBDA2434E48616E73LLU, // cnp_Hans_CN + 0xC1A2434D4C61746ELLU, // cnq_Latn_CM + 0xC9A249444C61746ELLU, // cns_Latn_ID + 0xCDA24D584C61746ELLU, // cnt_Latn_MX + 0xD9A24D4D4C61746ELLU, // cnw_Latn_MM + 0xDDA247424C61746ELLU, // cnx_Latn_GB 0x636F46524C61746ELLU, // co_Latn_FR + 0x81C241554C61746ELLU, // coa_Latn_AU + 0x85C24D584C61746ELLU, // cob_Latn_MX + 0x89C24D584C61746ELLU, // coc_Latn_MX + 0x8DC250454C61746ELLU, // cod_Latn_PE + 0x91C2434F4C61746ELLU, // coe_Latn_CO + 0x95C245434C61746ELLU, // cof_Latn_EC + 0x99C2544854686169LLU, // cog_Thai_TH + 0x9DC24B454C61746ELLU, // coh_Latn_KE + 0xA5C24D584C61746ELLU, // coj_Latn_MX + 0xA9C24D584C61746ELLU, // cok_Latn_MX + 0xADC255534C61746ELLU, // col_Latn_US + 0xB1C255534C61746ELLU, // com_Latn_US + 0xB9C243414C61746ELLU, // coo_Latn_CA 0xBDC24547436F7074LLU, // cop_Copt_EG + 0xC1C255534C61746ELLU, // coq_Latn_US + 0xCDC250454C61746ELLU, // cot_Latn_PE + 0xD1C2534E4C61746ELLU, // cou_Latn_SN + 0xDDC250454C61746ELLU, // cox_Latn_PE + 0xE5C24D584C61746ELLU, // coz_Latn_MX + 0x81E24D584C61746ELLU, // cpa_Latn_MX + 0x85E250454C61746ELLU, // cpb_Latn_PE + 0x89E250454C61746ELLU, // cpc_Latn_PE + 0x99E247524772656BLLU, // cpg_Grek_GR + 0xA1E24E524C61746ELLU, // cpi_Latn_NR + 0xB5E247484C61746ELLU, // cpn_Latn_GH + 0xB9E242464C61746ELLU, // cpo_Latn_BF 0xC9E250484C61746ELLU, // cps_Latn_PH + 0xD1E250454C61746ELLU, // cpu_Latn_PE + 0xDDE2434E4C61746ELLU, // cpx_Latn_CN + 0xE1E250454C61746ELLU, // cpy_Latn_PE + 0x8E02434E4C61746ELLU, // cqd_Latn_CN 0x6372434143616E73LLU, // cr_Cans_CA + 0x822245544C61746ELLU, // cra_Latn_ET + 0x862256434C61746ELLU, // crb_Latn_VC + 0x8A2256554C61746ELLU, // crc_Latn_VU + 0x8E2255534C61746ELLU, // crd_Latn_US + 0x9622434F4C61746ELLU, // crf_Latn_CO 0x9A2243414C61746ELLU, // crg_Latn_CA 0x9E2255414379726CLLU, // crh_Cyrl_UA + 0xA22253544C61746ELLU, // cri_Latn_ST + 0xA622434143616E73LLU, // crj_Cans_CA 0xAA22434143616E73LLU, // crk_Cans_CA 0xAE22434143616E73LLU, // crl_Cans_CA + 0xB222434143616E73LLU, // crm_Cans_CA + 0xB6224D584C61746ELLU, // crn_Latn_MX + 0xBA2255534C61746ELLU, // cro_Latn_US + 0xC22241524C61746ELLU, // crq_Latn_AR 0xCA2253434C61746ELLU, // crs_Latn_SC + 0xCE2241524C61746ELLU, // crt_Latn_AR + 0xD622494E4C61746ELLU, // crv_Latn_IN + 0xDA22564E4C61746ELLU, // crw_Latn_VN + 0xDE2243414C61746ELLU, // crx_Latn_CA + 0xE2224E474C61746ELLU, // cry_Latn_NG + 0xE62255534C61746ELLU, // crz_Latn_US 0x6373435A4C61746ELLU, // cs_Latn_CZ + 0x82424D584C61746ELLU, // csa_Latn_MX 0x8642504C4C61746ELLU, // csb_Latn_PL + 0x9E424D4D4D796D72LLU, // csh_Mymr_MM + 0xA6424D4D4C61746ELLU, // csj_Latn_MM + 0xAA42534E4C61746ELLU, // csk_Latn_SN + 0xB24255534C61746ELLU, // csm_Latn_US + 0xBA424D584C61746ELLU, // cso_Latn_MX + 0xBE42434E48616E73LLU, // csp_Hans_CN + 0xCA4255534C61746ELLU, // css_Latn_US + 0xCE4255534C61746ELLU, // cst_Latn_US + 0xD6424D4D4C61746ELLU, // csv_Latn_MM 0xDA42434143616E73LLU, // csw_Cans_CA + 0xE2424D4D4C61746ELLU, // csy_Latn_MM + 0xE64255534C61746ELLU, // csz_Latn_US + 0x82624D584C61746ELLU, // cta_Latn_MX + 0x8A6255534C61746ELLU, // ctc_Latn_US 0x8E624D4D50617563LLU, // ctd_Pauc_MM + 0x92624D584C61746ELLU, // cte_Latn_MX + 0x9A62424442656E67LLU, // ctg_Beng_BD + 0x9E624D4D4C61746ELLU, // cth_Latn_MM + 0xAE624D584C61746ELLU, // ctl_Latn_MX + 0xB26255534C61746ELLU, // ctm_Latn_US + 0xB6624E5044657661LLU, // ctn_Deva_NP + 0xBA62434F4C61746ELLU, // cto_Latn_CO + 0xBE624D584C61746ELLU, // ctp_Latn_MX + 0xCA6250484C61746ELLU, // cts_Latn_PH + 0xCE62494E54616D6CLLU, // ctt_Taml_IN + 0xD2624D584C61746ELLU, // ctu_Latn_MX + 0xE262494E54616D6CLLU, // cty_Taml_IN + 0xE6624D584C61746ELLU, // ctz_Latn_MX 0x637552554379726CLLU, // cu_Cyrl_RU 0x63754247476C6167LLU, // cu_Glag_BG + 0x8282564E4C61746ELLU, // cua_Latn_VN + 0x8682434F4C61746ELLU, // cub_Latn_CO + 0x8A824D584C61746ELLU, // cuc_Latn_MX + 0x9E824B454C61746ELLU, // cuh_Latn_KE + 0xA282434F4C61746ELLU, // cui_Latn_CO + 0xA68250454C61746ELLU, // cuj_Latn_PE + 0xAA8250414C61746ELLU, // cuk_Latn_PA + 0xAE8242524C61746ELLU, // cul_Latn_BR + 0xBA8256454C61746ELLU, // cuo_Latn_VE + 0xBE8255534C61746ELLU, // cup_Latn_US + 0xCE824D584C61746ELLU, // cut_Latn_MX + 0xD282434E4C616E61LLU, // cuu_Lana_CN + 0xD682434D4C61746ELLU, // cuv_Latn_CM + 0xDE824D584C61746ELLU, // cux_Latn_MX + 0xE2824D584C61746ELLU, // cuy_Latn_MX 0x637652554379726CLLU, // cv_Cyrl_RU + 0x9AA2494E4C61746ELLU, // cvg_Latn_IN + 0xB6A24D584C61746ELLU, // cvn_Latn_MX + 0x82C2545A4C61746ELLU, // cwa_Latn_TZ + 0x86C24D5A4C61746ELLU, // cwb_Latn_MZ + 0x92C2545A4C61746ELLU, // cwe_Latn_TZ + 0x9AC24D594C61746ELLU, // cwg_Latn_MY + 0xCEC2534E4C61746ELLU, // cwt_Latn_SN + 0x9EE24E474C61746ELLU, // cxh_Latn_NG 0x637947424C61746ELLU, // cy_Latn_GB + 0x83024D584C61746ELLU, // cya_Latn_MX + 0x8702424F4C61746ELLU, // cyb_Latn_BO + 0xBB0250484C61746ELLU, // cyo_Latn_PH + 0x9F22434E48616E73LLU, // czh_Hans_CN + 0xAB22435A48656272LLU, // czk_Hebr_CZ + 0xB7224D584C61746ELLU, // czn_Latn_MX + 0xCF224D4D4C61746ELLU, // czt_Latn_MM 0x6461444B4C61746ELLU, // da_Latn_DK - 0x940343494C61746ELLU, // daf_Latn_CI + 0x800354444C61746ELLU, // daa_Latn_TD + 0x880350474C61746ELLU, // dac_Latn_PG + 0x8C0350474C61746ELLU, // dad_Latn_PG + 0x9003434D4C61746ELLU, // dae_Latn_CM + 0x980347484C61746ELLU, // dag_Latn_GH + 0x9C0350474C61746ELLU, // dah_Latn_PG + 0xA00354444C61746ELLU, // dai_Latn_TD + 0xA40353444C61746ELLU, // daj_Latn_SD 0xA80355534C61746ELLU, // dak_Latn_US + 0xAC034B454C61746ELLU, // dal_Latn_KE + 0xB0034E474C61746ELLU, // dam_Latn_NG + 0xB8034D4D4C61746ELLU, // dao_Latn_MM + 0xC003494E44657661LLU, // daq_Deva_IN 0xC40352554379726CLLU, // dar_Cyrl_RU + 0xC80343494C61746ELLU, // das_Latn_CI + 0xD00354444C61746ELLU, // dau_Latn_TD 0xD4034B454C61746ELLU, // dav_Latn_KE + 0xD80350484C61746ELLU, // daw_Latn_PH + 0xDC0341554C61746ELLU, // dax_Latn_AU + 0xE40349444C61746ELLU, // daz_Latn_ID + 0x80234D4C4C61746ELLU, // dba_Latn_ML + 0x84234E474C61746ELLU, // dbb_Latn_NG + 0x8C234E474C61746ELLU, // dbd_Latn_NG + 0x902349444C61746ELLU, // dbe_Latn_ID + 0x942349444C61746ELLU, // dbf_Latn_ID + 0x98234D4C4C61746ELLU, // dbg_Latn_ML + 0xA0234E474C61746ELLU, // dbi_Latn_NG + 0xA4234D594C61746ELLU, // dbj_Latn_MY + 0xAC2341554C61746ELLU, // dbl_Latn_AU + 0xB0234E474C61746ELLU, // dbm_Latn_NG + 0xB42349444C61746ELLU, // dbn_Latn_ID + 0xB8234E474C61746ELLU, // dbo_Latn_NG + 0xBC234E474C61746ELLU, // dbp_Latn_NG + 0xC023434D4C61746ELLU, // dbq_Latn_CM + 0xCC234D4C4C61746ELLU, // dbt_Latn_ML + 0xD0234D4C4C61746ELLU, // dbu_Latn_ML + 0xD4234E474C61746ELLU, // dbv_Latn_NG + 0xD8234D4C4C61746ELLU, // dbw_Latn_ML + 0xE02350474C61746ELLU, // dby_Latn_PG 0x8843494E41726162LLU, // dcc_Arab_IN + 0xC44356494C61746ELLU, // dcr_Latn_VI + 0x806341554C61746ELLU, // dda_Latn_AU + 0x8C6353534C61746ELLU, // ddd_Latn_SS + 0x906343474C61746ELLU, // dde_Latn_CG + 0x9863544C4C61746ELLU, // ddg_Latn_TL + 0xA06350474C61746ELLU, // ddi_Latn_PG + 0xA46341554C61746ELLU, // ddj_Latn_AU + 0xB463424A4C61746ELLU, // ddn_Latn_BJ + 0xB86352554379726CLLU, // ddo_Cyrl_RU + 0xC46341554C61746ELLU, // ddr_Latn_AU + 0xC8634D4C4C61746ELLU, // dds_Latn_ML + 0xD86349444C61746ELLU, // ddw_Latn_ID 0x646544454C61746ELLU, // de_Latn_DE + 0x888353444C61746ELLU, // dec_Latn_SD + 0x8C8350474C61746ELLU, // ded_Latn_PG + 0x90834C524C61746ELLU, // dee_Latn_LR + 0x9483495241726162LLU, // def_Arab_IR + 0x98834E474C61746ELLU, // deg_Latn_NG + 0x9C83504B41726162LLU, // deh_Arab_PK + 0xA08349444C61746ELLU, // dei_Latn_ID + 0xA883434D4C61746ELLU, // dek_Latn_CM + 0xAC8355534C61746ELLU, // del_Latn_US + 0xB08349444C61746ELLU, // dem_Latn_ID 0xB48343414C61746ELLU, // den_Latn_CA + 0xC08343464C61746ELLU, // deq_Latn_CF + 0xC483494E42656E67LLU, // der_Beng_IN + 0xC88342524C61746ELLU, // des_Latn_BR + 0xD48350474C61746ELLU, // dev_Latn_PG + 0xE48343444C61746ELLU, // dez_Latn_CD + 0x80C347484C61746ELLU, // dga_Latn_GH + 0x84C34D4C4C61746ELLU, // dgb_Latn_ML + 0x88C350484C61746ELLU, // dgc_Latn_PH + 0x8CC342464C61746ELLU, // dgd_Latn_BF + 0x90C350474C61746ELLU, // dge_Latn_PG + 0x98C350474C61746ELLU, // dgg_Latn_PG + 0x9CC34E474C61746ELLU, // dgh_Latn_NG + 0xA0C342464C61746ELLU, // dgi_Latn_BF + 0xA8C343464C61746ELLU, // dgk_Latn_CF + 0xACC3534441726162LLU, // dgl_Arab_SD + 0xB4C341554C61746ELLU, // dgn_Latn_AU 0xC4C343414C61746ELLU, // dgr_Latn_CA + 0xC8C342464C61746ELLU, // dgs_Latn_BF + 0xCCC341554C61746ELLU, // dgt_Latn_AU + 0xD8C341554C61746ELLU, // dgw_Latn_AU + 0xDCC350474C61746ELLU, // dgx_Latn_PG + 0xE4C350474C61746ELLU, // dgz_Latn_PG + 0x98E341554C61746ELLU, // dhg_Latn_AU + 0xA0E34E5044657661LLU, // dhi_Deva_NP + 0xACE341554C61746ELLU, // dhl_Latn_AU + 0xB0E3414F4C61746ELLU, // dhm_Latn_AO + 0xB4E3494E47756A72LLU, // dhn_Gujr_IN + 0xB8E3494E44657661LLU, // dho_Deva_IN + 0xC4E341554C61746ELLU, // dhr_Latn_AU + 0xC8E3545A4C61746ELLU, // dhs_Latn_TZ + 0xD0E341554C61746ELLU, // dhu_Latn_AU + 0xD4E34E434C61746ELLU, // dhv_Latn_NC + 0xD8E34E5044657661LLU, // dhw_Deva_NP + 0xDCE341554C61746ELLU, // dhx_Latn_AU + 0x810350474C61746ELLU, // dia_Latn_PG + 0x850353534C61746ELLU, // dib_Latn_SS + 0x890343494C61746ELLU, // dic_Latn_CI + 0x8D0353534C61746ELLU, // did_Latn_SS + 0x950341554C61746ELLU, // dif_Latn_AU + 0x99034B454C61746ELLU, // dig_Latn_KE + 0x9D034D584C61746ELLU, // dih_Latn_MX + 0xA103434D4C61746ELLU, // dii_Latn_CM + 0xA50349444C61746ELLU, // dij_Latn_ID + 0xAD0353444C61746ELLU, // dil_Latn_SD + 0xB50353534C61746ELLU, // din_Latn_SS + 0xB9034E474C61746ELLU, // dio_Latn_NG + 0xBD0353534C61746ELLU, // dip_Latn_SS + 0xC5034E474C61746ELLU, // dir_Latn_NG + 0xC903494E4C61746ELLU, // dis_Latn_IN + 0xD1034E414C61746ELLU, // diu_Latn_NA + 0xD90353534C61746ELLU, // diw_Latn_SS + 0xDD0356554C61746ELLU, // dix_Latn_VU + 0xE10349444C61746ELLU, // diy_Latn_ID + 0xE50343444C61746ELLU, // diz_Latn_CD + 0x812341554C61746ELLU, // dja_Latn_AU + 0x852341554C61746ELLU, // djb_Latn_AU + 0x892354444C61746ELLU, // djc_Latn_TD + 0x8D2341554C61746ELLU, // djd_Latn_AU 0x91234E454C61746ELLU, // dje_Latn_NE + 0x952341554C61746ELLU, // djf_Latn_AU + 0xA12341554C61746ELLU, // dji_Latn_AU + 0xA52341554C61746ELLU, // djj_Latn_AU + 0xA92353524C61746ELLU, // djk_Latn_SR + 0xB1234D4C4C61746ELLU, // djm_Latn_ML + 0xB52341554C61746ELLU, // djn_Latn_AU + 0xB92349444C61746ELLU, // djo_Latn_ID + 0xC52341554C61746ELLU, // djr_Latn_AU + 0xD12350474C61746ELLU, // dju_Latn_PG + 0xD92341554C61746ELLU, // djw_Latn_AU + 0x8143425454696274LLU, // dka_Tibt_BT + 0x99434E474C61746ELLU, // dkg_Latn_NG + 0xA94349444C61746ELLU, // dkk_Latn_ID + 0xC5434D594C61746ELLU, // dkr_Latn_MY + 0xC94353534C61746ELLU, // dks_Latn_SS + 0xDD43434D4C61746ELLU, // dkx_Latn_CM + 0x996352554379726CLLU, // dlg_Cyrl_RU + 0xB16348524C61746ELLU, // dlm_Latn_HR + 0xB563494E4C61746ELLU, // dln_Latn_IN + 0x818347414C61746ELLU, // dma_Latn_GA + 0x85834D4C4C61746ELLU, // dmb_Latn_ML + 0x898350474C61746ELLU, // dmc_Latn_PG + 0x8D8341554C61746ELLU, // dmd_Latn_AU + 0x9183434D4C61746ELLU, // dme_Latn_CM 0x95834E474D656466LLU, // dmf_Medf_NG + 0x99834D594C61746ELLU, // dmg_Latn_MY + 0xA983504B41726162LLU, // dmk_Arab_PK + 0xAD83504B41726162LLU, // dml_Arab_PK + 0xB183434D4C61746ELLU, // dmm_Latn_CM + 0xB983434D4C61746ELLU, // dmo_Latn_CM + 0xC58349444C61746ELLU, // dmr_Latn_ID + 0xC98349444C61746ELLU, // dms_Latn_ID + 0xD18349444C61746ELLU, // dmu_Latn_ID + 0xD5834D594C61746ELLU, // dmv_Latn_MY + 0xD98341554C61746ELLU, // dmw_Latn_AU + 0xDD834D5A4C61746ELLU, // dmx_Latn_MZ + 0xE18349444C61746ELLU, // dmy_Latn_ID + 0x81A349444C61746ELLU, // dna_Latn_ID + 0x8DA350474C61746ELLU, // dnd_Latn_PG + 0x91A3545A4C61746ELLU, // dne_Latn_TZ + 0x99A34B474379726CLLU, // dng_Cyrl_KG + 0xA1A349444C61746ELLU, // dni_Latn_ID 0xA5A343494C61746ELLU, // dnj_Latn_CI + 0xA9A349444C61746ELLU, // dnk_Latn_ID + 0xB5A342464C61746ELLU, // dnn_Latn_BF + 0xB9A343444C61746ELLU, // dno_Latn_CD + 0xC5A350474C61746ELLU, // dnr_Latn_PG + 0xCDA349444C61746ELLU, // dnt_Latn_ID + 0xD1A34D4D4D796D72LLU, // dnu_Mymr_MM + 0xD5A34D4D4D796D72LLU, // dnv_Mymr_MM + 0xD9A349444C61746ELLU, // dnw_Latn_ID + 0xE1A342524C61746ELLU, // dny_Latn_BR + 0x81C350474C61746ELLU, // doa_Latn_PG + 0x85C350474C61746ELLU, // dob_Latn_PG + 0x89C3434E4C61746ELLU, // doc_Latn_CN + 0x91C3545A4C61746ELLU, // doe_Latn_TZ + 0x95C350474C61746ELLU, // dof_Latn_PG + 0x9DC34E474C61746ELLU, // doh_Latn_NG 0xA1C3494E44657661LLU, // doi_Deva_IN - 0x9E23434E4D6F6E67LLU, // drh_Mong_CN + 0xA9C349444C61746ELLU, // dok_Latn_ID + 0xADC350474C61746ELLU, // dol_Latn_PG + 0xB5C350474C61746ELLU, // don_Latn_PG + 0xB9C343444C61746ELLU, // doo_Latn_CD + 0xBDC3424A4C61746ELLU, // dop_Latn_BJ + 0xC5C353424C61746ELLU, // dor_Latn_SB + 0xC9C342464C61746ELLU, // dos_Latn_BF + 0xCDC34E474C61746ELLU, // dot_Latn_NG + 0xD5C35A574C61746ELLU, // dov_Latn_ZW + 0xD9C3434D4C61746ELLU, // dow_Latn_CM + 0xDDC3455445746869LLU, // dox_Ethi_ET + 0xE1C347484C61746ELLU, // doy_Latn_GH + 0xBDE34D594C61746ELLU, // dpp_Latn_MY + 0x8A2350544C61746ELLU, // drc_Latn_PT + 0x92234E5054696274LLU, // dre_Tibt_NP + 0x9A234D594C61746ELLU, // drg_Latn_MY + 0xA2234E474C61746ELLU, // dri_Latn_NG + 0xAE2341554C61746ELLU, // drl_Latn_AU + 0xB62349444C61746ELLU, // drn_Latn_ID + 0xBA234D594C61746ELLU, // dro_Latn_MY + 0xC2234E5044657661LLU, // drq_Deva_NP + 0xCA23455445746869LLU, // drs_Ethi_ET + 0xCE234E4C4C61746ELLU, // drt_Latn_NL + 0xD22354574C61746ELLU, // dru_Latn_TW + 0xE2234E5044657661LLU, // dry_Deva_NP 0x864344454C61746ELLU, // dsb_Latn_DE + 0x9E434B454C61746ELLU, // dsh_Latn_KE + 0xA24354444C61746ELLU, // dsi_Latn_TD + 0xAA434E474C61746ELLU, // dsk_Latn_NG + 0xB64349444C61746ELLU, // dsn_Latn_ID + 0xBA43494E4F727961LLU, // dso_Orya_IN + 0xC2434D4C4C61746ELLU, // dsq_Latn_ML + 0x8263434E4C61746ELLU, // dta_Latn_CN + 0x86634D594C61746ELLU, // dtb_Latn_MY + 0x8E6343414C61746ELLU, // dtd_Latn_CA + 0x9E6341554C61746ELLU, // dth_Latn_AU + 0xA2634D4C4C61746ELLU, // dti_Latn_ML + 0xAA634D4C4C61746ELLU, // dtk_Latn_ML 0xB2634D4C4C61746ELLU, // dtm_Latn_ML + 0xBA634D4C4C61746ELLU, // dto_Latn_ML 0xBE634D594C61746ELLU, // dtp_Latn_MY + 0xC6634D594C61746ELLU, // dtr_Latn_MY + 0xCA634D4C4C61746ELLU, // dts_Latn_ML + 0xCE634D4C4C61746ELLU, // dtt_Latn_ML + 0xD2634D4C4C61746ELLU, // dtu_Latn_ML 0xE2634E5044657661LLU, // dty_Deva_NP 0x8283434D4C61746ELLU, // dua_Latn_CM + 0x8683494E47756A72LLU, // dub_Gujr_IN + 0x8A8350474C61746ELLU, // duc_Latn_PG + 0x928350484C61746ELLU, // due_Latn_PH + 0x96834E434C61746ELLU, // duf_Latn_NC + 0x9A834B454C61746ELLU, // dug_Latn_KE + 0x9E83494E44657661LLU, // duh_Deva_IN + 0xA28350474C61746ELLU, // dui_Latn_PG + 0xAA8350474C61746ELLU, // duk_Latn_PG + 0xAE8350484C61746ELLU, // dul_Latn_PH + 0xB2834E4C4C61746ELLU, // dum_Latn_NL + 0xB68349444C61746ELLU, // dun_Latn_ID + 0xBA8350484C61746ELLU, // duo_Latn_PH + 0xBE8349444C61746ELLU, // dup_Latn_ID + 0xC28349444C61746ELLU, // duq_Latn_ID + 0xC683434D4C61746ELLU, // dur_Latn_CM + 0xCA834E5044657661LLU, // dus_Deva_NP + 0xD283434E4C61746ELLU, // duu_Latn_CN + 0xD68349444C61746ELLU, // duv_Latn_ID + 0xDA8349444C61746ELLU, // duw_Latn_ID + 0xDE834D4C4C61746ELLU, // dux_Latn_ML + 0xE28350484C61746ELLU, // duy_Latn_PH + 0xE683434D4C61746ELLU, // duz_Latn_CM 0x64764D5654686161LLU, // dv_Thaa_MV + 0x82A350474C61746ELLU, // dva_Latn_PG + 0x82C34E474C61746ELLU, // dwa_Latn_NG + 0xAAC3494E4F727961LLU, // dwk_Orya_IN + 0xC6C345544C61746ELLU, // dwr_Latn_ET + 0xD2C341554C61746ELLU, // dwu_Latn_AU + 0xDAC350474C61746ELLU, // dww_Latn_PG + 0xE2C341554C61746ELLU, // dwy_Latn_AU + 0xE6C34E5044657661LLU, // dwz_Deva_NP + 0x830342464C61746ELLU, // dya_Latn_BF + 0x870341554C61746ELLU, // dyb_Latn_AU + 0x8F0341554C61746ELLU, // dyd_Latn_AU + 0x9B0350484C61746ELLU, // dyg_Latn_PH + 0xA30343494C61746ELLU, // dyi_Latn_CI + 0xB3034D4C4C61746ELLU, // dym_Latn_ML + 0xB70341554C61746ELLU, // dyn_Latn_AU 0xBB03534E4C61746ELLU, // dyo_Latn_SN + 0xC7034E474C61746ELLU, // dyr_Latn_NG 0xD30342464C61746ELLU, // dyu_Latn_BF + 0xE30341554C61746ELLU, // dyy_Latn_AU 0x647A425454696274LLU, // dz_Tibt_BT + 0x83234E474C61746ELLU, // dza_Latn_NG + 0x8F234E474C61746ELLU, // dzd_Latn_NG + 0x932341554C61746ELLU, // dze_Latn_AU + 0x9B2354444C61746ELLU, // dzg_Latn_TD + 0xAF23425454696274LLU, // dzl_Tibt_BT + 0xB72343444C61746ELLU, // dzn_Latn_CD + 0x800441554C61746ELLU, // eaa_Latn_AU + 0x882449444C61746ELLU, // ebc_Latn_ID + 0x98244E474C61746ELLU, // ebg_Latn_NG + 0xA82450484C61746ELLU, // ebk_Latn_PH + 0xB82443474C61746ELLU, // ebo_Latn_CG + 0xC42443494C61746ELLU, // ebr_Latn_CI 0xD0244B454C61746ELLU, // ebu_Latn_KE + 0xC44447524772656BLLU, // ecr_Grek_GR + 0xE044435943707274LLU, // ecy_Cprt_CY 0x656547484C61746ELLU, // ee_Latn_GH + 0x80A44E474C61746ELLU, // efa_Latn_NG + 0x90A443444C61746ELLU, // efe_Latn_CD 0xA0A44E474C61746ELLU, // efi_Latn_NG + 0x80C443494C61746ELLU, // ega_Latn_CI 0xACC449544C61746ELLU, // egl_Latn_IT + 0xB0C4545A4C61746ELLU, // egm_Latn_TZ + 0xB8C44E474C61746ELLU, // ego_Latn_NG 0xE0C4454745677970LLU, // egy_Egyp_EG + 0xD0E44E474C61746ELLU, // ehu_Latn_NG + 0xBD0449444C61746ELLU, // eip_Latn_ID + 0xCD0450474C61746ELLU, // eit_Latn_PG + 0xD50450474C61746ELLU, // eiv_Latn_PG + 0x812447574C61746ELLU, // eja_Latn_GW + 0x81444E474C61746ELLU, // eka_Latn_NG + 0x91444E474C61746ELLU, // eke_Latn_NG + 0x994449444C61746ELLU, // ekg_Latn_ID + 0xA1444E474C61746ELLU, // eki_Latn_NG + 0xAD4442444C61746ELLU, // ekl_Latn_BD + 0xB144434D4C61746ELLU, // ekm_Latn_CM + 0xB9444D5A4C61746ELLU, // eko_Latn_MZ + 0xBD444E474C61746ELLU, // ekp_Latn_NG + 0xC5444E474C61746ELLU, // ekr_Latn_NG 0xE1444D4D4B616C69LLU, // eky_Kali_MM 0x656C47524772656BLLU, // el_Grek_GR + 0x916450474C61746ELLU, // ele_Latn_PG + 0xA96450474C61746ELLU, // elk_Latn_PG + 0xB1644E474C61746ELLU, // elm_Latn_NG + 0xB9644B454C61746ELLU, // elo_Latn_KE + 0xD16450474C61746ELLU, // elu_Latn_PG + 0x81844E474C61746ELLU, // ema_Latn_NG + 0x858449444C61746ELLU, // emb_Latn_ID + 0x918447464C61746ELLU, // eme_Latn_GF + 0x99844E5044657661LLU, // emg_Deva_NP + 0xA18450474C61746ELLU, // emi_Latn_PG + 0xB1844D584C61746ELLU, // emm_Latn_MX + 0xB584434D4C61746ELLU, // emn_Latn_CM + 0xBD8450414C61746ELLU, // emp_Latn_PA + 0xC98455534C61746ELLU, // ems_Latn_US + 0xD184494E44657661LLU, // emu_Deva_IN + 0xD98449444C61746ELLU, // emw_Latn_ID + 0xDD8446524C61746ELLU, // emx_Latn_FR + 0xE584434D4C61746ELLU, // emz_Latn_CM 0x656E47424C61746ELLU, // en_Latn_GB 0x656E55534C61746ELLU, // en_Latn_US 0x656E474253686177LLU, // en_Shaw_GB + 0x81A450474C61746ELLU, // ena_Latn_PG + 0x85A44B454C61746ELLU, // enb_Latn_KE + 0x89A4564E4C61746ELLU, // enc_Latn_VN + 0x8DA449444C61746ELLU, // end_Latn_ID + 0x95A452554379726CLLU, // enf_Cyrl_RU + 0x9DA452554379726CLLU, // enh_Cyrl_RU + 0xADA450594C61746ELLU, // enl_Latn_PY + 0xB1A447424C61746ELLU, // enm_Latn_GB + 0xB5A44E474C61746ELLU, // enn_Latn_NG + 0xB9A449444C61746ELLU, // eno_Latn_ID + 0xC1A450474C61746ELLU, // enq_Latn_PG + 0xC5A449444C61746ELLU, // enr_Latn_ID + 0xD5A44E474C61746ELLU, // env_Latn_NG + 0xD9A44E474C61746ELLU, // enw_Latn_NG + 0xDDA450594C61746ELLU, // enx_Latn_PY + 0xCDC443494C61746ELLU, // eot_Latn_CI + 0xA1E44E474C61746ELLU, // epi_Latn_NG + 0x8224494E54616D6CLLU, // era_Taml_IN + 0x9A2456554C61746ELLU, // erg_Latn_VU + 0x9E244E474C61746ELLU, // erh_Latn_NG + 0xA22450474C61746ELLU, // eri_Latn_PG + 0xAA2456554C61746ELLU, // erk_Latn_VU + 0xC62441554C61746ELLU, // err_Latn_AU + 0xCA24434E4C61746ELLU, // ers_Latn_CN + 0xCE2449444C61746ELLU, // ert_Latn_ID + 0xDA2449444C61746ELLU, // erw_Latn_ID 0x657345534C61746ELLU, // es_Latn_ES 0x65734D584C61746ELLU, // es_Latn_MX 0x657355534C61746ELLU, // es_Latn_US + 0x9244424F4C61746ELLU, // ese_Latn_BO 0x9A44494E476F6E6DLLU, // esg_Gonm_IN + 0x9E44495241726162LLU, // esh_Arab_IR + 0xA24455534C61746ELLU, // esi_Latn_US + 0xB24443494C61746ELLU, // esm_Latn_CI + 0xCA4455534C61746ELLU, // ess_Latn_US 0xD24455534C61746ELLU, // esu_Latn_US + 0xE24450484C61746ELLU, // esy_Latn_PH 0x657445454C61746ELLU, // et_Latn_EE + 0x86644E474C61746ELLU, // etb_Latn_NG + 0xB66456554C61746ELLU, // etn_Latn_VU + 0xBA64434D4C61746ELLU, // eto_Latn_CM + 0xC66450474C61746ELLU, // etr_Latn_PG + 0xCA644E474C61746ELLU, // ets_Latn_NG 0xCE6449544974616CLLU, // ett_Ital_IT + 0xD2644E474C61746ELLU, // etu_Latn_NG + 0xDE644E474C61746ELLU, // etx_Latn_NG + 0xE66449444C61746ELLU, // etz_Latn_ID 0x657545534C61746ELLU, // eu_Latn_ES + 0x8E844D584C61746ELLU, // eud_Latn_MX + 0x92A452554379726CLLU, // eve_Cyrl_RU + 0x9EA44E474C61746ELLU, // evh_Latn_NG + 0xB6A452554379726CLLU, // evn_Cyrl_RU 0xBAC4434D4C61746ELLU, // ewo_Latn_CM 0xCEE445534C61746ELLU, // ext_Latn_ES + 0x830455534C61746ELLU, // eya_Latn_US + 0xBB044B454C61746ELLU, // eyo_Latn_KE + 0x83244E474C61746ELLU, // eza_Latn_NG + 0x93244E474C61746ELLU, // eze_Latn_NG 0x6661495241726162LLU, // fa_Arab_IR + 0x800550474C61746ELLU, // faa_Latn_PG + 0x840547514C61746ELLU, // fab_Latn_GQ + 0x8C0550474C61746ELLU, // fad_Latn_PG + 0x940553424C61746ELLU, // faf_Latn_SB + 0x980550474C61746ELLU, // fag_Latn_PG + 0x9C054E474C61746ELLU, // fah_Latn_NG + 0xA00550474C61746ELLU, // fai_Latn_PG + 0xA40550474C61746ELLU, // faj_Latn_PG + 0xA805434D4C61746ELLU, // fak_Latn_CM + 0xAC05434D4C61746ELLU, // fal_Latn_CM + 0xB0054E474C61746ELLU, // fam_Latn_NG 0xB40547514C61746ELLU, // fan_Latn_GQ + 0xBC05534E4C61746ELLU, // fap_Latn_SN + 0xC40553424C61746ELLU, // far_Latn_SB + 0xD00549444C61746ELLU, // fau_Latn_ID + 0xDC0545534C61746ELLU, // fax_Latn_ES + 0xE005495241726162LLU, // fay_Arab_IR + 0xE405495241726162LLU, // faz_Arab_IR + 0xAC2550484C61746ELLU, // fbl_Latn_PH + 0xC48553534C61746ELLU, // fer_Latn_SS 0x6666474E41646C6DLLU, // ff_Adlm_GN 0x6666534E4C61746ELLU, // ff_Latn_SN + 0xA0A550474C61746ELLU, // ffi_Latn_PG 0xB0A54D4C4C61746ELLU, // ffm_Latn_ML + 0xC4C554444C61746ELLU, // fgr_Latn_TD 0x666946494C61746ELLU, // fi_Latn_FI 0x8105534441726162LLU, // fia_Arab_SD + 0x91054E474C61746ELLU, // fie_Latn_NG + 0x950553414C61746ELLU, // fif_Latn_SA 0xAD0550484C61746ELLU, // fil_Latn_PH + 0xBD05545A4C61746ELLU, // fip_Latn_TZ + 0xC5054E474C61746ELLU, // fir_Latn_NG 0xCD0553454C61746ELLU, // fit_Latn_SE + 0xD90550474C61746ELLU, // fiw_Latn_PG 0x666A464A4C61746ELLU, // fj_Latn_FJ + 0xA9454E474C61746ELLU, // fkk_Latn_NG + 0xD5454E4F4C61746ELLU, // fkv_Latn_NO + 0x816555534C61746ELLU, // fla_Latn_US + 0x9D6549444C61746ELLU, // flh_Latn_ID + 0xA1654E474C61746ELLU, // fli_Latn_NG + 0xAD65434D4C61746ELLU, // fll_Latn_CM + 0xB56541554C61746ELLU, // fln_Latn_AU + 0xC56543444C61746ELLU, // flr_Latn_CD + 0xE1655A414C61746ELLU, // fly_Latn_ZA + 0xBD85434D4C61746ELLU, // fmp_Latn_CM + 0xD185494E44657661LLU, // fmu_Deva_IN + 0x85A556554C61746ELLU, // fnb_Latn_VU + 0x99A55A414C61746ELLU, // fng_Latn_ZA + 0xA1A554444C61746ELLU, // fni_Latn_TD 0x666F464F4C61746ELLU, // fo_Latn_FO + 0x8DC5424A4C61746ELLU, // fod_Latn_BJ + 0xA1C550474C61746ELLU, // foi_Latn_PG + 0xB1C543444C61746ELLU, // fom_Latn_CD 0xB5C5424A4C61746ELLU, // fon_Latn_BJ + 0xC5C550474C61746ELLU, // for_Latn_PG + 0xC9C554574C61746ELLU, // fos_Latn_TW + 0x91E547514C61746ELLU, // fpe_Latn_GQ + 0xCA0550474C61746ELLU, // fqs_Latn_PG 0x667246524C61746ELLU, // fr_Latn_FR 0x8A2555534C61746ELLU, // frc_Latn_US + 0x8E2549444C61746ELLU, // frd_Latn_ID + 0xAA2544454C61746ELLU, // frk_Latn_DE + 0xB22546524C61746ELLU, // frm_Latn_FR + 0xBA2546524C61746ELLU, // fro_Latn_FR 0xBE2546524C61746ELLU, // frp_Latn_FR + 0xC22550474C61746ELLU, // frq_Latn_PG 0xC62544454C61746ELLU, // frr_Latn_DE 0xCA2544454C61746ELLU, // frs_Latn_DE + 0xCE2556554C61746ELLU, // frt_Latn_VU 0x8685434D41726162LLU, // fub_Arab_CM 0x8E8557464C61746ELLU, // fud_Latn_WF + 0x9285424A4C61746ELLU, // fue_Latn_BJ 0x9685474E4C61746ELLU, // fuf_Latn_GN + 0x9E854E454C61746ELLU, // fuh_Latn_NE + 0xA28554444C61746ELLU, // fui_Latn_TD + 0xB2854E474C61746ELLU, // fum_Latn_NG + 0xB68542524C61746ELLU, // fun_Latn_BR 0xC2854E454C61746ELLU, // fuq_Latn_NE 0xC68549544C61746ELLU, // fur_Latn_IT + 0xCE8556554C61746ELLU, // fut_Latn_VU + 0xD28543444C61746ELLU, // fuu_Latn_CD 0xD6854E474C61746ELLU, // fuv_Latn_NG + 0xE28550474C61746ELLU, // fuy_Latn_PG 0xC6A553444C61746ELLU, // fvr_Latn_SD + 0x82C54E434C61746ELLU, // fwa_Latn_NC + 0x92C54E414C61746ELLU, // fwe_Latn_NA 0x66794E4C4C61746ELLU, // fy_Latn_NL 0x676149454C61746ELLU, // ga_Latn_IE 0x800647484C61746ELLU, // gaa_Latn_GH + 0x840654444C61746ELLU, // gab_Latn_TD + 0x8806494E4C61746ELLU, // gac_Latn_IN + 0x8C0650484C61746ELLU, // gad_Latn_PH + 0x900656454C61746ELLU, // gae_Latn_VE + 0x940650474C61746ELLU, // gaf_Latn_PG 0x98064D444C61746ELLU, // gag_Latn_MD + 0x9C0650474C61746ELLU, // gah_Latn_PG + 0xA00650474C61746ELLU, // gai_Latn_PG + 0xA40650474C61746ELLU, // gaj_Latn_PG + 0xA80649444C61746ELLU, // gak_Latn_ID + 0xAC06544C4C61746ELLU, // gal_Latn_TL + 0xB00650474C61746ELLU, // gam_Latn_PG 0xB406434E48616E73LLU, // gan_Hans_CN + 0xB80650474C61746ELLU, // gao_Latn_PG + 0xBC0650474C61746ELLU, // gap_Latn_PG + 0xC006494E4F727961LLU, // gaq_Orya_IN + 0xC40650474C61746ELLU, // gar_Latn_PG + 0xC806494E47756A72LLU, // gas_Gujr_IN + 0xCC0650474C61746ELLU, // gat_Latn_PG + 0xD006494E54656C75LLU, // gau_Telu_IN + 0xD80650474C61746ELLU, // gaw_Latn_PG + 0xDC0645544C61746ELLU, // gax_Latn_ET 0xE00649444C61746ELLU, // gay_Latn_ID + 0x802643464C61746ELLU, // gba_Latn_CF + 0x842641554C61746ELLU, // gbb_Latn_AU + 0x8C2641554C61746ELLU, // gbd_Latn_AU + 0x902650474C61746ELLU, // gbe_Latn_PG + 0x942650474C61746ELLU, // gbf_Latn_PG + 0x982643464C61746ELLU, // gbg_Latn_CF + 0x9C26424A4C61746ELLU, // gbh_Latn_BJ + 0xA02649444C61746ELLU, // gbi_Latn_ID + 0xA426494E4F727961LLU, // gbj_Orya_IN + 0xA826494E44657661LLU, // gbk_Deva_IN + 0xAC26494E47756A72LLU, // gbl_Gujr_IN 0xB026494E44657661LLU, // gbm_Deva_IN + 0xB42653534C61746ELLU, // gbn_Latn_SS + 0xBC2643464C61746ELLU, // gbp_Latn_CF + 0xC02643464C61746ELLU, // gbq_Latn_CF + 0xC4264E474C61746ELLU, // gbr_Latn_NG + 0xC826424A4C61746ELLU, // gbs_Latn_BJ + 0xD02641554C61746ELLU, // gbu_Latn_AU + 0xD42643464C61746ELLU, // gbv_Latn_CF + 0xD82641554C61746ELLU, // gbw_Latn_AU + 0xDC26424A4C61746ELLU, // gbx_Latn_BJ + 0xE0264E474C61746ELLU, // gby_Latn_NG 0xE426495241726162LLU, // gbz_Arab_IR + 0x884650474C61746ELLU, // gcc_Latn_PG + 0x8C4641554C61746ELLU, // gcd_Latn_AU + 0x944647504C61746ELLU, // gcf_Latn_GP + 0xAC4647444C61746ELLU, // gcl_Latn_GD + 0xB44650474C61746ELLU, // gcn_Latn_PG 0xC44647464C61746ELLU, // gcr_Latn_GF + 0xCC4656454C61746ELLU, // gct_Latn_VE 0x676447424C61746ELLU, // gd_Latn_GB + 0x8466494E4F727961LLU, // gdb_Orya_IN + 0x886641554C61746ELLU, // gdc_Latn_AU + 0x8C6650474C61746ELLU, // gdd_Latn_PG + 0x90664E474C61746ELLU, // gde_Latn_NG + 0x94664E474C61746ELLU, // gdf_Latn_NG + 0x986650484C61746ELLU, // gdg_Latn_PH + 0x9C6641554C61746ELLU, // gdh_Latn_AU + 0xA06643464C61746ELLU, // gdi_Latn_CF + 0xA46641554C61746ELLU, // gdj_Latn_AU + 0xA86654444C61746ELLU, // gdk_Latn_TD + 0xAC6645544C61746ELLU, // gdl_Latn_ET + 0xB06654444C61746ELLU, // gdm_Latn_TD + 0xB46650474C61746ELLU, // gdn_Latn_PG + 0xB86652554379726CLLU, // gdo_Cyrl_RU + 0xC06659454C61746ELLU, // gdq_Latn_YE + 0xC46650474C61746ELLU, // gdr_Latn_PG + 0xCC6641554C61746ELLU, // gdt_Latn_AU + 0xD0664E474C61746ELLU, // gdu_Latn_NG + 0xDC66494E44657661LLU, // gdx_Deva_IN + 0x80864E474C61746ELLU, // gea_Latn_NG + 0x848650474C61746ELLU, // geb_Latn_PG + 0x88864C524C61746ELLU, // gec_Latn_LR + 0x8C864E474C61746ELLU, // ged_Latn_NG + 0x948649444C61746ELLU, // gef_Latn_ID + 0x98864E474C61746ELLU, // geg_Latn_NG + 0x9C8643414C61746ELLU, // geh_Latn_CA + 0xA08649444C61746ELLU, // gei_Latn_ID + 0xA48654474C61746ELLU, // gej_Latn_TG + 0xA8864E474C61746ELLU, // gek_Latn_NG + 0xAC864E474C61746ELLU, // gel_Latn_NG + 0xC08643464C61746ELLU, // geq_Latn_CF + 0xC88649444C61746ELLU, // ges_Latn_ID + 0xD48647414C61746ELLU, // gev_Latn_GA + 0xD8864E474C61746ELLU, // gew_Latn_NG + 0xDC86534F4C61746ELLU, // gex_Latn_SO + 0xE08643444C61746ELLU, // gey_Latn_CD 0xE486455445746869LLU, // gez_Ethi_ET - 0xB4C64E5044657661LLU, // ggn_Deva_NP + 0xA8A650474C61746ELLU, // gfk_Latn_PG + 0x80C653424C61746ELLU, // gga_Latn_SB + 0x84C64C524C61746ELLU, // ggb_Latn_LR + 0x8CC641554C61746ELLU, // ggd_Latn_AU + 0x90C641554C61746ELLU, // gge_Latn_AU + 0x98C6504B41726162LLU, // ggg_Arab_PK + 0xA8C641554C61746ELLU, // ggk_Latn_AU + 0xACC650474C61746ELLU, // ggl_Latn_PG + 0xCCC650474C61746ELLU, // ggt_Latn_PG + 0xD0C643494C61746ELLU, // ggu_Latn_CI + 0xD8C650474C61746ELLU, // ggw_Latn_PG + 0x80E64C5941726162LLU, // gha_Arab_LY + 0x88E647424C61746ELLU, // ghc_Latn_GB + 0x90E64E5044657661LLU, // ghe_Deva_NP + 0xA8E64D4D4C61746ELLU, // ghk_Latn_MM + 0xB4E653424C61746ELLU, // ghn_Latn_SB + 0xB8E64D4154666E67LLU, // gho_Tfng_MA + 0xC4E6504B41726162LLU, // ghr_Arab_PK + 0xC8E650474C61746ELLU, // ghs_Latn_PG + 0xCCE64E5054696274LLU, // ght_Tibt_NP + 0x810641554C61746ELLU, // gia_Latn_AU + 0x85064E474C61746ELLU, // gib_Latn_NG + 0x89065A414C61746ELLU, // gic_Latn_ZA + 0x8D06434D4C61746ELLU, // gid_Latn_CM + 0x910643494C61746ELLU, // gie_Latn_CI + 0x9906504B41726162LLU, // gig_Arab_PK + 0x9D0641554C61746ELLU, // gih_Latn_AU 0xAD064B494C61746ELLU, // gil_Latn_KI + 0xB10650474C61746ELLU, // gim_Latn_PG + 0xB50652554379726CLLU, // gin_Cyrl_RU + 0xBD0650474C61746ELLU, // gip_Latn_PG + 0xC106564E4C61746ELLU, // giq_Latn_VN + 0xC506564E4C61746ELLU, // gir_Latn_VN + 0xC906434D4C61746ELLU, // gis_Latn_CM + 0xCD0643414C61746ELLU, // git_Latn_CA + 0xDD0643444C61746ELLU, // gix_Latn_CD + 0xE10641554C61746ELLU, // giy_Latn_AU + 0xE506434D4C61746ELLU, // giz_Latn_CM 0xA926504B41726162LLU, // gjk_Arab_PK + 0xB12641554C61746ELLU, // gjm_Latn_AU + 0xB52647484C61746ELLU, // gjn_Latn_GH + 0xC52641554C61746ELLU, // gjr_Latn_AU 0xD126504B41726162LLU, // gju_Arab_PK + 0x814650474C61746ELLU, // gka_Latn_PG + 0x8D4650474C61746ELLU, // gkd_Latn_PG + 0x9146434D4C61746ELLU, // gke_Latn_CM + 0xB5464E474C61746ELLU, // gkn_Latn_NG + 0xB94641554C61746ELLU, // gko_Latn_AU + 0xBD46474E4C61746ELLU, // gkp_Latn_GN + 0xD1465A414C61746ELLU, // gku_Latn_ZA 0x676C45534C61746ELLU, // gl_Latn_ES + 0x85664E474C61746ELLU, // glb_Latn_NG + 0x896654444C61746ELLU, // glc_Latn_TD + 0x8D6652554379726CLLU, // gld_Cyrl_RU + 0x9D66414641726162LLU, // glh_Arab_AF + 0xA56654444C61746ELLU, // glj_Latn_TD 0xA966495241726162LLU, // glk_Arab_IR + 0xAD6641554C61746ELLU, // gll_Latn_AU + 0xB9664E474C61746ELLU, // glo_Latn_NG + 0xC5664C524C61746ELLU, // glr_Latn_LR + 0xD16654444C61746ELLU, // glu_Latn_TD + 0xD9664E474C61746ELLU, // glw_Latn_NG + 0x818641554C61746ELLU, // gma_Latn_AU + 0x858653424C61746ELLU, // gmb_Latn_SB + 0x8D864E474C61746ELLU, // gmd_Latn_NG + 0x998650474C61746ELLU, // gmg_Latn_PG + 0x9D8644454C61746ELLU, // gmh_Latn_DE + 0xAD8644454C617466LLU, // gml_Latf_DE + 0xB186434D4C61746ELLU, // gmm_Latn_CM + 0xB586434D4C61746ELLU, // gmn_Latn_CM + 0xC58641554C61746ELLU, // gmr_Latn_AU + 0xD18650474C61746ELLU, // gmu_Latn_PG + 0xD586455445746869LLU, // gmv_Ethi_ET + 0xDD86545A4C61746ELLU, // gmx_Latn_TZ + 0xE18647524C696E62LLU, // gmy_Linb_GR + 0xE5864E474C61746ELLU, // gmz_Latn_NG 0x676E50594C61746ELLU, // gn_Latn_PY - 0xB1C6494E44657661LLU, // gom_Deva_IN - 0xB5C6494E54656C75LLU, // gon_Telu_IN + 0x81A642464C61746ELLU, // gna_Latn_BF + 0x85A6494E4C61746ELLU, // gnb_Latn_IN + 0x89A645534C61746ELLU, // gnc_Latn_ES + 0x8DA6434D4C61746ELLU, // gnd_Latn_CM + 0x91A64E474C61746ELLU, // gne_Latn_NG + 0x99A654474C61746ELLU, // gng_Latn_TG + 0x9DA64E474C61746ELLU, // gnh_Latn_NG + 0xA1A641554C61746ELLU, // gni_Latn_AU + 0xA5A643494C61746ELLU, // gnj_Latn_CI + 0xA9A642574C61746ELLU, // gnk_Latn_BW + 0xADA641554C61746ELLU, // gnl_Latn_AU + 0xB1A650474C61746ELLU, // gnm_Latn_PG + 0xB5A641554C61746ELLU, // gnn_Latn_AU + 0xC1A64D594C61746ELLU, // gnq_Latn_MY + 0xC5A641554C61746ELLU, // gnr_Latn_AU + 0xCDA650474C61746ELLU, // gnt_Latn_PG + 0xD1A650474C61746ELLU, // gnu_Latn_PG + 0xD9A6424F4C61746ELLU, // gnw_Latn_BO + 0xE5A643464C61746ELLU, // gnz_Latn_CF + 0x81C643494C61746ELLU, // goa_Latn_CI + 0x85C6434F4C61746ELLU, // gob_Latn_CO + 0x89C650474C61746ELLU, // goc_Latn_PG + 0x8DC643494C61746ELLU, // god_Latn_CI + 0x91C6425454696274LLU, // goe_Tibt_BT + 0x95C6455445746869LLU, // gof_Ethi_ET + 0x99C6545A4C61746ELLU, // gog_Latn_TZ + 0x9DC644454C61746ELLU, // goh_Latn_DE + 0xA1C650474C61746ELLU, // goi_Latn_PG + 0xA5C6494E44657661LLU, // goj_Deva_IN + 0xA9C6494E44657661LLU, // gok_Deva_IN + 0xADC64C524C61746ELLU, // gol_Latn_LR + 0xB5C6494E44657661LLU, // gon_Deva_IN + 0xB9C6464A4C61746ELLU, // goo_Latn_FJ + 0xBDC649444C61746ELLU, // gop_Latn_ID + 0xC1C649444C61746ELLU, // goq_Latn_ID 0xC5C649444C61746ELLU, // gor_Latn_ID 0xC9C64E4C4C61746ELLU, // gos_Latn_NL 0xCDC65541476F7468LLU, // got_Goth_UA + 0xD1C6434D4C61746ELLU, // gou_Latn_CM + 0xD5C643494C61746ELLU, // gov_Latn_CI + 0xD9C6545A4C61746ELLU, // gow_Latn_TZ + 0xDDC643444C61746ELLU, // gox_Latn_CD + 0xE1C654444C61746ELLU, // goy_Latn_TD + 0x81E64E474C61746ELLU, // gpa_Latn_NG + 0x91E647484C61746ELLU, // gpe_Latn_GH + 0xB5E650474C61746ELLU, // gpn_Latn_PG + 0x82064E474C61746ELLU, // gqa_Latn_NG + 0xB60642524C61746ELLU, // gqn_Latn_BR + 0xC60654444C61746ELLU, // gqr_Latn_TD + 0x8226494E44657661LLU, // gra_Deva_IN + 0x86264C524C61746ELLU, // grb_Latn_LR 0x8A26435943707274LLU, // grc_Cprt_CY 0x8A2647524C696E62LLU, // grc_Linb_GR + 0x8E264E474C61746ELLU, // grd_Latn_NG + 0x9A2650474C61746ELLU, // grg_Latn_PG + 0x9E264E474C61746ELLU, // grh_Latn_NG + 0xA22653424C61746ELLU, // gri_Latn_SB + 0xA6264C524C61746ELLU, // grj_Latn_LR + 0xB2264D594C61746ELLU, // grm_Latn_MY + 0xC22650474C61746ELLU, // grq_Latn_PG + 0xCA2649444C61746ELLU, // grs_Latn_ID 0xCE26494E42656E67LLU, // grt_Beng_IN + 0xD226455445746869LLU, // gru_Ethi_ET + 0xD6264C524C61746ELLU, // grv_Latn_LR + 0xDA2650474C61746ELLU, // grw_Latn_PG + 0xDE2650474C61746ELLU, // grx_Latn_PG + 0xE2264C524C61746ELLU, // gry_Latn_LR + 0xE62650474C61746ELLU, // grz_Latn_PG + 0xAE46534E4C61746ELLU, // gsl_Latn_SN + 0xB64650474C61746ELLU, // gsn_Latn_PG + 0xBA4643464C61746ELLU, // gso_Latn_CF + 0xBE4650474C61746ELLU, // gsp_Latn_PG 0xDA4643484C61746ELLU, // gsw_Latn_CH + 0x826642524C61746ELLU, // gta_Latn_BR + 0xD26641554C61746ELLU, // gtu_Latn_AU 0x6775494E47756A72LLU, // gu_Gujr_IN + 0x82864E474C61746ELLU, // gua_Latn_NG 0x868642524C61746ELLU, // gub_Latn_BR 0x8A86434F4C61746ELLU, // guc_Latn_CO + 0x8E8643494C61746ELLU, // gud_Latn_CI + 0x928641554C61746ELLU, // gue_Latn_AU + 0x968641554C61746ELLU, // guf_Latn_AU + 0x9E86434F4C61746ELLU, // guh_Latn_CO + 0xA286424F4C61746ELLU, // gui_Latn_BO + 0xAA8645544C61746ELLU, // guk_Latn_ET + 0xAE8655534C61746ELLU, // gul_Latn_US + 0xB286434F4C61746ELLU, // gum_Latn_CO + 0xB68642524C61746ELLU, // gun_Latn_BR + 0xBA86434F4C61746ELLU, // guo_Latn_CO + 0xBE8641554C61746ELLU, // gup_Latn_AU + 0xC28650594C61746ELLU, // guq_Latn_PY 0xC68647484C61746ELLU, // gur_Latn_GH + 0xCE8643524C61746ELLU, // gut_Latn_CR + 0xD28656454C61746ELLU, // guu_Latn_VE + 0xDA86424A4C61746ELLU, // guw_Latn_BJ + 0xDE8642464C61746ELLU, // gux_Latn_BF 0xE6864B454C61746ELLU, // guz_Latn_KE 0x6776494D4C61746ELLU, // gv_Latn_IM + 0x82A650594C61746ELLU, // gva_Latn_PY + 0x8AA642524C61746ELLU, // gvc_Latn_BR + 0x92A650474C61746ELLU, // gve_Latn_PG + 0x96A650474C61746ELLU, // gvf_Latn_PG + 0xA6A642524C61746ELLU, // gvj_Latn_BR + 0xAEA654444C61746ELLU, // gvl_Latn_TD + 0xB2A64E474C61746ELLU, // gvm_Latn_NG + 0xB6A641554C61746ELLU, // gvn_Latn_AU + 0xBAA642524C61746ELLU, // gvo_Latn_BR + 0xBEA642524C61746ELLU, // gvp_Latn_BR 0xC6A64E5044657661LLU, // gvr_Deva_NP + 0xCAA650474C61746ELLU, // gvs_Latn_PG + 0xE2A641554C61746ELLU, // gvy_Latn_AU + 0x82C643494C61746ELLU, // gwa_Latn_CI + 0x86C64E474C61746ELLU, // gwb_Latn_NG + 0x8AC6504B41726162LLU, // gwc_Arab_PK + 0x8EC645544C61746ELLU, // gwd_Latn_ET + 0x92C6545A4C61746ELLU, // gwe_Latn_TZ + 0x96C6504B41726162LLU, // gwf_Arab_PK + 0x9AC64E474C61746ELLU, // gwg_Latn_NG 0xA2C643414C61746ELLU, // gwi_Latn_CA + 0xA6C642574C61746ELLU, // gwj_Latn_BW + 0xB2C641554C61746ELLU, // gwm_Latn_AU + 0xB6C64E474C61746ELLU, // gwn_Latn_NG + 0xC6C655474C61746ELLU, // gwr_Latn_UG + 0xCEC6414641726162LLU, // gwt_Arab_AF + 0xD2C641554C61746ELLU, // gwu_Latn_AU + 0xDAC641554C61746ELLU, // gww_Latn_AU + 0xDEC647484C61746ELLU, // gwx_Latn_GH + 0xDEE643494C61746ELLU, // gxx_Latn_CI + 0x870650474C61746ELLU, // gyb_Latn_PG + 0x8F0641554C61746ELLU, // gyd_Latn_AU + 0x93064E474C61746ELLU, // gye_Latn_NG + 0x970641554C61746ELLU, // gyf_Latn_AU + 0x9B0643464C61746ELLU, // gyg_Latn_CF + 0xA306434D4C61746ELLU, // gyi_Latn_CM + 0xAF0645544C61746ELLU, // gyl_Latn_ET + 0xB30650414C61746ELLU, // gym_Latn_PA + 0xB70647594C61746ELLU, // gyn_Latn_GY + 0xBB064E5044657661LLU, // gyo_Deva_NP + 0xC706424F4C61746ELLU, // gyr_Latn_BO + 0xE30641554C61746ELLU, // gyy_Latn_AU + 0xE7064E474C61746ELLU, // gyz_Latn_NG + 0x832653444C61746ELLU, // gza_Latn_SD + 0xA326495241726162LLU, // gzi_Arab_IR + 0xB72649444C61746ELLU, // gzn_Latn_ID 0x68614E474C61746ELLU, // ha_Latn_NG + 0x800755534C61746ELLU, // haa_Latn_US + 0x8807495241726162LLU, // hac_Arab_IR + 0x8C0749444C61746ELLU, // had_Latn_ID + 0x900745544C61746ELLU, // hae_Latn_ET + 0x980747484C61746ELLU, // hag_Latn_GH + 0x9C0750474C61746ELLU, // hah_Latn_PG + 0xA00743414C61746ELLU, // hai_Latn_CA + 0xA407494E4C61746ELLU, // haj_Latn_IN 0xA807434E48616E73LLU, // hak_Hans_CN + 0xAC07564E4C61746ELLU, // hal_Latn_VN + 0xB00750474C61746ELLU, // ham_Latn_PG + 0xB407545A4C61746ELLU, // han_Latn_TZ + 0xB80750474C61746ELLU, // hao_Latn_PG + 0xBC0749444C61746ELLU, // hap_Latn_ID + 0xC007545A4C61746ELLU, // haq_Latn_TZ + 0xC407455445746869LLU, // har_Ethi_ET + 0xC80743414C61746ELLU, // has_Latn_CA + 0xD40743444C61746ELLU, // hav_Latn_CD 0xD80755534C61746ELLU, // haw_Latn_US + 0xDC0743414C61746ELLU, // hax_Latn_CA + 0xE007545A4C61746ELLU, // hay_Latn_TZ 0xE407414641726162LLU, // haz_Arab_AF + 0x802743444C61746ELLU, // hba_Latn_CD + 0x84274E474C61746ELLU, // hbb_Latn_NG + 0xB42753444C61746ELLU, // hbn_Latn_SD + 0xB827494C48656272LLU, // hbo_Hebr_IL + 0xD027544C4C61746ELLU, // hbu_Latn_TL + 0x9C474D584C61746ELLU, // hch_Latn_MX + 0xE067455445746869LLU, // hdy_Ethi_ET 0x6865494C48656272LLU, // he_Hebr_IL + 0x8C8754444C61746ELLU, // hed_Latn_TD + 0x988749444C61746ELLU, // heg_Latn_ID + 0x9C87545A4C61746ELLU, // heh_Latn_TZ + 0xA08743414C61746ELLU, // hei_Latn_CA + 0xB08743444C61746ELLU, // hem_Latn_CD + 0xB0C74E414C61746ELLU, // hgm_Latn_NA + 0xD8C750474C61746ELLU, // hgw_Latn_PG + 0xA0E750474C61746ELLU, // hhi_Latn_PG + 0xC4E7534E4C61746ELLU, // hhr_Latn_SN + 0xE0E750474C61746ELLU, // hhy_Latn_PG 0x6869494E44657661LLU, // hi_Deva_IN - 0x6869494E4C61746ELLU, // hi_Latn_IN - 0x9507464A4C61746ELLU, // hif_Latn_FJ + 0x81074E474C61746ELLU, // hia_Latn_NG + 0x850750454C61746ELLU, // hib_Latn_PE + 0x8D0755534C61746ELLU, // hid_Latn_US + 0x9507464A44657661LLU, // hif_Deva_FJ + 0x99074E474C61746ELLU, // hig_Latn_NG + 0x9D0750474C61746ELLU, // hih_Latn_PG + 0xA107494E54616B72LLU, // hii_Takr_IN + 0xA507434D4C61746ELLU, // hij_Latn_CM + 0xA90749444C61746ELLU, // hik_Latn_ID 0xAD0750484C61746ELLU, // hil_Latn_PH + 0xB90742574C61746ELLU, // hio_Latn_BW + 0xC50742524C61746ELLU, // hir_Latn_BR + 0xCD07545258737578LLU, // hit_Xsux_TR + 0xD90756554C61746ELLU, // hiw_Latn_VU + 0xDD0742524C61746ELLU, // hix_Latn_BR + 0xA12749444C61746ELLU, // hji_Latn_ID + 0x8147545A4C61746ELLU, // hka_Latn_TZ + 0x914743444C61746ELLU, // hke_Latn_CD + 0x9D47494E41726162LLU, // hkh_Arab_IN + 0xA94750474C61746ELLU, // hkk_Latn_PG + 0x816750474C61746ELLU, // hla_Latn_PG + 0x8567494E44657661LLU, // hlb_Deva_IN + 0x8D67564E4C61746ELLU, // hld_Latn_VN + 0xCD674D4D4C61746ELLU, // hlt_Latn_MM 0xD1675452486C7577LLU, // hlu_Hluw_TR + 0x8187434E4C61746ELLU, // hma_Latn_CN + 0x85874D4C4C61746ELLU, // hmb_Latn_ML 0x8D87434E506C7264LLU, // hmd_Plrd_CN + 0x9587564E4C61746ELLU, // hmf_Latn_VN + 0xA587434E426F706FLLU, // hmj_Bopo_CN + 0xB187434E4C61746ELLU, // hmm_Latn_CN + 0xB587434E4C61746ELLU, // hmn_Latn_CN + 0xBD87434E4C61746ELLU, // hmp_Latn_CN + 0xC187434E426F706FLLU, // hmq_Bopo_CN + 0xC587494E4C61746ELLU, // hmr_Latn_IN + 0xC987434E4C61746ELLU, // hms_Latn_CN + 0xCD8750474C61746ELLU, // hmt_Latn_PG + 0xD18749444C61746ELLU, // hmu_Latn_ID + 0xD587564E4C61746ELLU, // hmv_Latn_VN + 0xD987434E4C61746ELLU, // hmw_Latn_CN + 0xE187434E4C61746ELLU, // hmy_Latn_CN + 0xE587434E4C61746ELLU, // hmz_Latn_CN + 0x81A7434D4C61746ELLU, // hna_Latn_CM 0x8DA7504B41726162LLU, // hnd_Arab_PK 0x91A7494E44657661LLU, // hne_Deva_IN + 0x99A7414F4C61746ELLU, // hng_Latn_AO + 0x9DA742574C61746ELLU, // hnh_Latn_BW + 0xA1A7434E4C61746ELLU, // hni_Latn_CN + 0xA5A74C41486D6E67LLU, // hnj_Hmng_LA 0xA5A75553486D6E70LLU, // hnj_Hmnp_US 0xB5A750484C61746ELLU, // hnn_Latn_PH 0xB9A7504B41726162LLU, // hno_Arab_PK + 0xC9A753524C61746ELLU, // hns_Latn_SR 0x686F50474C61746ELLU, // ho_Latn_PG + 0x81C753424C61746ELLU, // hoa_Latn_SB + 0x85C750474C61746ELLU, // hob_Latn_PG 0x89C7494E44657661LLU, // hoc_Deva_IN + 0x8DC74E474C61746ELLU, // hod_Latn_NG + 0x91C74E474C61746ELLU, // hoe_Latn_NG + 0x9DC74F4D41726162LLU, // hoh_Arab_OM + 0xA1C755534C61746ELLU, // hoi_Latn_US 0xA5C7494E44657661LLU, // hoj_Deva_IN + 0xADC7414F4C61746ELLU, // hol_Latn_AO + 0xB1C753534C61746ELLU, // hom_Latn_SS + 0xB9C743444C61746ELLU, // hoo_Latn_CD + 0xBDC755534C61746ELLU, // hop_Latn_US + 0xC5C754444C61746ELLU, // hor_Latn_TD + 0xCDC750474C61746ELLU, // hot_Latn_PG + 0xD5C749444C61746ELLU, // hov_Latn_ID + 0xD9C7434E48616E69LLU, // how_Hani_CN + 0xE1C7494E44657661LLU, // hoy_Deva_IN + 0xB9E74D4D4D796D72LLU, // hpo_Mymr_MM 0x687248524C61746ELLU, // hr_Latn_HR + 0x8227494E4C61746ELLU, // hra_Latn_IN + 0x8A2750474C61746ELLU, // hrc_Latn_PG + 0x9227564E4C61746ELLU, // hre_Latn_VN + 0xAA2749444C61746ELLU, // hrk_Latn_ID + 0xB227434E4C61746ELLU, // hrm_Latn_CN + 0xBA27564E4C61746ELLU, // hro_Latn_VN + 0xBE2741554C61746ELLU, // hrp_Latn_AU + 0xCE27545253797263LLU, // hrt_Syrc_TR + 0xD227494E4C61746ELLU, // hru_Latn_IN + 0xDA2750474C61746ELLU, // hrw_Latn_PG + 0xDE2742524C61746ELLU, // hrx_Latn_BR + 0xE627495241726162LLU, // hrz_Arab_IR 0x864744454C61746ELLU, // hsb_Latn_DE 0xB647434E48616E73LLU, // hsn_Hans_CN + 0xCA474F4D41726162LLU, // hss_Arab_OM 0x687448544C61746ELLU, // ht_Latn_HT + 0xA26749444C61746ELLU, // hti_Latn_ID + 0xBA67434F4C61746ELLU, // hto_Latn_CO + 0xCA67545A4C61746ELLU, // hts_Latn_TZ + 0xD26749444C61746ELLU, // htu_Latn_ID + 0xDE67545258737578LLU, // htx_Xsux_TR 0x687548554C61746ELLU, // hu_Latn_HU + 0x868750454C61746ELLU, // hub_Latn_PE + 0x8A8742574C61746ELLU, // huc_Latn_BW + 0x8E8749444C61746ELLU, // hud_Latn_ID + 0x92874D584C61746ELLU, // hue_Latn_MX + 0x968750474C61746ELLU, // huf_Latn_PG + 0x9A8750454C61746ELLU, // hug_Latn_PE + 0x9E87434C4C61746ELLU, // huh_Latn_CL + 0xA28750474C61746ELLU, // hui_Latn_PG + 0xAA8749444C61746ELLU, // huk_Latn_ID + 0xAE8750474C61746ELLU, // hul_Latn_PG + 0xB28743444C61746ELLU, // hum_Latn_CD + 0xBE8755534C61746ELLU, // hup_Latn_US 0xC68743414C61746ELLU, // hur_Latn_CA + 0xCA874D584C61746ELLU, // hus_Latn_MX + 0xCE874E5044657661LLU, // hut_Deva_NP + 0xD28750454C61746ELLU, // huu_Latn_PE + 0xD6874D584C61746ELLU, // huv_Latn_MX + 0xDA8749444C61746ELLU, // huw_Latn_ID + 0xDE8750454C61746ELLU, // hux_Latn_PE + 0xE287494C48656272LLU, // huy_Hebr_IL + 0xE68752554379726CLLU, // huz_Cyrl_RU + 0x8AA748544C61746ELLU, // hvc_Latn_HT + 0x92A74D584C61746ELLU, // hve_Latn_MX + 0xAAA74E434C61746ELLU, // hvk_Latn_NC + 0xB6A749444C61746ELLU, // hvn_Latn_ID + 0xD6A74D584C61746ELLU, // hvv_Latn_MX + 0x82C743494C61746ELLU, // hwa_Latn_CI + 0x8AC755534C61746ELLU, // hwc_Latn_US + 0xBAC74E474C61746ELLU, // hwo_Latn_NG 0x6879414D41726D6ELLU, // hy_Armn_AM + 0x8307434D4C61746ELLU, // hya_Latn_CM + 0xDB07414D41726D6ELLU, // hyw_Armn_AM 0x687A4E414C61746ELLU, // hz_Latn_NA + 0xA0084E434C61746ELLU, // iai_Latn_NC + 0xB40850474C61746ELLU, // ian_Latn_PG + 0xC40850474C61746ELLU, // iar_Latn_PG 0x80284D594C61746ELLU, // iba_Latn_MY 0x84284E474C61746ELLU, // ibb_Latn_NG + 0x8C2841554C61746ELLU, // ibd_Latn_AU + 0x90284E474C61746ELLU, // ibe_Latn_NG + 0x982850484C61746ELLU, // ibg_Latn_PH + 0x9C28564E4C61746ELLU, // ibh_Latn_VN + 0xAC2850484C61746ELLU, // ibl_Latn_PH + 0xB0284E474C61746ELLU, // ibm_Latn_NG + 0xB4284E474C61746ELLU, // ibn_Latn_NG + 0xC4284E474C61746ELLU, // ibr_Latn_NG + 0xD02849444C61746ELLU, // ibu_Latn_ID + 0xE0284E474C61746ELLU, // iby_Latn_NG + 0x8048424A4C61746ELLU, // ica_Latn_BJ + 0x9C484E474C61746ELLU, // ich_Latn_NG + 0xC448434F4C61746ELLU, // icr_Latn_CO 0x696449444C61746ELLU, // id_Latn_ID + 0x80684B454C61746ELLU, // ida_Latn_KE + 0x8468494E4C61746ELLU, // idb_Latn_IN + 0x88684E474C61746ELLU, // idc_Latn_NG + 0x8C68424A4C61746ELLU, // idd_Latn_BJ + 0x90684E474C61746ELLU, // ide_Latn_NG + 0xA06850474C61746ELLU, // idi_Latn_PG + 0xC46853534C61746ELLU, // idr_Latn_SS + 0xC8684E474C61746ELLU, // ids_Latn_NG + 0xCC68544C4C61746ELLU, // idt_Latn_TL + 0xD0684E474C61746ELLU, // idu_Latn_NG + 0x696545454C61746ELLU, // ie_Latn_EE + 0x80A850484C61746ELLU, // ifa_Latn_PH + 0x84A850484C61746ELLU, // ifb_Latn_PH 0x90A854474C61746ELLU, // ife_Latn_TG + 0x94A856554C61746ELLU, // iff_Latn_VU + 0xA8A850484C61746ELLU, // ifk_Latn_PH + 0xB0A843474C61746ELLU, // ifm_Latn_CG + 0xD0A850484C61746ELLU, // ifu_Latn_PH + 0xE0A850484C61746ELLU, // ify_Latn_PH 0x69674E474C61746ELLU, // ig_Latn_NG + 0x84C84E474C61746ELLU, // igb_Latn_NG + 0x90C84E474C61746ELLU, // ige_Latn_NG + 0x98C850474C61746ELLU, // igg_Latn_PG + 0xACC84E474C61746ELLU, // igl_Latn_NG + 0xB0C850474C61746ELLU, // igm_Latn_PG + 0xB4C8424F4C61746ELLU, // ign_Latn_BO + 0xB8C850474C61746ELLU, // igo_Latn_PG + 0xD8C84E474C61746ELLU, // igw_Latn_NG + 0x84E849444C61746ELLU, // ihb_Latn_ID + 0xA0E84E474C61746ELLU, // ihi_Latn_NG + 0xBCE849444C61746ELLU, // ihp_Latn_ID + 0xD8E841554C61746ELLU, // ihw_Latn_AU 0x6969434E59696969LLU, // ii_Yiii_CN + 0xB50841554C61746ELLU, // iin_Latn_AU + 0x89284E474C61746ELLU, // ijc_Latn_NG + 0x91284E474C61746ELLU, // ije_Latn_NG + 0xA528424A4C61746ELLU, // ijj_Latn_BJ + 0xB5284E474C61746ELLU, // ijn_Latn_NG + 0xC9284E474C61746ELLU, // ijs_Latn_NG 0x696B55534C61746ELLU, // ik_Latn_US + 0x9D484E474C61746ELLU, // ikh_Latn_NG + 0xA1484E474C61746ELLU, // iki_Latn_NG + 0xA9484E474C61746ELLU, // ikk_Latn_NG + 0xAD484E474C61746ELLU, // ikl_Latn_NG + 0xB9484E474C61746ELLU, // iko_Latn_NG + 0xBD484E474C61746ELLU, // ikp_Latn_NG + 0xC54841554C61746ELLU, // ikr_Latn_AU + 0xCD4843414C61746ELLU, // ikt_Latn_CA + 0xD5484E474C61746ELLU, // ikv_Latn_NG + 0xD9484E474C61746ELLU, // ikw_Latn_NG + 0xDD4855474C61746ELLU, // ikx_Latn_UG + 0xE548545A4C61746ELLU, // ikz_Latn_TZ + 0x816849444C61746ELLU, // ila_Latn_ID + 0x85685A4D4C61746ELLU, // ilb_Latn_ZM + 0x996841554C61746ELLU, // ilg_Latn_AU + 0xA168434E4C61746ELLU, // ili_Latn_CN + 0xA96850484C61746ELLU, // ilk_Latn_PH + 0xB1684D594C61746ELLU, // ilm_Latn_MY 0xB96850484C61746ELLU, // ilo_Latn_PH + 0xBD6850484C61746ELLU, // ilp_Latn_PH + 0xD16849444C61746ELLU, // ilu_Latn_ID + 0xD5684E474C61746ELLU, // ilv_Latn_NG + 0xA18850474C61746ELLU, // imi_Latn_PG + 0xAD8855534C61746ELLU, // iml_Latn_US + 0xB58850474C61746ELLU, // imn_Latn_PG + 0xB98850474C61746ELLU, // imo_Latn_PG + 0xC58849444C61746ELLU, // imr_Latn_ID + 0xC98849544C61746ELLU, // ims_Latn_IT + 0xCD8853534C61746ELLU, // imt_Latn_SS + 0xE18854524C796369LLU, // imy_Lyci_TR 0x696E49444C61746ELLU, // in_Latn_ID + 0x85A8434F4C61746ELLU, // inb_Latn_CO + 0x99A855534C61746ELLU, // ing_Latn_US 0x9DA852554379726CLLU, // inh_Cyrl_RU + 0xA5A8434F4C61746ELLU, // inj_Latn_CO + 0xB5A850484C61746ELLU, // inn_Latn_PH + 0xB9A850474C61746ELLU, // ino_Latn_PG + 0xBDA850454C61746ELLU, // inp_Latn_PE + 0xCDA84D4D4D796D72LLU, // int_Mymr_MM + 0xC5C8455445746869LLU, // ior_Ethi_ET + 0xD1C850474C61746ELLU, // iou_Latn_PG + 0xD9C855534C61746ELLU, // iow_Latn_US + 0xA1E850474C61746ELLU, // ipi_Latn_PG + 0xB9E850474C61746ELLU, // ipo_Latn_PG + 0xD20850454C61746ELLU, // iqu_Latn_PE + 0xDA084E474C61746ELLU, // iqw_Latn_NG + 0x922849444C61746ELLU, // ire_Latn_ID + 0x9E2849444C61746ELLU, // irh_Latn_ID + 0xA2284E474C61746ELLU, // iri_Latn_NG + 0xAA28545A4C61746ELLU, // irk_Latn_TZ + 0xB62842524C61746ELLU, // irn_Latn_BR + 0xD228494E54616D6CLLU, // iru_Taml_IN + 0xDE2849444C61746ELLU, // irx_Latn_ID + 0xE22850484C61746ELLU, // iry_Latn_PH 0x697349534C61746ELLU, // is_Latn_IS + 0x824850474C61746ELLU, // isa_Latn_PG + 0x8A4850454C61746ELLU, // isc_Latn_PE + 0x8E4850484C61746ELLU, // isd_Latn_PH + 0x9E484E474C61746ELLU, // ish_Latn_NG + 0xA2484E474C61746ELLU, // isi_Latn_NG + 0xAA48414641726162LLU, // isk_Arab_AF + 0xB24849444C61746ELLU, // ism_Latn_ID + 0xB648545A4C61746ELLU, // isn_Latn_TZ + 0xBA484E474C61746ELLU, // iso_Latn_NG + 0xCE4848524C61746ELLU, // ist_Latn_HR + 0xD248434D4C61746ELLU, // isu_Latn_CM 0x697449544C61746ELLU, // it_Latn_IT + 0x866850484C61746ELLU, // itb_Latn_PH + 0x8E6849444C61746ELLU, // itd_Latn_ID + 0x9268424F4C61746ELLU, // ite_Latn_BO + 0xA26850484C61746ELLU, // iti_Latn_PH + 0xAA68495448656272LLU, // itk_Hebr_IT + 0xAE6852554379726CLLU, // itl_Cyrl_RU + 0xB2684E474C61746ELLU, // itm_Latn_NG + 0xBA68424F4C61746ELLU, // ito_Latn_BO + 0xC66850474C61746ELLU, // itr_Latn_PG + 0xCA684E474C61746ELLU, // its_Latn_NG + 0xCE6850484C61746ELLU, // itt_Latn_PH + 0xD66850484C61746ELLU, // itv_Latn_PH + 0xDA684E474C61746ELLU, // itw_Latn_NG + 0xDE6849444C61746ELLU, // itx_Latn_ID + 0xE26850484C61746ELLU, // ity_Latn_PH + 0xE66847544C61746ELLU, // itz_Latn_GT 0x6975434143616E73LLU, // iu_Cans_CA + 0xB288434E4C61746ELLU, // ium_Latn_CN + 0x86A850484C61746ELLU, // ivb_Latn_PH + 0xD6A850484C61746ELLU, // ivv_Latn_PH 0x6977494C48656272LLU, // iw_Hebr_IL + 0xAAC850484C61746ELLU, // iwk_Latn_PH + 0xB2C850474C61746ELLU, // iwm_Latn_PG + 0xBAC849444C61746ELLU, // iwo_Latn_ID + 0xCAC850474C61746ELLU, // iws_Latn_PG + 0x8AE84D584C61746ELLU, // ixc_Latn_MX + 0xAEE847544C61746ELLU, // ixl_Latn_GT + 0x83084E474C61746ELLU, // iya_Latn_NG + 0xBB08434D4C61746ELLU, // iyo_Latn_CM + 0xDF0843474C61746ELLU, // iyx_Latn_CG 0x9F2852554C61746ELLU, // izh_Latn_RU + 0xB3284E474C61746ELLU, // izm_Latn_NG + 0xC7284E474C61746ELLU, // izr_Latn_NG + 0xE7284E474C61746ELLU, // izz_Latn_NG 0x6A614A504A70616ELLU, // ja_Jpan_JP + 0x800942524C61746ELLU, // jaa_Latn_BR + 0x84094E474C61746ELLU, // jab_Latn_NG + 0x880947544C61746ELLU, // jac_Latn_GT + 0x8C09474E41726162LLU, // jad_Arab_GN + 0x900950474C61746ELLU, // jae_Latn_PG + 0x94094E474C61746ELLU, // jaf_Latn_NG + 0x9C094D594C61746ELLU, // jah_Latn_MY + 0xA40953424C61746ELLU, // jaj_Latn_SB + 0xA8094D594C61746ELLU, // jak_Latn_MY + 0xAC0949444C61746ELLU, // jal_Latn_ID 0xB0094A4D4C61746ELLU, // jam_Latn_JM + 0xB40941554C61746ELLU, // jan_Latn_AU + 0xB80941554C61746ELLU, // jao_Latn_AU + 0xC00949444C61746ELLU, // jaq_Latn_ID + 0xC8094E434C61746ELLU, // jas_Latn_NC + 0xCC09414641726162LLU, // jat_Arab_AF + 0xD00949444C61746ELLU, // jau_Latn_ID + 0xDC0949444C61746ELLU, // jax_Latn_ID + 0xE00941554C61746ELLU, // jay_Latn_AU + 0xE4094E434C61746ELLU, // jaz_Latn_NC + 0x9029494C48656272LLU, // jbe_Hebr_IL + 0xA02941554C61746ELLU, // jbi_Latn_AU + 0xA42949444C61746ELLU, // jbj_Latn_ID + 0xA82950474C61746ELLU, // jbk_Latn_PG + 0xB0294E474C61746ELLU, // jbm_Latn_NG + 0xB4294C5941726162LLU, // jbn_Arab_LY + 0xC42949444C61746ELLU, // jbr_Latn_ID + 0xCC2942524C61746ELLU, // jbt_Latn_BR + 0xD029434D4C61746ELLU, // jbu_Latn_CM + 0xD82941554C61746ELLU, // jbw_Latn_AU + 0xCC4955414379726CLLU, // jct_Cyrl_UA + 0x8069494E54696274LLU, // jda_Tibt_IN + 0x9869504B41726162LLU, // jdg_Arab_PK + 0xCC6952554379726CLLU, // jdt_Cyrl_RU + 0x848950454C61746ELLU, // jeb_Latn_PE + 0x90894E5044657661LLU, // jee_Deva_NP + 0x9C89564E4C61746ELLU, // jeh_Latn_VN + 0xA08949444C61746ELLU, // jei_Latn_ID + 0xA88943494C61746ELLU, // jek_Latn_CI + 0xAC8949444C61746ELLU, // jel_Latn_ID + 0xB4894E474C61746ELLU, // jen_Latn_NG + 0xC4894E474C61746ELLU, // jer_Latn_NG + 0xCC8950474C61746ELLU, // jet_Latn_PG + 0xD08954444C61746ELLU, // jeu_Latn_TD + 0x84C943444C61746ELLU, // jgb_Latn_CD + 0x90C9474547656F72LLU, // jge_Geor_GE + 0xA8C94E474C61746ELLU, // jgk_Latn_NG 0xB8C9434D4C61746ELLU, // jgo_Latn_CM + 0xA0E94D594C61746ELLU, // jhi_Latn_MY + 0x6A69554148656272LLU, // ji_Hebr_UA + 0x8109434D4C61746ELLU, // jia_Latn_CM + 0x85094E474C61746ELLU, // jib_Latn_NG + 0x8909484E4C61746ELLU, // jic_Latn_HN + 0x8D094E474C61746ELLU, // jid_Latn_NG + 0x91094E474C61746ELLU, // jie_Latn_NG + 0x990941554C61746ELLU, // jig_Latn_AU + 0xAD0950474C61746ELLU, // jil_Latn_PG + 0xB109434D4C61746ELLU, // jim_Latn_CM + 0xCD09545A4C61746ELLU, // jit_Latn_TZ + 0xD109434E4C61746ELLU, // jiu_Latn_CN + 0xD50945434C61746ELLU, // jiv_Latn_EC + 0xE109434E4C61746ELLU, // jiy_Latn_CN + 0x91294B5248616E67LLU, // jje_Hang_KR + 0xC5294E474C61746ELLU, // jjr_Latn_NG + 0x814949444C61746ELLU, // jka_Latn_ID + 0xB1494D4D4D796D72LLU, // jkm_Mymr_MM + 0xB94950474C61746ELLU, // jko_Latn_PG + 0xD1494E474C61746ELLU, // jku_Latn_NG + 0x916953444C61746ELLU, // jle_Latn_SD + 0x818950474C61746ELLU, // jma_Latn_PG + 0x85894E474C61746ELLU, // jmb_Latn_NG 0x8989545A4C61746ELLU, // jmc_Latn_TZ + 0x8D8949444C61746ELLU, // jmd_Latn_ID + 0xA1894E474C61746ELLU, // jmi_Latn_NG 0xAD894E5044657661LLU, // jml_Deva_NP + 0xB5894D4D4C61746ELLU, // jmn_Latn_MM + 0xC58947484C61746ELLU, // jmr_Latn_GH + 0xC9894E474C61746ELLU, // jms_Latn_NG + 0xD98950474C61746ELLU, // jmw_Latn_PG + 0xDD894D584C61746ELLU, // jmx_Latn_MX + 0x81A9494E54616B72LLU, // jna_Takr_IN + 0x8DA9504B41726162LLU, // jnd_Arab_PK + 0x99A941554C61746ELLU, // jng_Latn_AU + 0xA1A94E474C61746ELLU, // jni_Latn_NG + 0xA5A945544C61746ELLU, // jnj_Latn_ET + 0xADA9494E44657661LLU, // jnl_Deva_IN + 0xC9A9494E44657661LLU, // jns_Deva_IN + 0x85C943444C61746ELLU, // job_Latn_CD + 0x8DC943494C61746ELLU, // jod_Latn_CI + 0x99C9504B41726162LLU, // jog_Arab_PK + 0xC5C9424F4C61746ELLU, // jor_Latn_BO + 0xD9C94D4C4C61746ELLU, // jow_Latn_ML + 0x81E9505348656272LLU, // jpa_Hebr_PS + 0xC5E9494C48656272LLU, // jpr_Hebr_IL + 0xC60950454C61746ELLU, // jqr_Latn_PE + 0x8229564E4C61746ELLU, // jra_Latn_VN + 0x8629494C48656272LLU, // jrb_Hebr_IL + 0xC6294E474C61746ELLU, // jrr_Latn_NG + 0xCE294E474C61746ELLU, // jrt_Latn_NG + 0xD22956454C61746ELLU, // jru_Latn_VE + 0x828942524C61746ELLU, // jua_Latn_BR + 0x86894E474C61746ELLU, // jub_Latn_NG + 0x8E8943494C61746ELLU, // jud_Latn_CI + 0x9E894E474C61746ELLU, // juh_Latn_NG + 0xA28941554C61746ELLU, // jui_Latn_AU + 0xAA894E474C61746ELLU, // juk_Latn_NG + 0xAE894E5044657661LLU, // jul_Deva_NP + 0xB28953444C61746ELLU, // jum_Latn_SD + 0xB689494E4F727961LLU, // jun_Orya_IN + 0xBA894E474C61746ELLU, // juo_Latn_NG + 0xBE8942524C61746ELLU, // jup_Latn_BR + 0xC68942524C61746ELLU, // jur_Latn_BR 0xCE89444B4C61746ELLU, // jut_Latn_DK + 0xD2894E474C61746ELLU, // juu_Latn_NG + 0xDA894E474C61746ELLU, // juw_Latn_NG + 0xE289494E4F727961LLU, // juy_Orya_IN 0x6A7649444C61746ELLU, // jv_Latn_ID + 0x8EA949444C61746ELLU, // jvd_Latn_ID + 0xB6A953524C61746ELLU, // jvn_Latn_SR 0x6A7749444C61746ELLU, // jw_Latn_ID + 0xA2C947484C61746ELLU, // jwi_Latn_GH + 0x8309434E54696274LLU, // jya_Tibt_CN + 0x9309494C48656272LLU, // jye_Hebr_IL + 0xE30954444C61746ELLU, // jyy_Latn_TD 0x6B61474547656F72LLU, // ka_Geor_GE 0x800A555A4379726CLLU, // kaa_Cyrl_UZ 0x840A445A4C61746ELLU, // kab_Latn_DZ 0x880A4D4D4C61746ELLU, // kac_Latn_MM + 0x8C0A4E474C61746ELLU, // kad_Latn_NG + 0x980A4D594C61746ELLU, // kag_Latn_MY + 0x9C0A43464C61746ELLU, // kah_Latn_CF + 0xA00A4E474C61746ELLU, // kai_Latn_NG 0xA40A4E474C61746ELLU, // kaj_Latn_NG + 0xA80A50484C61746ELLU, // kak_Latn_PH 0xB00A4B454C61746ELLU, // kam_Latn_KE 0xB80A4D4C4C61746ELLU, // kao_Latn_ML + 0xBC0A52554379726CLLU, // kap_Cyrl_RU + 0xC00A50454C61746ELLU, // kaq_Latn_PE + 0xD40A42524C61746ELLU, // kav_Latn_BR 0xD80A49444B617769LLU, // kaw_Kawi_ID + 0xDC0A49444C61746ELLU, // kax_Latn_ID + 0xE00A42524C61746ELLU, // kay_Latn_BR + 0x802A41554C61746ELLU, // kba_Latn_AU + 0x842A42524C61746ELLU, // kbb_Latn_BR + 0x882A42524C61746ELLU, // kbc_Latn_BR 0x8C2A52554379726CLLU, // kbd_Cyrl_RU + 0x902A41554C61746ELLU, // kbe_Latn_AU + 0x982A494E54696274LLU, // kbg_Tibt_IN + 0x9C2A434F4C61746ELLU, // kbh_Latn_CO + 0xA02A49444C61746ELLU, // kbi_Latn_ID + 0xA42A43444C61746ELLU, // kbj_Latn_CD + 0xA82A50474C61746ELLU, // kbk_Latn_PG + 0xAC2A54444C61746ELLU, // kbl_Latn_TD + 0xB02A50474C61746ELLU, // kbm_Latn_PG + 0xB42A43464C61746ELLU, // kbn_Latn_CF + 0xB82A53534C61746ELLU, // kbo_Latn_SS + 0xBC2A54474C61746ELLU, // kbp_Latn_TG + 0xC02A50474C61746ELLU, // kbq_Latn_PG + 0xC42A45544C61746ELLU, // kbr_Latn_ET + 0xC82A47414C61746ELLU, // kbs_Latn_GA + 0xCC2A50474C61746ELLU, // kbt_Latn_PG + 0xD02A504B41726162LLU, // kbu_Arab_PK + 0xD42A49444C61746ELLU, // kbv_Latn_ID + 0xD82A50474C61746ELLU, // kbw_Latn_PG + 0xDC2A50474C61746ELLU, // kbx_Latn_PG 0xE02A4E4541726162LLU, // kby_Arab_NE + 0xE42A4E474C61746ELLU, // kbz_Latn_NG + 0x804A52554379726CLLU, // kca_Cyrl_RU + 0x844A50474C61746ELLU, // kcb_Latn_PG + 0x884A4E474C61746ELLU, // kcc_Latn_NG + 0x8C4A49444C61746ELLU, // kcd_Latn_ID + 0x904A4E474C61746ELLU, // kce_Latn_NG + 0x944A4E474C61746ELLU, // kcf_Latn_NG 0x984A4E474C61746ELLU, // kcg_Latn_NG + 0x9C4A4E474C61746ELLU, // kch_Latn_NG + 0xA04A4E474C61746ELLU, // kci_Latn_NG + 0xA44A47574C61746ELLU, // kcj_Latn_GW 0xA84A5A574C61746ELLU, // kck_Latn_ZW + 0xAC4A50474C61746ELLU, // kcl_Latn_PG + 0xB04A43464C61746ELLU, // kcm_Latn_CF + 0xB44A55474C61746ELLU, // kcn_Latn_UG + 0xB84A50474C61746ELLU, // kco_Latn_PG + 0xBC4A53444C61746ELLU, // kcp_Latn_SD + 0xC04A4E474C61746ELLU, // kcq_Latn_NG + 0xC84A4E474C61746ELLU, // kcs_Latn_NG + 0xCC4A50474C61746ELLU, // kct_Latn_PG + 0xD04A545A4C61746ELLU, // kcu_Latn_TZ + 0xD44A43444C61746ELLU, // kcv_Latn_CD + 0xD84A43444C61746ELLU, // kcw_Latn_CD + 0xE04A445A41726162LLU, // kcy_Arab_DZ + 0xE44A545A4C61746ELLU, // kcz_Latn_TZ + 0x806A41554C61746ELLU, // kda_Latn_AU + 0x886A545A4C61746ELLU, // kdc_Latn_TZ + 0x8C6A41554C61746ELLU, // kdd_Latn_AU 0x906A545A4C61746ELLU, // kde_Latn_TZ + 0x946A50474C61746ELLU, // kdf_Latn_PG + 0x986A43444C61746ELLU, // kdg_Latn_CD 0x9C6A54474C61746ELLU, // kdh_Latn_TG + 0xA06A55474C61746ELLU, // kdi_Latn_UG + 0xA46A55474C61746ELLU, // kdj_Latn_UG + 0xA86A4E434C61746ELLU, // kdk_Latn_NC + 0xAC6A4E474C61746ELLU, // kdl_Latn_NG + 0xB06A4E474C61746ELLU, // kdm_Latn_NG + 0xB46A5A574C61746ELLU, // kdn_Latn_ZW + 0xBC6A4E474C61746ELLU, // kdp_Latn_NG + 0xC06A494E42656E67LLU, // kdq_Beng_IN + 0xC46A4C544C61746ELLU, // kdr_Latn_LT 0xCC6A544854686169LLU, // kdt_Thai_TH + 0xD86A49444C61746ELLU, // kdw_Latn_ID + 0xDC6A4E474C61746ELLU, // kdx_Latn_NG + 0xE06A49444C61746ELLU, // kdy_Latn_ID + 0xE46A434D4C61746ELLU, // kdz_Latn_CM 0x808A43564C61746ELLU, // kea_Latn_CV + 0x848A47414C61746ELLU, // keb_Latn_GA + 0x888A53444C61746ELLU, // kec_Latn_SD + 0x8C8A545A4C61746ELLU, // ked_Latn_TZ + 0x908A55534C61746ELLU, // kee_Latn_US + 0x948A54474C61746ELLU, // kef_Latn_TG + 0x988A53444C61746ELLU, // keg_Latn_SD + 0x9C8A50474C61746ELLU, // keh_Latn_PG + 0xA08A49444C61746ELLU, // kei_Latn_ID + 0xA88A47544C61746ELLU, // kek_Latn_GT + 0xAC8A43444C61746ELLU, // kel_Latn_CD + 0xB08A544C4C61746ELLU, // kem_Latn_TL 0xB48A434D4C61746ELLU, // ken_Latn_CM + 0xB88A55474C61746ELLU, // keo_Latn_UG + 0xC48A54444C61746ELLU, // ker_Latn_TD + 0xC88A4E474C61746ELLU, // kes_Latn_NG + 0xCC8A52554379726CLLU, // ket_Cyrl_RU + 0xD08A54474C61746ELLU, // keu_Latn_TG + 0xD48A494E4D6C796DLLU, // kev_Mlym_IN + 0xD88A50474C61746ELLU, // kew_Latn_PG + 0xDC8A494E44657661LLU, // kex_Deva_IN + 0xE08A494E54656C75LLU, // key_Telu_IN + 0xE48A4E474C61746ELLU, // kez_Latn_NG + 0x80AA494E4B6E6461LLU, // kfa_Knda_IN + 0x84AA494E44657661LLU, // kfb_Deva_IN + 0x88AA494E54656C75LLU, // kfc_Telu_IN + 0x8CAA494E4B6E6461LLU, // kfd_Knda_IN + 0x90AA494E54616D6CLLU, // kfe_Taml_IN + 0x94AA494E4C61746ELLU, // kff_Latn_IN + 0x98AA494E4B6E6461LLU, // kfg_Knda_IN + 0x9CAA494E4D6C796DLLU, // kfh_Mlym_IN + 0xA0AA494E54616D6CLLU, // kfi_Taml_IN + 0xA8AA494E44657661LLU, // kfk_Deva_IN + 0xACAA434D4C61746ELLU, // kfl_Latn_CM + 0xB0AA495241726162LLU, // kfm_Arab_IR + 0xB4AA434D4C61746ELLU, // kfn_Latn_CM 0xB8AA43494C61746ELLU, // kfo_Latn_CI + 0xBCAA494E44657661LLU, // kfp_Deva_IN + 0xC0AA494E44657661LLU, // kfq_Deva_IN 0xC4AA494E44657661LLU, // kfr_Deva_IN + 0xC8AA494E44657661LLU, // kfs_Deva_IN + 0xD0AA494E44657661LLU, // kfu_Deva_IN + 0xD4AA494E4C61746ELLU, // kfv_Latn_IN + 0xD8AA494E4C61746ELLU, // kfw_Latn_IN + 0xDCAA494E44657661LLU, // kfx_Deva_IN 0xE0AA494E44657661LLU, // kfy_Deva_IN + 0xE4AA42464C61746ELLU, // kfz_Latn_BF 0x6B6743444C61746ELLU, // kg_Latn_CD + 0x80CA43494C61746ELLU, // kga_Latn_CI + 0x84CA49444C61746ELLU, // kgb_Latn_ID 0x90CA49444C61746ELLU, // kge_Latn_ID + 0x94CA50474C61746ELLU, // kgf_Latn_PG + 0xA4CA4E5044657661LLU, // kgj_Deva_NP + 0xA8CA42524C61746ELLU, // kgk_Latn_BR + 0xACCA41554C61746ELLU, // kgl_Latn_AU + 0xB8CA53444C61746ELLU, // kgo_Latn_SD 0xBCCA42524C61746ELLU, // kgp_Latn_BR + 0xC0CA49444C61746ELLU, // kgq_Latn_ID + 0xC4CA49444C61746ELLU, // kgr_Latn_ID + 0xC8CA41554C61746ELLU, // kgs_Latn_AU + 0xCCCA4E474C61746ELLU, // kgt_Latn_NG + 0xD0CA50474C61746ELLU, // kgu_Latn_PG + 0xD4CA49444C61746ELLU, // kgv_Latn_ID + 0xD8CA49444C61746ELLU, // kgw_Latn_ID + 0xDCCA49444C61746ELLU, // kgx_Latn_ID + 0xE0CA4E5044657661LLU, // kgy_Deva_NP 0x80EA494E4C61746ELLU, // kha_Latn_IN 0x84EA434E54616C75LLU, // khb_Talu_CN + 0x88EA49444C61746ELLU, // khc_Latn_ID + 0x8CEA49444C61746ELLU, // khd_Latn_ID + 0x90EA49444C61746ELLU, // khe_Latn_ID + 0x94EA4C4154686169LLU, // khf_Thai_LA + 0x98EA434E54696274LLU, // khg_Tibt_CN + 0x9CEA49444C61746ELLU, // khh_Latn_ID + 0xA4EA4E474C61746ELLU, // khj_Latn_NG + 0xACEA50474C61746ELLU, // khl_Latn_PG 0xB4EA494E44657661LLU, // khn_Deva_IN + 0xB8EA495242726168LLU, // kho_Brah_IR + 0xBCEA49444C61746ELLU, // khp_Latn_ID 0xC0EA4D4C4C61746ELLU, // khq_Latn_ML + 0xC4EA494E4C61746ELLU, // khr_Latn_IN + 0xC8EA50474C61746ELLU, // khs_Latn_PG 0xCCEA494E4D796D72LLU, // kht_Mymr_IN + 0xD0EA414F4C61746ELLU, // khu_Latn_AO + 0xD4EA52554379726CLLU, // khv_Cyrl_RU 0xD8EA504B41726162LLU, // khw_Arab_PK + 0xDCEA43444C61746ELLU, // khx_Latn_CD + 0xE0EA43444C61746ELLU, // khy_Latn_CD + 0xE4EA50474C61746ELLU, // khz_Latn_PG 0x6B694B454C61746ELLU, // ki_Latn_KE + 0x810A54444C61746ELLU, // kia_Latn_TD + 0x850A53444C61746ELLU, // kib_Latn_SD + 0x890A55534C61746ELLU, // kic_Latn_US + 0x8D0A434D4C61746ELLU, // kid_Latn_CM + 0x910A54444C61746ELLU, // kie_Latn_TD + 0x950A4E5044657661LLU, // kif_Deva_NP + 0x990A49444C61746ELLU, // kig_Latn_ID + 0x9D0A50474C61746ELLU, // kih_Latn_PG + 0xA50A50474C61746ELLU, // kij_Latn_PG + 0xAD0A4E474C61746ELLU, // kil_Latn_NG + 0xB10A52554379726CLLU, // kim_Cyrl_RU + 0xB90A55534C61746ELLU, // kio_Latn_US + 0xBD0A4E5044657661LLU, // kip_Deva_NP + 0xC10A49444C61746ELLU, // kiq_Latn_ID + 0xC90A50474C61746ELLU, // kis_Latn_PG + 0xCD0A50474C61746ELLU, // kit_Latn_PG 0xD10A54524C61746ELLU, // kiu_Latn_TR + 0xD50A545A4C61746ELLU, // kiv_Latn_TZ + 0xD90A50474C61746ELLU, // kiw_Latn_PG + 0xDD0A494E4C61746ELLU, // kix_Latn_IN + 0xE10A49444C61746ELLU, // kiy_Latn_ID + 0xE50A545A4C61746ELLU, // kiz_Latn_TZ 0x6B6A4E414C61746ELLU, // kj_Latn_NA + 0x812A49444C61746ELLU, // kja_Latn_ID + 0x852A47544C61746ELLU, // kjb_Latn_GT + 0x892A49444C61746ELLU, // kjc_Latn_ID + 0x8D2A50474C61746ELLU, // kjd_Latn_PG + 0x912A49444C61746ELLU, // kje_Latn_ID 0x992A4C414C616F6FLLU, // kjg_Laoo_LA + 0x9D2A52554379726CLLU, // kjh_Cyrl_RU + 0xA12A53424C61746ELLU, // kji_Latn_SB + 0xA52A415A4C61746ELLU, // kjj_Latn_AZ + 0xA92A49444C61746ELLU, // kjk_Latn_ID + 0xAD2A4E5044657661LLU, // kjl_Deva_NP + 0xB12A564E4C61746ELLU, // kjm_Latn_VN + 0xB52A41554C61746ELLU, // kjn_Latn_AU + 0xB92A494E44657661LLU, // kjo_Deva_IN + 0xBD2A4D4D4D796D72LLU, // kjp_Mymr_MM + 0xC12A55534C61746ELLU, // kjq_Latn_US + 0xC52A49444C61746ELLU, // kjr_Latn_ID + 0xC92A50474C61746ELLU, // kjs_Latn_PG + 0xCD2A544854686169LLU, // kjt_Thai_TH + 0xD12A55534C61746ELLU, // kju_Latn_US + 0xDD2A50474C61746ELLU, // kjx_Latn_PG + 0xE12A50474C61746ELLU, // kjy_Latn_PG + 0xE52A425454696274LLU, // kjz_Tibt_BT 0x6B6B434E41726162LLU, // kk_Arab_CN 0x6B6B4B5A4379726CLLU, // kk_Cyrl_KZ + 0x814A4E474C61746ELLU, // kka_Latn_NG + 0x854A49444C61746ELLU, // kkb_Latn_ID + 0x894A50474C61746ELLU, // kkc_Latn_PG + 0x8D4A4E474C61746ELLU, // kkd_Latn_NG + 0x914A474E4C61746ELLU, // kke_Latn_GN + 0x954A494E54696274LLU, // kkf_Tibt_IN + 0x994A50484C61746ELLU, // kkg_Latn_PH + 0x9D4A4D4D4C616E61LLU, // kkh_Lana_MM + 0xA14A545A4C61746ELLU, // kki_Latn_TZ 0xA54A434D4C61746ELLU, // kkj_Latn_CM + 0xA94A53424C61746ELLU, // kkk_Latn_SB + 0xAD4A49444C61746ELLU, // kkl_Latn_ID + 0xB14A4E474C61746ELLU, // kkm_Latn_NG + 0xB94A53444C61746ELLU, // kko_Latn_SD + 0xBD4A41554C61746ELLU, // kkp_Latn_AU + 0xC14A43444C61746ELLU, // kkq_Latn_CD + 0xC54A4E474C61746ELLU, // kkr_Latn_NG + 0xC94A4E474C61746ELLU, // kks_Latn_NG + 0xCD4A4E5044657661LLU, // kkt_Deva_NP + 0xD14A4E474C61746ELLU, // kku_Latn_NG + 0xD54A49444C61746ELLU, // kkv_Latn_ID + 0xD94A43474C61746ELLU, // kkw_Latn_CG + 0xDD4A49444C61746ELLU, // kkx_Latn_ID + 0xE14A41554C61746ELLU, // kky_Latn_AU + 0xE54A43414C61746ELLU, // kkz_Latn_CA 0x6B6C474C4C61746ELLU, // kl_Latn_GL + 0x816A55534C61746ELLU, // kla_Latn_US + 0x856A4D584C61746ELLU, // klb_Latn_MX + 0x896A434D4C61746ELLU, // klc_Latn_CM + 0x8D6A41554C61746ELLU, // kld_Latn_AU + 0x916A4E5044657661LLU, // kle_Deva_NP + 0x956A54444C61746ELLU, // klf_Latn_TD + 0x996A50484C61746ELLU, // klg_Latn_PH + 0x9D6A50474C61746ELLU, // klh_Latn_PG + 0xA16A49444C61746ELLU, // kli_Latn_ID + 0xA56A495241726162LLU, // klj_Arab_IR + 0xA96A4E474C61746ELLU, // klk_Latn_NG + 0xAD6A50484C61746ELLU, // kll_Latn_PH + 0xB16A50474C61746ELLU, // klm_Latn_PG 0xB56A4B454C61746ELLU, // kln_Latn_KE + 0xB96A4E474C61746ELLU, // klo_Latn_NG + 0xBD6A50474C61746ELLU, // klp_Latn_PG + 0xC16A50474C61746ELLU, // klq_Latn_PG + 0xC56A4E5044657661LLU, // klr_Deva_NP + 0xC96A504B4C61746ELLU, // kls_Latn_PK + 0xCD6A50474C61746ELLU, // klt_Latn_PG + 0xD16A4C524C61746ELLU, // klu_Latn_LR + 0xD56A56554C61746ELLU, // klv_Latn_VU + 0xD96A49444C61746ELLU, // klw_Latn_ID + 0xDD6A50474C61746ELLU, // klx_Latn_PG + 0xE16A49444C61746ELLU, // kly_Latn_ID + 0xE56A49444C61746ELLU, // klz_Latn_ID 0x6B6D4B484B686D72LLU, // km_Khmr_KH + 0x818A47484C61746ELLU, // kma_Latn_GH 0x858A414F4C61746ELLU, // kmb_Latn_AO + 0x898A434E4C61746ELLU, // kmc_Latn_CN + 0x8D8A50484C61746ELLU, // kmd_Latn_PH + 0x918A434D4C61746ELLU, // kme_Latn_CM + 0x958A50474C61746ELLU, // kmf_Latn_PG + 0x998A50474C61746ELLU, // kmg_Latn_PG + 0x9D8A50474C61746ELLU, // kmh_Latn_PG + 0xA18A4E474C61746ELLU, // kmi_Latn_NG + 0xA58A494E44657661LLU, // kmj_Deva_IN + 0xA98A50484C61746ELLU, // kmk_Latn_PH + 0xAD8A50484C61746ELLU, // kml_Latn_PH + 0xB18A494E4C61746ELLU, // kmm_Latn_IN + 0xB58A50474C61746ELLU, // kmn_Latn_PG + 0xB98A50474C61746ELLU, // kmo_Latn_PG + 0xBD8A434D4C61746ELLU, // kmp_Latn_CM + 0xC18A45544C61746ELLU, // kmq_Latn_ET + 0xC98A50474C61746ELLU, // kms_Latn_PG + 0xCD8A49444C61746ELLU, // kmt_Latn_ID + 0xD18A50474C61746ELLU, // kmu_Latn_PG + 0xD58A42524C61746ELLU, // kmv_Latn_BR + 0xD98A43444C61746ELLU, // kmw_Latn_CD + 0xDD8A50474C61746ELLU, // kmx_Latn_PG + 0xE18A4E474C61746ELLU, // kmy_Latn_NG + 0xE58A495241726162LLU, // kmz_Arab_IR 0x6B6E494E4B6E6461LLU, // kn_Knda_IN + 0x81AA4E474C61746ELLU, // kna_Latn_NG + 0x85AA50484C61746ELLU, // knb_Latn_PH + 0x8DAA49444C61746ELLU, // knd_Latn_ID + 0x91AA50484C61746ELLU, // kne_Latn_PH 0x95AA47574C61746ELLU, // knf_Latn_GW + 0xA1AA4E474C61746ELLU, // kni_Latn_NG + 0xA5AA47544C61746ELLU, // knj_Latn_GT + 0xA9AA534C4C61746ELLU, // knk_Latn_SL + 0xADAA49444C61746ELLU, // knl_Latn_ID + 0xB1AA42524C61746ELLU, // knm_Latn_BR + 0xB5AA494E44657661LLU, // knn_Deva_IN + 0xB9AA534C4C61746ELLU, // kno_Latn_SL + 0xBDAA434D4C61746ELLU, // knp_Latn_CM + 0xC1AA4D594C61746ELLU, // knq_Latn_MY + 0xC5AA50474C61746ELLU, // knr_Latn_PG + 0xC9AA4D594C61746ELLU, // kns_Latn_MY + 0xCDAA42524C61746ELLU, // knt_Latn_BR + 0xD1AA474E4C61746ELLU, // knu_Latn_GN + 0xD5AA50474C61746ELLU, // knv_Latn_PG + 0xD9AA4E414C61746ELLU, // knw_Latn_NA + 0xDDAA49444C61746ELLU, // knx_Latn_ID + 0xE1AA43444C61746ELLU, // kny_Latn_CD + 0xE5AA42464C61746ELLU, // knz_Latn_BF 0x6B6F4B524B6F7265LLU, // ko_Kore_KR + 0x81CA50474C61746ELLU, // koa_Latn_PG + 0x89CA4E474C61746ELLU, // koc_Latn_NG + 0x8DCA49444C61746ELLU, // kod_Latn_ID + 0x91CA53534C61746ELLU, // koe_Latn_SS + 0x95CA4E474C61746ELLU, // kof_Latn_NG + 0x99CA434F4C61746ELLU, // kog_Latn_CO + 0x9DCA43474C61746ELLU, // koh_Latn_CG 0xA1CA52554379726CLLU, // koi_Cyrl_RU 0xA9CA494E44657661LLU, // kok_Deva_IN + 0xADCA50474C61746ELLU, // kol_Latn_PG + 0xB9CA55474C61746ELLU, // koo_Latn_UG + 0xBDCA50474C61746ELLU, // kop_Latn_PG + 0xC1CA47414C61746ELLU, // koq_Latn_GA 0xC9CA464D4C61746ELLU, // kos_Latn_FM + 0xCDCA434D4C61746ELLU, // kot_Latn_CM + 0xD1CA54444C61746ELLU, // kou_Latn_TD + 0xD5CA4E474C61746ELLU, // kov_Latn_NG + 0xD9CA4E474C61746ELLU, // kow_Latn_NG + 0xE1CA55534C61746ELLU, // koy_Latn_US + 0xE5CA50474C61746ELLU, // koz_Latn_PG + 0x81EA4E474C61746ELLU, // kpa_Latn_NG + 0x89EA434F4C61746ELLU, // kpc_Latn_CO + 0x8DEA49444C61746ELLU, // kpd_Latn_ID 0x91EA4C524C61746ELLU, // kpe_Latn_LR + 0x95EA50474C61746ELLU, // kpf_Latn_PG + 0x99EA464D4C61746ELLU, // kpg_Latn_FM + 0x9DEA47484C61746ELLU, // kph_Latn_GH + 0xA1EA49444C61746ELLU, // kpi_Latn_ID + 0xA5EA42524C61746ELLU, // kpj_Latn_BR + 0xA9EA4E474C61746ELLU, // kpk_Latn_NG + 0xADEA43444C61746ELLU, // kpl_Latn_CD + 0xB1EA564E4C61746ELLU, // kpm_Latn_VN + 0xB5EA42524C61746ELLU, // kpn_Latn_BR + 0xB9EA54474C61746ELLU, // kpo_Latn_TG + 0xC1EA49444C61746ELLU, // kpq_Latn_ID + 0xC5EA50474C61746ELLU, // kpr_Latn_PG + 0xC9EA49444C61746ELLU, // kps_Latn_ID + 0xCDEA52554379726CLLU, // kpt_Cyrl_RU + 0xD1EA49444C61746ELLU, // kpu_Latn_ID + 0xD9EA50474C61746ELLU, // kpw_Latn_PG + 0xDDEA50474C61746ELLU, // kpx_Latn_PG + 0xE1EA52554379726CLLU, // kpy_Cyrl_RU + 0xE5EA55474C61746ELLU, // kpz_Latn_UG + 0x820A50474C61746ELLU, // kqa_Latn_PG + 0x860A50474C61746ELLU, // kqb_Latn_PG + 0x8A0A50474C61746ELLU, // kqc_Latn_PG + 0x8E0A495153797263LLU, // kqd_Syrc_IQ + 0x920A50484C61746ELLU, // kqe_Latn_PH + 0x960A50474C61746ELLU, // kqf_Latn_PG + 0x9A0A42464C61746ELLU, // kqg_Latn_BF + 0x9E0A545A4C61746ELLU, // kqh_Latn_TZ + 0xA20A50474C61746ELLU, // kqi_Latn_PG + 0xA60A50474C61746ELLU, // kqj_Latn_PG + 0xAA0A424A4C61746ELLU, // kqk_Latn_BJ + 0xAE0A50474C61746ELLU, // kql_Latn_PG + 0xB20A43494C61746ELLU, // kqm_Latn_CI + 0xB60A5A4D4C61746ELLU, // kqn_Latn_ZM + 0xBA0A4C524C61746ELLU, // kqo_Latn_LR + 0xBE0A54444C61746ELLU, // kqp_Latn_TD + 0xC20A42524C61746ELLU, // kqq_Latn_BR + 0xC60A4D594C61746ELLU, // kqr_Latn_MY + 0xCA0A474E4C61746ELLU, // kqs_Latn_GN + 0xCE0A4D594C61746ELLU, // kqt_Latn_MY + 0xD20A5A414C61746ELLU, // kqu_Latn_ZA + 0xD60A49444C61746ELLU, // kqv_Latn_ID + 0xDA0A50474C61746ELLU, // kqw_Latn_PG + 0xDE0A434D4C61746ELLU, // kqx_Latn_CM + 0xE20A455445746869LLU, // kqy_Ethi_ET + 0xE60A5A414C61746ELLU, // kqz_Latn_ZA + 0x6B724E474C61746ELLU, // kr_Latn_NG + 0x822A4E5044657661LLU, // kra_Deva_NP + 0x862A55534C61746ELLU, // krb_Latn_US 0x8A2A52554379726CLLU, // krc_Cyrl_RU + 0x8E2A544C4C61746ELLU, // krd_Latn_TL + 0x922A42524C61746ELLU, // kre_Latn_BR + 0x962A56554C61746ELLU, // krf_Latn_VU + 0x9E2A4E474C61746ELLU, // krh_Latn_NG 0xA22A534C4C61746ELLU, // kri_Latn_SL 0xA62A50484C61746ELLU, // krj_Latn_PH + 0xAA2A52554379726CLLU, // krk_Cyrl_RU 0xAE2A52554C61746ELLU, // krl_Latn_RU + 0xB62A4C524C61746ELLU, // krn_Latn_LR + 0xBE2A4E474C61746ELLU, // krp_Latn_NG + 0xC62A4B484B686D72LLU, // krr_Khmr_KH + 0xCA2A53534C61746ELLU, // krs_Latn_SS + 0xCE2A4E454C61746ELLU, // krt_Latn_NE 0xD22A494E44657661LLU, // kru_Deva_IN + 0xD62A4B484B686D72LLU, // krv_Khmr_KH + 0xDA2A4C524C61746ELLU, // krw_Latn_LR + 0xDE2A534E4C61746ELLU, // krx_Latn_SN + 0xE22A415A4C61746ELLU, // kry_Latn_AZ + 0xE62A49444C61746ELLU, // krz_Latn_ID 0x6B73494E41726162LLU, // ks_Arab_IN 0x864A545A4C61746ELLU, // ksb_Latn_TZ + 0x8A4A50484C61746ELLU, // ksc_Latn_PH + 0x8E4A50474C61746ELLU, // ksd_Latn_PG + 0x924A50474C61746ELLU, // kse_Latn_PG 0x964A434D4C61746ELLU, // ksf_Latn_CM + 0x9A4A53424C61746ELLU, // ksg_Latn_SB 0x9E4A44454C61746ELLU, // ksh_Latn_DE - 0xC66A4D594C61746ELLU, // ktr_Latn_MY + 0xA24A50474C61746ELLU, // ksi_Latn_PG + 0xA64A50474C61746ELLU, // ksj_Latn_PG + 0xAA4A55534C61746ELLU, // ksk_Latn_US + 0xAE4A50474C61746ELLU, // ksl_Latn_PG + 0xB24A4E474C61746ELLU, // ksm_Latn_NG + 0xB64A50484C61746ELLU, // ksn_Latn_PH + 0xBA4A4E474C61746ELLU, // kso_Latn_NG + 0xBE4A43464C61746ELLU, // ksp_Latn_CF + 0xC24A4E474C61746ELLU, // ksq_Latn_NG + 0xC64A50474C61746ELLU, // ksr_Latn_PG + 0xCA4A4C524C61746ELLU, // kss_Latn_LR + 0xCE4A42464C61746ELLU, // kst_Latn_BF + 0xD24A494E4D796D72LLU, // ksu_Mymr_IN + 0xD64A43444C61746ELLU, // ksv_Latn_CD + 0xDA4A4D4D4D796D72LLU, // ksw_Mymr_MM + 0xDE4A49444C61746ELLU, // ksx_Latn_ID + 0xE64A494E44657661LLU, // ksz_Deva_IN + 0x826A564E4C61746ELLU, // kta_Latn_VN + 0x866A455445746869LLU, // ktb_Ethi_ET + 0x8A6A4E474C61746ELLU, // ktc_Latn_NG + 0x8E6A41554C61746ELLU, // ktd_Latn_AU + 0x926A4E5044657661LLU, // kte_Deva_NP + 0x966A43444C61746ELLU, // ktf_Latn_CD + 0x9A6A41554C61746ELLU, // ktg_Latn_AU + 0x9E6A54444C61746ELLU, // kth_Latn_TD + 0xA26A49444C61746ELLU, // kti_Latn_ID + 0xA66A43494C61746ELLU, // ktj_Latn_CI + 0xAA6A50474C61746ELLU, // ktk_Latn_PG + 0xAE6A495241726162LLU, // ktl_Arab_IR + 0xB26A50474C61746ELLU, // ktm_Latn_PG + 0xB66A42524C61746ELLU, // ktn_Latn_BR + 0xBA6A50474C61746ELLU, // kto_Latn_PG + 0xBE6A434E506C7264LLU, // ktp_Plrd_CN + 0xC26A50484C61746ELLU, // ktq_Latn_PH + 0xCA6A49444C61746ELLU, // kts_Latn_ID + 0xCE6A49444C61746ELLU, // ktt_Latn_ID + 0xD26A43444C61746ELLU, // ktu_Latn_CD + 0xD66A564E4C61746ELLU, // ktv_Latn_VN + 0xDA6A55534C61746ELLU, // ktw_Latn_US + 0xDE6A42524C61746ELLU, // ktx_Latn_BR + 0xE26A43444C61746ELLU, // kty_Latn_CD + 0xE66A4E414C61746ELLU, // ktz_Latn_NA 0x6B75495141726162LLU, // ku_Arab_IQ 0x6B7554524C61746ELLU, // ku_Latn_TR 0x6B75474559657A69LLU, // ku_Yezi_GE + 0x868A4E474C61746ELLU, // kub_Latn_NG + 0x8A8A49444C61746ELLU, // kuc_Latn_ID + 0x8E8A50474C61746ELLU, // kud_Latn_PG + 0x928A50474C61746ELLU, // kue_Latn_PG + 0x968A4C414C616F6FLLU, // kuf_Laoo_LA + 0x9A8A4E474C61746ELLU, // kug_Latn_NG + 0x9E8A4E474C61746ELLU, // kuh_Latn_NG + 0xA28A42524C61746ELLU, // kui_Latn_BR + 0xA68A545A4C61746ELLU, // kuj_Latn_TZ + 0xAA8A49444C61746ELLU, // kuk_Latn_ID + 0xAE8A4E474C61746ELLU, // kul_Latn_NG 0xB28A52554379726CLLU, // kum_Cyrl_RU + 0xB68A45524C61746ELLU, // kun_Latn_ER + 0xBA8A50474C61746ELLU, // kuo_Latn_PG + 0xBE8A50474C61746ELLU, // kup_Latn_PG + 0xC28A42524C61746ELLU, // kuq_Latn_BR + 0xCA8A47484C61746ELLU, // kus_Latn_GH + 0xCE8A43414C61746ELLU, // kut_Latn_CA + 0xD28A55534C61746ELLU, // kuu_Latn_US + 0xD68A49444C61746ELLU, // kuv_Latn_ID + 0xDA8A43464C61746ELLU, // kuw_Latn_CF + 0xDE8A41554C61746ELLU, // kux_Latn_AU + 0xE28A41554C61746ELLU, // kuy_Latn_AU + 0xE68A434C4C61746ELLU, // kuz_Latn_CL 0x6B7652554379726CLLU, // kv_Cyrl_RU + 0x82AA52554379726CLLU, // kva_Cyrl_RU + 0x86AA49444C61746ELLU, // kvb_Latn_ID + 0x8AAA50474C61746ELLU, // kvc_Latn_PG + 0x8EAA49444C61746ELLU, // kvd_Latn_ID + 0x92AA4D594C61746ELLU, // kve_Latn_MY + 0x96AA54444C61746ELLU, // kvf_Latn_TD + 0x9AAA50474C61746ELLU, // kvg_Latn_PG + 0x9EAA49444C61746ELLU, // kvh_Latn_ID + 0xA2AA54444C61746ELLU, // kvi_Latn_TD + 0xA6AA434D4C61746ELLU, // kvj_Latn_CM + 0xAEAA4D4D4C61746ELLU, // kvl_Latn_MM + 0xB2AA434D4C61746ELLU, // kvm_Latn_CM + 0xB6AA434F4C61746ELLU, // kvn_Latn_CO + 0xBAAA49444C61746ELLU, // kvo_Latn_ID + 0xBEAA49444C61746ELLU, // kvp_Latn_ID + 0xC2AA4D4D4D796D72LLU, // kvq_Mymr_MM 0xC6AA49444C61746ELLU, // kvr_Latn_ID + 0xCEAA4D4D4D796D72LLU, // kvt_Mymr_MM + 0xD6AA49444C61746ELLU, // kvv_Latn_ID + 0xDAAA49444C61746ELLU, // kvw_Latn_ID 0xDEAA504B41726162LLU, // kvx_Arab_PK + 0xE2AA4D4D4B616C69LLU, // kvy_Kali_MM + 0xE6AA49444C61746ELLU, // kvz_Latn_ID 0x6B7747424C61746ELLU, // kw_Latn_GB + 0x82CA42524C61746ELLU, // kwa_Latn_BR + 0x86CA4E474C61746ELLU, // kwb_Latn_NG + 0x8ACA43474C61746ELLU, // kwc_Latn_CG + 0x8ECA53424C61746ELLU, // kwd_Latn_SB + 0x92CA49444C61746ELLU, // kwe_Latn_ID + 0x96CA53424C61746ELLU, // kwf_Latn_SB + 0x9ACA54444C61746ELLU, // kwg_Latn_TD + 0x9ECA49444C61746ELLU, // kwh_Latn_ID + 0xA2CA434F4C61746ELLU, // kwi_Latn_CO + 0xA6CA50474C61746ELLU, // kwj_Latn_PG 0xAACA43414C61746ELLU, // kwk_Latn_CA - 0xAEEA494E44657661LLU, // kxl_Deva_IN + 0xAECA4E474C61746ELLU, // kwl_Latn_NG + 0xB2CA4E414C61746ELLU, // kwm_Latn_NA + 0xB6CA4E414C61746ELLU, // kwn_Latn_NA + 0xBACA50474C61746ELLU, // kwo_Latn_PG + 0xBECA43494C61746ELLU, // kwp_Latn_CI + 0xC6CA49444C61746ELLU, // kwr_Latn_ID + 0xCACA43444C61746ELLU, // kws_Latn_CD + 0xCECA49444C61746ELLU, // kwt_Latn_ID + 0xD2CA434D4C61746ELLU, // kwu_Latn_CM + 0xD6CA54444C61746ELLU, // kwv_Latn_TD + 0xDACA53524C61746ELLU, // kww_Latn_SR + 0xE2CA414F4C61746ELLU, // kwy_Latn_AO + 0xE6CA414F4C61746ELLU, // kwz_Latn_AO + 0x82EA50474C61746ELLU, // kxa_Latn_PG + 0x86EA43494C61746ELLU, // kxb_Latn_CI + 0x8AEA45544C61746ELLU, // kxc_Latn_ET + 0x8EEA424E4C61746ELLU, // kxd_Latn_BN + 0x96EA4D4D4D796D72LLU, // kxf_Mymr_MM + 0xA2EA4D594C61746ELLU, // kxi_Latn_MY + 0xA6EA54444C61746ELLU, // kxj_Latn_TD + 0xAAEA4D4D4D796D72LLU, // kxk_Mymr_MM 0xB2EA544854686169LLU, // kxm_Thai_TH + 0xB6EA4D594C61746ELLU, // kxn_Latn_MY + 0xBAEA42524C61746ELLU, // kxo_Latn_BR 0xBEEA504B41726162LLU, // kxp_Arab_PK + 0xC2EA49444C61746ELLU, // kxq_Latn_ID + 0xC6EA50474C61746ELLU, // kxr_Latn_PG + 0xCEEA50474C61746ELLU, // kxt_Latn_PG + 0xD6EA494E4C61746ELLU, // kxv_Latn_IN + 0xDAEA50474C61746ELLU, // kxw_Latn_PG + 0xDEEA43474C61746ELLU, // kxx_Latn_CG + 0xE2EA564E4C61746ELLU, // kxy_Latn_VN + 0xE6EA50474C61746ELLU, // kxz_Latn_PG 0x6B79434E41726162LLU, // ky_Arab_CN 0x6B794B474379726CLLU, // ky_Cyrl_KG 0x6B7954524C61746ELLU, // ky_Latn_TR - 0xA72A4D594C61746ELLU, // kzj_Latn_MY - 0xCF2A4D594C61746ELLU, // kzt_Latn_MY + 0x830A545A4C61746ELLU, // kya_Latn_TZ + 0x870A50484C61746ELLU, // kyb_Latn_PH + 0x8B0A50474C61746ELLU, // kyc_Latn_PG + 0x8F0A49444C61746ELLU, // kyd_Latn_ID + 0x930A47484C61746ELLU, // kye_Latn_GH + 0x970A43494C61746ELLU, // kyf_Latn_CI + 0x9B0A50474C61746ELLU, // kyg_Latn_PG + 0x9F0A55534C61746ELLU, // kyh_Latn_US + 0xA30A4D594C61746ELLU, // kyi_Latn_MY + 0xA70A50484C61746ELLU, // kyj_Latn_PH + 0xAB0A50484C61746ELLU, // kyk_Latn_PH + 0xAF0A55534C61746ELLU, // kyl_Latn_US + 0xB30A43464C61746ELLU, // kym_Latn_CF + 0xB70A50484C61746ELLU, // kyn_Latn_PH + 0xBB0A49444C61746ELLU, // kyo_Latn_ID + 0xC30A54444C61746ELLU, // kyq_Latn_TD + 0xC70A42524C61746ELLU, // kyr_Latn_BR + 0xCB0A4D594C61746ELLU, // kys_Latn_MY + 0xCF0A49444C61746ELLU, // kyt_Latn_ID + 0xD30A4D4D4B616C69LLU, // kyu_Kali_MM + 0xD70A4E5044657661LLU, // kyv_Deva_NP + 0xDB0A494E44657661LLU, // kyw_Deva_IN + 0xDF0A50474C61746ELLU, // kyx_Latn_PG + 0xE30A50474C61746ELLU, // kyy_Latn_PG + 0xE70A42524C61746ELLU, // kyz_Latn_BR + 0x832A42464C61746ELLU, // kza_Latn_BF + 0x872A49444C61746ELLU, // kzb_Latn_ID + 0x8B2A43494C61746ELLU, // kzc_Latn_CI + 0x8F2A49444C61746ELLU, // kzd_Latn_ID + 0x932A50474C61746ELLU, // kze_Latn_PG + 0x972A49444C61746ELLU, // kzf_Latn_ID + 0xA32A4D594C61746ELLU, // kzi_Latn_MY + 0xAB2A53424C61746ELLU, // kzk_Latn_SB + 0xAF2A49444C61746ELLU, // kzl_Latn_ID + 0xB32A49444C61746ELLU, // kzm_Latn_ID + 0xB72A4D574C61746ELLU, // kzn_Latn_MW + 0xBB2A47414C61746ELLU, // kzo_Latn_GA + 0xBF2A49444C61746ELLU, // kzp_Latn_ID + 0xC72A434D4C61746ELLU, // kzr_Latn_CM + 0xCB2A4D594C61746ELLU, // kzs_Latn_MY + 0xD32A49444C61746ELLU, // kzu_Latn_ID + 0xD72A49444C61746ELLU, // kzv_Latn_ID + 0xDB2A42524C61746ELLU, // kzw_Latn_BR + 0xDF2A49444C61746ELLU, // kzx_Latn_ID + 0xE32A43444C61746ELLU, // kzy_Latn_CD + 0xE72A49444C61746ELLU, // kzz_Latn_ID 0x6C6156414C61746ELLU, // la_Latn_VA + 0x800B50484C61746ELLU, // laa_Latn_PH 0x840B47524C696E61LLU, // lab_Lina_GR + 0x880B4D584C61746ELLU, // lac_Latn_MX 0x8C0B494C48656272LLU, // lad_Hebr_IL + 0x900B494E44657661LLU, // lae_Deva_IN 0x980B545A4C61746ELLU, // lag_Latn_TZ 0x9C0B504B41726162LLU, // lah_Arab_PK + 0xA00B4D574C61746ELLU, // lai_Latn_MW 0xA40B55474C61746ELLU, // laj_Latn_UG + 0xAC0B43444C61746ELLU, // lal_Latn_CD + 0xB00B5A4D4C61746ELLU, // lam_Latn_ZM + 0xB40B4E474C61746ELLU, // lan_Latn_NG + 0xBC0B54444C61746ELLU, // lap_Latn_TD + 0xC00B564E4C61746ELLU, // laq_Latn_VN + 0xC40B47484C61746ELLU, // lar_Latn_GH + 0xC80B54474C61746ELLU, // las_Latn_TG + 0xD00B49444C61746ELLU, // lau_Latn_ID + 0xD80B49444C61746ELLU, // law_Latn_ID + 0xDC0B494E4C61746ELLU, // lax_Latn_IN + 0xE40B50474C61746ELLU, // laz_Latn_PG 0x6C624C554C61746ELLU, // lb_Latn_LU + 0x842B50474C61746ELLU, // lbb_Latn_PG 0x902B52554379726CLLU, // lbe_Cyrl_RU + 0x942B494E44657661LLU, // lbf_Deva_IN + 0xA02B434D4C61746ELLU, // lbi_Latn_CM + 0xA42B494E54696274LLU, // lbj_Tibt_IN + 0xAC2B50484C61746ELLU, // lbl_Latn_PH + 0xB02B494E44657661LLU, // lbm_Deva_IN + 0xB42B4C414C61746ELLU, // lbn_Latn_LA + 0xB82B4C414C616F6FLLU, // lbo_Laoo_LA + 0xC02B50474C61746ELLU, // lbq_Latn_PG + 0xC42B4E5044657661LLU, // lbr_Deva_NP + 0xCC2B564E4C61746ELLU, // lbt_Latn_VN + 0xD02B50474C61746ELLU, // lbu_Latn_PG + 0xD42B50474C61746ELLU, // lbv_Latn_PG 0xD82B49444C61746ELLU, // lbw_Latn_ID + 0xDC2B49444C61746ELLU, // lbx_Latn_ID + 0xE02B41554C61746ELLU, // lby_Latn_AU + 0xE42B41554C61746ELLU, // lbz_Latn_AU + 0x884B49444C61746ELLU, // lcc_Latn_ID + 0x8C4B49444C61746ELLU, // lcd_Latn_ID + 0x904B49444C61746ELLU, // lce_Latn_ID + 0x944B49444C61746ELLU, // lcf_Latn_ID + 0x9C4B414F4C61746ELLU, // lch_Latn_AO + 0xAC4B49444C61746ELLU, // lcl_Latn_ID + 0xB04B50474C61746ELLU, // lcm_Latn_PG 0xBC4B434E54686169LLU, // lcp_Thai_CN + 0xC04B49444C61746ELLU, // lcq_Latn_ID + 0xC84B49444C61746ELLU, // lcs_Latn_ID + 0x806B43494C61746ELLU, // lda_Latn_CI + 0x846B4E474C61746ELLU, // ldb_Latn_NG + 0x8C6B4E474C61746ELLU, // ldd_Latn_NG + 0x986B4E474C61746ELLU, // ldg_Latn_NG + 0x9C6B4E474C61746ELLU, // ldh_Latn_NG + 0xA06B43474C61746ELLU, // ldi_Latn_CG + 0xA46B4E474C61746ELLU, // ldj_Latn_NG + 0xA86B4E474C61746ELLU, // ldk_Latn_NG + 0xAC6B4E474C61746ELLU, // ldl_Latn_NG + 0xB06B474E4C61746ELLU, // ldm_Latn_GN + 0xB86B4E474C61746ELLU, // ldo_Latn_NG + 0xBC6B4E474C61746ELLU, // ldp_Latn_NG + 0xC06B4E474C61746ELLU, // ldq_Latn_NG + 0x808B43444C61746ELLU, // lea_Latn_CD + 0x848B5A4D4C61746ELLU, // leb_Latn_ZM + 0x888B424F4C61746ELLU, // lec_Latn_BO + 0x8C8B43444C61746ELLU, // led_Latn_CD + 0x908B42464C61746ELLU, // lee_Latn_BF + 0x948B47484C61746ELLU, // lef_Latn_GH + 0x9C8B5A4D4C61746ELLU, // leh_Latn_ZM + 0xA08B50474C61746ELLU, // lei_Latn_PG + 0xA48B43444C61746ELLU, // lej_Latn_CD + 0xA88B50474C61746ELLU, // lek_Latn_PG + 0xAC8B43444C61746ELLU, // lel_Latn_CD + 0xB08B434D4C61746ELLU, // lem_Latn_CM + 0xB48B484E4C61746ELLU, // len_Latn_HN + 0xB88B434D4C61746ELLU, // leo_Latn_CM 0xBC8B494E4C657063LLU, // lep_Lepc_IN + 0xC08B50474C61746ELLU, // leq_Latn_PG + 0xC48B50474C61746ELLU, // ler_Latn_PG + 0xC88B43444C61746ELLU, // les_Latn_CD + 0xCC8B50474C61746ELLU, // let_Latn_PG + 0xD08B50474C61746ELLU, // leu_Latn_PG + 0xD48B49444C61746ELLU, // lev_Latn_ID + 0xD88B49444C61746ELLU, // lew_Latn_ID + 0xDC8B49444C61746ELLU, // lex_Latn_ID + 0xE08B49444C61746ELLU, // ley_Latn_ID 0xE48B52554379726CLLU, // lez_Cyrl_RU + 0x80AB434D4C61746ELLU, // lfa_Latn_CM 0x6C6755474C61746ELLU, // lg_Latn_UG + 0x80CB53424C61746ELLU, // lga_Latn_SB + 0x84CB53424C61746ELLU, // lgb_Latn_SB + 0x98CB55474C61746ELLU, // lgg_Latn_UG + 0x9CCB564E4C61746ELLU, // lgh_Latn_VN + 0xA0CB49444C61746ELLU, // lgi_Latn_ID + 0xA8CB56554C61746ELLU, // lgk_Latn_VU + 0xACCB53424C61746ELLU, // lgl_Latn_SB + 0xB0CB43444C61746ELLU, // lgm_Latn_CD + 0xB4CB45544C61746ELLU, // lgn_Latn_ET + 0xB8CB53534C61746ELLU, // lgo_Latn_SS + 0xC0CB47484C61746ELLU, // lgq_Latn_GH + 0xC4CB53424C61746ELLU, // lgr_Latn_SB + 0xCCCB50474C61746ELLU, // lgt_Latn_PG + 0xD0CB53424C61746ELLU, // lgu_Latn_SB + 0xE4CB43444C61746ELLU, // lgz_Latn_CD + 0x80EB564E4C61746ELLU, // lha_Latn_VN + 0x9CEB49444C61746ELLU, // lhh_Latn_ID + 0xA0EB434E4C61746ELLU, // lhi_Latn_CN + 0xB0EB4E5044657661LLU, // lhm_Deva_NP + 0xB4EB4D594C61746ELLU, // lhn_Latn_MY + 0xC8EB535953797263LLU, // lhs_Syrc_SY + 0xCCEB56554C61746ELLU, // lht_Latn_VU + 0xD0EB434E4C61746ELLU, // lhu_Latn_CN 0x6C694E4C4C61746ELLU, // li_Latn_NL + 0x810B534C4C61746ELLU, // lia_Latn_SL + 0x850B50474C61746ELLU, // lib_Latn_PG + 0x890B434E4C61746ELLU, // lic_Latn_CN + 0x8D0B50474C61746ELLU, // lid_Latn_PG + 0x910B43444C61746ELLU, // lie_Latn_CD 0x950B4E5044657661LLU, // lif_Deva_NP 0x950B494E4C696D62LLU, // lif_Limb_IN + 0x990B47484C61746ELLU, // lig_Latn_GH + 0x9D0B50474C61746ELLU, // lih_Latn_PG 0xA50B49544C61746ELLU, // lij_Latn_IT + 0xA90B43444C61746ELLU, // lik_Latn_CD 0xAD0B43414C61746ELLU, // lil_Latn_CA + 0xB90B49444C61746ELLU, // lio_Latn_ID + 0xBD0B47484C61746ELLU, // lip_Latn_GH + 0xC10B45544C61746ELLU, // liq_Latn_ET + 0xC50B4C524C61746ELLU, // lir_Latn_LR 0xC90B434E4C697375LLU, // lis_Lisu_CN + 0xD10B53444C61746ELLU, // liu_Latn_SD + 0xD50B4C564C61746ELLU, // liv_Latn_LV + 0xD90B49444C61746ELLU, // liw_Latn_ID + 0xDD0B49444C61746ELLU, // lix_Latn_ID + 0xE10B43464C61746ELLU, // liy_Latn_CF + 0xE50B43444C61746ELLU, // liz_Latn_CD + 0x812B41554C61746ELLU, // lja_Latn_AU + 0x912B49444C61746ELLU, // lje_Latn_ID + 0xA12B49444C61746ELLU, // lji_Latn_ID + 0xAD2B49444C61746ELLU, // ljl_Latn_ID 0xBD2B49444C61746ELLU, // ljp_Latn_ID + 0xD92B41554C61746ELLU, // ljw_Latn_AU + 0xDD2B41554C61746ELLU, // ljx_Latn_AU + 0x814B544C4C61746ELLU, // lka_Latn_TL + 0x854B4B454C61746ELLU, // lkb_Latn_KE + 0x894B564E4C61746ELLU, // lkc_Latn_VN + 0x8D4B42524C61746ELLU, // lkd_Latn_BR + 0x914B55474C61746ELLU, // lke_Latn_UG + 0x9D4B425454696274LLU, // lkh_Tibt_BT 0xA14B495241726162LLU, // lki_Arab_IR + 0xA54B4D594C61746ELLU, // lkj_Latn_MY + 0xAD4B50474C61746ELLU, // lkl_Latn_PG + 0xB14B41554C61746ELLU, // lkm_Latn_AU + 0xB54B56554C61746ELLU, // lkn_Latn_VU + 0xB94B4B454C61746ELLU, // lko_Latn_KE + 0xC54B53534C61746ELLU, // lkr_Latn_SS + 0xC94B4B454C61746ELLU, // lks_Latn_KE 0xCD4B55534C61746ELLU, // lkt_Latn_US + 0xD14B41554C61746ELLU, // lku_Latn_AU + 0xE14B53534C61746ELLU, // lky_Latn_SS + 0x816B4E474C61746ELLU, // lla_Latn_NG + 0x856B4D5A4C61746ELLU, // llb_Latn_MZ + 0x896B474E4C61746ELLU, // llc_Latn_GN + 0x8D6B49544C61746ELLU, // lld_Latn_IT + 0x916B50474C61746ELLU, // lle_Latn_PG + 0x956B50474C61746ELLU, // llf_Latn_PG + 0x996B49444C61746ELLU, // llg_Latn_ID + 0xA16B43474C61746ELLU, // lli_Latn_CG + 0xA56B41554C61746ELLU, // llj_Latn_AU + 0xA96B4D594C61746ELLU, // llk_Latn_MY + 0xAD6B50474C61746ELLU, // lll_Latn_PG + 0xB16B49444C61746ELLU, // llm_Latn_ID + 0xB56B54444C61746ELLU, // lln_Latn_TD + 0xBD6B56554C61746ELLU, // llp_Latn_VU + 0xC16B49444C61746ELLU, // llq_Latn_ID + 0xD16B53424C61746ELLU, // llu_Latn_SB + 0xDD6B464A4C61746ELLU, // llx_Latn_FJ + 0x818B474E4C61746ELLU, // lma_Latn_GN + 0x858B56554C61746ELLU, // lmb_Latn_VU + 0x898B41554C61746ELLU, // lmc_Latn_AU + 0x8D8B53444C61746ELLU, // lmd_Latn_SD + 0x918B54444C61746ELLU, // lme_Latn_TD + 0x958B49444C61746ELLU, // lmf_Latn_ID + 0x998B50474C61746ELLU, // lmg_Latn_PG + 0x9D8B4E5044657661LLU, // lmh_Deva_NP + 0xA18B43444C61746ELLU, // lmi_Latn_CD + 0xA58B49444C61746ELLU, // lmj_Latn_ID + 0xA98B494E4C61746ELLU, // lmk_Latn_IN + 0xAD8B56554C61746ELLU, // lml_Latn_VU 0xB58B494E54656C75LLU, // lmn_Telu_IN 0xB98B49544C61746ELLU, // lmo_Latn_IT + 0xBD8B434D4C61746ELLU, // lmp_Latn_CM + 0xC18B49444C61746ELLU, // lmq_Latn_ID + 0xC58B49444C61746ELLU, // lmr_Latn_ID + 0xD18B56554C61746ELLU, // lmu_Latn_VU + 0xD58B464A4C61746ELLU, // lmv_Latn_FJ + 0xD98B55534C61746ELLU, // lmw_Latn_US + 0xDD8B434D4C61746ELLU, // lmx_Latn_CM + 0xE18B49444C61746ELLU, // lmy_Latn_ID 0x6C6E43444C61746ELLU, // ln_Latn_CD + 0x81AB43464C61746ELLU, // lna_Latn_CF + 0x85AB4E414C61746ELLU, // lnb_Latn_NA + 0x8DAB49444C61746ELLU, // lnd_Latn_ID + 0x99AB48554C61746ELLU, // lng_Latn_HU + 0x9DAB4D594C61746ELLU, // lnh_Latn_MY + 0xA1AB50474C61746ELLU, // lni_Latn_PG + 0xA5AB41554C61746ELLU, // lnj_Latn_AU + 0xADAB43464C61746ELLU, // lnl_Latn_CF + 0xB1AB50474C61746ELLU, // lnm_Latn_PG + 0xB5AB56554C61746ELLU, // lnn_Latn_VU + 0xC9AB434D4C61746ELLU, // lns_Latn_CM + 0xD1AB4E474C61746ELLU, // lnu_Latn_NG + 0xD9AB41554C61746ELLU, // lnw_Latn_AU + 0xE5AB43444C61746ELLU, // lnz_Latn_CD 0x6C6F4C414C616F6FLLU, // lo_Laoo_LA + 0x81CB49444C61746ELLU, // loa_Latn_ID + 0x85CB42464C61746ELLU, // lob_Latn_BF + 0x89CB50484C61746ELLU, // loc_Latn_PH + 0x91CB49444C61746ELLU, // loe_Latn_ID + 0x99CB43444C61746ELLU, // log_Latn_CD + 0x9DCB53534C61746ELLU, // loh_Latn_SS + 0xA1CB43494C61746ELLU, // loi_Latn_CI + 0xA5CB50474C61746ELLU, // loj_Latn_PG + 0xA9CB534C4C61746ELLU, // lok_Latn_SL 0xADCB43444C61746ELLU, // lol_Latn_CD + 0xB1CB4C524C61746ELLU, // lom_Latn_LR + 0xB5CB4D574C61746ELLU, // lon_Latn_MW + 0xB9CB43444C61746ELLU, // loo_Latn_CD + 0xBDCB4E474C61746ELLU, // lop_Latn_NG + 0xC1CB43444C61746ELLU, // loq_Latn_CD + 0xC5CB43494C61746ELLU, // lor_Latn_CI + 0xC9CB50474C61746ELLU, // los_Latn_PG + 0xCDCB53534C61746ELLU, // lot_Latn_SS + 0xD1CB55534C61746ELLU, // lou_Latn_US + 0xD9CB4D594C61746ELLU, // low_Latn_MY + 0xDDCB49444C61746ELLU, // lox_Latn_ID + 0xE1CB4E5044657661LLU, // loy_Deva_NP 0xE5CB5A4D4C61746ELLU, // loz_Latn_ZM + 0x81EB56554C61746ELLU, // lpa_Latn_VU + 0x91EB49444C61746ELLU, // lpe_Latn_ID + 0xB5EB4D4D4C61746ELLU, // lpn_Latn_MM + 0xB9EB434E506C7264LLU, // lpo_Plrd_CN + 0xDDEB53534C61746ELLU, // lpx_Latn_SS + 0xC60B53534C61746ELLU, // lqr_Latn_SS + 0x822B4D594C61746ELLU, // lra_Latn_MY 0x8A2B495241726162LLU, // lrc_Arab_IR + 0x9A2B41554C61746ELLU, // lrg_Latn_AU + 0xA22B4B454C61746ELLU, // lri_Latn_KE + 0xAA2B504B41726162LLU, // lrk_Arab_PK + 0xAE2B495241726162LLU, // lrl_Arab_IR + 0xB22B4B454C61746ELLU, // lrm_Latn_KE + 0xB62B49444C61746ELLU, // lrn_Latn_ID + 0xBA2B53444C61746ELLU, // lro_Latn_SD + 0xCE2B49444C61746ELLU, // lrt_Latn_ID + 0xD62B56554C61746ELLU, // lrv_Latn_VU + 0xE62B56554C61746ELLU, // lrz_Latn_VU + 0x824B495241726162LLU, // lsa_Arab_IR + 0x8E4B494C48656272LLU, // lsd_Hebr_IL + 0x924B43444C61746ELLU, // lse_Latn_CD + 0xA24B4D4D4C61746ELLU, // lsi_Latn_MM + 0xB24B55474C61746ELLU, // lsm_Latn_UG + 0xC64B50474C61746ELLU, // lsr_Latn_PG + 0xCA4B504B41726162LLU, // lss_Arab_PK 0x6C744C544C61746ELLU, // lt_Latn_LT + 0x8A6B434E48616E74LLU, // ltc_Hant_CN 0x9A6B4C564C61746ELLU, // ltg_Latn_LV + 0x9E6B55474C61746ELLU, // lth_Latn_UG + 0xA26B49444C61746ELLU, // lti_Latn_ID + 0xB66B42524C61746ELLU, // ltn_Latn_BR + 0xBA6B4B454C61746ELLU, // lto_Latn_KE + 0xCA6B4B454C61746ELLU, // lts_Latn_KE + 0xD26B49444C61746ELLU, // ltu_Latn_ID 0x6C7543444C61746ELLU, // lu_Latn_CD 0x828B43444C61746ELLU, // lua_Latn_CD + 0x8A8B55474C61746ELLU, // luc_Latn_UG + 0x8E8B52554C61746ELLU, // lud_Latn_RU + 0x928B5A4D4C61746ELLU, // lue_Latn_ZM + 0x968B50474C61746ELLU, // luf_Latn_PG + 0xA28B55534C61746ELLU, // lui_Latn_US + 0xA68B43444C61746ELLU, // luj_Latn_CD + 0xAA8B425454696274LLU, // luk_Tibt_BT + 0xAE8B53534C61746ELLU, // lul_Latn_SS + 0xB28B414F4C61746ELLU, // lum_Latn_AO + 0xB68B5A4D4C61746ELLU, // lun_Latn_ZM 0xBA8B4B454C61746ELLU, // luo_Latn_KE + 0xBE8B47414C61746ELLU, // lup_Latn_GA + 0xC28B43554C61746ELLU, // luq_Latn_CU + 0xC68B49444C61746ELLU, // lur_Latn_ID + 0xCA8B494E4C61746ELLU, // lus_Latn_IN + 0xCE8B55534C61746ELLU, // lut_Latn_US + 0xD28B4E5044657661LLU, // luu_Deva_NP + 0xD68B4F4D41726162LLU, // luv_Arab_OM + 0xDA8B434D4C61746ELLU, // luw_Latn_CM 0xE28B4B454C61746ELLU, // luy_Latn_KE 0xE68B495241726162LLU, // luz_Arab_IR 0x6C764C564C61746ELLU, // lv_Latn_LV + 0x82AB544C4C61746ELLU, // lva_Latn_TL + 0xA2AB4C414C61746ELLU, // lvi_Latn_LA + 0xAAAB53424C61746ELLU, // lvk_Latn_SB + 0xAEAB43444C61746ELLU, // lvl_Latn_CD + 0xD2AB49444C61746ELLU, // lvu_Latn_ID + 0x82CB43444C61746ELLU, // lwa_Latn_CD + 0x92CB49444C61746ELLU, // lwe_Latn_ID + 0x9ACB4B454C61746ELLU, // lwg_Latn_KE + 0x9ECB564E4C61746ELLU, // lwh_Latn_VN 0xAECB544854686169LLU, // lwl_Thai_TH + 0xB2CB434E54686169LLU, // lwm_Thai_CN + 0xBACB53534C61746ELLU, // lwo_Latn_SS + 0xCECB49444C61746ELLU, // lwt_Latn_ID + 0xDACB56554C61746ELLU, // lww_Latn_VU + 0xB2EB50474C61746ELLU, // lxm_Latn_PG + 0x830B425454696274LLU, // lya_Tibt_BT + 0xB70B5A4D4C61746ELLU, // lyn_Latn_ZM 0x9F2B434E48616E73LLU, // lzh_Hans_CN + 0xAF2B56554C61746ELLU, // lzl_Latn_VU + 0xB72B4D4D4C61746ELLU, // lzn_Latn_MM 0xE72B54524C61746ELLU, // lzz_Latn_TR + 0x800C4D584C61746ELLU, // maa_Latn_MX + 0x840C4D584C61746ELLU, // mab_Latn_MX 0x8C0C49444C61746ELLU, // mad_Latn_ID + 0x900C4E474C61746ELLU, // mae_Latn_NG 0x940C434D4C61746ELLU, // maf_Latn_CM 0x980C494E44657661LLU, // mag_Deva_IN 0xA00C494E44657661LLU, // mai_Deva_IN + 0xA40C4D584C61746ELLU, // maj_Latn_MX 0xA80C49444C61746ELLU, // mak_Latn_ID + 0xB00C47544C61746ELLU, // mam_Latn_GT 0xB40C474D4C61746ELLU, // man_Latn_GM 0xB40C474E4E6B6F6FLLU, // man_Nkoo_GN + 0xC00C4D584C61746ELLU, // maq_Latn_MX 0xC80C4B454C61746ELLU, // mas_Latn_KE + 0xCC0C4D584C61746ELLU, // mat_Latn_MX + 0xD00C4D584C61746ELLU, // mau_Latn_MX + 0xD40C42524C61746ELLU, // mav_Latn_BR + 0xD80C47484C61746ELLU, // maw_Latn_GH + 0xDC0C49444C61746ELLU, // max_Latn_ID 0xE40C4D584C61746ELLU, // maz_Latn_MX + 0x802C50484C61746ELLU, // mba_Latn_PH + 0x842C50484C61746ELLU, // mbb_Latn_PH + 0x882C42524C61746ELLU, // mbc_Latn_BR + 0x8C2C50484C61746ELLU, // mbd_Latn_PH + 0x942C53474C61746ELLU, // mbf_Latn_SG + 0x9C2C50474C61746ELLU, // mbh_Latn_PG + 0xA02C50484C61746ELLU, // mbi_Latn_PH + 0xA42C42524C61746ELLU, // mbj_Latn_BR + 0xA82C50474C61746ELLU, // mbk_Latn_PG + 0xAC2C42524C61746ELLU, // mbl_Latn_BR + 0xB02C43474C61746ELLU, // mbm_Latn_CG + 0xB42C434F4C61746ELLU, // mbn_Latn_CO + 0xB82C434D4C61746ELLU, // mbo_Latn_CM + 0xBC2C434F4C61746ELLU, // mbp_Latn_CO + 0xC02C50474C61746ELLU, // mbq_Latn_PG + 0xC42C434F4C61746ELLU, // mbr_Latn_CO + 0xC82C50484C61746ELLU, // mbs_Latn_PH + 0xCC2C50484C61746ELLU, // mbt_Latn_PH + 0xD02C4E474C61746ELLU, // mbu_Latn_NG + 0xD42C474E4C61746ELLU, // mbv_Latn_GN + 0xD82C50474C61746ELLU, // mbw_Latn_PG + 0xDC2C50474C61746ELLU, // mbx_Latn_PG + 0xE02C504B41726162LLU, // mby_Arab_PK + 0xE42C4D584C61746ELLU, // mbz_Latn_MX + 0x804C50594C61746ELLU, // mca_Latn_PY + 0x844C50454C61746ELLU, // mcb_Latn_PE + 0x884C50474C61746ELLU, // mcc_Latn_PG + 0x8C4C50454C61746ELLU, // mcd_Latn_PE + 0x904C4D584C61746ELLU, // mce_Latn_MX + 0x944C50454C61746ELLU, // mcf_Latn_PE + 0x984C56454C61746ELLU, // mcg_Latn_VE + 0x9C4C56454C61746ELLU, // mch_Latn_VE + 0xA04C50474C61746ELLU, // mci_Latn_PG + 0xA44C4E474C61746ELLU, // mcj_Latn_NG + 0xA84C414F4C61746ELLU, // mck_Latn_AO + 0xAC4C434F4C61746ELLU, // mcl_Latn_CO + 0xB04C4D594C61746ELLU, // mcm_Latn_MY + 0xB44C54444C61746ELLU, // mcn_Latn_TD + 0xB84C4D584C61746ELLU, // mco_Latn_MX + 0xBC4C434D4C61746ELLU, // mcp_Latn_CM + 0xC04C50474C61746ELLU, // mcq_Latn_PG + 0xC44C50474C61746ELLU, // mcr_Latn_PG + 0xC84C434D4C61746ELLU, // mcs_Latn_CM + 0xCC4C434D4C61746ELLU, // mct_Latn_CM + 0xD04C434D4C61746ELLU, // mcu_Latn_CM + 0xD44C50474C61746ELLU, // mcv_Latn_PG + 0xD84C54444C61746ELLU, // mcw_Latn_TD + 0xDC4C43464C61746ELLU, // mcx_Latn_CF + 0xE04C50474C61746ELLU, // mcy_Latn_PG + 0xE44C50474C61746ELLU, // mcz_Latn_PG + 0x806C4E474C61746ELLU, // mda_Latn_NG + 0x846C50474C61746ELLU, // mdb_Latn_PG + 0x886C50474C61746ELLU, // mdc_Latn_PG + 0x8C6C434D4C61746ELLU, // mdd_Latn_CM + 0x906C544441726162LLU, // mde_Arab_TD 0x946C52554379726CLLU, // mdf_Cyrl_RU + 0x986C54444C61746ELLU, // mdg_Latn_TD 0x9C6C50484C61746ELLU, // mdh_Latn_PH + 0xA06C43444C61746ELLU, // mdi_Latn_CD + 0xA46C43444C61746ELLU, // mdj_Latn_CD + 0xA86C43444C61746ELLU, // mdk_Latn_CD + 0xB06C43444C61746ELLU, // mdm_Latn_CD + 0xB46C43464C61746ELLU, // mdn_Latn_CF + 0xBC6C43444C61746ELLU, // mdp_Latn_CD + 0xC06C43444C61746ELLU, // mdq_Latn_CD 0xC46C49444C61746ELLU, // mdr_Latn_ID + 0xC86C50474C61746ELLU, // mds_Latn_PG + 0xCC6C43474C61746ELLU, // mdt_Latn_CG + 0xD06C43474C61746ELLU, // mdu_Latn_CG + 0xD46C4D584C61746ELLU, // mdv_Latn_MX + 0xD86C43474C61746ELLU, // mdw_Latn_CG + 0xDC6C455445746869LLU, // mdx_Ethi_ET + 0xE06C455445746869LLU, // mdy_Ethi_ET + 0xE46C42524C61746ELLU, // mdz_Latn_BR + 0x808C434D4C61746ELLU, // mea_Latn_CM + 0x848C50474C61746ELLU, // meb_Latn_PG + 0x888C41554C61746ELLU, // mec_Latn_AU + 0x8C8C50474C61746ELLU, // med_Latn_PG + 0x908C50474C61746ELLU, // mee_Latn_PG + 0x9C8C4D584C61746ELLU, // meh_Latn_MX + 0xA48C49444C61746ELLU, // mej_Latn_ID + 0xA88C50474C61746ELLU, // mek_Latn_PG + 0xAC8C4D594C61746ELLU, // mel_Latn_MY + 0xB08C41554C61746ELLU, // mem_Latn_AU 0xB48C534C4C61746ELLU, // men_Latn_SL + 0xB88C4D594C61746ELLU, // meo_Latn_MY + 0xBC8C41554C61746ELLU, // mep_Latn_AU + 0xC08C434D4C61746ELLU, // meq_Latn_CM 0xC48C4B454C61746ELLU, // mer_Latn_KE + 0xC88C54444C61746ELLU, // mes_Latn_TD + 0xCC8C50474C61746ELLU, // met_Latn_PG + 0xD08C50474C61746ELLU, // meu_Latn_PG + 0xD48C4C524C61746ELLU, // mev_Latn_LR + 0xD88C4E474C61746ELLU, // mew_Latn_NG + 0xE08C534E4C61746ELLU, // mey_Latn_SN + 0xE48C55534C61746ELLU, // mez_Latn_US 0x80AC544841726162LLU, // mfa_Arab_TH + 0x84AC49444C61746ELLU, // mfb_Latn_ID + 0x88AC43444C61746ELLU, // mfc_Latn_CD + 0x8CAC434D4C61746ELLU, // mfd_Latn_CM 0x90AC4D554C61746ELLU, // mfe_Latn_MU + 0x94AC434D4C61746ELLU, // mff_Latn_CM + 0x98AC474E4C61746ELLU, // mfg_Latn_GN + 0x9CAC434D4C61746ELLU, // mfh_Latn_CM + 0xA0AC434D41726162LLU, // mfi_Arab_CM + 0xA4AC434D4C61746ELLU, // mfj_Latn_CM + 0xA8AC434D4C61746ELLU, // mfk_Latn_CM + 0xACAC4E474C61746ELLU, // mfl_Latn_NG + 0xB0AC4E474C61746ELLU, // mfm_Latn_NG + 0xB4AC4E474C61746ELLU, // mfn_Latn_NG + 0xB8AC4E474C61746ELLU, // mfo_Latn_NG + 0xBCAC49444C61746ELLU, // mfp_Latn_ID + 0xC0AC54474C61746ELLU, // mfq_Latn_TG + 0xC4AC41554C61746ELLU, // mfr_Latn_AU + 0xCCAC50474C61746ELLU, // mft_Latn_PG + 0xD0AC414F4C61746ELLU, // mfu_Latn_AO + 0xD4AC534E4C61746ELLU, // mfv_Latn_SN + 0xD8AC50474C61746ELLU, // mfw_Latn_PG + 0xDCAC45544C61746ELLU, // mfx_Latn_ET + 0xE0AC4D584C61746ELLU, // mfy_Latn_MX + 0xE4AC53534C61746ELLU, // mfz_Latn_SS 0x6D674D474C61746ELLU, // mg_Latn_MG + 0x80CC49454C617467LLU, // mga_Latg_IE + 0x84CC54444C61746ELLU, // mgb_Latn_TD + 0x88CC53534C61746ELLU, // mgc_Latn_SS + 0x8CCC53534C61746ELLU, // mgd_Latn_SS + 0x90CC54444C61746ELLU, // mge_Latn_TD + 0x94CC49444C61746ELLU, // mgf_Latn_ID + 0x98CC434D4C61746ELLU, // mgg_Latn_CM 0x9CCC4D5A4C61746ELLU, // mgh_Latn_MZ + 0xA0CC4E474C61746ELLU, // mgi_Latn_NG + 0xA4CC4E474C61746ELLU, // mgj_Latn_NG + 0xA8CC49444C61746ELLU, // mgk_Latn_ID + 0xACCC50474C61746ELLU, // mgl_Latn_PG + 0xB0CC544C4C61746ELLU, // mgm_Latn_TL + 0xB4CC43464C61746ELLU, // mgn_Latn_CF 0xB8CC434D4C61746ELLU, // mgo_Latn_CM 0xBCCC4E5044657661LLU, // mgp_Deva_NP + 0xC0CC545A4C61746ELLU, // mgq_Latn_TZ + 0xC4CC5A4D4C61746ELLU, // mgr_Latn_ZM + 0xC8CC545A4C61746ELLU, // mgs_Latn_TZ + 0xCCCC50474C61746ELLU, // mgt_Latn_PG + 0xD0CC50474C61746ELLU, // mgu_Latn_PG + 0xD4CC545A4C61746ELLU, // mgv_Latn_TZ + 0xD8CC545A4C61746ELLU, // mgw_Latn_TZ 0xE0CC545A4C61746ELLU, // mgy_Latn_TZ + 0xE4CC545A4C61746ELLU, // mgz_Latn_TZ 0x6D684D484C61746ELLU, // mh_Latn_MH + 0x84EC47414C61746ELLU, // mhb_Latn_GA + 0x88EC4D584C61746ELLU, // mhc_Latn_MX + 0x8CEC545A4C61746ELLU, // mhd_Latn_TZ + 0x90EC4D594C61746ELLU, // mhe_Latn_MY + 0x94EC50474C61746ELLU, // mhf_Latn_PG + 0x98EC41554C61746ELLU, // mhg_Latn_AU + 0xA0EC55474C61746ELLU, // mhi_Latn_UG + 0xA4EC414641726162LLU, // mhj_Arab_AF + 0xA8EC434D4C61746ELLU, // mhk_Latn_CM + 0xACEC50474C61746ELLU, // mhl_Latn_PG + 0xB0EC4D5A4C61746ELLU, // mhm_Latn_MZ + 0xB4EC49544C61746ELLU, // mhn_Latn_IT + 0xB8EC5A4D4C61746ELLU, // mho_Latn_ZM + 0xBCEC49444C61746ELLU, // mhp_Latn_ID + 0xC0EC55534C61746ELLU, // mhq_Latn_US + 0xC8EC49444C61746ELLU, // mhs_Latn_ID + 0xCCEC56454C61746ELLU, // mht_Latn_VE + 0xD0EC494E4C61746ELLU, // mhu_Latn_IN + 0xD8EC42574C61746ELLU, // mhw_Latn_BW + 0xDCEC4D4D4C61746ELLU, // mhx_Latn_MM + 0xE0EC49444C61746ELLU, // mhy_Latn_ID + 0xE4EC49444C61746ELLU, // mhz_Latn_ID 0x6D694E5A4C61746ELLU, // mi_Latn_NZ + 0x810C55534C61746ELLU, // mia_Latn_US + 0x850C4D584C61746ELLU, // mib_Latn_MX 0x890C43414C61746ELLU, // mic_Latn_CA + 0x8D0C49514D616E64LLU, // mid_Mand_IQ + 0x910C4D584C61746ELLU, // mie_Latn_MX + 0x950C434D4C61746ELLU, // mif_Latn_CM + 0x990C4D584C61746ELLU, // mig_Latn_MX + 0x9D0C4D584C61746ELLU, // mih_Latn_MX + 0xA10C4D584C61746ELLU, // mii_Latn_MX + 0xA50C434D4C61746ELLU, // mij_Latn_CM + 0xA90C55534C61746ELLU, // mik_Latn_US + 0xAD0C4D584C61746ELLU, // mil_Latn_MX + 0xB10C4D584C61746ELLU, // mim_Latn_MX 0xB50C49444C61746ELLU, // min_Latn_ID + 0xB90C4D584C61746ELLU, // mio_Latn_MX + 0xBD0C4D584C61746ELLU, // mip_Latn_MX + 0xC10C4E494C61746ELLU, // miq_Latn_NI + 0xC50C4D584C61746ELLU, // mir_Latn_MX + 0xCD0C4D584C61746ELLU, // mit_Latn_MX + 0xD10C4D584C61746ELLU, // miu_Latn_MX + 0xD90C50474C61746ELLU, // miw_Latn_PG + 0xDD0C4D584C61746ELLU, // mix_Latn_MX + 0xE10C4D584C61746ELLU, // miy_Latn_MX + 0xE50C4D584C61746ELLU, // miz_Latn_MX + 0x852C544C4C61746ELLU, // mjb_Latn_TL + 0x892C4D584C61746ELLU, // mjc_Latn_MX + 0x8D2C55534C61746ELLU, // mjd_Latn_US + 0x912C54444C61746ELLU, // mje_Latn_TD + 0x992C434E4C61746ELLU, // mjg_Latn_CN + 0x9D2C545A4C61746ELLU, // mjh_Latn_TZ + 0xA12C434E4C61746ELLU, // mji_Latn_CN + 0xA52C50474C61746ELLU, // mjj_Latn_PG + 0xA92C50474C61746ELLU, // mjk_Latn_PG + 0xAD2C494E44657661LLU, // mjl_Deva_IN + 0xB12C50474C61746ELLU, // mjm_Latn_PG + 0xB52C50474C61746ELLU, // mjn_Latn_PG + 0xC12C494E4D6C796DLLU, // mjq_Mlym_IN + 0xC52C494E4D6C796DLLU, // mjr_Mlym_IN + 0xC92C4E474C61746ELLU, // mjs_Latn_NG + 0xCD2C494E44657661LLU, // mjt_Deva_IN + 0xD12C494E54656C75LLU, // mju_Telu_IN + 0xD52C494E4D6C796DLLU, // mjv_Mlym_IN + 0xD92C494E4C61746ELLU, // mjw_Latn_IN + 0xDD2C42444C61746ELLU, // mjx_Latn_BD + 0xE12C55534C61746ELLU, // mjy_Latn_US + 0xE52C4E5044657661LLU, // mjz_Deva_NP 0x6D6B4D4B4379726CLLU, // mk_Cyrl_MK + 0x814C43494C61746ELLU, // mka_Latn_CI + 0x854C494E44657661LLU, // mkb_Deva_IN + 0x894C50474C61746ELLU, // mkc_Latn_PG + 0x914C494E44657661LLU, // mke_Deva_IN + 0x954C4E474C61746ELLU, // mkf_Latn_NG + 0xA14C504B41726162LLU, // mki_Arab_PK + 0xA54C464D4C61746ELLU, // mkj_Latn_FM + 0xA94C434D4C61746ELLU, // mkk_Latn_CM + 0xAD4C424A4C61746ELLU, // mkl_Latn_BJ + 0xB14C544854686169LLU, // mkm_Thai_TH + 0xB54C49444C61746ELLU, // mkn_Latn_ID + 0xB94C4E474C61746ELLU, // mko_Latn_NG + 0xBD4C50474C61746ELLU, // mkp_Latn_PG + 0xC54C50474C61746ELLU, // mkr_Latn_PG + 0xC94C4D584C61746ELLU, // mks_Latn_MX + 0xCD4C4E434C61746ELLU, // mkt_Latn_NC + 0xD14C474E4C61746ELLU, // mku_Latn_GN + 0xD54C56554C61746ELLU, // mkv_Latn_VU + 0xD94C43474C61746ELLU, // mkw_Latn_CG + 0xDD4C50484C61746ELLU, // mkx_Latn_PH + 0xE14C49444C61746ELLU, // mky_Latn_ID + 0xE54C544C4C61746ELLU, // mkz_Latn_TL 0x6D6C494E4D6C796DLLU, // ml_Mlym_IN + 0x816C56554C61746ELLU, // mla_Latn_VU + 0x856C434D4C61746ELLU, // mlb_Latn_CM + 0x896C564E4C61746ELLU, // mlc_Latn_VN + 0x916C50474C61746ELLU, // mle_Latn_PG + 0x956C4C4154686169LLU, // mlf_Thai_LA + 0x9D6C50474C61746ELLU, // mlh_Latn_PG + 0xA16C49444C61746ELLU, // mli_Latn_ID + 0xA56C54444C61746ELLU, // mlj_Latn_TD + 0xA96C4B454C61746ELLU, // mlk_Latn_KE + 0xAD6C56554C61746ELLU, // mll_Latn_VU + 0xB56C53424C61746ELLU, // mln_Latn_SB + 0xB96C534E4C61746ELLU, // mlo_Latn_SN + 0xBD6C50474C61746ELLU, // mlp_Latn_PG + 0xC16C534E4C61746ELLU, // mlq_Latn_SN + 0xC56C434D4C61746ELLU, // mlr_Latn_CM 0xC96C53444C61746ELLU, // mls_Latn_SD + 0xD16C53424C61746ELLU, // mlu_Latn_SB + 0xD56C56554C61746ELLU, // mlv_Latn_VU + 0xD96C434D4C61746ELLU, // mlw_Latn_CM + 0xDD6C56554C61746ELLU, // mlx_Latn_VU + 0xE56C50484C61746ELLU, // mlz_Latn_PH + 0x818C4E474C61746ELLU, // mma_Latn_NG + 0x858C49444C61746ELLU, // mmb_Latn_ID + 0x898C4D584C61746ELLU, // mmc_Latn_MX + 0x8D8C434E4C61746ELLU, // mmd_Latn_CN + 0x918C56554C61746ELLU, // mme_Latn_VU + 0x958C4E474C61746ELLU, // mmf_Latn_NG + 0x998C56554C61746ELLU, // mmg_Latn_VU + 0x9D8C42524C61746ELLU, // mmh_Latn_BR + 0xA18C50474C61746ELLU, // mmi_Latn_PG + 0xB18C56554C61746ELLU, // mmm_Latn_VU + 0xB58C50484C61746ELLU, // mmn_Latn_PH + 0xB98C50474C61746ELLU, // mmo_Latn_PG + 0xBD8C50474C61746ELLU, // mmp_Latn_PG + 0xC18C50474C61746ELLU, // mmq_Latn_PG + 0xC58C434E4C61746ELLU, // mmr_Latn_CN + 0xCD8C50474C61746ELLU, // mmt_Latn_PG + 0xD18C434D4C61746ELLU, // mmu_Latn_CM + 0xD58C42524C61746ELLU, // mmv_Latn_BR + 0xD98C56554C61746ELLU, // mmw_Latn_VU + 0xDD8C50474C61746ELLU, // mmx_Latn_PG + 0xE18C54444C61746ELLU, // mmy_Latn_TD + 0xE58C43444C61746ELLU, // mmz_Latn_CD 0x6D6E4D4E4379726CLLU, // mn_Cyrl_MN 0x6D6E434E4D6F6E67LLU, // mn_Mong_CN + 0x81AC50474C61746ELLU, // mna_Latn_PG + 0x85AC49444C61746ELLU, // mnb_Latn_ID + 0x89AC434E4D6F6E67LLU, // mnc_Mong_CN + 0x8DAC42524C61746ELLU, // mnd_Latn_BR + 0x91AC54444C61746ELLU, // mne_Latn_TD + 0x95AC434D4C61746ELLU, // mnf_Latn_CM + 0x99AC564E4C61746ELLU, // mng_Latn_VN + 0x9DAC43444C61746ELLU, // mnh_Latn_CD 0xA1AC494E42656E67LLU, // mni_Beng_IN + 0xA5AC414641726162LLU, // mnj_Arab_AF + 0xADAC56554C61746ELLU, // mnl_Latn_VU + 0xB1AC50474C61746ELLU, // mnm_Latn_PG + 0xB5AC564E4C61746ELLU, // mnn_Latn_VN + 0xBDAC434E4C61746ELLU, // mnp_Latn_CN + 0xC1AC4D594C61746ELLU, // mnq_Latn_MY + 0xC5AC55534C61746ELLU, // mnr_Latn_US + 0xC9AC52554379726CLLU, // mns_Cyrl_RU + 0xD1AC49444C61746ELLU, // mnu_Latn_ID + 0xD5AC53424C61746ELLU, // mnv_Latn_SB 0xD9AC4D4D4D796D72LLU, // mnw_Mymr_MM + 0xDDAC49444C61746ELLU, // mnx_Latn_ID + 0xE1AC4D5A4C61746ELLU, // mny_Latn_MZ + 0xE5AC49444C61746ELLU, // mnz_Latn_ID 0x6D6F524F4C61746ELLU, // mo_Latn_RO + 0x81CC43494C61746ELLU, // moa_Latn_CI + 0x89CC41524C61746ELLU, // moc_Latn_AR + 0x8DCC55534C61746ELLU, // mod_Latn_US 0x91CC43414C61746ELLU, // moe_Latn_CA + 0x99CC49444C61746ELLU, // mog_Latn_ID 0x9DCC43414C61746ELLU, // moh_Latn_CA + 0xA1CC4E474C61746ELLU, // moi_Latn_NG + 0xA5CC43474C61746ELLU, // moj_Latn_CG + 0xA9CC49444C61746ELLU, // mok_Latn_ID + 0xB1CC4E494C61746ELLU, // mom_Latn_NI + 0xB9CC564E4C61746ELLU, // moo_Latn_VN + 0xBDCC425A4C61746ELLU, // mop_Latn_BZ + 0xC1CC49444C61746ELLU, // moq_Latn_ID + 0xC5CC53444C61746ELLU, // mor_Latn_SD 0xC9CC42464C61746ELLU, // mos_Latn_BF + 0xCDCC434F4C61746ELLU, // mot_Latn_CO + 0xD1CC54444C61746ELLU, // mou_Latn_TD + 0xD5CC55534C61746ELLU, // mov_Latn_US + 0xD9CC43474C61746ELLU, // mow_Latn_CG + 0xDDCC50474C61746ELLU, // mox_Latn_PG + 0xE1CC45544C61746ELLU, // moy_Latn_ET + 0xE5CC54444C61746ELLU, // moz_Latn_TD + 0x81EC545A4C61746ELLU, // mpa_Latn_TZ + 0x85EC41554C61746ELLU, // mpb_Latn_AU + 0x89EC41554C61746ELLU, // mpc_Latn_AU + 0x8DEC42524C61746ELLU, // mpd_Latn_BR + 0x91EC45544C61746ELLU, // mpe_Latn_ET + 0x99EC54444C61746ELLU, // mpg_Latn_TD + 0x9DEC41554C61746ELLU, // mph_Latn_AU + 0xA1EC434D4C61746ELLU, // mpi_Latn_CM + 0xA5EC41554C61746ELLU, // mpj_Latn_AU + 0xA9EC54444C61746ELLU, // mpk_Latn_TD + 0xADEC50474C61746ELLU, // mpl_Latn_PG + 0xB1EC4D584C61746ELLU, // mpm_Latn_MX + 0xB5EC50474C61746ELLU, // mpn_Latn_PG + 0xB9EC50474C61746ELLU, // mpo_Latn_PG + 0xBDEC50474C61746ELLU, // mpp_Latn_PG + 0xC1EC42524C61746ELLU, // mpq_Latn_BR + 0xC5EC53424C61746ELLU, // mpr_Latn_SB + 0xC9EC50474C61746ELLU, // mps_Latn_PG + 0xCDEC50474C61746ELLU, // mpt_Latn_PG + 0xD1EC42524C61746ELLU, // mpu_Latn_BR + 0xD5EC50474C61746ELLU, // mpv_Latn_PG + 0xD9EC42524C61746ELLU, // mpw_Latn_BR + 0xDDEC50474C61746ELLU, // mpx_Latn_PG + 0xE1EC49444C61746ELLU, // mpy_Latn_ID + 0xE5EC544854686169LLU, // mpz_Thai_TH + 0x820C49444C61746ELLU, // mqa_Latn_ID + 0x860C434D4C61746ELLU, // mqb_Latn_CM + 0x8A0C49444C61746ELLU, // mqc_Latn_ID + 0x920C50474C61746ELLU, // mqe_Latn_PG + 0x960C49444C61746ELLU, // mqf_Latn_ID + 0x9A0C49444C61746ELLU, // mqg_Latn_ID + 0x9E0C4D584C61746ELLU, // mqh_Latn_MX + 0xA20C49444C61746ELLU, // mqi_Latn_ID + 0xA60C49444C61746ELLU, // mqj_Latn_ID + 0xAA0C50484C61746ELLU, // mqk_Latn_PH + 0xAE0C424A4C61746ELLU, // mql_Latn_BJ + 0xB20C50464C61746ELLU, // mqm_Latn_PF + 0xB60C49444C61746ELLU, // mqn_Latn_ID + 0xBA0C49444C61746ELLU, // mqo_Latn_ID + 0xBE0C49444C61746ELLU, // mqp_Latn_ID + 0xC20C4D594C61746ELLU, // mqq_Latn_MY + 0xC60C49444C61746ELLU, // mqr_Latn_ID + 0xCA0C49444C61746ELLU, // mqs_Latn_ID + 0xD20C53534C61746ELLU, // mqu_Latn_SS + 0xD60C50474C61746ELLU, // mqv_Latn_PG + 0xDA0C50474C61746ELLU, // mqw_Latn_PG + 0xDE0C49444C61746ELLU, // mqx_Latn_ID + 0xE20C49444C61746ELLU, // mqy_Latn_ID + 0xE60C50474C61746ELLU, // mqz_Latn_PG 0x6D72494E44657661LLU, // mr_Deva_IN + 0x822C544854686169LLU, // mra_Thai_TH + 0x862C56554C61746ELLU, // mrb_Latn_VU + 0x8A2C55534C61746ELLU, // mrc_Latn_US 0x8E2C4E5044657661LLU, // mrd_Deva_NP + 0x962C49444C61746ELLU, // mrf_Latn_ID + 0x9A2C494E4C61746ELLU, // mrg_Latn_IN + 0x9E2C494E4C61746ELLU, // mrh_Latn_IN 0xA62C52554379726CLLU, // mrj_Cyrl_RU + 0xAA2C4E434C61746ELLU, // mrk_Latn_NC + 0xAE2C464D4C61746ELLU, // mrl_Latn_FM + 0xB22C56554C61746ELLU, // mrm_Latn_VU + 0xB62C53424C61746ELLU, // mrn_Latn_SB 0xBA2C42444D726F6FLLU, // mro_Mroo_BD + 0xBE2C56554C61746ELLU, // mrp_Latn_VU + 0xC22C50464C61746ELLU, // mrq_Latn_PF + 0xC62C494E44657661LLU, // mrr_Deva_IN + 0xCA2C56554C61746ELLU, // mrs_Latn_VU + 0xCE2C4E474C61746ELLU, // mrt_Latn_NG + 0xD22C434D4C61746ELLU, // mru_Latn_CM + 0xD62C50464C61746ELLU, // mrv_Latn_PF + 0xDA2C50484C61746ELLU, // mrw_Latn_PH + 0xDE2C49444C61746ELLU, // mrx_Latn_ID + 0xE22C50484C61746ELLU, // mry_Latn_PH + 0xE62C49444C61746ELLU, // mrz_Latn_ID 0x6D734D594C61746ELLU, // ms_Latn_MY + 0x864C50484C61746ELLU, // msb_Latn_PH + 0x8A4C474E4C61746ELLU, // msc_Latn_GN + 0x924C54444C61746ELLU, // mse_Latn_TD + 0x964C49444C61746ELLU, // msf_Latn_ID + 0x9A4C49444C61746ELLU, // msg_Latn_ID + 0x9E4C4D474C61746ELLU, // msh_Latn_MG + 0xA24C4D594C61746ELLU, // msi_Latn_MY + 0xA64C43444C61746ELLU, // msj_Latn_CD + 0xAA4C50484C61746ELLU, // msk_Latn_PH + 0xAE4C49444C61746ELLU, // msl_Latn_ID + 0xB24C50484C61746ELLU, // msm_Latn_PH + 0xB64C56554C61746ELLU, // msn_Latn_VU + 0xBA4C49444C61746ELLU, // mso_Latn_ID + 0xBE4C42524C61746ELLU, // msp_Latn_BR + 0xC24C4E434C61746ELLU, // msq_Latn_NC + 0xCA4C49444C61746ELLU, // mss_Latn_ID + 0xD24C50474C61746ELLU, // msu_Latn_PG + 0xD64C434D4C61746ELLU, // msv_Latn_CM + 0xDA4C47574C61746ELLU, // msw_Latn_GW + 0xDE4C50474C61746ELLU, // msx_Latn_PG + 0xE24C50474C61746ELLU, // msy_Latn_PG + 0xE64C50474C61746ELLU, // msz_Latn_PG 0x6D744D544C61746ELLU, // mt_Latn_MT + 0x826C50484C61746ELLU, // mta_Latn_PH + 0x866C43494C61746ELLU, // mtb_Latn_CI + 0x8A6C50474C61746ELLU, // mtc_Latn_PG + 0x8E6C49444C61746ELLU, // mtd_Latn_ID + 0x926C53424C61746ELLU, // mte_Latn_SB + 0x966C50474C61746ELLU, // mtf_Latn_PG + 0x9A6C49444C61746ELLU, // mtg_Latn_ID + 0x9E6C49444C61746ELLU, // mth_Latn_ID + 0xA26C50474C61746ELLU, // mti_Latn_PG + 0xA66C49444C61746ELLU, // mtj_Latn_ID + 0xAA6C434D4C61746ELLU, // mtk_Latn_CM + 0xAE6C4E474C61746ELLU, // mtl_Latn_NG + 0xB26C52554379726CLLU, // mtm_Cyrl_RU + 0xB66C4E494C61746ELLU, // mtn_Latn_NI + 0xBA6C4D584C61746ELLU, // mto_Latn_MX + 0xBE6C424F4C61746ELLU, // mtp_Latn_BO + 0xC26C564E4C61746ELLU, // mtq_Latn_VN 0xC66C494E44657661LLU, // mtr_Deva_IN + 0xCA6C50454C61746ELLU, // mts_Latn_PE + 0xCE6C56554C61746ELLU, // mtt_Latn_VU + 0xD26C4D584C61746ELLU, // mtu_Latn_MX + 0xD66C50474C61746ELLU, // mtv_Latn_PG + 0xDA6C50484C61746ELLU, // mtw_Latn_PH + 0xDE6C4D584C61746ELLU, // mtx_Latn_MX + 0xE26C50474C61746ELLU, // mty_Latn_PG 0x828C434D4C61746ELLU, // mua_Latn_CM + 0x868C54444C61746ELLU, // mub_Latn_TD + 0x8A8C434D4C61746ELLU, // muc_Latn_CM + 0x8E8C52554379726CLLU, // mud_Cyrl_RU + 0x928C45434C61746ELLU, // mue_Latn_EC + 0x9A8C434D4C61746ELLU, // mug_Latn_CM + 0x9E8C53534C61746ELLU, // muh_Latn_SS + 0xA28C49444C61746ELLU, // mui_Latn_ID + 0xA68C54444C61746ELLU, // muj_Latn_TD + 0xAA8C4E5054696274LLU, // muk_Tibt_NP + 0xB28C50474C61746ELLU, // mum_Latn_PG + 0xBA8C434D4C61746ELLU, // muo_Latn_CM + 0xC28C434E4C61746ELLU, // muq_Latn_CN + 0xC68C53534C61746ELLU, // mur_Latn_SS 0xCA8C55534C61746ELLU, // mus_Latn_US + 0xCE8C494E44657661LLU, // mut_Deva_IN + 0xD28C4B454C61746ELLU, // muu_Latn_KE + 0xD68C494E54616D6CLLU, // muv_Taml_IN + 0xDE8C50474C61746ELLU, // mux_Latn_PG + 0xE28C434D4C61746ELLU, // muy_Latn_CM + 0xE68C455445746869LLU, // muz_Ethi_ET + 0x82AC50474C61746ELLU, // mva_Latn_PG + 0x8EAC49444C61746ELLU, // mvd_Latn_ID + 0x92AC504B41726162LLU, // mve_Arab_PK + 0x96AC434E4D6F6E67LLU, // mvf_Mong_CN + 0x9AAC4D584C61746ELLU, // mvg_Latn_MX + 0x9EAC54444C61746ELLU, // mvh_Latn_TD + 0xAAAC50474C61746ELLU, // mvk_Latn_PG + 0xAEAC41554C61746ELLU, // mvl_Latn_AU + 0xB6AC50474C61746ELLU, // mvn_Latn_PG + 0xBAAC53424C61746ELLU, // mvo_Latn_SB + 0xBEAC49444C61746ELLU, // mvp_Latn_ID + 0xC2AC50474C61746ELLU, // mvq_Latn_PG + 0xC6AC49444C61746ELLU, // mvr_Latn_ID + 0xCAAC49444C61746ELLU, // mvs_Latn_ID + 0xCEAC56554C61746ELLU, // mvt_Latn_VU + 0xD2AC54444C61746ELLU, // mvu_Latn_TD + 0xD6AC4D594C61746ELLU, // mvv_Latn_MY + 0xDAAC545A4C61746ELLU, // mvw_Latn_TZ + 0xDEAC49444C61746ELLU, // mvx_Latn_ID 0xE2AC504B41726162LLU, // mvy_Arab_PK + 0xE6AC455445746869LLU, // mvz_Ethi_ET + 0x82CC50474C61746ELLU, // mwa_Latn_PG + 0x86CC50474C61746ELLU, // mwb_Latn_PG + 0x8ACC50474C61746ELLU, // mwc_Latn_PG + 0x92CC545A4C61746ELLU, // mwe_Latn_TZ + 0x96CC41554C61746ELLU, // mwf_Latn_AU + 0x9ACC50474C61746ELLU, // mwg_Latn_PG + 0x9ECC50474C61746ELLU, // mwh_Latn_PG + 0xA2CC56554C61746ELLU, // mwi_Latn_VU 0xAACC4D4C4C61746ELLU, // mwk_Latn_ML + 0xAECC50544C61746ELLU, // mwl_Latn_PT + 0xB2CC54444C61746ELLU, // mwm_Latn_TD + 0xB6CC5A4D4C61746ELLU, // mwn_Latn_ZM + 0xBACC56554C61746ELLU, // mwo_Latn_VU + 0xBECC41554C61746ELLU, // mwp_Latn_AU + 0xC2CC4D4D4C61746ELLU, // mwq_Latn_MM 0xC6CC494E44657661LLU, // mwr_Deva_IN + 0xCACC4B454C61746ELLU, // mws_Latn_KE + 0xCECC4D4D4D796D72LLU, // mwt_Mymr_MM + 0xD2CC53534C61746ELLU, // mwu_Latn_SS 0xD6CC49444C61746ELLU, // mwv_Latn_ID 0xDACC5553486D6E70LLU, // mww_Hmnp_US + 0xE6CC43444C61746ELLU, // mwz_Latn_CD + 0x82EC4D584C61746ELLU, // mxa_Latn_MX + 0x86EC4D584C61746ELLU, // mxb_Latn_MX 0x8AEC5A574C61746ELLU, // mxc_Latn_ZW + 0x8EEC49444C61746ELLU, // mxd_Latn_ID + 0x92EC56554C61746ELLU, // mxe_Latn_VU + 0x96EC434D4C61746ELLU, // mxf_Latn_CM + 0x9AEC414F4C61746ELLU, // mxg_Latn_AO + 0x9EEC43444C61746ELLU, // mxh_Latn_CD + 0xA2EC45534C61746ELLU, // mxi_Latn_ES + 0xA6EC494E4C61746ELLU, // mxj_Latn_IN + 0xAAEC50474C61746ELLU, // mxk_Latn_PG + 0xAEEC424A4C61746ELLU, // mxl_Latn_BJ + 0xB2EC50474C61746ELLU, // mxm_Latn_PG + 0xB6EC49444C61746ELLU, // mxn_Latn_ID + 0xBAEC5A4D4C61746ELLU, // mxo_Latn_ZM + 0xBEEC4D584C61746ELLU, // mxp_Latn_MX + 0xC2EC4D584C61746ELLU, // mxq_Latn_MX + 0xC6EC4D594C61746ELLU, // mxr_Latn_MY + 0xCAEC4D584C61746ELLU, // mxs_Latn_MX + 0xCEEC4D584C61746ELLU, // mxt_Latn_MX + 0xD2EC434D4C61746ELLU, // mxu_Latn_CM + 0xD6EC4D584C61746ELLU, // mxv_Latn_MX + 0xDAEC50474C61746ELLU, // mxw_Latn_PG + 0xDEEC43494C61746ELLU, // mxx_Latn_CI + 0xE2EC4D584C61746ELLU, // mxy_Latn_MX + 0xE6EC49444C61746ELLU, // mxz_Latn_ID 0x6D794D4D4D796D72LLU, // my_Mymr_MM + 0x870C54444C61746ELLU, // myb_Latn_TD + 0x8B0C43444C61746ELLU, // myc_Latn_CD + 0x930C47414C61746ELLU, // mye_Latn_GA + 0x970C45544C61746ELLU, // myf_Latn_ET + 0x9B0C434D4C61746ELLU, // myg_Latn_CM + 0x9F0C55534C61746ELLU, // myh_Latn_US + 0xA70C53534C61746ELLU, // myj_Latn_SS + 0xAB0C4D4C4C61746ELLU, // myk_Latn_ML + 0xAF0C49444C61746ELLU, // myl_Latn_ID + 0xB30C455445746869LLU, // mym_Ethi_ET + 0xBF0C42524C61746ELLU, // myp_Latn_BR + 0xC70C50454C61746ELLU, // myr_Latn_PE + 0xD30C42524C61746ELLU, // myu_Latn_BR 0xD70C52554379726CLLU, // myv_Cyrl_RU + 0xDB0C50474C61746ELLU, // myw_Latn_PG 0xDF0C55474C61746ELLU, // myx_Latn_UG + 0xE30C434F4C61746ELLU, // myy_Latn_CO 0xE70C49524D616E64LLU, // myz_Mand_IR + 0x832C4D584C61746ELLU, // mza_Latn_MX + 0x8F2C434D4C61746ELLU, // mzd_Latn_CM + 0x932C50474C61746ELLU, // mze_Latn_PG + 0x9F2C41524C61746ELLU, // mzh_Latn_AR + 0xA32C4D584C61746ELLU, // mzi_Latn_MX + 0xA72C4C524C61746ELLU, // mzj_Latn_LR + 0xAB2C4E474C61746ELLU, // mzk_Latn_NG + 0xAF2C4D584C61746ELLU, // mzl_Latn_MX + 0xB32C4E474C61746ELLU, // mzm_Latn_NG 0xB72C495241726162LLU, // mzn_Arab_IR + 0xBB2C42524C61746ELLU, // mzo_Latn_BR + 0xBF2C424F4C61746ELLU, // mzp_Latn_BO + 0xC32C49444C61746ELLU, // mzq_Latn_ID + 0xC72C42524C61746ELLU, // mzr_Latn_BR + 0xCF2C4D594C61746ELLU, // mzt_Latn_MY + 0xD32C50474C61746ELLU, // mzu_Latn_PG + 0xD72C43464C61746ELLU, // mzv_Latn_CF + 0xDB2C47484C61746ELLU, // mzw_Latn_GH + 0xDF2C47594C61746ELLU, // mzx_Latn_GY + 0xE72C50474C61746ELLU, // mzz_Latn_PG 0x6E614E524C61746ELLU, // na_Latn_NR + 0x800D49444C61746ELLU, // naa_Latn_ID + 0x840D42524C61746ELLU, // nab_Latn_BR + 0x880D50474C61746ELLU, // nac_Latn_PG + 0x900D49444C61746ELLU, // nae_Latn_ID + 0x940D50474C61746ELLU, // naf_Latn_PG + 0x980D494E4C61746ELLU, // nag_Latn_IN + 0xA40D474E4C61746ELLU, // naj_Latn_GN + 0xA80D50474C61746ELLU, // nak_Latn_PG + 0xAC0D50474C61746ELLU, // nal_Latn_PG + 0xB00D41554C61746ELLU, // nam_Latn_AU 0xB40D434E48616E73LLU, // nan_Hans_CN + 0xB80D4E5044657661LLU, // nao_Deva_NP 0xBC0D49544C61746ELLU, // nap_Latn_IT 0xC00D4E414C61746ELLU, // naq_Latn_NA + 0xC40D4E474C61746ELLU, // nar_Latn_NG + 0xC80D50474C61746ELLU, // nas_Latn_PG + 0xCC0D4E474C61746ELLU, // nat_Latn_NG + 0xD80D47484C61746ELLU, // naw_Latn_GH + 0xDC0D50474C61746ELLU, // nax_Latn_PG + 0xE00D41554C61746ELLU, // nay_Latn_AU + 0xE40D4D584C61746ELLU, // naz_Latn_MX 0x6E624E4F4C61746ELLU, // nb_Latn_NO + 0x802D414F4C61746ELLU, // nba_Latn_AO + 0x842D4E474C61746ELLU, // nbb_Latn_NG + 0x882D494E4C61746ELLU, // nbc_Latn_IN + 0x8C2D43444C61746ELLU, // nbd_Latn_CD + 0x902D494E4C61746ELLU, // nbe_Latn_IN + 0x9C2D4E474C61746ELLU, // nbh_Latn_NG + 0xA02D494E4C61746ELLU, // nbi_Latn_IN + 0xA42D41554C61746ELLU, // nbj_Latn_AU + 0xA82D50474C61746ELLU, // nbk_Latn_PG + 0xB02D43464C61746ELLU, // nbm_Latn_CF + 0xB42D49444C61746ELLU, // nbn_Latn_ID + 0xB82D4E474C61746ELLU, // nbo_Latn_NG + 0xBC2D4E474C61746ELLU, // nbp_Latn_NG + 0xC02D49444C61746ELLU, // nbq_Latn_ID + 0xC42D4E474C61746ELLU, // nbr_Latn_NG + 0xCC2D494E4C61746ELLU, // nbt_Latn_IN + 0xD02D494E4C61746ELLU, // nbu_Latn_IN + 0xD42D434D4C61746ELLU, // nbv_Latn_CM + 0xD82D43444C61746ELLU, // nbw_Latn_CD + 0xE02D50474C61746ELLU, // nby_Latn_PG + 0x804D50474C61746ELLU, // nca_Latn_PG + 0x844D494E4C61746ELLU, // ncb_Latn_IN + 0x884D50474C61746ELLU, // ncc_Latn_PG + 0x8C4D4E5044657661LLU, // ncd_Deva_NP + 0x904D50474C61746ELLU, // nce_Latn_PG + 0x944D50474C61746ELLU, // ncf_Latn_PG + 0x984D43414C61746ELLU, // ncg_Latn_CA 0x9C4D4D584C61746ELLU, // nch_Latn_MX + 0xA04D4D584C61746ELLU, // nci_Latn_MX + 0xA44D4D584C61746ELLU, // ncj_Latn_MX + 0xA84D41554C61746ELLU, // nck_Latn_AU + 0xAC4D4D584C61746ELLU, // ncl_Latn_MX + 0xB04D50474C61746ELLU, // ncm_Latn_PG + 0xB44D50474C61746ELLU, // ncn_Latn_PG + 0xB84D50474C61746ELLU, // nco_Latn_PG + 0xC04D4C414C616F6FLLU, // ncq_Laoo_LA + 0xC44D434D4C61746ELLU, // ncr_Latn_CM + 0xCC4D494E4C61746ELLU, // nct_Latn_IN + 0xD04D47484C61746ELLU, // ncu_Latn_GH + 0xDC4D4D584C61746ELLU, // ncx_Latn_MX + 0xE44D55534C61746ELLU, // ncz_Latn_US 0x6E645A574C61746ELLU, // nd_Latn_ZW + 0x806D43474C61746ELLU, // nda_Latn_CG + 0x846D434D4C61746ELLU, // ndb_Latn_CM 0x886D4D5A4C61746ELLU, // ndc_Latn_MZ + 0x8C6D4E474C61746ELLU, // ndd_Latn_NG + 0x946D52554379726CLLU, // ndf_Cyrl_RU + 0x986D545A4C61746ELLU, // ndg_Latn_TZ + 0x9C6D545A4C61746ELLU, // ndh_Latn_TZ + 0xA06D4E474C61746ELLU, // ndi_Latn_NG + 0xA46D545A4C61746ELLU, // ndj_Latn_TZ + 0xA86D43444C61746ELLU, // ndk_Latn_CD + 0xAC6D43444C61746ELLU, // ndl_Latn_CD + 0xB06D54444C61746ELLU, // ndm_Latn_TD + 0xB46D43474C61746ELLU, // ndn_Latn_CG + 0xBC6D55474C61746ELLU, // ndp_Latn_UG + 0xC06D414F4C61746ELLU, // ndq_Latn_AO + 0xC46D4E474C61746ELLU, // ndr_Latn_NG 0xC86D44454C61746ELLU, // nds_Latn_DE + 0xCC6D43444C61746ELLU, // ndt_Latn_CD + 0xD06D434D4C61746ELLU, // ndu_Latn_CM + 0xD46D534E4C61746ELLU, // ndv_Latn_SN + 0xD86D43444C61746ELLU, // ndw_Latn_CD + 0xDC6D49444C61746ELLU, // ndx_Latn_ID + 0xE06D43464C61746ELLU, // ndy_Latn_CF + 0xE46D53534C61746ELLU, // ndz_Latn_SS 0x6E654E5044657661LLU, // ne_Deva_NP + 0x808D49444C61746ELLU, // nea_Latn_ID + 0x848D43494C61746ELLU, // neb_Latn_CI + 0x888D49444C61746ELLU, // nec_Latn_ID + 0x8C8D4E474C61746ELLU, // ned_Latn_NG + 0x908D4E434C61746ELLU, // nee_Latn_NC + 0x988D52554379726CLLU, // neg_Cyrl_RU + 0x9C8D425454696274LLU, // neh_Tibt_BT + 0xA08D545258737578LLU, // nei_Xsux_TR + 0xA48D50474C61746ELLU, // nej_Latn_PG + 0xA88D4E434C61746ELLU, // nek_Latn_NC + 0xB08D4E434C61746ELLU, // nem_Latn_NC + 0xB48D4E434C61746ELLU, // nen_Latn_NC + 0xB88D564E4C61746ELLU, // neo_Latn_VN + 0xC08D4D584C61746ELLU, // neq_Latn_MX + 0xC48D49444C61746ELLU, // ner_Latn_ID + 0xCC8D50474C61746ELLU, // net_Latn_PG 0xD88D4E5044657661LLU, // new_Deva_NP + 0xDC8D50474C61746ELLU, // nex_Latn_PG + 0xE08D43494C61746ELLU, // ney_Latn_CI + 0xE48D55534C61746ELLU, // nez_Latn_US + 0x80AD49444C61746ELLU, // nfa_Latn_ID + 0x8CAD4E474C61746ELLU, // nfd_Latn_NG + 0xACAD53424C61746ELLU, // nfl_Latn_SB + 0xC4AD47484C61746ELLU, // nfr_Latn_GH + 0xD0AD434D4C61746ELLU, // nfu_Latn_CM 0x6E674E414C61746ELLU, // ng_Latn_NA + 0x80CD43444C61746ELLU, // nga_Latn_CD + 0x84CD43444C61746ELLU, // ngb_Latn_CD + 0x88CD43444C61746ELLU, // ngc_Latn_CD + 0x8CCD43464C61746ELLU, // ngd_Latn_CF + 0x90CD434D4C61746ELLU, // nge_Latn_CM + 0x98CD43464C61746ELLU, // ngg_Latn_CF + 0x9CCD5A414C61746ELLU, // ngh_Latn_ZA + 0xA0CD4E474C61746ELLU, // ngi_Latn_NG + 0xA4CD434D4C61746ELLU, // ngj_Latn_CM + 0xA8CD41554C61746ELLU, // ngk_Latn_AU 0xACCD4D5A4C61746ELLU, // ngl_Latn_MZ + 0xB0CD464D4C61746ELLU, // ngm_Latn_FM + 0xB4CD434D4C61746ELLU, // ngn_Latn_CM + 0xBCCD545A4C61746ELLU, // ngp_Latn_TZ + 0xC0CD545A4C61746ELLU, // ngq_Latn_TZ + 0xC4CD53424C61746ELLU, // ngr_Latn_SB + 0xC8CD4E474C61746ELLU, // ngs_Latn_NG + 0xCCCD4C414C616F6FLLU, // ngt_Laoo_LA + 0xD0CD4D584C61746ELLU, // ngu_Latn_MX + 0xD4CD434D4C61746ELLU, // ngv_Latn_CM + 0xD8CD4E474C61746ELLU, // ngw_Latn_NG + 0xDCCD4E474C61746ELLU, // ngx_Latn_NG + 0xE0CD434D4C61746ELLU, // ngy_Latn_CM + 0xE4CD43474C61746ELLU, // ngz_Latn_CG + 0x80ED41554C61746ELLU, // nha_Latn_AU + 0x84ED43494C61746ELLU, // nhb_Latn_CI + 0x88ED4D584C61746ELLU, // nhc_Latn_MX + 0x8CED50594C61746ELLU, // nhd_Latn_PY 0x90ED4D584C61746ELLU, // nhe_Latn_MX + 0x94ED41554C61746ELLU, // nhf_Latn_AU + 0x98ED4D584C61746ELLU, // nhg_Latn_MX + 0xA0ED4D584C61746ELLU, // nhi_Latn_MX + 0xA8ED4D584C61746ELLU, // nhk_Latn_MX + 0xB0ED4D584C61746ELLU, // nhm_Latn_MX + 0xB4ED4D584C61746ELLU, // nhn_Latn_MX + 0xB8ED50474C61746ELLU, // nho_Latn_PG + 0xBCED4D584C61746ELLU, // nhp_Latn_MX + 0xC0ED4D584C61746ELLU, // nhq_Latn_MX + 0xC4ED42574C61746ELLU, // nhr_Latn_BW + 0xCCED4D584C61746ELLU, // nht_Latn_MX + 0xD0ED434D4C61746ELLU, // nhu_Latn_CM + 0xD4ED4D584C61746ELLU, // nhv_Latn_MX 0xD8ED4D584C61746ELLU, // nhw_Latn_MX + 0xDCED4D584C61746ELLU, // nhx_Latn_MX + 0xE0ED4D584C61746ELLU, // nhy_Latn_MX + 0xE4ED4D584C61746ELLU, // nhz_Latn_MX + 0x810D49444C61746ELLU, // nia_Latn_ID + 0x850D50474C61746ELLU, // nib_Latn_PG + 0x8D0D41554C61746ELLU, // nid_Latn_AU + 0x910D54444C61746ELLU, // nie_Latn_TD + 0x950D50474C61746ELLU, // nif_Latn_PG + 0x990D41554C61746ELLU, // nig_Latn_AU + 0x9D0D545A4C61746ELLU, // nih_Latn_TZ + 0xA10D50474C61746ELLU, // nii_Latn_PG 0xA50D49444C61746ELLU, // nij_Latn_ID + 0xAD0D49444C61746ELLU, // nil_Latn_ID + 0xB10D545A4C61746ELLU, // nim_Latn_TZ + 0xB50D4E474C61746ELLU, // nin_Latn_NG + 0xB90D52554379726CLLU, // nio_Cyrl_RU + 0xC10D4B454C61746ELLU, // niq_Latn_KE + 0xC50D49444C61746ELLU, // nir_Latn_ID + 0xC90D50474C61746ELLU, // nis_Latn_PG + 0xCD0D494E54656C75LLU, // nit_Telu_IN 0xD10D4E554C61746ELLU, // niu_Latn_NU + 0xD50D52554379726CLLU, // niv_Cyrl_RU + 0xD90D50474C61746ELLU, // niw_Latn_PG + 0xDD0D43444C61746ELLU, // nix_Latn_CD + 0xE10D43444C61746ELLU, // niy_Latn_CD + 0xE50D50474C61746ELLU, // niz_Latn_PG + 0x812D4E474C61746ELLU, // nja_Latn_NG + 0x852D494E4C61746ELLU, // njb_Latn_IN + 0x8D2D545A4C61746ELLU, // njd_Latn_TZ + 0x9D2D494E4C61746ELLU, // njh_Latn_IN + 0xA12D41554C61746ELLU, // nji_Latn_AU + 0xA52D434D4C61746ELLU, // njj_Latn_CM + 0xAD2D53534C61746ELLU, // njl_Latn_SS + 0xB12D494E4C61746ELLU, // njm_Latn_IN + 0xB52D494E4C61746ELLU, // njn_Latn_IN 0xB92D494E4C61746ELLU, // njo_Latn_IN + 0xC52D4E474C61746ELLU, // njr_Latn_NG + 0xC92D49444C61746ELLU, // njs_Latn_ID + 0xCD2D53524C61746ELLU, // njt_Latn_SR + 0xD12D41554C61746ELLU, // nju_Latn_AU + 0xDD2D43474C61746ELLU, // njx_Latn_CG + 0xE12D434D4C61746ELLU, // njy_Latn_CM + 0xE52D494E4C61746ELLU, // njz_Latn_IN + 0x814D5A4D4C61746ELLU, // nka_Latn_ZM + 0x854D494E4C61746ELLU, // nkb_Latn_IN + 0x894D434D4C61746ELLU, // nkc_Latn_CM + 0x8D4D494E4C61746ELLU, // nkd_Latn_IN + 0x914D53424C61746ELLU, // nke_Latn_SB + 0x954D494E4C61746ELLU, // nkf_Latn_IN + 0x994D50474C61746ELLU, // nkg_Latn_PG + 0x9D4D494E4C61746ELLU, // nkh_Latn_IN + 0xA14D494E4C61746ELLU, // nki_Latn_IN + 0xA54D49444C61746ELLU, // nkj_Latn_ID + 0xA94D56554C61746ELLU, // nkk_Latn_VU + 0xB14D50474C61746ELLU, // nkm_Latn_PG + 0xB54D414F4C61746ELLU, // nkn_Latn_AO + 0xB94D47484C61746ELLU, // nko_Latn_GH + 0xC14D47484C61746ELLU, // nkq_Latn_GH + 0xC54D464D4C61746ELLU, // nkr_Latn_FM + 0xC94D49444C61746ELLU, // nks_Latn_ID + 0xCD4D545A4C61746ELLU, // nkt_Latn_TZ + 0xD14D43494C61746ELLU, // nku_Latn_CI + 0xD54D4D574C61746ELLU, // nkv_Latn_MW + 0xD94D43444C61746ELLU, // nkw_Latn_CD + 0xDD4D4E474C61746ELLU, // nkx_Latn_NG + 0xE54D4E474C61746ELLU, // nkz_Latn_NG 0x6E6C4E4C4C61746ELLU, // nl_Latn_NL + 0x816D434D4C61746ELLU, // nla_Latn_CM + 0x896D49444C61746ELLU, // nlc_Latn_ID + 0x916D4B454C61746ELLU, // nle_Latn_KE + 0x996D53424C61746ELLU, // nlg_Latn_SB + 0xA16D414641726162LLU, // nli_Arab_AF + 0xA56D43444C61746ELLU, // nlj_Latn_CD + 0xA96D49444C61746ELLU, // nlk_Latn_ID + 0xB16D504B41726162LLU, // nlm_Arab_PK + 0xB96D43444C61746ELLU, // nlo_Latn_CD + 0xC16D4D4D4C61746ELLU, // nlq_Latn_MM + 0xD16D47484C61746ELLU, // nlu_Latn_GH + 0xD56D4D584C61746ELLU, // nlv_Latn_MX + 0xD96D41554C61746ELLU, // nlw_Latn_AU + 0xDD6D494E44657661LLU, // nlx_Deva_IN + 0xE16D41554C61746ELLU, // nly_Latn_AU + 0xE56D53424C61746ELLU, // nlz_Latn_SB + 0x818D494E4C61746ELLU, // nma_Latn_IN + 0x858D56554C61746ELLU, // nmb_Latn_VU + 0x898D54444C61746ELLU, // nmc_Latn_TD + 0x8D8D47414C61746ELLU, // nmd_Latn_GA + 0x918D494E4C61746ELLU, // nme_Latn_IN + 0x958D494E4C61746ELLU, // nmf_Latn_IN 0x998D434D4C61746ELLU, // nmg_Latn_CM + 0x9D8D494E4C61746ELLU, // nmh_Latn_IN + 0xA18D4E474C61746ELLU, // nmi_Latn_NG + 0xA58D43464C61746ELLU, // nmj_Latn_CF + 0xA98D56554C61746ELLU, // nmk_Latn_VU + 0xAD8D434D4C61746ELLU, // nml_Latn_CM + 0xB18D4E5044657661LLU, // nmm_Deva_NP + 0xB58D42574C61746ELLU, // nmn_Latn_BW + 0xB98D494E4C61746ELLU, // nmo_Latn_IN + 0xBD8D41554C61746ELLU, // nmp_Latn_AU + 0xC18D5A574C61746ELLU, // nmq_Latn_ZW + 0xC58D434D4C61746ELLU, // nmr_Latn_CM + 0xC98D56554C61746ELLU, // nms_Latn_VU + 0xCD8D464D4C61746ELLU, // nmt_Latn_FM + 0xD18D55534C61746ELLU, // nmu_Latn_US + 0xD58D41554C61746ELLU, // nmv_Latn_AU + 0xD98D50474C61746ELLU, // nmw_Latn_PG + 0xDD8D50474C61746ELLU, // nmx_Latn_PG + 0xE58D54474C61746ELLU, // nmz_Latn_TG 0x6E6E4E4F4C61746ELLU, // nn_Latn_NO + 0x81AD41554C61746ELLU, // nna_Latn_AU + 0x85AD43444C61746ELLU, // nnb_Latn_CD + 0x89AD54444C61746ELLU, // nnc_Latn_TD + 0x8DAD56554C61746ELLU, // nnd_Latn_VU + 0x91AD414F4C61746ELLU, // nne_Latn_AO + 0x95AD50474C61746ELLU, // nnf_Latn_PG + 0x99AD494E4C61746ELLU, // nng_Latn_IN 0x9DAD434D4C61746ELLU, // nnh_Latn_CM + 0xA1AD49444C61746ELLU, // nni_Latn_ID + 0xA5AD45544C61746ELLU, // nnj_Latn_ET + 0xA9AD50474C61746ELLU, // nnk_Latn_PG + 0xADAD494E4C61746ELLU, // nnl_Latn_IN + 0xB1AD50474C61746ELLU, // nnm_Latn_PG + 0xB5AD54444C61746ELLU, // nnn_Latn_TD 0xBDAD494E5763686FLLU, // nnp_Wcho_IN + 0xC1AD545A4C61746ELLU, // nnq_Latn_TZ + 0xC5AD41554C61746ELLU, // nnr_Latn_AU + 0xCDAD55534C61746ELLU, // nnt_Latn_US + 0xD1AD47484C61746ELLU, // nnu_Latn_GH + 0xD5AD41554C61746ELLU, // nnv_Latn_AU + 0xD9AD42464C61746ELLU, // nnw_Latn_BF + 0xE1AD41554C61746ELLU, // nny_Latn_AU + 0xE5AD434D4C61746ELLU, // nnz_Latn_CM 0x6E6F4E4F4C61746ELLU, // no_Latn_NO + 0x81CD434F4C61746ELLU, // noa_Latn_CO + 0x89CD50474C61746ELLU, // noc_Latn_PG 0x8DCD54484C616E61LLU, // nod_Lana_TH 0x91CD494E44657661LLU, // noe_Deva_IN + 0x95CD50474C61746ELLU, // nof_Latn_PG + 0x99CD52554379726CLLU, // nog_Cyrl_RU + 0x9DCD50474C61746ELLU, // noh_Latn_PG + 0xA1CD494E44657661LLU, // noi_Deva_IN + 0xA5CD434F4C61746ELLU, // noj_Latn_CO + 0xA9CD55534C61746ELLU, // nok_Latn_US 0xB5CD534552756E72LLU, // non_Runr_SE + 0xBDCD50474C61746ELLU, // nop_Latn_PG + 0xC1CD43444C61746ELLU, // noq_Latn_CD + 0xC9CD434E59696969LLU, // nos_Yiii_CN + 0xCDCD50454C61746ELLU, // not_Latn_PE + 0xD1CD50474C61746ELLU, // nou_Latn_PG + 0xD9CD545A4C61746ELLU, // now_Latn_TZ + 0xE1CD54444C61746ELLU, // noy_Latn_TD + 0x85ED425454696274LLU, // npb_Tibt_BT + 0x99ED4D4D4C61746ELLU, // npg_Latn_MM + 0x9DED494E4C61746ELLU, // nph_Latn_IN + 0xADED4D584C61746ELLU, // npl_Latn_MX + 0xB5ED50474C61746ELLU, // npn_Latn_PG + 0xB9ED494E4C61746ELLU, // npo_Latn_IN + 0xC9ED49444C61746ELLU, // nps_Latn_ID + 0xD1ED494E4C61746ELLU, // npu_Latn_IN + 0xDDED53424C61746ELLU, // npx_Latn_SB + 0xE1ED49444C61746ELLU, // npy_Latn_ID + 0x9A0D424A4C61746ELLU, // nqg_Latn_BJ + 0xAA0D424A4C61746ELLU, // nqk_Latn_BJ + 0xAE0D414F4C61746ELLU, // nql_Latn_AO + 0xB20D49444C61746ELLU, // nqm_Latn_ID + 0xB60D50474C61746ELLU, // nqn_Latn_PG 0xBA0D474E4E6B6F6FLLU, // nqo_Nkoo_GN + 0xC20D4D4D4C61746ELLU, // nqq_Latn_MM + 0xCE0D4E474C61746ELLU, // nqt_Latn_NG + 0xE20D4D4D4C61746ELLU, // nqy_Latn_MM 0x6E725A414C61746ELLU, // nr_Latn_ZA + 0x822D47414C61746ELLU, // nra_Latn_GA + 0x862D45524C61746ELLU, // nrb_Latn_ER + 0x922D494E4C61746ELLU, // nre_Latn_IN + 0x962D4A454C61746ELLU, // nrf_Latn_JE + 0x9A2D56554C61746ELLU, // nrg_Latn_VU + 0xA22D494E4C61746ELLU, // nri_Latn_IN + 0xAA2D41554C61746ELLU, // nrk_Latn_AU + 0xAE2D41554C61746ELLU, // nrl_Latn_AU + 0xB22D4D594C61746ELLU, // nrm_Latn_MY + 0xB62D474252756E72LLU, // nrn_Runr_GB + 0xBE2D49544C61746ELLU, // nrp_Latn_IT + 0xD22D434E4C61746ELLU, // nru_Latn_CN + 0xDE2D41554C61746ELLU, // nrx_Latn_AU + 0xE62D50474C61746ELLU, // nrz_Latn_PG + 0x824D494E4C61746ELLU, // nsa_Latn_IN + 0x864D5A414C61746ELLU, // nsb_Latn_ZA + 0x8A4D4E474C61746ELLU, // nsc_Latn_NG + 0x8E4D434E59696969LLU, // nsd_Yiii_CN + 0x924D5A4D4C61746ELLU, // nse_Latn_ZM + 0x964D434E59696969LLU, // nsf_Yiii_CN + 0x9A4D545A4C61746ELLU, // nsg_Latn_TZ + 0x9E4D434D4C61746ELLU, // nsh_Latn_CM 0xAA4D434143616E73LLU, // nsk_Cans_CA + 0xB24D494E4C61746ELLU, // nsm_Latn_IN + 0xB64D50474C61746ELLU, // nsn_Latn_PG 0xBA4D5A414C61746ELLU, // nso_Latn_ZA + 0xC24D55534C61746ELLU, // nsq_Latn_US + 0xCA4D50474C61746ELLU, // nss_Latn_PG 0xCE4D494E546E7361LLU, // nst_Tnsa_IN + 0xD24D4D584C61746ELLU, // nsu_Latn_MX + 0xD64D434E59696969LLU, // nsv_Yiii_CN + 0xDA4D56554C61746ELLU, // nsw_Latn_VU + 0xDE4D414F4C61746ELLU, // nsx_Latn_AO + 0xE24D49444C61746ELLU, // nsy_Latn_ID + 0xE64D55534C61746ELLU, // nsz_Latn_US + 0x8E6D4D594C61746ELLU, // ntd_Latn_MY + 0x926D4D5A4C61746ELLU, // nte_Latn_MZ + 0x9A6D41554C61746ELLU, // ntg_Latn_AU + 0xA26D42464C61746ELLU, // nti_Latn_BF + 0xA66D41554C61746ELLU, // ntj_Latn_AU + 0xAA6D545A4C61746ELLU, // ntk_Latn_TZ + 0xB26D424A4C61746ELLU, // ntm_Latn_BJ + 0xBA6D43444C61746ELLU, // nto_Latn_CD + 0xBE6D4D584C61746ELLU, // ntp_Latn_MX + 0xC66D47484C61746ELLU, // ntr_Latn_GH + 0xD26D53424C61746ELLU, // ntu_Latn_SB + 0xDE6D4D4D4C61746ELLU, // ntx_Latn_MM + 0xE26D564E59696969LLU, // nty_Yiii_VN + 0xE66D495241726162LLU, // ntz_Arab_IR + 0x828D4E434C61746ELLU, // nua_Latn_NC + 0x8A8D42524C61746ELLU, // nuc_Latn_BR + 0x8E8D50474C61746ELLU, // nud_Latn_PG + 0x928D43444C61746ELLU, // nue_Latn_CD + 0x968D434E4C61746ELLU, // nuf_Latn_CN + 0x9A8D41554C61746ELLU, // nug_Latn_AU + 0x9E8D4E474C61746ELLU, // nuh_Latn_NG + 0xA28D47514C61746ELLU, // nui_Latn_GQ + 0xA68D55474C61746ELLU, // nuj_Latn_UG + 0xAA8D43414C61746ELLU, // nuk_Latn_CA + 0xB28D544F4C61746ELLU, // num_Latn_TO + 0xB68D4D4D4C61746ELLU, // nun_Latn_MM + 0xBA8D564E4C61746ELLU, // nuo_Latn_VN + 0xBE8D4E474C61746ELLU, // nup_Latn_NG + 0xC28D50474C61746ELLU, // nuq_Latn_PG + 0xC68D50474C61746ELLU, // nur_Latn_PG 0xCA8D53534C61746ELLU, // nus_Latn_SS + 0xCE8D564E4C61746ELLU, // nut_Latn_VN + 0xD28D43444C61746ELLU, // nuu_Latn_CD + 0xD68D42464C61746ELLU, // nuv_Latn_BF + 0xDA8D464D4C61746ELLU, // nuw_Latn_FM + 0xDE8D50474C61746ELLU, // nux_Latn_PG + 0xE28D41554C61746ELLU, // nuy_Latn_AU + 0xE68D4D584C61746ELLU, // nuz_Latn_MX 0x6E7655534C61746ELLU, // nv_Latn_US + 0x9EAD56554C61746ELLU, // nvh_Latn_VU + 0xB2AD50474C61746ELLU, // nvm_Latn_PG + 0xBAAD434D4C61746ELLU, // nvo_Latn_CM + 0x86CD43494C61746ELLU, // nwb_Latn_CI + 0x8ACD4E504E657761LLU, // nwc_Newa_NP + 0x92CD434D4C61746ELLU, // nwe_Latn_CM + 0x9ACD41554C61746ELLU, // nwg_Latn_AU + 0xA2CD56554C61746ELLU, // nwi_Latn_VU + 0xB2CD53534C61746ELLU, // nwm_Latn_SS + 0xBACD41554C61746ELLU, // nwo_Latn_AU + 0xC6CD50474C61746ELLU, // nwr_Latn_PG + 0xDACD545A4C61746ELLU, // nww_Latn_TZ + 0xDECD4E5044657661LLU, // nwx_Deva_NP + 0x82ED544C4C61746ELLU, // nxa_Latn_TL + 0x8EED43444C61746ELLU, // nxd_Latn_CD + 0x92ED49444C61746ELLU, // nxe_Latn_ID + 0x9AED49444C61746ELLU, // nxg_Latn_ID + 0xA2ED545A4C61746ELLU, // nxi_Latn_TZ + 0xAEED49444C61746ELLU, // nxl_Latn_ID + 0xB6ED41554C61746ELLU, // nxn_Latn_AU + 0xBAED47414C61746ELLU, // nxo_Latn_GA 0xC2ED434E4C61746ELLU, // nxq_Latn_CN + 0xC6ED50474C61746ELLU, // nxr_Latn_PG + 0xDEED49444C61746ELLU, // nxx_Latn_ID 0x6E794D574C61746ELLU, // ny_Latn_MW + 0x870D47484C61746ELLU, // nyb_Latn_GH + 0x8B0D43444C61746ELLU, // nyc_Latn_CD + 0x8F0D4B454C61746ELLU, // nyd_Latn_KE + 0x930D414F4C61746ELLU, // nye_Latn_AO + 0x970D4B454C61746ELLU, // nyf_Latn_KE + 0x9B0D43444C61746ELLU, // nyg_Latn_CD + 0x9F0D41554C61746ELLU, // nyh_Latn_AU + 0xA30D53444C61746ELLU, // nyi_Latn_SD + 0xA70D43444C61746ELLU, // nyj_Latn_CD + 0xAB0D414F4C61746ELLU, // nyk_Latn_AO + 0xAF0D544854686169LLU, // nyl_Thai_TH 0xB30D545A4C61746ELLU, // nym_Latn_TZ 0xB70D55474C61746ELLU, // nyn_Latn_UG + 0xBB0D55474C61746ELLU, // nyo_Latn_UG + 0xBF0D55474C61746ELLU, // nyp_Latn_UG + 0xC30D495241726162LLU, // nyq_Arab_IR + 0xC70D4D574C61746ELLU, // nyr_Latn_MW + 0xCB0D41554C61746ELLU, // nys_Latn_AU + 0xCF0D41554C61746ELLU, // nyt_Latn_AU + 0xD30D4D5A4C61746ELLU, // nyu_Latn_MZ + 0xD70D41554C61746ELLU, // nyv_Latn_AU + 0xDB0D544854686169LLU, // nyw_Thai_TH + 0xDF0D41554C61746ELLU, // nyx_Latn_AU + 0xE30D545A4C61746ELLU, // nyy_Latn_TZ + 0x832D434D4C61746ELLU, // nza_Latn_CM + 0x872D47414C61746ELLU, // nzb_Latn_GA + 0x8F2D43444C61746ELLU, // nzd_Latn_CD 0xA32D47484C61746ELLU, // nzi_Latn_GH + 0xAB2D43464C61746ELLU, // nzk_Latn_CF + 0xB32D494E4C61746ELLU, // nzm_Latn_IN + 0xC72D4E474C61746ELLU, // nzr_Latn_NG + 0xD32D43474C61746ELLU, // nzu_Latn_CG + 0xE32D54444C61746ELLU, // nzy_Latn_TD + 0xE72D4D4C4C61746ELLU, // nzz_Latn_ML + 0x800E52554379726CLLU, // oaa_Cyrl_RU + 0x880E52554379726CLLU, // oac_Cyrl_RU + 0xC40E535953797263LLU, // oar_Syrc_SY + 0xD40E474547656F72LLU, // oav_Geor_GE + 0xA02E55534C61746ELLU, // obi_Latn_US + 0xA82E50484C61746ELLU, // obk_Latn_PH + 0xAC2E434D4C61746ELLU, // obl_Latn_CM + 0xB02E4A4F50686E78LLU, // obm_Phnx_JO + 0xB82E50484C61746ELLU, // obo_Latn_PH + 0xC42E4D4D4D796D72LLU, // obr_Mymr_MM + 0xCC2E46524C61746ELLU, // obt_Latn_FR + 0xD02E4E474C61746ELLU, // obu_Latn_NG 0x6F6346524C61746ELLU, // oc_Latn_FR + 0x804E50454C61746ELLU, // oca_Latn_PE + 0xB84E47424C61746ELLU, // oco_Latn_GB + 0xD04E4D584C61746ELLU, // ocu_Latn_MX + 0x806E4E474C61746ELLU, // oda_Latn_NG + 0xA86E504B41726162LLU, // odk_Arab_PK + 0xCC6E4E4C4C61746ELLU, // odt_Latn_NL + 0xD06E4E474C61746ELLU, // odu_Latn_NG + 0xC8AE4E4C4C61746ELLU, // ofs_Latn_NL + 0xD0AE4E474C61746ELLU, // ofu_Latn_NG + 0x84CE4E474C61746ELLU, // ogb_Latn_NG + 0x88CE4E474C61746ELLU, // ogc_Latn_NG + 0x98CE4E474C61746ELLU, // ogg_Latn_NG + 0xB8CE4E474C61746ELLU, // ogo_Latn_NG + 0xD0CE4E474C61746ELLU, // ogu_Latn_NG + 0xCCEE545258737578LLU, // oht_Xsux_TR + 0xD0EE48554C61746ELLU, // ohu_Latn_HU + 0x810E49444C61746ELLU, // oia_Latn_ID + 0x910E53534C61746ELLU, // oie_Latn_SS + 0xB50E50474C61746ELLU, // oin_Latn_PG 0x6F6A434143616E73LLU, // oj_Cans_CA + 0x852E43414C61746ELLU, // ojb_Latn_CA + 0x892E43414C61746ELLU, // ojc_Latn_CA 0xC92E434143616E73LLU, // ojs_Cans_CA + 0xD52E53424C61746ELLU, // ojv_Latn_SB + 0xD92E43414C61746ELLU, // ojw_Latn_CA 0x814E43414C61746ELLU, // oka_Latn_CA + 0x854E4E474C61746ELLU, // okb_Latn_NG + 0x894E43444C61746ELLU, // okc_Latn_CD + 0x8D4E4E474C61746ELLU, // okd_Latn_NG + 0x914E4E474C61746ELLU, // oke_Latn_NG + 0x994E41554C61746ELLU, // okg_Latn_AU + 0xA14E4B454C61746ELLU, // oki_Latn_KE + 0xA94E50474C61746ELLU, // okk_Latn_PG + 0xB14E4B5248616E67LLU, // okm_Hang_KR + 0xB94E4B5248616E69LLU, // oko_Hani_KR + 0xC54E4E474C61746ELLU, // okr_Latn_NG + 0xC94E4E474C61746ELLU, // oks_Latn_NG + 0xD14E434D4C61746ELLU, // oku_Latn_CM + 0xD54E50474C61746ELLU, // okv_Latn_PG + 0xDD4E4E474C61746ELLU, // okx_Latn_NG + 0xE54E4B484B686D72LLU, // okz_Khmr_KH + 0x816E4E5044657661LLU, // ola_Deva_NP + 0x8D6E545A4C61746ELLU, // old_Latn_TZ + 0x916E425454696274LLU, // ole_Tibt_BT + 0xA96E41554C61746ELLU, // olk_Latn_AU + 0xB16E4E474C61746ELLU, // olm_Latn_NG + 0xB96E52554C61746ELLU, // olo_Latn_RU + 0xC56E56554C61746ELLU, // olr_Latn_VU + 0xCD6E4C544C61746ELLU, // olt_Latn_LT + 0xD16E414F4C61746ELLU, // olu_Latn_AO 0x6F6D45544C61746ELLU, // om_Latn_ET + 0x818E55534C61746ELLU, // oma_Latn_US + 0x858E56554C61746ELLU, // omb_Latn_VU + 0x898E50454C61746ELLU, // omc_Latn_PE + 0x998E50454C61746ELLU, // omg_Latn_PE + 0xA18E43444C61746ELLU, // omi_Latn_CD + 0xA98E52554379726CLLU, // omk_Cyrl_RU + 0xAD8E43444C61746ELLU, // oml_Latn_CD + 0xB98E50474C61746ELLU, // omo_Latn_PG + 0xBD8E494E4D746569LLU, // omp_Mtei_IN + 0xC58E494E4D6F6469LLU, // omr_Modi_IN + 0xCD8E4B454C61746ELLU, // omt_Latn_KE + 0xD18E50454C61746ELLU, // omu_Latn_PE + 0xD98E50474C61746ELLU, // omw_Latn_PG + 0xDD8E4D4D4D796D72LLU, // omx_Mymr_MM + 0x81AE41524C61746ELLU, // ona_Latn_AR + 0x91AE43414C61746ELLU, // one_Latn_CA + 0x99AE50474C61746ELLU, // ong_Latn_PG + 0xA1AE49444C61746ELLU, // oni_Latn_ID + 0xA5AE50474C61746ELLU, // onj_Latn_PG + 0xA9AE50474C61746ELLU, // onk_Latn_PG + 0xB5AE50474C61746ELLU, // onn_Latn_PG + 0xB9AE43414C61746ELLU, // ono_Latn_CA + 0xBDAE494E4C61746ELLU, // onp_Latn_IN + 0xC5AE50474C61746ELLU, // onr_Latn_PG + 0xC9AE50474C61746ELLU, // ons_Latn_PG + 0xCDAE50474C61746ELLU, // ont_Latn_PG + 0xD1AE56554C61746ELLU, // onu_Latn_VU + 0xDDAE49444C61746ELLU, // onx_Latn_ID + 0x8DCE55534C61746ELLU, // ood_Latn_US + 0xB5CE494E44657661LLU, // oon_Deva_IN + 0xC5CE5A414C61746ELLU, // oor_Latn_ZA + 0x81EE4E474C61746ELLU, // opa_Latn_NG + 0xA9EE49444C61746ELLU, // opk_Latn_ID + 0xB1EE50474C61746ELLU, // opm_Latn_PG + 0xB9EE50474C61746ELLU, // opo_Latn_PG + 0xCDEE4D584C61746ELLU, // opt_Latn_MX + 0xE1EE42524C61746ELLU, // opy_Latn_BR 0x6F72494E4F727961LLU, // or_Orya_IN + 0x822E53424C61746ELLU, // ora_Latn_SB + 0x8A2E4B454C61746ELLU, // orc_Latn_KE + 0x922E50454C61746ELLU, // ore_Latn_PE + 0x9A2E4E474C61746ELLU, // org_Latn_NG + 0xB62E4D594C61746ELLU, // orn_Latn_MY + 0xBA2E50474C61746ELLU, // oro_Latn_PG + 0xC62E4E474C61746ELLU, // orr_Latn_NG + 0xCA2E4D594C61746ELLU, // ors_Latn_MY + 0xCE2E494E54656C75LLU, // ort_Telu_IN + 0xD22E504B41726162LLU, // oru_Arab_PK + 0xD62E52554379726CLLU, // orv_Cyrl_RU + 0xDA2E42524C61746ELLU, // orw_Latn_BR + 0xDE2E4E474C61746ELLU, // orx_Latn_NG + 0xE62E49444C61746ELLU, // orz_Latn_ID 0x6F7347454379726CLLU, // os_Cyrl_GE 0x824E55534F736765LLU, // osa_Osge_US + 0x8A4E49544974616CLLU, // osc_Ital_IT + 0xA24E49444A617661LLU, // osi_Java_ID + 0xBA4E4E474C61746ELLU, // oso_Latn_NG + 0xBE4E45534C61746ELLU, // osp_Latn_ES + 0xCE4E434D4C61746ELLU, // ost_Latn_CM + 0xD24E50474C61746ELLU, // osu_Latn_PG + 0xDE4E44454C61746ELLU, // osx_Latn_DE + 0x826E545241726162LLU, // ota_Arab_TR + 0x866E434E54696274LLU, // otb_Tibt_CN + 0x8E6E49444C61746ELLU, // otd_Latn_ID + 0x926E4D584C61746ELLU, // ote_Latn_MX + 0xA26E42524C61746ELLU, // oti_Latn_BR 0xAA6E4D4E4F726B68LLU, // otk_Orkh_MN - 0xA28E8C814F756772LLU, // oui_Ougr_143 + 0xAE6E4D584C61746ELLU, // otl_Latn_MX + 0xB26E4D584C61746ELLU, // otm_Latn_MX + 0xB66E4D584C61746ELLU, // otn_Latn_MX + 0xC26E4D584C61746ELLU, // otq_Latn_MX + 0xC66E53444C61746ELLU, // otr_Latn_SD + 0xCA6E4D584C61746ELLU, // ots_Latn_MX + 0xCE6E4D584C61746ELLU, // ott_Latn_MX + 0xD26E42524C61746ELLU, // otu_Latn_BR + 0xDA6E43414C61746ELLU, // otw_Latn_CA + 0xDE6E4D584C61746ELLU, // otx_Latn_MX + 0xE26E494E4772616ELLU, // oty_Gran_IN + 0xE66E4D584C61746ELLU, // otz_Latn_MX + 0x868E4C524C61746ELLU, // oub_Latn_LR + 0x928E50474C61746ELLU, // oue_Latn_PG + 0xA28E434E4F756772LLU, // oui_Ougr_CN + 0xB28E50474C61746ELLU, // oum_Latn_PG + 0x8EAE53454C61746ELLU, // ovd_Latn_SE + 0xA2CE50474C61746ELLU, // owi_Latn_PG + 0xAECE47424C61746ELLU, // owl_Latn_GB + 0x8F0E45544C61746ELLU, // oyd_Latn_ET + 0xB30E42524C61746ELLU, // oym_Latn_BR + 0xE30E50474C61746ELLU, // oyy_Latn_PG + 0xB32E434D4C61746ELLU, // ozm_Latn_CM 0x7061504B41726162LLU, // pa_Arab_PK 0x7061494E47757275LLU, // pa_Guru_IN + 0x840F42524C61746ELLU, // pab_Latn_BR + 0x880F564E4C61746ELLU, // pac_Latn_VN + 0x8C0F42524C61746ELLU, // pad_Latn_BR + 0x900F43444C61746ELLU, // pae_Latn_CD + 0x940F42524C61746ELLU, // paf_Latn_BR 0x980F50484C61746ELLU, // pag_Latn_PH + 0x9C0F42524C61746ELLU, // pah_Latn_BR + 0xA00F4E474C61746ELLU, // pai_Latn_NG + 0xA80F42524C61746ELLU, // pak_Latn_BR 0xAC0F495250686C69LLU, // pal_Phli_IR 0xAC0F434E50686C70LLU, // pal_Phlp_CN 0xB00F50484C61746ELLU, // pam_Latn_PH - 0xBC0F41574C61746ELLU, // pap_Latn_AW + 0xB80F55534C61746ELLU, // pao_Latn_US + 0xBC0F43574C61746ELLU, // pap_Latn_CW + 0xC00F544A4379726CLLU, // paq_Cyrl_TJ + 0xC40F55534C61746ELLU, // par_Latn_US + 0xC80F49444C61746ELLU, // pas_Latn_ID 0xD00F50574C61746ELLU, // pau_Latn_PW + 0xD40F42524C61746ELLU, // pav_Latn_BR + 0xD80F55534C61746ELLU, // paw_Latn_US + 0xDC0F42524C61746ELLU, // pax_Latn_BR + 0xE00F484E4C61746ELLU, // pay_Latn_HN + 0xE40F42524C61746ELLU, // paz_Latn_BR + 0x842F434F4C61746ELLU, // pbb_Latn_CO + 0x882F47594C61746ELLU, // pbc_Latn_GY + 0x902F4D584C61746ELLU, // pbe_Latn_MX + 0x942F4D584C61746ELLU, // pbf_Latn_MX + 0x982F56454C61746ELLU, // pbg_Latn_VE + 0x9C2F56454C61746ELLU, // pbh_Latn_VE + 0xA02F434D4C61746ELLU, // pbi_Latn_CM + 0xAC2F4E474C61746ELLU, // pbl_Latn_NG + 0xB02F4D584C61746ELLU, // pbm_Latn_MX + 0xB42F4E474C61746ELLU, // pbn_Latn_NG + 0xB82F47574C61746ELLU, // pbo_Latn_GW + 0xBC2F474E4C61746ELLU, // pbp_Latn_GN + 0xC42F545A4C61746ELLU, // pbr_Latn_TZ + 0xC82F4D584C61746ELLU, // pbs_Latn_MX + 0xCC2F414641726162LLU, // pbt_Arab_AF + 0xD42F494E4C61746ELLU, // pbv_Latn_IN + 0xE02F50474C61746ELLU, // pby_Latn_PG + 0x804F4D584C61746ELLU, // pca_Latn_MX + 0x844F4B484B686D72LLU, // pcb_Khmr_KH + 0x884F434E4C61746ELLU, // pcc_Latn_CN 0x8C4F46524C61746ELLU, // pcd_Latn_FR + 0x904F4D4D4D796D72LLU, // pce_Mymr_MM + 0x944F494E4D6C796DLLU, // pcf_Mlym_IN + 0x984F494E4D6C796DLLU, // pcg_Mlym_IN + 0x9C4F494E44657661LLU, // pch_Deva_IN + 0xA04F494E44657661LLU, // pci_Deva_IN + 0xA44F494E54656C75LLU, // pcj_Telu_IN + 0xA84F494E4C61746ELLU, // pck_Latn_IN 0xB04F4E474C61746ELLU, // pcm_Latn_NG + 0xB44F4E474C61746ELLU, // pcn_Latn_NG + 0xBC4F424F4C61746ELLU, // pcp_Latn_BO + 0xD84F4E474C61746ELLU, // pcw_Latn_NG + 0x806F50474C61746ELLU, // pda_Latn_PG 0x886F55534C61746ELLU, // pdc_Latn_US + 0xB46F49444C61746ELLU, // pdn_Latn_ID + 0xB86F49444C61746ELLU, // pdo_Latn_ID 0xCC6F43414C61746ELLU, // pdt_Latn_CA + 0xD06F4D4D4C61746ELLU, // pdu_Latn_MM + 0x808F49444C61746ELLU, // pea_Latn_ID + 0x848F55534C61746ELLU, // peb_Latn_US + 0x8C8F50474C61746ELLU, // ped_Latn_PG + 0x908F49444C61746ELLU, // pee_Latn_ID + 0x988F494E4F727961LLU, // peg_Orya_IN + 0xA08F4D584C61746ELLU, // pei_Latn_MX + 0xA88F50474C61746ELLU, // pek_Latn_PG + 0xAC8F49444C61746ELLU, // pel_Latn_ID + 0xB08F43444C61746ELLU, // pem_Latn_CD 0xB88F49525870656FLLU, // peo_Xpeo_IR + 0xBC8F50474C61746ELLU, // pep_Latn_PG + 0xC08F55534C61746ELLU, // peq_Latn_US + 0xD48F56454C61746ELLU, // pev_Latn_VE + 0xDC8F50474C61746ELLU, // pex_Latn_PG + 0xE08F49444C61746ELLU, // pey_Latn_ID + 0xE48F4D594C61746ELLU, // pez_Latn_MY + 0x80AF464D4C61746ELLU, // pfa_Latn_FM + 0x90AF434D4C61746ELLU, // pfe_Latn_CM 0xACAF44454C61746ELLU, // pfl_Latn_DE + 0x80CF53534C61746ELLU, // pga_Latn_SS + 0x8CCF504B4B686172LLU, // pgd_Khar_PK + 0x98CF494E44657661LLU, // pgg_Deva_IN + 0xA0CF50474C61746ELLU, // pgi_Latn_PG + 0xA8CF56554C61746ELLU, // pgk_Latn_VU + 0xACCF49454F67616DLLU, // pgl_Ogam_IE + 0xB4CF49544974616CLLU, // pgn_Ital_IT + 0xC8CF4E474C61746ELLU, // pgs_Latn_NG + 0xD0CF49444C61746ELLU, // pgu_Latn_ID + 0x8CEF494E44657661LLU, // phd_Deva_IN + 0x98EF564E4C61746ELLU, // phg_Latn_VN + 0x9CEF564E4C61746ELLU, // phh_Latn_VN + 0xA8EF494E4D796D72LLU, // phk_Mymr_IN + 0xACEF504B41726162LLU, // phl_Arab_PK + 0xB0EF4D5A4C61746ELLU, // phm_Latn_MZ 0xB4EF4C4250686E78LLU, // phn_Phnx_LB + 0xB8EF4C414C616F6FLLU, // pho_Laoo_LA + 0xC4EF504B41726162LLU, // phr_Arab_PK + 0xCCEF544854686169LLU, // pht_Thai_TH + 0xD0EF544854686169LLU, // phu_Thai_TH + 0xD4EF414641726162LLU, // phv_Arab_AF + 0xD8EF4E5044657661LLU, // phw_Deva_NP + 0x7069494E53696E68LLU, // pi_Sinh_IN + 0x810F4D584C61746ELLU, // pia_Latn_MX + 0x850F50454C61746ELLU, // pib_Latn_PE + 0x890F47414C61746ELLU, // pic_Latn_GA + 0x8D0F56454C61746ELLU, // pid_Latn_VE + 0x950F464D4C61746ELLU, // pif_Latn_FM + 0x990F50454C61746ELLU, // pig_Latn_PE + 0x9D0F4E464C61746ELLU, // pih_Latn_NF + 0xA50F434F4C61746ELLU, // pij_Latn_CO + 0xAD0F424A4C61746ELLU, // pil_Latn_BJ + 0xB10F55534C61746ELLU, // pim_Latn_US + 0xB50F50474C61746ELLU, // pin_Latn_PG + 0xB90F434F4C61746ELLU, // pio_Latn_CO + 0xBD0F4E474C61746ELLU, // pip_Latn_NG + 0xC50F42524C61746ELLU, // pir_Latn_BR 0xC90F53424C61746ELLU, // pis_Latn_SB + 0xCD0F41554C61746ELLU, // pit_Latn_AU + 0xD10F41554C61746ELLU, // piu_Latn_AU + 0xD50F53424C61746ELLU, // piv_Latn_SB + 0xD90F545A4C61746ELLU, // piw_Latn_TZ + 0xDD0F50474C61746ELLU, // pix_Latn_PG + 0xE10F4E474C61746ELLU, // piy_Latn_NG + 0xE50F4E434C61746ELLU, // piz_Latn_NC + 0xCD2F41554C61746ELLU, // pjt_Latn_AU 0x814F494E42726168LLU, // pka_Brah_IN + 0x854F4B454C61746ELLU, // pkb_Latn_KE + 0x994F50474C61746ELLU, // pkg_Latn_PG + 0x9D4F42444C61746ELLU, // pkh_Latn_BD + 0xB54F41554C61746ELLU, // pkn_Latn_AU 0xB94F4B454C61746ELLU, // pko_Latn_KE + 0xBD4F434B4C61746ELLU, // pkp_Latn_CK + 0xC54F494E4D6C796DLLU, // pkr_Mlym_IN + 0xD14F49444C61746ELLU, // pku_Latn_ID 0x706C504C4C61746ELLU, // pl_Latn_PL + 0x816F50474C61746ELLU, // pla_Latn_PG + 0x856F56554C61746ELLU, // plb_Latn_VU + 0x896F50484C61746ELLU, // plc_Latn_PH + 0x8D6F47424C61746ELLU, // pld_Latn_GB + 0x916F49444C61746ELLU, // ple_Latn_ID + 0x996F41524C61746ELLU, // plg_Latn_AR + 0x9D6F49444C61746ELLU, // plh_Latn_ID + 0xA96F504B41726162LLU, // plk_Arab_PK + 0xAD6F4D4D4D796D72LLU, // pll_Mymr_MM + 0xB56F434F4C61746ELLU, // pln_Latn_CO + 0xB96F4D584C61746ELLU, // plo_Latn_MX + 0xC56F43494C61746ELLU, // plr_Latn_CI + 0xC96F4D584C61746ELLU, // pls_Latn_MX + 0xD16F42524C61746ELLU, // plu_Latn_BR + 0xD56F50484C61746ELLU, // plv_Latn_PH + 0xD96F50484C61746ELLU, // plw_Latn_PH + 0xE56F4D594C61746ELLU, // plz_Latn_MY + 0x818F56554C61746ELLU, // pma_Latn_VU + 0x858F43444C61746ELLU, // pmb_Latn_CD + 0x8D8F41554C61746ELLU, // pmd_Latn_AU + 0x918F4E434C61746ELLU, // pme_Latn_NC + 0x958F49444C61746ELLU, // pmf_Latn_ID + 0x9D8F494E42726168LLU, // pmh_Brah_IN + 0xA18F434E4C61746ELLU, // pmi_Latn_CN + 0xA58F434E4C61746ELLU, // pmj_Latn_CN + 0xAD8F544E4C61746ELLU, // pml_Latn_TN + 0xB18F434D4C61746ELLU, // pmm_Latn_CM + 0xB58F434D4C61746ELLU, // pmn_Latn_CM + 0xB98F49444C61746ELLU, // pmo_Latn_ID + 0xC18F4D584C61746ELLU, // pmq_Latn_MX + 0xC58F50474C61746ELLU, // pmr_Latn_PG 0xC98F49544C61746ELLU, // pms_Latn_IT + 0xCD8F50464C61746ELLU, // pmt_Latn_PF + 0xD98F55534C61746ELLU, // pmw_Latn_US + 0xDD8F494E4C61746ELLU, // pmx_Latn_IN + 0xE18F49444C61746ELLU, // pmy_Latn_ID + 0xE58F4D584C61746ELLU, // pmz_Latn_MX + 0x81AF4D594C61746ELLU, // pna_Latn_MY + 0x89AF49444C61746ELLU, // pnc_Latn_ID + 0x8DAF414F4C61746ELLU, // pnd_Latn_AO + 0x91AF4D594C61746ELLU, // pne_Latn_MY + 0x99AF4E474C61746ELLU, // png_Latn_NG + 0x9DAF434B4C61746ELLU, // pnh_Latn_CK + 0xA1AF49444C61746ELLU, // pni_Latn_ID + 0xA5AF41554C61746ELLU, // pnj_Latn_AU + 0xA9AF424F4C61746ELLU, // pnk_Latn_BO + 0xADAF42464C61746ELLU, // pnl_Latn_BF + 0xB1AF4D594C61746ELLU, // pnm_Latn_MY + 0xB5AF50474C61746ELLU, // pnn_Latn_PG + 0xB9AF50454C61746ELLU, // pno_Latn_PE + 0xBDAF49444C61746ELLU, // pnp_Latn_ID + 0xC1AF42464C61746ELLU, // pnq_Latn_BF + 0xC5AF50474C61746ELLU, // pnr_Latn_PG + 0xC9AF49444C61746ELLU, // pns_Latn_ID 0xCDAF47524772656BLLU, // pnt_Grek_GR + 0xD5AF41554C61746ELLU, // pnv_Latn_AU + 0xD9AF41554C61746ELLU, // pnw_Latn_AU + 0xE1AF434D4C61746ELLU, // pny_Latn_CM + 0xE5AF43464C61746ELLU, // pnz_Latn_CF + 0x89CF47544C61746ELLU, // poc_Latn_GT + 0x91CF4D584C61746ELLU, // poe_Latn_MX + 0x95CF43444C61746ELLU, // pof_Latn_CD + 0x99CF42524C61746ELLU, // pog_Latn_BR + 0x9DCF47544C61746ELLU, // poh_Latn_GT + 0xA1CF4D584C61746ELLU, // poi_Latn_MX + 0xA9CF42524C61746ELLU, // pok_Latn_BR + 0xB1CF55534C61746ELLU, // pom_Latn_US 0xB5CF464D4C61746ELLU, // pon_Latn_FM - 0x81EF494E44657661LLU, // ppa_Deva_IN + 0xB9CF55534C61746ELLU, // poo_Latn_US + 0xBDCF4E434C61746ELLU, // pop_Latn_NC + 0xC1CF4D584C61746ELLU, // poq_Latn_MX + 0xC9CF4D584C61746ELLU, // pos_Latn_MX + 0xCDCF55534C61746ELLU, // pot_Latn_US + 0xD5CF47574C61746ELLU, // pov_Latn_GW + 0xD9CF4D584C61746ELLU, // pow_Latn_MX + 0xE1CF545A4C61746ELLU, // poy_Latn_TZ + 0x91EF50474C61746ELLU, // ppe_Latn_PG + 0xA1EF4D584C61746ELLU, // ppi_Latn_MX + 0xA9EF49444C61746ELLU, // ppk_Latn_ID + 0xADEF53564C61746ELLU, // ppl_Latn_SV + 0xB1EF49444C61746ELLU, // ppm_Latn_ID + 0xB5EF50474C61746ELLU, // ppn_Latn_PG + 0xB9EF50474C61746ELLU, // ppo_Latn_PG + 0xBDEF43444C61746ELLU, // ppp_Latn_CD + 0xC1EF50474C61746ELLU, // ppq_Latn_PG + 0xC9EF4D584C61746ELLU, // pps_Latn_MX + 0xCDEF50474C61746ELLU, // ppt_Latn_PG + 0x820F4E474C61746ELLU, // pqa_Latn_NG 0xB20F43414C61746ELLU, // pqm_Latn_CA 0x822F504B4B686172LLU, // pra_Khar_PK + 0x8A2F414641726162LLU, // prc_Arab_AF 0x8E2F495241726162LLU, // prd_Arab_IR + 0x922F53544C61746ELLU, // pre_Latn_ST + 0x962F50484C61746ELLU, // prf_Latn_PH + 0x9A2F504C4C61746ELLU, // prg_Latn_PL + 0x9E2F50484C61746ELLU, // prh_Latn_PH + 0xA22F4E434C61746ELLU, // pri_Latn_NC + 0xAA2F4D4D4C61746ELLU, // prk_Latn_MM + 0xB22F50474C61746ELLU, // prm_Latn_PG + 0xBA2F46524C61746ELLU, // pro_Latn_FR + 0xC22F50454C61746ELLU, // prq_Latn_PE + 0xC62F42524C61746ELLU, // prr_Latn_BR + 0xCE2F544854686169LLU, // prt_Thai_TH + 0xD22F49444C61746ELLU, // pru_Latn_ID + 0xDA2F50474C61746ELLU, // prw_Latn_PG + 0xDE2F494E41726162LLU, // prx_Arab_IN 0x7073414641726162LLU, // ps_Arab_AF + 0x824F49444C61746ELLU, // psa_Latn_ID + 0x924F49444C61746ELLU, // pse_Latn_ID + 0x9E4F414641726162LLU, // psh_Arab_AF + 0xA24F414641726162LLU, // psi_Arab_AF + 0xB24F424F4C61746ELLU, // psm_Latn_BO + 0xB64F49444C61746ELLU, // psn_Latn_ID + 0xC24F50474C61746ELLU, // psq_Latn_PG + 0xCA4F50474C61746ELLU, // pss_Latn_PG + 0xCE4F504B41726162LLU, // pst_Arab_PK + 0xD24F494E42726168LLU, // psu_Brah_IN + 0xDA4F56554C61746ELLU, // psw_Latn_VU 0x707442524C61746ELLU, // pt_Latn_BR + 0x826F50594C61746ELLU, // pta_Latn_PY + 0x9E6F42524C61746ELLU, // pth_Latn_BR + 0xA26F41554C61746ELLU, // pti_Latn_AU + 0xB66F49444C61746ELLU, // ptn_Latn_ID + 0xBA6F42524C61746ELLU, // pto_Latn_BR + 0xBE6F50474C61746ELLU, // ptp_Latn_PG + 0xC66F56554C61746ELLU, // ptr_Latn_VU + 0xCE6F49444C61746ELLU, // ptt_Latn_ID + 0xD26F49444C61746ELLU, // ptu_Latn_ID + 0xD66F56554C61746ELLU, // ptv_Latn_VU + 0x828F4D584C61746ELLU, // pua_Latn_MX + 0x868F494E4C61746ELLU, // pub_Latn_IN + 0x8A8F49444C61746ELLU, // puc_Latn_ID + 0x8E8F49444C61746ELLU, // pud_Latn_ID + 0x928F41524C61746ELLU, // pue_Latn_AR + 0x968F49444C61746ELLU, // puf_Latn_ID + 0x9A8F42464C61746ELLU, // pug_Latn_BF + 0xA28F434F4C61746ELLU, // pui_Latn_CO + 0xA68F49444C61746ELLU, // puj_Latn_ID + 0xB28F4E5044657661LLU, // pum_Deva_NP + 0xBA8F564E4C61746ELLU, // puo_Latn_VN + 0xBE8F50474C61746ELLU, // pup_Latn_PG + 0xC28F424F4C61746ELLU, // puq_Latn_BO + 0xC68F42524C61746ELLU, // pur_Latn_BR + 0xCE8F49444C61746ELLU, // put_Latn_ID 0xD28F47414C61746ELLU, // puu_Latn_GA + 0xDA8F464D4C61746ELLU, // puw_Latn_FM + 0xDE8F50474C61746ELLU, // pux_Latn_PG + 0xE28F55534C61746ELLU, // puy_Latn_US + 0x82CF50474C61746ELLU, // pwa_Latn_PG + 0x86CF4E474C61746ELLU, // pwb_Latn_NG + 0x9ACF50474C61746ELLU, // pwg_Latn_PG + 0xB2CF50484C61746ELLU, // pwm_Latn_PH + 0xB6CF54574C61746ELLU, // pwn_Latn_TW + 0xBACF4D4D4D796D72LLU, // pwo_Mymr_MM + 0xC6CF494E44657661LLU, // pwr_Deva_IN + 0xDACF544854686169LLU, // pww_Thai_TH + 0xB2EF4D584C61746ELLU, // pxm_Latn_MX + 0x930F43494C61746ELLU, // pye_Latn_CI + 0xB30F4E474C61746ELLU, // pym_Latn_NG + 0xB70F42524C61746ELLU, // pyn_Latn_BR + 0xD30F54574C61746ELLU, // pyu_Latn_TW + 0xDF0F4D4D4D796D72LLU, // pyx_Mymr_MM + 0xE30F4D4D4C61746ELLU, // pyy_Latn_MM + 0x932F4E474C61746ELLU, // pze_Latn_NG + 0x9F2F54574C61746ELLU, // pzh_Latn_TW + 0xB72F4D4D4C61746ELLU, // pzn_Latn_MM 0x717550454C61746ELLU, // qu_Latn_PE + 0x829055534C61746ELLU, // qua_Latn_US + 0x869050454C61746ELLU, // qub_Latn_PE 0x8A9047544C61746ELLU, // quc_Latn_GT + 0x8E9045434C61746ELLU, // qud_Latn_EC + 0x969050454C61746ELLU, // quf_Latn_PE 0x9A9045434C61746ELLU, // qug_Latn_EC + 0xA29055534C61746ELLU, // qui_Latn_US + 0xAA9050454C61746ELLU, // quk_Latn_PE + 0xAE90424F4C61746ELLU, // qul_Latn_BO + 0xB29047544C61746ELLU, // qum_Latn_GT + 0xB69055534C61746ELLU, // qun_Latn_US + 0xBE9050454C61746ELLU, // qup_Latn_PE + 0xC29045534C61746ELLU, // quq_Latn_ES + 0xC69050454C61746ELLU, // qur_Latn_PE + 0xCA9041524C61746ELLU, // qus_Latn_AR + 0xD69047544C61746ELLU, // quv_Latn_GT + 0xDA9045434C61746ELLU, // quw_Latn_EC + 0xDE9050454C61746ELLU, // qux_Latn_PE + 0xE29050454C61746ELLU, // quy_Latn_PE + 0x82B050454C61746ELLU, // qva_Latn_PE + 0x8AB050454C61746ELLU, // qvc_Latn_PE + 0x92B050454C61746ELLU, // qve_Latn_PE + 0x9EB050454C61746ELLU, // qvh_Latn_PE + 0xA2B045434C61746ELLU, // qvi_Latn_EC + 0xA6B045434C61746ELLU, // qvj_Latn_EC + 0xAEB050454C61746ELLU, // qvl_Latn_PE + 0xB2B050454C61746ELLU, // qvm_Latn_PE + 0xB6B050454C61746ELLU, // qvn_Latn_PE + 0xBAB050454C61746ELLU, // qvo_Latn_PE + 0xBEB050454C61746ELLU, // qvp_Latn_PE + 0xCAB050454C61746ELLU, // qvs_Latn_PE + 0xDAB050454C61746ELLU, // qvw_Latn_PE + 0xE6B045434C61746ELLU, // qvz_Latn_EC + 0x82D050454C61746ELLU, // qwa_Latn_PE + 0x8AD050454C61746ELLU, // qwc_Latn_PE + 0x9ED050454C61746ELLU, // qwh_Latn_PE + 0xB2D048554C61746ELLU, // qwm_Latn_HU + 0xCAD050454C61746ELLU, // qws_Latn_PE + 0xCED055534C61746ELLU, // qwt_Latn_US + 0x82F050454C61746ELLU, // qxa_Latn_PE + 0x8AF050454C61746ELLU, // qxc_Latn_PE + 0x9EF050454C61746ELLU, // qxh_Latn_PE + 0xAEF045434C61746ELLU, // qxl_Latn_EC + 0xB6F050454C61746ELLU, // qxn_Latn_PE + 0xBAF050454C61746ELLU, // qxo_Latn_PE + 0xBEF050454C61746ELLU, // qxp_Latn_PE + 0xC2F0495241726162LLU, // qxq_Arab_IR + 0xC6F045434C61746ELLU, // qxr_Latn_EC + 0xCEF050454C61746ELLU, // qxt_Latn_PE + 0xD2F050454C61746ELLU, // qxu_Latn_PE + 0xDAF050454C61746ELLU, // qxw_Latn_PE + 0xBF1055534C61746ELLU, // qyp_Latn_US + 0x80114E5044657661LLU, // raa_Deva_NP + 0x84114E5044657661LLU, // rab_Deva_NP + 0x881149444C61746ELLU, // rac_Latn_ID + 0x8C11564E4C61746ELLU, // rad_Latn_VN + 0x94114E5044657661LLU, // raf_Deva_NP + 0x98114B454C61746ELLU, // rag_Latn_KE + 0x9C11494E42656E67LLU, // rah_Beng_IN + 0xA01150474C61746ELLU, // rai_Latn_PG 0xA411494E44657661LLU, // raj_Deva_IN + 0xA81150474C61746ELLU, // rak_Latn_PG + 0xB01142524C61746ELLU, // ram_Latn_BR + 0xB41149444C61746ELLU, // ran_Latn_ID + 0xB81150474C61746ELLU, // rao_Latn_PG + 0xBC11434C4C61746ELLU, // rap_Latn_CL + 0xC411434B4C61746ELLU, // rar_Latn_CK + 0xD4114E5044657661LLU, // rav_Deva_NP + 0xD8114D4D4C61746ELLU, // raw_Latn_MM + 0xDC114E474C61746ELLU, // rax_Latn_NG + 0xE01150464C61746ELLU, // ray_Latn_PF + 0xE41149444C61746ELLU, // raz_Latn_ID + 0x84314D4D4D796D72LLU, // rbb_Mymr_MM + 0xA83150484C61746ELLU, // rbk_Latn_PH + 0xAC3150484C61746ELLU, // rbl_Latn_PH + 0xBC3141554C61746ELLU, // rbp_Latn_AU 0x945152454C61746ELLU, // rcf_Latn_RE + 0x8471495241726162LLU, // rdb_Arab_IR + 0x809150474C61746ELLU, // rea_Latn_PG + 0x849149444C61746ELLU, // reb_Latn_ID + 0x90914D594C61746ELLU, // ree_Latn_MY + 0x9891545A4C61746ELLU, // reg_Latn_TZ + 0xA091494E4F727961LLU, // rei_Orya_IN 0xA49149444C61746ELLU, // rej_Latn_ID + 0xAC914B454C61746ELLU, // rel_Latn_KE + 0xB09150454C61746ELLU, // rem_Latn_PE + 0xB491564E4C61746ELLU, // ren_Latn_VN + 0xC8914E474C61746ELLU, // res_Latn_NG + 0xCC9149444C61746ELLU, // ret_Latn_ID + 0xE091424F4C61746ELLU, // rey_Latn_BO + 0x80D156554C61746ELLU, // rga_Latn_VU 0xB4D149544C61746ELLU, // rgn_Latn_IT + 0xC4D150454C61746ELLU, // rgr_Latn_PE + 0xC8D1564E4C61746ELLU, // rgs_Latn_VN + 0xD0D149444C61746ELLU, // rgu_Latn_ID 0x98F14D4D526F6867LLU, // rhg_Rohg_MM + 0xBCF150474C61746ELLU, // rhp_Latn_PG 0x8111494E4C61746ELLU, // ria_Latn_IN - 0x95114D4154666E67LLU, // rif_Tfng_MA + 0x95114D414C61746ELLU, // rif_Latn_MA + 0xAD114D4D4C61746ELLU, // ril_Latn_MM + 0xB111545A4C61746ELLU, // rim_Latn_TZ + 0xB5114E474C61746ELLU, // rin_Latn_NG + 0xC51149444C61746ELLU, // rir_Latn_ID + 0xCD1141554C61746ELLU, // rit_Latn_AU + 0xD11149444C61746ELLU, // riu_Latn_ID + 0x993149444C61746ELLU, // rjg_Latn_ID + 0xA1314E5044657661LLU, // rji_Deva_NP 0xC9314E5044657661LLU, // rjs_Deva_NP + 0x81514B484B686D72LLU, // rka_Khmr_KH + 0x855142524C61746ELLU, // rkb_Latn_BR + 0x9D51434B4C61746ELLU, // rkh_Latn_CK + 0xA1514D4D4D796D72LLU, // rki_Mymr_MM + 0xB15142464C61746ELLU, // rkm_Latn_BF 0xCD51424442656E67LLU, // rkt_Beng_BD + 0xD95141554C61746ELLU, // rkw_Latn_AU 0x726D43484C61746ELLU, // rm_Latn_CH + 0x81914E494C61746ELLU, // rma_Latn_NI + 0x859141554C61746ELLU, // rmb_Latn_AU + 0x8991534B4C61746ELLU, // rmc_Latn_SK + 0x8D91444B4C61746ELLU, // rmd_Latn_DK + 0x919147424C61746ELLU, // rme_Latn_GB 0x959146494C61746ELLU, // rmf_Latn_FI + 0x99914E4F4C61746ELLU, // rmg_Latn_NO + 0x9D9149444C61746ELLU, // rmh_Latn_ID + 0xA191414D41726D6ELLU, // rmi_Armn_AM + 0xA99150474C61746ELLU, // rmk_Latn_PG + 0xAD91504C4C61746ELLU, // rml_Latn_PL + 0xB19149444C61746ELLU, // rmm_Latn_ID + 0xB59152534C61746ELLU, // rmn_Latn_RS 0xB99143484C61746ELLU, // rmo_Latn_CH + 0xBD9150474C61746ELLU, // rmp_Latn_PG + 0xC19145534C61746ELLU, // rmq_Latn_ES 0xCD91495241726162LLU, // rmt_Arab_IR 0xD19153454C61746ELLU, // rmu_Latn_SE + 0xD99147424C61746ELLU, // rmw_Latn_GB + 0xDD91564E4C61746ELLU, // rmx_Latn_VN + 0xE591494E4D796D72LLU, // rmz_Mymr_IN 0x726E42494C61746ELLU, // rn_Latn_BI + 0x8DB143444C61746ELLU, // rnd_Latn_CD 0x99B14D5A4C61746ELLU, // rng_Latn_MZ + 0xADB1494E4C61746ELLU, // rnl_Latn_IN + 0xB5B149444C61746ELLU, // rnn_Latn_ID + 0xC5B141554C61746ELLU, // rnr_Latn_AU + 0xD9B1545A4C61746ELLU, // rnw_Latn_TZ 0x726F524F4C61746ELLU, // ro_Latn_RO 0x85D149444C61746ELLU, // rob_Latn_ID + 0x89D1564E4C61746ELLU, // roc_Latn_VN + 0x8DD14E474C61746ELLU, // rod_Latn_NG + 0x91D150474C61746ELLU, // roe_Latn_PG 0x95D1545A4C61746ELLU, // rof_Latn_TZ + 0x99D1564E4C61746ELLU, // rog_Latn_VN + 0xADD150484C61746ELLU, // rol_Latn_PH + 0xB1D1524F4C61746ELLU, // rom_Latn_RO + 0xB9D150474C61746ELLU, // roo_Latn_PG + 0xBDD141554C61746ELLU, // rop_Latn_AU + 0xC5D149444C61746ELLU, // ror_Latn_ID + 0xD1D154444C61746ELLU, // rou_Latn_TD + 0xD9D149444C61746ELLU, // row_Latn_ID + 0xB5F156554C61746ELLU, // rpn_Latn_VU + 0xCDF150474C61746ELLU, // rpt_Latn_PG + 0xA23153424C61746ELLU, // rri_Latn_SB + 0xB2314E5A4C61746ELLU, // rrm_Latn_NZ + 0xBA3150474C61746ELLU, // rro_Latn_PG + 0xCE3141554C61746ELLU, // rrt_Latn_AU + 0xAA5152534379726CLLU, // rsk_Cyrl_RS + 0xDA514E474C61746ELLU, // rsw_Latn_NG + 0x8A714D4D4C61746ELLU, // rtc_Latn_MM + 0x9E7149444C61746ELLU, // rth_Latn_ID 0xB271464A4C61746ELLU, // rtm_Latn_FJ + 0xDA71494E44657661LLU, // rtw_Deva_IN 0x727552554379726CLLU, // ru_Cyrl_RU + 0x869155474C61746ELLU, // rub_Latn_UG + 0x8A9155474C61746ELLU, // ruc_Latn_UG 0x929155414379726CLLU, // rue_Cyrl_UA + 0x9691545A4C61746ELLU, // ruf_Latn_TZ 0x9A9153424C61746ELLU, // rug_Latn_SB + 0xA291545A4C61746ELLU, // rui_Latn_TZ + 0xAA914E474C61746ELLU, // ruk_Latn_NG + 0xBA9148524C61746ELLU, // ruo_Latn_HR + 0xBE91524F4C61746ELLU, // rup_Latn_RO + 0xC29147524C61746ELLU, // ruq_Latn_GR + 0xCE9152554379726CLLU, // rut_Cyrl_RU + 0xD2914D594C61746ELLU, // ruu_Latn_MY + 0xE2914E474C61746ELLU, // ruy_Latn_NG + 0xE6914E474C61746ELLU, // ruz_Latn_NG 0x727752574C61746ELLU, // rw_Latn_RW + 0x82D150474C61746ELLU, // rwa_Latn_PG 0xAAD1545A4C61746ELLU, // rwk_Latn_TZ + 0xAED1545A4C61746ELLU, // rwl_Latn_TZ + 0xB2D155474C61746ELLU, // rwm_Latn_UG + 0xBAD150474C61746ELLU, // rwo_Latn_PG + 0xC6D1494E44657661LLU, // rwr_Deva_IN + 0x8EF141554C61746ELLU, // rxd_Latn_AU + 0xDAF141554C61746ELLU, // rxw_Latn_AU 0xD3114A504B616E61LLU, // ryu_Kana_JP 0x7361494E44657661LLU, // sa_Deva_IN + 0x801254444C61746ELLU, // saa_Latn_TD + 0x841250414C61746ELLU, // sab_Latn_PA + 0x881255534C61746ELLU, // sac_Latn_US + 0x8C12545A4C61746ELLU, // sad_Latn_TZ + 0x901242524C61746ELLU, // sae_Latn_BR 0x941247484C61746ELLU, // saf_Latn_GH 0x9C1252554379726CLLU, // sah_Cyrl_RU + 0xA41249444C61746ELLU, // saj_Latn_ID + 0xA81247414C61746ELLU, // sak_Latn_GA + 0xB012505353616D72LLU, // sam_Samr_PS + 0xB81249444C61746ELLU, // sao_Latn_ID 0xC0124B454C61746ELLU, // saq_Latn_KE + 0xC412424F4C61746ELLU, // sar_Latn_BO 0xC81249444C61746ELLU, // sas_Latn_ID 0xCC12494E4F6C636BLLU, // sat_Olck_IN + 0xD01249444C61746ELLU, // sau_Latn_ID 0xD412534E4C61746ELLU, // sav_Latn_SN + 0xD81249444C61746ELLU, // saw_Latn_ID + 0xDC1256554C61746ELLU, // sax_Latn_VU + 0xE0124E474C61746ELLU, // say_Latn_NG 0xE412494E53617572LLU, // saz_Saur_IN + 0x803254444C61746ELLU, // sba_Latn_TD + 0x843253424C61746ELLU, // sbb_Latn_SB + 0x883250474C61746ELLU, // sbc_Latn_PG + 0x8C3242464C61746ELLU, // sbd_Latn_BF + 0x903250474C61746ELLU, // sbe_Latn_PG + 0x983249444C61746ELLU, // sbg_Latn_ID + 0x9C3250474C61746ELLU, // sbh_Latn_PG + 0xA03250474C61746ELLU, // sbi_Latn_PG + 0xA43254444C61746ELLU, // sbj_Latn_TD + 0xA832545A4C61746ELLU, // sbk_Latn_TZ + 0xAC3250484C61746ELLU, // sbl_Latn_PH + 0xB032545A4C61746ELLU, // sbm_Latn_TZ + 0xB432504B41726162LLU, // sbn_Arab_PK + 0xB8324D594C61746ELLU, // sbo_Latn_MY 0xBC32545A4C61746ELLU, // sbp_Latn_TZ + 0xC03250474C61746ELLU, // sbq_Latn_PG + 0xC43249444C61746ELLU, // sbr_Latn_ID + 0xC8324E414C61746ELLU, // sbs_Latn_NA + 0xCC3249444C61746ELLU, // sbt_Latn_ID + 0xD032494E54696274LLU, // sbu_Tibt_IN + 0xD43249544C61746ELLU, // sbv_Latn_IT + 0xD83247414C61746ELLU, // sbw_Latn_GA + 0xDC3249444C61746ELLU, // sbx_Latn_ID + 0xE0325A4D4C61746ELLU, // sby_Latn_ZM + 0xE43243464C61746ELLU, // sbz_Latn_CF 0x736349544C61746ELLU, // sc_Latn_IT + 0x8452564E4C61746ELLU, // scb_Latn_VN + 0x9052434E4C61746ELLU, // sce_Latn_CN + 0x945250414C61746ELLU, // scf_Latn_PA + 0x985249444C61746ELLU, // scg_Latn_ID + 0x9C52494E4C61746ELLU, // sch_Latn_IN + 0xA0524C4B4C61746ELLU, // sci_Latn_LK 0xA852494E44657661LLU, // sck_Deva_IN + 0xAC52504B41726162LLU, // scl_Arab_PK 0xB45249544C61746ELLU, // scn_Latn_IT 0xB85247424C61746ELLU, // sco_Latn_GB + 0xBC524E5044657661LLU, // scp_Deva_NP + 0xC85243414C61746ELLU, // scs_Latn_CA + 0xCC524C414C616F6FLLU, // sct_Laoo_LA + 0xD052494E54616B72LLU, // scu_Takr_IN + 0xD4524E474C61746ELLU, // scv_Latn_NG + 0xD8524E474C61746ELLU, // scw_Latn_NG + 0xDC5249544772656BLLU, // scx_Grek_IT 0x7364504B41726162LLU, // sd_Arab_PK 0x7364494E44657661LLU, // sd_Deva_IN 0x7364494E4B686F6ALLU, // sd_Khoj_IN 0x7364494E53696E64LLU, // sd_Sind_IN + 0x807249444C61746ELLU, // sda_Latn_ID + 0x8472495141726162LLU, // sdb_Arab_IQ 0x887249544C61746ELLU, // sdc_Latn_IT + 0x90724E474C61746ELLU, // sde_Latn_NG + 0x9472495141726162LLU, // sdf_Arab_IQ + 0x9872414641726162LLU, // sdg_Arab_AF 0x9C72495241726162LLU, // sdh_Arab_IR + 0xA47243474C61746ELLU, // sdj_Latn_CG + 0xA87250474C61746ELLU, // sdk_Latn_PG + 0xB47249544C61746ELLU, // sdn_Latn_IT + 0xB8724D594C61746ELLU, // sdo_Latn_MY + 0xC07249444C61746ELLU, // sdq_Latn_ID + 0xC472424442656E67LLU, // sdr_Beng_BD + 0xC872544E41726162LLU, // sds_Arab_TN + 0xD07249444C61746ELLU, // sdu_Latn_ID + 0xDC724D594C61746ELLU, // sdx_Latn_MY 0x73654E4F4C61746ELLU, // se_Latn_NO + 0x80924D594C61746ELLU, // sea_Latn_MY + 0x849243494C61746ELLU, // seb_Latn_CI + 0x889243414C61746ELLU, // sec_Latn_CA + 0x8C92564E4C61746ELLU, // sed_Latn_VN + 0x909255534C61746ELLU, // see_Latn_US 0x949243494C61746ELLU, // sef_Latn_CI + 0x9892545A4C61746ELLU, // seg_Latn_TZ 0x9C924D5A4C61746ELLU, // seh_Latn_MZ 0xA0924D584C61746ELLU, // sei_Latn_MX + 0xA49250474C61746ELLU, // sej_Latn_PG + 0xA89243414C61746ELLU, // sek_Latn_CA + 0xAC9252554379726CLLU, // sel_Cyrl_RU + 0xB49242464C61746ELLU, // sen_Latn_BF + 0xB89250474C61746ELLU, // seo_Latn_PG + 0xBC9242464C61746ELLU, // sep_Latn_BF + 0xC09242464C61746ELLU, // seq_Latn_BF + 0xC49255534C61746ELLU, // ser_Latn_US 0xC8924D4C4C61746ELLU, // ses_Latn_ML + 0xCC9249444C61746ELLU, // set_Latn_ID + 0xD09249444C61746ELLU, // seu_Latn_ID + 0xD49243494C61746ELLU, // sev_Latn_CI + 0xD89250474C61746ELLU, // sew_Latn_PG + 0xE09245434C61746ELLU, // sey_Latn_EC + 0xE4924D4D4C61746ELLU, // sez_Latn_MM + 0x90B250484C61746ELLU, // sfe_Latn_PH + 0xB0B2434E506C7264LLU, // sfm_Plrd_CN + 0xD8B247484C61746ELLU, // sfw_Latn_GH 0x736743464C61746ELLU, // sg_Latn_CF 0x80D249454F67616DLLU, // sga_Ogam_IE + 0x84D250484C61746ELLU, // sgb_Latn_PH + 0x88D24B454C61746ELLU, // sgc_Latn_KE + 0x8CD250484C61746ELLU, // sgd_Latn_PH + 0x90D249444C61746ELLU, // sge_Latn_ID + 0x9CD2544A4379726CLLU, // sgh_Cyrl_TJ + 0xA0D2434D4C61746ELLU, // sgi_Latn_CM + 0xA4D2494E44657661LLU, // sgj_Deva_IN + 0xB0D24B454C61746ELLU, // sgm_Latn_KE + 0xBCD2494E4C61746ELLU, // sgp_Latn_IN + 0xC4D2495241726162LLU, // sgr_Arab_IR 0xC8D24C544C61746ELLU, // sgs_Latn_LT + 0xCCD2425454696274LLU, // sgt_Tibt_BT + 0xD0D249444C61746ELLU, // sgu_Latn_ID + 0xD8D2455445746869LLU, // sgw_Ethi_ET + 0xE0D2414641726162LLU, // sgy_Arab_AF + 0xE4D250474C61746ELLU, // sgz_Latn_PG + 0x80F24E474C61746ELLU, // sha_Latn_NG + 0x84F242524C61746ELLU, // shb_Latn_BR + 0x88F243444C61746ELLU, // shc_Latn_CD + 0x8CF2504B41726162LLU, // shd_Arab_PK + 0x90F245544C61746ELLU, // she_Latn_ET + 0x98F242574C61746ELLU, // shg_Latn_BW + 0x9CF255534C61746ELLU, // shh_Latn_US 0xA0F24D4154666E67LLU, // shi_Tfng_MA + 0xA4F253444C61746ELLU, // shj_Latn_SD + 0xA8F253534C61746ELLU, // shk_Latn_SS + 0xB0F2495241726162LLU, // shm_Arab_IR 0xB4F24D4D4D796D72LLU, // shn_Mymr_MM + 0xB8F24E474C61746ELLU, // sho_Latn_NG + 0xBCF250454C61746ELLU, // shp_Latn_PE + 0xC0F25A4D4C61746ELLU, // shq_Latn_ZM + 0xC4F243444C61746ELLU, // shr_Latn_CD + 0xC8F243414C61746ELLU, // shs_Latn_CA + 0xCCF255534C61746ELLU, // sht_Latn_US + 0xD0F2544441726162LLU, // shu_Arab_TD + 0xD4F24F4D41726162LLU, // shv_Arab_OM + 0xD8F253444C61746ELLU, // shw_Latn_SD + 0xE0F2445A4C61746ELLU, // shy_Latn_DZ + 0xE4F24D4C4C61746ELLU, // shz_Latn_ML 0x73694C4B53696E68LLU, // si_Sinh_LK + 0x811252554379726CLLU, // sia_Cyrl_RU + 0x85124D594C61746ELLU, // sib_Latn_MY 0x8D1245544C61746ELLU, // sid_Latn_ET + 0x91125A4D4C61746ELLU, // sie_Latn_ZM + 0x951242464C61746ELLU, // sif_Latn_BF + 0x991247484C61746ELLU, // sig_Latn_GH + 0x9D124E434C61746ELLU, // sih_Latn_NC + 0xA112494E4C61746ELLU, // sii_Latn_IN + 0xA51250474C61746ELLU, // sij_Latn_PG + 0xA91242524C61746ELLU, // sik_Latn_BR + 0xAD1247484C61746ELLU, // sil_Latn_GH + 0xB11250474C61746ELLU, // sim_Latn_PG + 0xBD12494E54696274LLU, // sip_Tibt_IN + 0xC11250474C61746ELLU, // siq_Latn_PG + 0xC5124E474C61746ELLU, // sir_Latn_NG + 0xC91255534C61746ELLU, // sis_Latn_US + 0xD11250474C61746ELLU, // siu_Latn_PG + 0xD51250474C61746ELLU, // siv_Latn_PG + 0xD91250474C61746ELLU, // siw_Latn_PG + 0xDD1250474C61746ELLU, // six_Latn_PG + 0xE112495241726162LLU, // siy_Arab_IR + 0xE512454741726162LLU, // siz_Arab_EG + 0x8132434F4C61746ELLU, // sja_Latn_CO + 0x853249444C61746ELLU, // sjb_Latn_ID + 0x8D3252554379726CLLU, // sjd_Cyrl_RU + 0x913253454C61746ELLU, // sje_Latn_SE + 0x993254444C61746ELLU, // sjg_Latn_TD + 0xAD32494E4C61746ELLU, // sjl_Latn_IN + 0xB13250484C61746ELLU, // sjm_Latn_PH + 0xBD32494E44657661LLU, // sjp_Deva_IN + 0xC53250474C61746ELLU, // sjr_Latn_PG + 0xCD3252554379726CLLU, // sjt_Cyrl_RU + 0xD13253454C61746ELLU, // sju_Latn_SE + 0xD93255534C61746ELLU, // sjw_Latn_US 0x736B534B4C61746ELLU, // sk_Latn_SK + 0x815255534C61746ELLU, // ska_Latn_US + 0x8552544854686169LLU, // skb_Thai_TH + 0x895250474C61746ELLU, // skc_Latn_PG + 0x8D5255534C61746ELLU, // skd_Latn_US + 0x915256554C61746ELLU, // ske_Latn_VU + 0x955242524C61746ELLU, // skf_Latn_BR + 0x99524D474C61746ELLU, // skg_Latn_MG + 0x9D5249444C61746ELLU, // skh_Latn_ID + 0xA15249444C61746ELLU, // ski_Latn_ID + 0xA5524E5044657661LLU, // skj_Deva_NP + 0xB15250474C61746ELLU, // skm_Latn_PG + 0xB55250484C61746ELLU, // skn_Latn_PH + 0xB95249444C61746ELLU, // sko_Latn_ID + 0xBD524D594C61746ELLU, // skp_Latn_MY + 0xC15242464C61746ELLU, // skq_Latn_BF 0xC552504B41726162LLU, // skr_Arab_PK + 0xC95250474C61746ELLU, // sks_Latn_PG + 0xCD5243444C61746ELLU, // skt_Latn_CD + 0xD15256554C61746ELLU, // sku_Latn_VU + 0xD55249444C61746ELLU, // skv_Latn_ID + 0xD95247594C61746ELLU, // skw_Latn_GY + 0xDD5249444C61746ELLU, // skx_Latn_ID + 0xE15253424C61746ELLU, // sky_Latn_SB + 0xE55249444C61746ELLU, // skz_Latn_ID 0x736C53494C61746ELLU, // sl_Latn_SI + 0x8972434F4C61746ELLU, // slc_Latn_CO + 0x8D7242464C61746ELLU, // sld_Latn_BF + 0x997249444C61746ELLU, // slg_Latn_ID + 0x9D7255534C61746ELLU, // slh_Latn_US 0xA172504C4C61746ELLU, // sli_Latn_PL + 0xA57242524C61746ELLU, // slj_Latn_BR + 0xAD7250474C61746ELLU, // sll_Latn_PG + 0xB17250484C61746ELLU, // slm_Latn_PH + 0xB57255534C61746ELLU, // sln_Latn_US + 0xBD7249444C61746ELLU, // slp_Latn_ID + 0xC572434E4C61746ELLU, // slr_Latn_CN + 0xD17249444C61746ELLU, // slu_Latn_ID + 0xD97250474C61746ELLU, // slw_Latn_PG + 0xDD7243444C61746ELLU, // slx_Latn_CD 0xE17249444C61746ELLU, // sly_Latn_ID + 0xE57249444C61746ELLU, // slz_Latn_ID 0x736D57534C61746ELLU, // sm_Latn_WS 0x819253454C61746ELLU, // sma_Latn_SE - 0x8D92414F4C61746ELLU, // smd_Latn_AO + 0x859250474C61746ELLU, // smb_Latn_PG + 0x899250474C61746ELLU, // smc_Latn_PG + 0x959250474C61746ELLU, // smf_Latn_PG + 0x999250474C61746ELLU, // smg_Latn_PG + 0x9D92434E59696969LLU, // smh_Yiii_CN 0xA59253454C61746ELLU, // smj_Latn_SE + 0xA99250484C61746ELLU, // smk_Latn_PH + 0xAD9250484C61746ELLU, // sml_Latn_PH 0xB59246494C61746ELLU, // smn_Latn_FI 0xBD92494C53616D72LLU, // smp_Samr_IL + 0xC19250474C61746ELLU, // smq_Latn_PG + 0xC59249444C61746ELLU, // smr_Latn_ID 0xC99246494C61746ELLU, // sms_Latn_FI + 0xCD92494E4C61746ELLU, // smt_Latn_IN + 0xD1924B484B686D72LLU, // smu_Khmr_KH + 0xD99249444C61746ELLU, // smw_Latn_ID + 0xDD9243444C61746ELLU, // smx_Latn_CD + 0xE192495241726162LLU, // smy_Arab_IR + 0xE59250474C61746ELLU, // smz_Latn_PG 0x736E5A574C61746ELLU, // sn_Latn_ZW - 0x85B24D594C61746ELLU, // snb_Latn_MY + 0x89B250474C61746ELLU, // snc_Latn_PG + 0x91B24D594C61746ELLU, // sne_Latn_MY + 0x95B2534E4C61746ELLU, // snf_Latn_SN + 0x99B243444C61746ELLU, // sng_Latn_CD + 0xA1B250454C61746ELLU, // sni_Latn_PE + 0xA5B243464C61746ELLU, // snj_Latn_CF 0xA9B24D4C4C61746ELLU, // snk_Latn_ML + 0xADB250484C61746ELLU, // snl_Latn_PH + 0xB1B255474C61746ELLU, // snm_Latn_UG + 0xB5B2434F4C61746ELLU, // snn_Latn_CO + 0xB9B255534C61746ELLU, // sno_Latn_US + 0xBDB250474C61746ELLU, // snp_Latn_PG + 0xC1B247414C61746ELLU, // snq_Latn_GA + 0xC5B250474C61746ELLU, // snr_Latn_PG + 0xC9B256554C61746ELLU, // sns_Latn_VU + 0xD1B249444C61746ELLU, // snu_Latn_ID + 0xD5B24D594C61746ELLU, // snv_Latn_MY + 0xD9B247484C61746ELLU, // snw_Latn_GH + 0xDDB250474C61746ELLU, // snx_Latn_PG + 0xE1B250474C61746ELLU, // sny_Latn_PG + 0xE5B250474C61746ELLU, // snz_Latn_PG 0x736F534F4C61746ELLU, // so_Latn_SO + 0x81D2544854617674LLU, // soa_Tavt_TH + 0x85D249444C61746ELLU, // sob_Latn_ID + 0x89D243444C61746ELLU, // soc_Latn_CD + 0x8DD243444C61746ELLU, // sod_Latn_CD + 0x91D243444C61746ELLU, // soe_Latn_CD 0x99D2555A536F6764LLU, // sog_Sogd_UZ + 0xA1D24E5044657661LLU, // soi_Deva_NP + 0xA9D254444C61746ELLU, // sok_Latn_TD + 0xADD250474C61746ELLU, // sol_Latn_PG + 0xB9D243444C61746ELLU, // soo_Latn_CD + 0xBDD243444C61746ELLU, // sop_Latn_CD + 0xC1D250474C61746ELLU, // soq_Latn_PG + 0xC5D254444C61746ELLU, // sor_Latn_TD + 0xC9D242464C61746ELLU, // sos_Latn_BF 0xD1D2544854686169LLU, // sou_Thai_TH + 0xD5D250574C61746ELLU, // sov_Latn_PW + 0xD9D250474C61746ELLU, // sow_Latn_PG + 0xDDD2434D4C61746ELLU, // sox_Latn_CM + 0xE1D2424A4C61746ELLU, // soy_Latn_BJ + 0xE5D2545A4C61746ELLU, // soz_Latn_TZ + 0x85F249444C61746ELLU, // spb_Latn_ID + 0x89F256454C61746ELLU, // spc_Latn_VE + 0x8DF250474C61746ELLU, // spd_Latn_PG + 0x91F250474C61746ELLU, // spe_Latn_PG + 0x99F24D594C61746ELLU, // spg_Latn_MY + 0xA1F249444C61746ELLU, // spi_Latn_ID + 0xA9F250474C61746ELLU, // spk_Latn_PG + 0xADF250474C61746ELLU, // spl_Latn_PG + 0xB1F250474C61746ELLU, // spm_Latn_PG + 0xB5F250594C61746ELLU, // spn_Latn_PY + 0xB9F255534C61746ELLU, // spo_Latn_US + 0xBDF24D4C4C61746ELLU, // spp_Latn_ML + 0xC1F250454C61746ELLU, // spq_Latn_PE + 0xC5F249444C61746ELLU, // spr_Latn_ID + 0xC9F250474C61746ELLU, // sps_Latn_PG + 0xCDF2494E54696274LLU, // spt_Tibt_IN + 0xD5F2494E4F727961LLU, // spv_Orya_IN 0x7371414C4C61746ELLU, // sq_Latn_AL + 0x82124E474C61746ELLU, // sqa_Latn_NG + 0x9E124E474C61746ELLU, // sqh_Latn_NG + 0xB21243464C61746ELLU, // sqm_Latn_CF + 0xBA12495241726162LLU, // sqo_Arab_IR + 0xC2124C414C616F6FLLU, // sqq_Laoo_LA + 0xCE12594541726162LLU, // sqt_Arab_YE + 0xD21243414C61746ELLU, // squ_Latn_CA 0x737252534379726CLLU, // sr_Cyrl_RS - 0x737252534C61746ELLU, // sr_Latn_RS + 0x823250474C61746ELLU, // sra_Latn_PG 0x8632494E536F7261LLU, // srb_Sora_IN + 0x923249444C61746ELLU, // sre_Latn_ID + 0x963250474C61746ELLU, // srf_Latn_PG + 0x9A3250484C61746ELLU, // srg_Latn_PH + 0x9E32434E41726162LLU, // srh_Arab_CN + 0xA232434F4C61746ELLU, // sri_Latn_CO + 0xAA324D594C61746ELLU, // srk_Latn_MY + 0xAE3249444C61746ELLU, // srl_Latn_ID + 0xB23253524C61746ELLU, // srm_Latn_SR 0xB63253524C61746ELLU, // srn_Latn_SR + 0xBA3249544C61746ELLU, // sro_Latn_IT + 0xC232424F4C61746ELLU, // srq_Latn_BO 0xC632534E4C61746ELLU, // srr_Latn_SN + 0xCA3243414C61746ELLU, // srs_Latn_CA + 0xCE3249444C61746ELLU, // srt_Latn_ID + 0xD23242524C61746ELLU, // sru_Latn_BR + 0xD63250484C61746ELLU, // srv_Latn_PH + 0xDA3249444C61746ELLU, // srw_Latn_ID 0xDE32494E44657661LLU, // srx_Deva_IN + 0xE23250474C61746ELLU, // sry_Latn_PG + 0xE632495241726162LLU, // srz_Arab_IR 0x73735A414C61746ELLU, // ss_Latn_ZA + 0x865250484C61746ELLU, // ssb_Latn_PH + 0x8A52545A4C61746ELLU, // ssc_Latn_TZ + 0x8E5250474C61746ELLU, // ssd_Latn_PG + 0x925250484C61746ELLU, // sse_Latn_PH + 0x965254574C61746ELLU, // ssf_Latn_TW + 0x9A5250474C61746ELLU, // ssg_Latn_PG + 0x9E52414541726162LLU, // ssh_Arab_AE + 0xA65250474C61746ELLU, // ssj_Latn_PG + 0xAE5247484C61746ELLU, // ssl_Latn_GH + 0xB2524D594C61746ELLU, // ssm_Latn_MY + 0xB6524B454C61746ELLU, // ssn_Latn_KE + 0xBA5250474C61746ELLU, // sso_Latn_PG + 0xC25249444C61746ELLU, // ssq_Latn_ID + 0xCA524C414C616F6FLLU, // sss_Laoo_LA + 0xCE5250474C61746ELLU, // sst_Latn_PG + 0xD25250474C61746ELLU, // ssu_Latn_PG + 0xD65256554C61746ELLU, // ssv_Latn_VU + 0xDE5250474C61746ELLU, // ssx_Latn_PG 0xE25245524C61746ELLU, // ssy_Latn_ER + 0xE65250474C61746ELLU, // ssz_Latn_PG 0x73745A414C61746ELLU, // st_Latn_ZA + 0x82725A4D4C61746ELLU, // sta_Latn_ZM + 0x867250484C61746ELLU, // stb_Latn_PH + 0x927249444C61746ELLU, // ste_Latn_ID + 0x967250474C61746ELLU, // stf_Latn_PG + 0x9A72564E4C61746ELLU, // stg_Latn_VN + 0x9E7249454C61746ELLU, // sth_Latn_IE + 0xA272564E4C61746ELLU, // sti_Latn_VN + 0xA67242464C61746ELLU, // stj_Latn_BF + 0xAA7250474C61746ELLU, // stk_Latn_PG + 0xAE724E4C4C61746ELLU, // stl_Latn_NL + 0xB27250474C61746ELLU, // stm_Latn_PG + 0xB67253424C61746ELLU, // stn_Latn_SB + 0xBA7243414C61746ELLU, // sto_Latn_CA + 0xBE724D584C61746ELLU, // stp_Latn_MX 0xC27244454C61746ELLU, // stq_Latn_DE + 0xC67243414C61746ELLU, // str_Latn_CA + 0xCA72414641726162LLU, // sts_Arab_AF + 0xCE72564E4C61746ELLU, // stt_Latn_VN + 0xD672455445746869LLU, // stv_Ethi_ET + 0xDA72464D4C61746ELLU, // stw_Latn_FM + 0xE27252554379726CLLU, // sty_Cyrl_RU 0x737549444C61746ELLU, // su_Latn_ID + 0x829250474C61746ELLU, // sua_Latn_PG + 0x869243444C61746ELLU, // sub_Latn_CD + 0x8A9250484C61746ELLU, // suc_Latn_PH + 0x929250474C61746ELLU, // sue_Latn_PG + 0x9A9250474C61746ELLU, // sug_Latn_PG + 0xA29250474C61746ELLU, // sui_Latn_PG + 0xA692545A4C61746ELLU, // suj_Latn_TZ 0xAA92545A4C61746ELLU, // suk_Latn_TZ + 0xBA9250474C61746ELLU, // suo_Latn_PG + 0xC29245544C61746ELLU, // suq_Latn_ET + 0xC6924E474C61746ELLU, // sur_Latn_NG 0xCA92474E4C61746ELLU, // sus_Latn_GN + 0xCE924E494C61746ELLU, // sut_Latn_NI + 0xD692494E4C61746ELLU, // suv_Latn_IN + 0xDA92545A4C61746ELLU, // suw_Latn_TZ + 0xE29242524C61746ELLU, // suy_Latn_BR + 0xE6924E5053756E75LLU, // suz_Sunu_NP 0x737653454C61746ELLU, // sv_Latn_SE + 0x82B2474547656F72LLU, // sva_Geor_GE + 0x86B250474C61746ELLU, // svb_Latn_PG + 0x8AB256434C61746ELLU, // svc_Latn_VC + 0x92B249444C61746ELLU, // sve_Latn_ID + 0xB2B249544C61746ELLU, // svm_Latn_IT + 0xCAB253424C61746ELLU, // svs_Latn_SB 0x7377545A4C61746ELLU, // sw_Latn_TZ 0x86D2595441726162LLU, // swb_Arab_YT - 0x8AD243444C61746ELLU, // swc_Latn_CD + 0x96D243444C61746ELLU, // swf_Latn_CD 0x9AD244454C61746ELLU, // swg_Latn_DE + 0xA2D2434E48616E69LLU, // swi_Hani_CN + 0xA6D247414C61746ELLU, // swj_Latn_GA + 0xAAD24D574C61746ELLU, // swk_Latn_MW + 0xB2D250474C61746ELLU, // swm_Latn_PG + 0xBAD242524C61746ELLU, // swo_Latn_BR + 0xBED250474C61746ELLU, // swp_Latn_PG + 0xC2D2434D4C61746ELLU, // swq_Latn_CM + 0xC6D249444C61746ELLU, // swr_Latn_ID + 0xCAD249444C61746ELLU, // sws_Latn_ID + 0xCED249444C61746ELLU, // swt_Latn_ID + 0xD2D249444C61746ELLU, // swu_Latn_ID 0xD6D2494E44657661LLU, // swv_Deva_IN + 0xDAD256554C61746ELLU, // sww_Latn_VU + 0xDED242524C61746ELLU, // swx_Latn_BR + 0xE2D254444C61746ELLU, // swy_Latn_TD + 0x86F24B454C61746ELLU, // sxb_Latn_KE + 0x92F247414C61746ELLU, // sxe_Latn_GA 0xB6F249444C61746ELLU, // sxn_Latn_ID + 0xC6F254574C61746ELLU, // sxr_Latn_TW + 0xCAF24E474C61746ELLU, // sxs_Latn_NG + 0xD2F2444552756E72LLU, // sxu_Runr_DE + 0xDAF2424A4C61746ELLU, // sxw_Latn_BJ + 0x831249444C61746ELLU, // sya_Latn_ID + 0x871250484C61746ELLU, // syb_Latn_PH + 0x8B12545253797263LLU, // syc_Syrc_TR + 0xA31247414C61746ELLU, // syi_Latn_GA + 0xAB124E474C61746ELLU, // syk_Latn_NG 0xAF12424442656E67LLU, // syl_Beng_BD + 0xB31242464C61746ELLU, // sym_Latn_BF + 0xB712495253797263LLU, // syn_Syrc_IR + 0xBB124B484C61746ELLU, // syo_Latn_KH 0xC712495153797263LLU, // syr_Syrc_IQ + 0xCB1254444C61746ELLU, // sys_Latn_TD + 0xDB124E5044657661LLU, // syw_Deva_NP + 0xDF1247414C61746ELLU, // syx_Latn_GA + 0x83324D594C61746ELLU, // sza_Latn_MY + 0x873249444C61746ELLU, // szb_Latn_ID + 0x8B324D594C61746ELLU, // szc_Latn_MY + 0x9B3243444C61746ELLU, // szg_Latn_CD 0xAF32504C4C61746ELLU, // szl_Latn_PL + 0xB73249444C61746ELLU, // szn_Latn_ID + 0xBF3249444C61746ELLU, // szp_Latn_ID + 0xD732434D4C61746ELLU, // szv_Latn_CM + 0xDB3249444C61746ELLU, // szw_Latn_ID + 0xE33254574C61746ELLU, // szy_Latn_TW 0x7461494E54616D6CLLU, // ta_Taml_IN + 0x801355534C61746ELLU, // taa_Latn_US + 0x841352554379726CLLU, // tab_Cyrl_RU + 0x88134D584C61746ELLU, // tac_Latn_MX + 0x8C1349444C61746ELLU, // tad_Latn_ID + 0x901342524C61746ELLU, // tae_Latn_BR + 0x941342524C61746ELLU, // taf_Latn_BR + 0x981353444C61746ELLU, // tag_Latn_SD 0xA4134E5044657661LLU, // taj_Deva_NP + 0xA8134E474C61746ELLU, // tak_Latn_NG + 0xAC134E474C61746ELLU, // tal_Latn_NG + 0xB4134E474C61746ELLU, // tan_Latn_NG + 0xB81354574C61746ELLU, // tao_Latn_TW + 0xBC1343444C61746ELLU, // tap_Latn_CD + 0xC0134D4C4C61746ELLU, // taq_Latn_ML + 0xC4134D584C61746ELLU, // tar_Latn_MX + 0xC813564E4C61746ELLU, // tas_Latn_VN + 0xD01355534C61746ELLU, // tau_Latn_US + 0xD413434F4C61746ELLU, // tav_Latn_CO + 0xD81350474C61746ELLU, // taw_Latn_PG + 0xDC1354444C61746ELLU, // tax_Latn_TD + 0xE01354574C61746ELLU, // tay_Latn_TW + 0xE41353444C61746ELLU, // taz_Latn_SD + 0x803342524C61746ELLU, // tba_Latn_BR + 0x883350474C61746ELLU, // tbc_Latn_PG + 0x8C3350474C61746ELLU, // tbd_Latn_PG + 0x903353424C61746ELLU, // tbe_Latn_SB + 0x943350474C61746ELLU, // tbf_Latn_PG + 0x983350474C61746ELLU, // tbg_Latn_PG + 0x9C3341554C61746ELLU, // tbh_Latn_AU + 0xA03353444C61746ELLU, // tbi_Latn_SD + 0xA43350474C61746ELLU, // tbj_Latn_PG + 0xA833504854616762LLU, // tbk_Tagb_PH + 0xAC3350484C61746ELLU, // tbl_Latn_PH + 0xB03343444C61746ELLU, // tbm_Latn_CD + 0xB433434F4C61746ELLU, // tbn_Latn_CO + 0xB83350474C61746ELLU, // tbo_Latn_PG + 0xBC3349444C61746ELLU, // tbp_Latn_ID + 0xC83350474C61746ELLU, // tbs_Latn_PG + 0xCC3343444C61746ELLU, // tbt_Latn_CD + 0xD0334D584C61746ELLU, // tbu_Latn_MX + 0xD43350474C61746ELLU, // tbv_Latn_PG 0xD83350484C61746ELLU, // tbw_Latn_PH + 0xDC3350474C61746ELLU, // tbx_Latn_PG + 0xE03349444C61746ELLU, // tby_Latn_ID + 0xE433424A4C61746ELLU, // tbz_Latn_BJ + 0x805342524C61746ELLU, // tca_Latn_BR + 0x845355534C61746ELLU, // tcb_Latn_US + 0x8853545A4C61746ELLU, // tcc_Latn_TZ + 0x8C5347484C61746ELLU, // tcd_Latn_GH + 0x905343414C61746ELLU, // tce_Latn_CA + 0x94534D584C61746ELLU, // tcf_Latn_MX + 0x985349444C61746ELLU, // tcg_Latn_ID + 0x9C5354434C61746ELLU, // tch_Latn_TC + 0xA05350474C61746ELLU, // tci_Latn_PG + 0xA85347414C61746ELLU, // tck_Latn_GA + 0xB05349444C61746ELLU, // tcm_Latn_ID + 0xB4534E5054696274LLU, // tcn_Tibt_NP + 0xB8534D4D4D796D72LLU, // tco_Mymr_MM + 0xBC534D4D4C61746ELLU, // tcp_Latn_MM + 0xC05349444C61746ELLU, // tcq_Latn_ID + 0xC85341554C61746ELLU, // tcs_Latn_AU + 0xD0534D584C61746ELLU, // tcu_Latn_MX + 0xD8534D584C61746ELLU, // tcw_Latn_MX + 0xDC53494E54616D6CLLU, // tcx_Taml_IN 0xE053494E4B6E6461LLU, // tcy_Knda_IN + 0xE453494E4C61746ELLU, // tcz_Latn_IN + 0x80734E4554666E67LLU, // tda_Tfng_NE + 0x8473494E44657661LLU, // tdb_Deva_IN + 0x8873434F4C61746ELLU, // tdc_Latn_CO 0x8C73434E54616C65LLU, // tdd_Tale_CN + 0x90734D4C4C61746ELLU, // tde_Latn_ML 0x98734E5044657661LLU, // tdg_Deva_NP 0x9C734E5044657661LLU, // tdh_Deva_NP - 0xD0734D594C61746ELLU, // tdu_Latn_MY + 0xA07349444C61746ELLU, // tdi_Latn_ID + 0xA47349444C61746ELLU, // tdj_Latn_ID + 0xA8734E474C61746ELLU, // tdk_Latn_NG + 0xAC734E474C61746ELLU, // tdl_Latn_NG + 0xB07347594C61746ELLU, // tdm_Latn_GY + 0xB47349444C61746ELLU, // tdn_Latn_ID + 0xB8734E474C61746ELLU, // tdo_Latn_NG + 0xC0734E474C61746ELLU, // tdq_Latn_NG + 0xC473564E4C61746ELLU, // tdr_Latn_VN + 0xC87349444C61746ELLU, // tds_Latn_ID + 0xCC73544C4C61746ELLU, // tdt_Latn_TL + 0xD4734E474C61746ELLU, // tdv_Latn_NG + 0xDC734D474C61746ELLU, // tdx_Latn_MG + 0xE07350484C61746ELLU, // tdy_Latn_PH 0x7465494E54656C75LLU, // te_Telu_IN + 0x80934D594C61746ELLU, // tea_Latn_MY + 0x849345434C61746ELLU, // teb_Latn_EC + 0x88934B454C61746ELLU, // tec_Latn_KE + 0x8C9343494C61746ELLU, // ted_Latn_CI + 0x90934D584C61746ELLU, // tee_Latn_MX + 0x989347414C61746ELLU, // teg_Latn_GA + 0x9C9341524C61746ELLU, // teh_Latn_AR + 0xA09350474C61746ELLU, // tei_Latn_PG + 0xA89343444C61746ELLU, // tek_Latn_CD 0xB093534C4C61746ELLU, // tem_Latn_SL + 0xB493434F4C61746ELLU, // ten_Latn_CO 0xB89355474C61746ELLU, // teo_Latn_UG + 0xBC934D584C61746ELLU, // tep_Latn_MX + 0xC09353444C61746ELLU, // teq_Latn_SD + 0xC49342524C61746ELLU, // ter_Latn_BR + 0xC89349444A617661LLU, // tes_Java_ID 0xCC93544C4C61746ELLU, // tet_Latn_TL + 0xD09355474C61746ELLU, // teu_Latn_UG + 0xD49349444C61746ELLU, // tev_Latn_ID + 0xD89355534C61746ELLU, // tew_Latn_US + 0xDC9353534C61746ELLU, // tex_Latn_SS + 0xE09353444C61746ELLU, // tey_Latn_SD + 0xE4934E454C61746ELLU, // tez_Latn_NE + 0xA0B3424A4C61746ELLU, // tfi_Latn_BJ + 0xB4B355534C61746ELLU, // tfn_Latn_US + 0xB8B349444C61746ELLU, // tfo_Latn_ID + 0xC4B350414C61746ELLU, // tfr_Latn_PA + 0xCCB349444C61746ELLU, // tft_Latn_ID 0x7467504B41726162LLU, // tg_Arab_PK 0x7467544A4379726CLLU, // tg_Cyrl_TJ + 0x80D34B454C61746ELLU, // tga_Latn_KE + 0x84D34D594C61746ELLU, // tgb_Latn_MY + 0x88D350474C61746ELLU, // tgc_Latn_PG + 0x8CD34E474C61746ELLU, // tgd_Latn_NG + 0x90D34E5044657661LLU, // tge_Deva_NP + 0x94D3425454696274LLU, // tgf_Tibt_BT + 0x9CD354544C61746ELLU, // tgh_Latn_TT + 0xA0D350474C61746ELLU, // tgi_Latn_PG + 0xA4D3494E4C61746ELLU, // tgj_Latn_IN + 0xB4D350484C61746ELLU, // tgn_Latn_PH + 0xB8D350474C61746ELLU, // tgo_Latn_PG + 0xBCD356554C61746ELLU, // tgp_Latn_VU + 0xC0D34D594C61746ELLU, // tgq_Latn_MY + 0xC8D356554C61746ELLU, // tgs_Latn_VU + 0xCCD350484C61746ELLU, // tgt_Latn_PH + 0xD0D350474C61746ELLU, // tgu_Latn_PG + 0xD4D342524C61746ELLU, // tgv_Latn_BR + 0xD8D343494C61746ELLU, // tgw_Latn_CI + 0xDCD343414C61746ELLU, // tgx_Latn_CA + 0xE0D353534C61746ELLU, // tgy_Latn_SS + 0xE4D341554C61746ELLU, // tgz_Latn_AU 0x7468544854686169LLU, // th_Thai_TH + 0x8CF341554C61746ELLU, // thd_Latn_AU + 0x90F34E5044657661LLU, // the_Deva_NP + 0x94F34E5044657661LLU, // thf_Deva_NP + 0x9CF34D584C61746ELLU, // thh_Latn_MX + 0xA0F34C4154616C65LLU, // thi_Tale_LA + 0xA8F34B454C61746ELLU, // thk_Latn_KE 0xACF34E5044657661LLU, // thl_Deva_NP + 0xB0F3544854686169LLU, // thm_Thai_TH + 0xBCF343414C61746ELLU, // thp_Latn_CA 0xC0F34E5044657661LLU, // thq_Deva_NP 0xC4F34E5044657661LLU, // thr_Deva_NP + 0xC8F34E5044657661LLU, // ths_Deva_NP + 0xCCF343414C61746ELLU, // tht_Latn_CA + 0xD0F353534C61746ELLU, // thu_Latn_SS + 0xD4F3445A4C61746ELLU, // thv_Latn_DZ + 0xE0F34E474C61746ELLU, // thy_Latn_NG + 0xE4F34E454C61746ELLU, // thz_Latn_NE 0x7469455445746869LLU, // ti_Ethi_ET + 0x891353444C61746ELLU, // tic_Latn_SD + 0x951350474C61746ELLU, // tif_Latn_PG 0x9913455245746869LLU, // tig_Ethi_ER + 0x9D134D594C61746ELLU, // tih_Latn_MY + 0xA11343444C61746ELLU, // tii_Latn_CD + 0xA5134E5044657661LLU, // tij_Deva_NP + 0xA913434D4C61746ELLU, // tik_Latn_CM + 0xAD1355534C61746ELLU, // til_Latn_US + 0xB11350474C61746ELLU, // tim_Latn_PG + 0xB51352554379726CLLU, // tin_Cyrl_RU + 0xB91350474C61746ELLU, // tio_Latn_PG + 0xBD1349444C61746ELLU, // tip_Latn_ID + 0xC11342464C61746ELLU, // tiq_Latn_BF + 0xC91350484C61746ELLU, // tis_Latn_PH + 0xCD13434F4C61746ELLU, // tit_Latn_CO + 0xD11350484C61746ELLU, // tiu_Latn_PH 0xD5134E474C61746ELLU, // tiv_Latn_NG + 0xD91341554C61746ELLU, // tiw_Latn_AU + 0xDD1355534C61746ELLU, // tix_Latn_US + 0xE11350484C61746ELLU, // tiy_Latn_PH + 0x81334C524C61746ELLU, // tja_Latn_LR + 0x993349444C61746ELLU, // tjg_Latn_ID + 0xA133434E4C61746ELLU, // tji_Latn_CN + 0xA53341554C61746ELLU, // tjj_Latn_AU + 0xAD334D4D4D796D72LLU, // tjl_Mymr_MM + 0xB53343494C61746ELLU, // tjn_Latn_CI + 0xB933445A41726162LLU, // tjo_Arab_DZ + 0xBD3341554C61746ELLU, // tjp_Latn_AU + 0xC933434E4C61746ELLU, // tjs_Latn_CN + 0xD13341554C61746ELLU, // tju_Latn_AU + 0xD93341554C61746ELLU, // tjw_Latn_AU 0x746B544D4C61746ELLU, // tk_Latn_TM + 0x815342524C61746ELLU, // tka_Latn_BR + 0x8553494E44657661LLU, // tkb_Deva_IN + 0x8D53544C4C61746ELLU, // tkd_Latn_TL + 0x91534D5A4C61746ELLU, // tke_Latn_MZ + 0x955342524C61746ELLU, // tkf_Latn_BR + 0x99534D474C61746ELLU, // tkg_Latn_MG 0xAD53544B4C61746ELLU, // tkl_Latn_TK + 0xBD5353424C61746ELLU, // tkp_Latn_SB + 0xC1534E474C61746ELLU, // tkq_Latn_NG 0xC553415A4C61746ELLU, // tkr_Latn_AZ + 0xC953495241726162LLU, // tks_Arab_IR 0xCD534E5044657661LLU, // tkt_Deva_NP + 0xD1534D584C61746ELLU, // tku_Latn_MX + 0xD55350474C61746ELLU, // tkv_Latn_PG + 0xD95353424C61746ELLU, // tkw_Latn_SB + 0xDD5349444C61746ELLU, // tkx_Latn_ID + 0xE553564E4C61746ELLU, // tkz_Latn_VN 0x746C50484C61746ELLU, // tl_Latn_PH + 0x81734D584C61746ELLU, // tla_Latn_MX + 0x857349444C61746ELLU, // tlb_Latn_ID + 0x89734D584C61746ELLU, // tlc_Latn_MX + 0x8D7349444C61746ELLU, // tld_Latn_ID + 0x957350474C61746ELLU, // tlf_Latn_PG + 0x997349444C61746ELLU, // tlg_Latn_ID + 0xA17355534C61746ELLU, // tli_Latn_US + 0xA57355474C61746ELLU, // tlj_Latn_UG + 0xA97349444C61746ELLU, // tlk_Latn_ID + 0xAD7343444C61746ELLU, // tll_Latn_CD + 0xB17356554C61746ELLU, // tlm_Latn_VU + 0xB57349444C61746ELLU, // tln_Latn_ID + 0xBD734D584C61746ELLU, // tlp_Latn_MX + 0xC1734D4D4C61746ELLU, // tlq_Latn_MM + 0xC57353424C61746ELLU, // tlr_Latn_SB + 0xC97356554C61746ELLU, // tls_Latn_VU + 0xCD7349444C61746ELLU, // tlt_Latn_ID + 0xD17349444C61746ELLU, // tlu_Latn_ID + 0xD57349444C61746ELLU, // tlv_Latn_ID + 0xDD7350474C61746ELLU, // tlx_Latn_PG 0xE173415A4C61746ELLU, // tly_Latn_AZ + 0x819354444C61746ELLU, // tma_Latn_TD + 0x859356554C61746ELLU, // tmb_Latn_VU + 0x899354444C61746ELLU, // tmc_Latn_TD + 0x8D9350474C61746ELLU, // tmd_Latn_PG + 0x919342524C61746ELLU, // tme_Latn_BR + 0x959350594C61746ELLU, // tmf_Latn_PY + 0x999349444C61746ELLU, // tmg_Latn_ID 0x9D934E454C61746ELLU, // tmh_Latn_NE + 0xA19356554C61746ELLU, // tmi_Latn_VU + 0xA59349444C61746ELLU, // tmj_Latn_ID + 0xAD9349444C61746ELLU, // tml_Latn_ID + 0xB193564E4C61746ELLU, // tmm_Latn_VN + 0xB59349444C61746ELLU, // tmn_Latn_ID + 0xB9934D594C61746ELLU, // tmo_Latn_MY + 0xC19350474C61746ELLU, // tmq_Latn_PG + 0xC593494C53797263LLU, // tmr_Syrc_IL + 0xCD9356554C61746ELLU, // tmt_Latn_VU + 0xD19349444C61746ELLU, // tmu_Latn_ID + 0xD59343444C61746ELLU, // tmv_Latn_CD + 0xD9934D594C61746ELLU, // tmw_Latn_MY + 0xE19350474C61746ELLU, // tmy_Latn_PG + 0xE59356454C61746ELLU, // tmz_Latn_VE 0x746E5A414C61746ELLU, // tn_Latn_ZA + 0x81B3424F4C61746ELLU, // tna_Latn_BO + 0x85B3434F4C61746ELLU, // tnb_Latn_CO + 0x89B3434F4C61746ELLU, // tnc_Latn_CO + 0x8DB3434F4C61746ELLU, // tnd_Latn_CO + 0x99B354444C61746ELLU, // tng_Latn_TD + 0x9DB350474C61746ELLU, // tnh_Latn_PG + 0xA1B349444C61746ELLU, // tni_Latn_ID + 0xA9B356554C61746ELLU, // tnk_Latn_VU + 0xADB356554C61746ELLU, // tnl_Latn_VU + 0xB1B349444C61746ELLU, // tnm_Latn_ID + 0xB5B356554C61746ELLU, // tnn_Latn_VU + 0xB9B3424F4C61746ELLU, // tno_Latn_BO + 0xBDB356554C61746ELLU, // tnp_Latn_VU + 0xC1B350524C61746ELLU, // tnq_Latn_PR + 0xC5B3534E4C61746ELLU, // tnr_Latn_SN + 0xC9B350474C61746ELLU, // tns_Latn_PG + 0xCDB349444C61746ELLU, // tnt_Latn_ID + 0xD5B3424443616B6DLLU, // tnv_Cakm_BD + 0xD9B349444C61746ELLU, // tnw_Latn_ID + 0xDDB353424C61746ELLU, // tnx_Latn_SB + 0xE1B3545A4C61746ELLU, // tny_Latn_TZ 0x746F544F4C61746ELLU, // to_Latn_TO + 0x85D341524C61746ELLU, // tob_Latn_AR + 0x89D34D584C61746ELLU, // toc_Latn_MX + 0x8DD3474E4C61746ELLU, // tod_Latn_GN + 0x95D350474C61746ELLU, // tof_Latn_PG 0x99D34D574C61746ELLU, // tog_Latn_MW + 0x9DD34D5A4C61746ELLU, // toh_Latn_MZ + 0xA1D35A4D4C61746ELLU, // toi_Latn_ZM + 0xA5D34D584C61746ELLU, // toj_Latn_MX + 0xADD355534C61746ELLU, // tol_Latn_US + 0xB1D349444C61746ELLU, // tom_Latn_ID + 0xB9D34D584C61746ELLU, // too_Latn_MX + 0xBDD34D584C61746ELLU, // top_Latn_MX + 0xC1D353534C61746ELLU, // toq_Latn_SS + 0xC5D343444C61746ELLU, // tor_Latn_CD + 0xC9D34D584C61746ELLU, // tos_Latn_MX + 0xD1D3564E4C61746ELLU, // tou_Latn_VN + 0xD5D3495241726162LLU, // tov_Arab_IR + 0xD9D355534C61746ELLU, // tow_Latn_US + 0xDDD350574C61746ELLU, // tox_Latn_PW + 0xE1D349444C61746ELLU, // toy_Latn_ID + 0xE5D3434D4C61746ELLU, // toz_Latn_CM + 0x81F350474C61746ELLU, // tpa_Latn_PG + 0x89F34D584C61746ELLU, // tpc_Latn_MX + 0x91F342444C61746ELLU, // tpe_Latn_BD + 0x95F349444C61746ELLU, // tpf_Latn_ID + 0x99F349444C61746ELLU, // tpg_Latn_ID 0xA1F350474C61746ELLU, // tpi_Latn_PG + 0xA5F350594C61746ELLU, // tpj_Latn_PY + 0xA9F342524C61746ELLU, // tpk_Latn_BR + 0xADF34D584C61746ELLU, // tpl_Latn_MX + 0xB1F347484C61746ELLU, // tpm_Latn_GH + 0xB5F342524C61746ELLU, // tpn_Latn_BR + 0xBDF34D584C61746ELLU, // tpp_Latn_MX + 0xC5F342524C61746ELLU, // tpr_Latn_BR + 0xCDF34D584C61746ELLU, // tpt_Latn_MX + 0xD1F34B484B686D72LLU, // tpu_Khmr_KH + 0xD5F34D504C61746ELLU, // tpv_Latn_MP + 0xDDF34D584C61746ELLU, // tpx_Latn_MX + 0xE1F342524C61746ELLU, // tpy_Latn_BR + 0xE5F350474C61746ELLU, // tpz_Latn_PG + 0x861342524C61746ELLU, // tqb_Latn_BR + 0xAE1356554C61746ELLU, // tql_Latn_VU + 0xB21350474C61746ELLU, // tqm_Latn_PG + 0xB61355534C61746ELLU, // tqn_Latn_US + 0xBA1350474C61746ELLU, // tqo_Latn_PG + 0xBE1350474C61746ELLU, // tqp_Latn_PG + 0xCE134D584C61746ELLU, // tqt_Latn_MX + 0xD21353424C61746ELLU, // tqu_Latn_SB + 0xDA1355534C61746ELLU, // tqw_Latn_US 0x747254524C61746ELLU, // tr_Latn_TR + 0x8233414641726162LLU, // tra_Arab_AF + 0x863350474C61746ELLU, // trb_Latn_PG + 0x8A334D584C61746ELLU, // trc_Latn_MX + 0x923349444C61746ELLU, // tre_Latn_ID + 0x963354544C61746ELLU, // trf_Latn_TT + 0x9A33494C48656272LLU, // trg_Hebr_IL + 0x9E3350474C61746ELLU, // trh_Latn_PG + 0xA23353524C61746ELLU, // tri_Latn_SR + 0xA63354444C61746ELLU, // trj_Latn_TD + 0xAE3347424C61746ELLU, // trl_Latn_GB + 0xB233414641726162LLU, // trm_Arab_AF + 0xB633424F4C61746ELLU, // trn_Latn_BO + 0xBA33494E4C61746ELLU, // tro_Latn_IN + 0xBE33494E4C61746ELLU, // trp_Latn_IN + 0xC2334D584C61746ELLU, // trq_Latn_MX + 0xC63350454C61746ELLU, // trr_Latn_PE + 0xCA334D584C61746ELLU, // trs_Latn_MX + 0xCE3349444C61746ELLU, // trt_Latn_ID 0xD23354524C61746ELLU, // tru_Latn_TR 0xD63354574C61746ELLU, // trv_Latn_TW 0xDA33504B41726162LLU, // trw_Arab_PK + 0xDE334D594C61746ELLU, // trx_Latn_MY + 0xE233494E4C61746ELLU, // try_Latn_IN + 0xE63342524C61746ELLU, // trz_Latn_BR 0x74735A414C61746ELLU, // ts_Latn_ZA + 0x825343474C61746ELLU, // tsa_Latn_CG + 0x865345544C61746ELLU, // tsb_Latn_ET + 0x8A534D5A4C61746ELLU, // tsc_Latn_MZ 0x8E5347524772656BLLU, // tsd_Grek_GR - 0x96534E5044657661LLU, // tsf_Deva_NP 0x9A5350484C61746ELLU, // tsg_Latn_PH + 0x9E53434D4C61746ELLU, // tsh_Latn_CM + 0xA25343414C61746ELLU, // tsi_Latn_CA 0xA653425454696274LLU, // tsj_Tibt_BT + 0xAE53564E4C61746ELLU, // tsl_Latn_VN + 0xBE5342464C61746ELLU, // tsp_Latn_BF + 0xC65356554C61746ELLU, // tsr_Latn_VU + 0xCE534D4C4C61746ELLU, // tst_Latn_ML + 0xD25354574C61746ELLU, // tsu_Latn_TW + 0xD65347414C61746ELLU, // tsv_Latn_GA + 0xDA534E474C61746ELLU, // tsw_Latn_NG + 0xDE5350474C61746ELLU, // tsx_Latn_PG + 0xE6534D584C61746ELLU, // tsz_Latn_MX 0x747452554379726CLLU, // tt_Cyrl_RU + 0x86734E474C61746ELLU, // ttb_Latn_NG + 0x8A7347544C61746ELLU, // ttc_Latn_GT + 0x8E7350474C61746ELLU, // ttd_Latn_PG + 0x927350474C61746ELLU, // tte_Latn_PG + 0x9673434D4C61746ELLU, // ttf_Latn_CM + 0x9E734C414C616F6FLLU, // tth_Laoo_LA + 0xA27349444C61746ELLU, // tti_Latn_ID 0xA67355474C61746ELLU, // ttj_Latn_UG + 0xAA73434F4C61746ELLU, // ttk_Latn_CO + 0xAE735A4D4C61746ELLU, // ttl_Latn_ZM + 0xB27343414C61746ELLU, // ttm_Latn_CA + 0xB67349444C61746ELLU, // ttn_Latn_ID + 0xBA734C414C616F6FLLU, // tto_Laoo_LA + 0xBE7349444C61746ELLU, // ttp_Latn_ID + 0xC6734E474C61746ELLU, // ttr_Latn_NG 0xCA73544854686169LLU, // tts_Thai_TH 0xCE73415A4C61746ELLU, // ttt_Latn_AZ + 0xD27350474C61746ELLU, // ttu_Latn_PG + 0xD67350474C61746ELLU, // ttv_Latn_PG + 0xDA734D594C61746ELLU, // ttw_Latn_MY + 0xE27349444C61746ELLU, // tty_Latn_ID + 0xE6734E5044657661LLU, // ttz_Deva_NP + 0x829350474C61746ELLU, // tua_Latn_PG + 0x869355534C61746ELLU, // tub_Latn_US + 0x8A9350474C61746ELLU, // tuc_Latn_PG + 0x8E9342524C61746ELLU, // tud_Latn_BR + 0x9293434F4C61746ELLU, // tue_Latn_CO + 0x9693434F4C61746ELLU, // tuf_Latn_CO + 0x9A9354444C61746ELLU, // tug_Latn_TD + 0x9E9350474C61746ELLU, // tuh_Latn_PG + 0xA293434D4C61746ELLU, // tui_Latn_CM + 0xA69349444C61746ELLU, // tuj_Latn_ID + 0xAE934E474C61746ELLU, // tul_Latn_NG 0xB2934D574C61746ELLU, // tum_Latn_MW + 0xB69355534C61746ELLU, // tun_Latn_US + 0xBA9342524C61746ELLU, // tuo_Latn_BR + 0xC29354444C61746ELLU, // tuq_Latn_TD + 0xCA9343414C61746ELLU, // tus_Latn_CA + 0xD29355534C61746ELLU, // tuu_Latn_US + 0xD6934B454C61746ELLU, // tuv_Latn_KE + 0xDE9342524C61746ELLU, // tux_Latn_BR + 0xE2934B454C61746ELLU, // tuy_Latn_KE + 0xE69342464C61746ELLU, // tuz_Latn_BF + 0x82B353424C61746ELLU, // tva_Latn_SB + 0x8EB34E474C61746ELLU, // tvd_Latn_NG + 0x92B349444C61746ELLU, // tve_Latn_ID + 0xA2B34E474C61746ELLU, // tvi_Latn_NG + 0xAAB356554C61746ELLU, // tvk_Latn_VU 0xAEB354564C61746ELLU, // tvl_Latn_TV + 0xB2B349444C61746ELLU, // tvm_Latn_ID + 0xB6B34D4D4D796D72LLU, // tvn_Mymr_MM + 0xBAB349444C61746ELLU, // tvo_Latn_ID + 0xCAB34B454C61746ELLU, // tvs_Latn_KE + 0xCEB3494E4C61746ELLU, // tvt_Latn_IN + 0xD2B3434D4C61746ELLU, // tvu_Latn_CM + 0xDAB349444C61746ELLU, // tvw_Latn_ID + 0xDEB354574C61746ELLU, // tvx_Latn_TW + 0x82D355534C61746ELLU, // twa_Latn_US + 0x86D350484C61746ELLU, // twb_Latn_PH + 0x8ED34E4C4C61746ELLU, // twd_Latn_NL + 0x92D349444C61746ELLU, // twe_Latn_ID + 0x96D355534C61746ELLU, // twf_Latn_US + 0x9AD349444C61746ELLU, // twg_Latn_ID + 0x9ED3564E4C61746ELLU, // twh_Latn_VN + 0xAED34D5A4C61746ELLU, // twl_Latn_MZ + 0xB2D3494E44657661LLU, // twm_Deva_IN + 0xB6D3434D4C61746ELLU, // twn_Latn_CM + 0xBAD342574C61746ELLU, // two_Latn_BW + 0xBED350474C61746ELLU, // twp_Latn_PG 0xC2D34E454C61746ELLU, // twq_Latn_NE + 0xC6D34D584C61746ELLU, // twr_Latn_MX + 0xCED342524C61746ELLU, // twt_Latn_BR + 0xD2D349444C61746ELLU, // twu_Latn_ID + 0xDAD350474C61746ELLU, // tww_Latn_PG + 0xDED34D5A4C61746ELLU, // twx_Latn_MZ + 0xE2D349444C61746ELLU, // twy_Latn_ID + 0x82F34D594C61746ELLU, // txa_Latn_MY + 0x92F349444C61746ELLU, // txe_Latn_ID 0x9AF3434E54616E67LLU, // txg_Tang_CN + 0xA2F342524C61746ELLU, // txi_Latn_BR + 0xA6F34E474C61746ELLU, // txj_Latn_NG + 0xB2F349444C61746ELLU, // txm_Latn_ID + 0xB6F349444C61746ELLU, // txn_Latn_ID 0xBAF3494E546F746FLLU, // txo_Toto_IN + 0xC2F349444C61746ELLU, // txq_Latn_ID + 0xCAF349444C61746ELLU, // txs_Latn_ID + 0xCEF349444C61746ELLU, // txt_Latn_ID + 0xD2F342524C61746ELLU, // txu_Latn_BR + 0xDEF34D594C61746ELLU, // txx_Latn_MY + 0xE2F34D474C61746ELLU, // txy_Latn_MG 0x747950464C61746ELLU, // ty_Latn_PF + 0x831350474C61746ELLU, // tya_Latn_PG + 0x93134E474C61746ELLU, // tye_Latn_NG + 0x9F13564E4C61746ELLU, // tyh_Latn_VN + 0xA31343474C61746ELLU, // tyi_Latn_CG + 0xA713564E4C61746ELLU, // tyj_Latn_VN + 0xAF13564E4C61746ELLU, // tyl_Latn_VN + 0xB71349444C61746ELLU, // tyn_Latn_ID + 0xBF1341554C61746ELLU, // typ_Latn_AU + 0xC713564E54617674LLU, // tyr_Tavt_VN + 0xCB13564E4C61746ELLU, // tys_Latn_VN + 0xCF13564E4C61746ELLU, // tyt_Latn_VN + 0xD31342574C61746ELLU, // tyu_Latn_BW 0xD71352554379726CLLU, // tyv_Cyrl_RU + 0xDF1343474C61746ELLU, // tyx_Latn_CG + 0xE3134E474C61746ELLU, // tyy_Latn_NG + 0xE713564E4C61746ELLU, // tyz_Latn_VN + 0x9F334D584C61746ELLU, // tzh_Latn_MX + 0xA73347544C61746ELLU, // tzj_Latn_GT 0xB3334D414C61746ELLU, // tzm_Latn_MA - 0xA074525541676862LLU, // udi_Aghb_RU + 0xB73349444C61746ELLU, // tzn_Latn_ID + 0xBB334D584C61746ELLU, // tzo_Latn_MX + 0xDF3350474C61746ELLU, // tzx_Latn_PG + 0xB01442524C61746ELLU, // uam_Latn_BR + 0xC41450474C61746ELLU, // uar_Latn_PG + 0x80344E474C61746ELLU, // uba_Latn_NG + 0xA03454444C61746ELLU, // ubi_Latn_TD + 0xAC3450484C61746ELLU, // ubl_Latn_PH + 0xC43450474C61746ELLU, // ubr_Latn_PG + 0xD03450474C61746ELLU, // ubu_Latn_PG + 0xE03454524C61746ELLU, // uby_Latn_TR + 0x80744E474C61746ELLU, // uda_Latn_NG + 0x907452554379726CLLU, // ude_Cyrl_RU + 0x9874494E4D6C796DLLU, // udg_Mlym_IN + 0xA07452554379726CLLU, // udi_Cyrl_RU + 0xA47449444C61746ELLU, // udj_Latn_ID + 0xAC74434D4C61746ELLU, // udl_Latn_CM 0xB07452554379726CLLU, // udm_Cyrl_RU + 0xD07453444C61746ELLU, // udu_Latn_SD + 0xC89449444C61746ELLU, // ues_Latn_ID + 0xA0B450474C61746ELLU, // ufi_Latn_PG 0x7567434E41726162LLU, // ug_Arab_CN 0x75674B5A4379726CLLU, // ug_Cyrl_KZ 0x80D4535955676172LLU, // uga_Ugar_SY + 0x84D441554C61746ELLU, // ugb_Latn_AU + 0x90D453424C61746ELLU, // uge_Latn_SB + 0x9CD452554379726CLLU, // ugh_Cyrl_RU + 0xB8D4544854686169LLU, // ugo_Thai_TH + 0x80F44E474C61746ELLU, // uha_Latn_NG + 0xB4F449444C61746ELLU, // uhn_Latn_ID + 0xC91450474C61746ELLU, // uis_Latn_PG + 0xD514434D4C61746ELLU, // uiv_Latn_CM + 0xA1344E474C61746ELLU, // uji_Latn_NG 0x756B55414379726CLLU, // uk_Cyrl_UA + 0x815449444C61746ELLU, // uka_Latn_ID + 0x995450474C61746ELLU, // ukg_Latn_PG + 0x9D5443464C61746ELLU, // ukh_Latn_CF + 0xA154494E4F727961LLU, // uki_Orya_IN + 0xA9544D4D4C61746ELLU, // ukk_Latn_MM + 0xBD544E474C61746ELLU, // ukp_Latn_NG + 0xC1544E474C61746ELLU, // ukq_Latn_NG + 0xD1544E474C61746ELLU, // uku_Latn_NG + 0xD55453534C61746ELLU, // ukv_Latn_SS + 0xD9544E474C61746ELLU, // ukw_Latn_NG + 0xE15441554C61746ELLU, // uky_Latn_AU + 0x81744E474C61746ELLU, // ula_Latn_NG + 0x85744E474C61746ELLU, // ulb_Latn_NG + 0x897452554379726CLLU, // ulc_Cyrl_RU + 0x917441524C61746ELLU, // ule_Latn_AR + 0x957449444C61746ELLU, // ulf_Latn_ID 0xA174464D4C61746ELLU, // uli_Latn_FM + 0xA97441554C61746ELLU, // ulk_Latn_AU + 0xB17449444C61746ELLU, // ulm_Latn_ID + 0xB57450474C61746ELLU, // uln_Latn_PG + 0xD17449444C61746ELLU, // ulu_Latn_ID + 0xD9744E494C61746ELLU, // ulw_Latn_NI + 0xE1744E474C61746ELLU, // uly_Latn_NG + 0x819455534C61746ELLU, // uma_Latn_US 0x8594414F4C61746ELLU, // umb_Latn_AO + 0x8D9441554C61746ELLU, // umd_Latn_AU + 0x999441554C61746ELLU, // umg_Latn_AU + 0xA1944D594C61746ELLU, // umi_Latn_MY + 0xB1944E474C61746ELLU, // umm_Latn_NG + 0xB5944D4D4C61746ELLU, // umn_Latn_MM + 0xB99442524C61746ELLU, // umo_Latn_BR + 0xBD9441554C61746ELLU, // ump_Latn_AU + 0xC59441554C61746ELLU, // umr_Latn_AU + 0xC99449444C61746ELLU, // ums_Latn_ID + 0x81B450474C61746ELLU, // una_Latn_PG + 0x91B44E474C61746ELLU, // une_Latn_NG + 0x99B441554C61746ELLU, // ung_Latn_AU + 0xA1B450474C61746ELLU, // uni_Latn_PG + 0xA9B442524C61746ELLU, // unk_Latn_BR + 0xB1B455534C61746ELLU, // unm_Latn_US + 0xB5B441554C61746ELLU, // unn_Latn_AU 0xC5B4494E42656E67LLU, // unr_Beng_IN 0xC5B44E5044657661LLU, // unr_Deva_NP + 0xD1B450474C61746ELLU, // unu_Latn_PG 0xDDB4494E42656E67LLU, // unx_Beng_IN + 0xE5B449444C61746ELLU, // unz_Latn_ID + 0xB5D454574C61746ELLU, // uon_Latn_TW + 0xA1F450474C61746ELLU, // upi_Latn_PG + 0xD5F456554C61746ELLU, // upv_Latn_VU 0x7572504B41726162LLU, // ur_Arab_PK + 0x823450454C61746ELLU, // ura_Latn_PE + 0x863442524C61746ELLU, // urb_Latn_BR + 0x8A3441554C61746ELLU, // urc_Latn_AU + 0x9234424F4C61746ELLU, // ure_Latn_BO + 0x963441554C61746ELLU, // urf_Latn_AU + 0x9A3450474C61746ELLU, // urg_Latn_PG + 0x9E344E474C61746ELLU, // urh_Latn_NG + 0xA23450474C61746ELLU, // uri_Latn_PG + 0xAA34544854686169LLU, // urk_Thai_TH + 0xB23450474C61746ELLU, // urm_Latn_PG + 0xB63449444C61746ELLU, // urn_Latn_ID + 0xBA3450474C61746ELLU, // uro_Latn_PG + 0xBE3442524C61746ELLU, // urp_Latn_BR + 0xC63456554C61746ELLU, // urr_Latn_VU + 0xCE3450474C61746ELLU, // urt_Latn_PG + 0xD23442524C61746ELLU, // uru_Latn_BR + 0xD63450474C61746ELLU, // urv_Latn_PG + 0xDA3450474C61746ELLU, // urw_Latn_PG + 0xDE3450474C61746ELLU, // urx_Latn_PG + 0xE23449444C61746ELLU, // ury_Latn_ID + 0xE63442524C61746ELLU, // urz_Latn_BR + 0x825450474C61746ELLU, // usa_Latn_PG + 0x9E54504B41726162LLU, // ush_Arab_PK + 0xA25442444C61746ELLU, // usi_Latn_BD + 0xAA54434D4C61746ELLU, // usk_Latn_CM + 0xBE5447544C61746ELLU, // usp_Latn_GT + 0xCA544E474C61746ELLU, // uss_Latn_NG + 0xD25450474C61746ELLU, // usu_Latn_PG + 0x82744E474C61746ELLU, // uta_Latn_NG + 0x927455534C61746ELLU, // ute_Latn_US + 0x9E744E474C61746ELLU, // uth_Latn_NG + 0xBE7453424C61746ELLU, // utp_Latn_SB + 0xC6744E474C61746ELLU, // utr_Latn_NG + 0xD27450474C61746ELLU, // utu_Latn_PG + 0xB29447454772656BLLU, // uum_Grek_GE + 0xC69456554C61746ELLU, // uur_Latn_VU + 0x92B44E434C61746ELLU, // uve_Latn_NC + 0x9EB450474C61746ELLU, // uvh_Latn_PG + 0xAEB450474C61746ELLU, // uvl_Latn_PG + 0x82D441554C61746ELLU, // uwa_Latn_AU + 0x83144E474C61746ELLU, // uya_Latn_NG 0x757A414641726162LLU, // uz_Arab_AF 0x757A555A4C61746ELLU, // uz_Latn_UZ + 0xCB34414641726162LLU, // uzs_Arab_AF + 0x8015494E54616D6CLLU, // vaa_Taml_IN + 0x901543464C61746ELLU, // vae_Latn_CF + 0x9415495241726162LLU, // vaf_Arab_IR + 0x981547484C61746ELLU, // vag_Latn_GH + 0x9C15494E44657661LLU, // vah_Deva_IN 0xA0154C5256616969LLU, // vai_Vaii_LR + 0xA4154E414C61746ELLU, // vaj_Latn_NA + 0xAC1550474C61746ELLU, // val_Latn_PG + 0xB01550474C61746ELLU, // vam_Latn_PG + 0xB41550474C61746ELLU, // van_Latn_PG + 0xB81556554C61746ELLU, // vao_Latn_VU + 0xBC15494E4C61746ELLU, // vap_Latn_IN + 0xC4154D584C61746ELLU, // var_Latn_MX + 0xC815494E44657661LLU, // vas_Deva_IN + 0xD01543444C61746ELLU, // vau_Latn_CD + 0xD415494E44657661LLU, // vav_Deva_IN + 0xE0154E5044657661LLU, // vay_Deva_NP + 0x843549444C61746ELLU, // vbb_Latn_ID + 0xA83550484C61746ELLU, // vbk_Latn_PH 0x76655A414C61746ELLU, // ve_Latn_ZA 0x889549544C61746ELLU, // vec_Latn_IT + 0xB0954E474C61746ELLU, // vem_Latn_NG + 0xB89555534C61746ELLU, // veo_Latn_US 0xBC9552554C61746ELLU, // vep_Latn_RU + 0xC4954E474C61746ELLU, // ver_Latn_NG + 0xC4D5504B41726162LLU, // vgr_Arab_PK 0x7669564E4C61746ELLU, // vi_Latn_VN 0x891553584C61746ELLU, // vic_Latn_SX + 0x8D15545A4C61746ELLU, // vid_Latn_TZ + 0x951543474C61746ELLU, // vif_Latn_CG + 0x991542464C61746ELLU, // vig_Latn_BF + 0xAD1541524C61746ELLU, // vil_Latn_AR + 0xB515545A4C61746ELLU, // vin_Latn_TZ + 0xCD154E474C61746ELLU, // vit_Latn_NG + 0xD51550474C61746ELLU, // viv_Latn_PG + 0xA935494E44657661LLU, // vjk_Deva_IN + 0x815541554C61746ELLU, // vka_Latn_AU + 0xA55554444C61746ELLU, // vkj_Latn_TD + 0xA95549444C61746ELLU, // vkk_Latn_ID + 0xAD5549444C61746ELLU, // vkl_Latn_ID + 0xB15542524C61746ELLU, // vkm_Latn_BR + 0xB5554E474C61746ELLU, // vkn_Latn_NG + 0xB95549444C61746ELLU, // vko_Latn_ID + 0xBD55494E4C61746ELLU, // vkp_Latn_IN + 0xCD5549444C61746ELLU, // vkt_Latn_ID + 0xD15541554C61746ELLU, // vku_Latn_AU + 0xE5554E474C61746ELLU, // vkz_Latn_NG + 0xBD7556554C61746ELLU, // vlp_Latn_VU 0xC97542454C61746ELLU, // vls_Latn_BE + 0x819541554C61746ELLU, // vma_Latn_AU + 0x859541554C61746ELLU, // vmb_Latn_AU + 0x89954D584C61746ELLU, // vmc_Latn_MX + 0x8D95494E4B6E6461LLU, // vmd_Knda_IN + 0x919549444C61746ELLU, // vme_Latn_ID 0x959544454C61746ELLU, // vmf_Latn_DE + 0x999550474C61746ELLU, // vmg_Latn_PG + 0x9D95495241726162LLU, // vmh_Arab_IR + 0xA19541554C61746ELLU, // vmi_Latn_AU + 0xA5954D584C61746ELLU, // vmj_Latn_MX + 0xA9954D5A4C61746ELLU, // vmk_Latn_MZ + 0xAD9541554C61746ELLU, // vml_Latn_AU + 0xB1954D584C61746ELLU, // vmm_Latn_MX + 0xBD954D584C61746ELLU, // vmp_Latn_MX + 0xC1954D584C61746ELLU, // vmq_Latn_MX + 0xC5954D5A4C61746ELLU, // vmr_Latn_MZ + 0xC99549444C61746ELLU, // vms_Latn_ID + 0xD19541554C61746ELLU, // vmu_Latn_AU 0xD9954D5A4C61746ELLU, // vmw_Latn_MZ + 0xDD954D584C61746ELLU, // vmx_Latn_MX + 0xE1954D584C61746ELLU, // vmy_Latn_MX + 0xE5954D584C61746ELLU, // vmz_Latn_MX + 0xA9B553424C61746ELLU, // vnk_Latn_SB + 0xB1B556554C61746ELLU, // vnm_Latn_VU + 0xBDB556554C61746ELLU, // vnp_Latn_VU + 0xC5D54E474C61746ELLU, // vor_Latn_NG 0xCDD552554C61746ELLU, // vot_Latn_RU + 0x823556554C61746ELLU, // vra_Latn_VU 0xBA3545454C61746ELLU, // vro_Latn_EE + 0xCA3553424C61746ELLU, // vrs_Latn_SB + 0xCE3556554C61746ELLU, // vrt_Latn_VU + 0xBA7549444C61746ELLU, // vto_Latn_ID + 0xB29547414C61746ELLU, // vum_Latn_GA 0xB695545A4C61746ELLU, // vun_Latn_TZ + 0xCE95434D4C61746ELLU, // vut_Latn_CM + 0x82D5434E4C61746ELLU, // vwa_Latn_CN 0x776142454C61746ELLU, // wa_Latn_BE + 0x801655534C61746ELLU, // waa_Latn_US + 0x841650474C61746ELLU, // wab_Latn_PG + 0x881655534C61746ELLU, // wac_Latn_US + 0x8C1649444C61746ELLU, // wad_Latn_ID 0x901643484C61746ELLU, // wae_Latn_CH + 0x941642524C61746ELLU, // waf_Latn_BR + 0x981650474C61746ELLU, // wag_Latn_PG + 0x9C1649444C61746ELLU, // wah_Latn_ID + 0xA01649444C61746ELLU, // wai_Latn_ID + 0xA41650474C61746ELLU, // waj_Latn_PG 0xAC16455445746869LLU, // wal_Ethi_ET + 0xB01655534C61746ELLU, // wam_Latn_US + 0xB41643494C61746ELLU, // wan_Latn_CI + 0xBC1647594C61746ELLU, // wap_Latn_GY + 0xC01641554C61746ELLU, // waq_Latn_AU 0xC41650484C61746ELLU, // war_Latn_PH + 0xC81655534C61746ELLU, // was_Latn_US + 0xCC1650474C61746ELLU, // wat_Latn_PG + 0xD01642524C61746ELLU, // wau_Latn_BR + 0xD4164E474C61746ELLU, // wav_Latn_NG + 0xD81642524C61746ELLU, // waw_Latn_BR + 0xDC1650474C61746ELLU, // wax_Latn_PG + 0xE01653524C61746ELLU, // way_Latn_SR + 0xE41650474C61746ELLU, // waz_Latn_PG + 0x803656454C61746ELLU, // wba_Latn_VE + 0x843649444C61746ELLU, // wbb_Latn_ID + 0x903649444C61746ELLU, // wbe_Latn_ID + 0x943642464C61746ELLU, // wbf_Latn_BF + 0x9C36545A4C61746ELLU, // wbh_Latn_TZ + 0xA036545A4C61746ELLU, // wbi_Latn_TZ + 0xA436545A4C61746ELLU, // wbj_Latn_TZ + 0xA836414641726162LLU, // wbk_Arab_AF + 0xAC36504B4C61746ELLU, // wbl_Latn_PK + 0xB036434E4C61746ELLU, // wbm_Latn_CN 0xBC3641554C61746ELLU, // wbp_Latn_AU 0xC036494E54656C75LLU, // wbq_Telu_IN 0xC436494E44657661LLU, // wbr_Deva_IN + 0xCC3641554C61746ELLU, // wbt_Latn_AU + 0xD43641554C61746ELLU, // wbv_Latn_AU + 0xD83649444C61746ELLU, // wbw_Latn_ID + 0x805642524C61746ELLU, // wca_Latn_BR + 0xA05654474C61746ELLU, // wci_Latn_TG + 0x8C7647414C61746ELLU, // wdd_Latn_GA + 0x987650474C61746ELLU, // wdg_Latn_PG + 0xA47641554C61746ELLU, // wdj_Latn_AU + 0xA87641554C61746ELLU, // wdk_Latn_AU + 0xCC7643414C61746ELLU, // wdt_Latn_CA + 0xD07641554C61746ELLU, // wdu_Latn_AU + 0xE07641554C61746ELLU, // wdy_Latn_AU + 0x889643494C61746ELLU, // wec_Latn_CI + 0x8C9650474C61746ELLU, // wed_Latn_PG + 0x989641554C61746ELLU, // weg_Latn_AU + 0x9C96434D4C61746ELLU, // weh_Latn_CM + 0xA09650474C61746ELLU, // wei_Latn_PG + 0xB096424A4C61746ELLU, // wem_Latn_BJ + 0xB89649444C61746ELLU, // weo_Latn_ID + 0xBC9644454C61746ELLU, // wep_Latn_DE + 0xC49650474C61746ELLU, // wer_Latn_PG + 0xC896434D4C61746ELLU, // wes_Latn_CM + 0xCC9649444C61746ELLU, // wet_Latn_ID + 0xD0964D4D4C61746ELLU, // weu_Latn_MM + 0xD89649444C61746ELLU, // wew_Latn_ID + 0x98B649444C61746ELLU, // wfg_Latn_ID + 0x80D641554C61746ELLU, // wga_Latn_AU + 0x84D650474C61746ELLU, // wgb_Latn_PG + 0x98D641554C61746ELLU, // wgg_Latn_AU + 0xA0D650474C61746ELLU, // wgi_Latn_PG + 0xB8D649444C61746ELLU, // wgo_Latn_ID + 0xD0D641554C61746ELLU, // wgu_Latn_AU + 0xE0D641554C61746ELLU, // wgy_Latn_AU + 0x80F649444C61746ELLU, // wha_Latn_ID + 0x98F650474C61746ELLU, // whg_Latn_PG + 0xA8F649444C61746ELLU, // whk_Latn_ID + 0xD0F649444C61746ELLU, // whu_Latn_ID + 0x851642464C61746ELLU, // wib_Latn_BF + 0x891655534C61746ELLU, // wic_Latn_US + 0x911641554C61746ELLU, // wie_Latn_AU + 0x951641554C61746ELLU, // wif_Latn_AU + 0x991641554C61746ELLU, // wig_Latn_AU + 0x9D1641554C61746ELLU, // wih_Latn_AU + 0xA11650474C61746ELLU, // wii_Latn_PG + 0xA51641554C61746ELLU, // wij_Latn_AU + 0xA91641554C61746ELLU, // wik_Latn_AU + 0xAD1641554C61746ELLU, // wil_Latn_AU + 0xB11641554C61746ELLU, // wim_Latn_AU + 0xB51655534C61746ELLU, // win_Latn_US + 0xC51642524C61746ELLU, // wir_Latn_BR + 0xD11650474C61746ELLU, // wiu_Latn_PG + 0xD51650474C61746ELLU, // wiv_Latn_PG + 0xE11655534C61746ELLU, // wiy_Latn_US + 0x81364E474C61746ELLU, // wja_Latn_NG + 0xA1364E474C61746ELLU, // wji_Latn_NG + 0x8156545A4C61746ELLU, // wka_Latn_TZ + 0x8D5649444C61746ELLU, // wkd_Latn_ID + 0xC55641554C61746ELLU, // wkr_Latn_AU + 0xD95641554C61746ELLU, // wkw_Latn_AU + 0xE15641554C61746ELLU, // wky_Latn_AU + 0x817650474C61746ELLU, // wla_Latn_PG + 0x9176455445746869LLU, // wle_Ethi_ET + 0x997641554C61746ELLU, // wlg_Latn_AU + 0x9D76544C4C61746ELLU, // wlh_Latn_TL + 0xA17649444C61746ELLU, // wli_Latn_ID + 0xB17647424C61746ELLU, // wlm_Latn_GB + 0xB976494441726162LLU, // wlo_Arab_ID + 0xC57656554C61746ELLU, // wlr_Latn_VU 0xC97657464C61746ELLU, // wls_Latn_WF + 0xD17641554C61746ELLU, // wlu_Latn_AU + 0xD57641524C61746ELLU, // wlv_Latn_AR + 0xD97649444C61746ELLU, // wlw_Latn_ID + 0xDD7647484C61746ELLU, // wlx_Latn_GH + 0x81964E474C61746ELLU, // wma_Latn_NG + 0x859641554C61746ELLU, // wmb_Latn_AU + 0x899650474C61746ELLU, // wmc_Latn_PG + 0x8D9642524C61746ELLU, // wmd_Latn_BR + 0x91964E5044657661LLU, // wme_Deva_NP + 0x9D96544C4C61746ELLU, // wmh_Latn_TL + 0xA19641554C61746ELLU, // wmi_Latn_AU + 0xB19649444C61746ELLU, // wmm_Latn_ID + 0xB5964E434C61746ELLU, // wmn_Latn_NC + 0xB99650474C61746ELLU, // wmo_Latn_PG + 0xC99649444C61746ELLU, // wms_Latn_ID + 0xCD9641554C61746ELLU, // wmt_Latn_AU + 0xD9964D5A4C61746ELLU, // wmw_Latn_MZ + 0xDD9650474C61746ELLU, // wmx_Latn_PG + 0x85B650474C61746ELLU, // wnb_Latn_PG + 0x89B650474C61746ELLU, // wnc_Latn_PG + 0x8DB641554C61746ELLU, // wnd_Latn_AU + 0x91B6504B41726162LLU, // wne_Arab_PK + 0x99B649444C61746ELLU, // wng_Latn_ID 0xA1B64B4D41726162LLU, // wni_Arab_KM + 0xA9B649444C61746ELLU, // wnk_Latn_ID + 0xB1B641554C61746ELLU, // wnm_Latn_AU + 0xB5B641554C61746ELLU, // wnn_Latn_AU + 0xB9B649444C61746ELLU, // wno_Latn_ID + 0xBDB650474C61746ELLU, // wnp_Latn_PG + 0xD1B650474C61746ELLU, // wnu_Latn_PG + 0xD9B655534C61746ELLU, // wnw_Latn_US + 0xE1B641554C61746ELLU, // wny_Latn_AU 0x776F534E4C61746ELLU, // wo_Latn_SN + 0x81D641554C61746ELLU, // woa_Latn_AU + 0x85D643494C61746ELLU, // wob_Latn_CI + 0x89D650474C61746ELLU, // woc_Latn_PG + 0x8DD649444C61746ELLU, // wod_Latn_ID + 0x91D6464D4C61746ELLU, // woe_Latn_FM + 0x95D6474D4C61746ELLU, // wof_Latn_GM + 0x99D650474C61746ELLU, // wog_Latn_PG + 0xA1D649444C61746ELLU, // woi_Latn_ID + 0xA9D6434D4C61746ELLU, // wok_Latn_CM + 0xB1D64E474C61746ELLU, // wom_Latn_NG + 0xB5D643444C61746ELLU, // won_Latn_CD + 0xB9D649444C61746ELLU, // woo_Latn_ID + 0xC5D649444C61746ELLU, // wor_Latn_ID + 0xC9D650474C61746ELLU, // wos_Latn_PG + 0xD9D649444C61746ELLU, // wow_Latn_ID + 0x89F656454C61746ELLU, // wpc_Latn_VE + 0x863641554C61746ELLU, // wrb_Latn_AU + 0x9A3641554C61746ELLU, // wrg_Latn_AU + 0x9E3641554C61746ELLU, // wrh_Latn_AU + 0xA23641554C61746ELLU, // wri_Latn_AU + 0xAA3641554C61746ELLU, // wrk_Latn_AU + 0xAE3641554C61746ELLU, // wrl_Latn_AU + 0xB23641554C61746ELLU, // wrm_Latn_AU + 0xBA3641554C61746ELLU, // wro_Latn_AU + 0xBE3649444C61746ELLU, // wrp_Latn_ID + 0xC63641554C61746ELLU, // wrr_Latn_AU + 0xCA3650474C61746ELLU, // wrs_Latn_PG + 0xD23649444C61746ELLU, // wru_Latn_ID + 0xD63650474C61746ELLU, // wrv_Latn_PG + 0xDA3641554C61746ELLU, // wrw_Latn_AU + 0xDE3649444C61746ELLU, // wrx_Latn_ID + 0xE63641554C61746ELLU, // wrz_Latn_AU + 0x825649444C61746ELLU, // wsa_Latn_ID 0x9A56494E476F6E67LLU, // wsg_Gong_IN + 0xA25656554C61746ELLU, // wsi_Latn_VU + 0xAA5650474C61746ELLU, // wsk_Latn_PG + 0xC65650474C61746ELLU, // wsr_Latn_PG + 0xCA5647484C61746ELLU, // wss_Latn_GH + 0xD25642524C61746ELLU, // wsu_Latn_BR + 0xD656414641726162LLU, // wsv_Arab_AF + 0x8676545A4C61746ELLU, // wtb_Latn_TZ + 0x967650474C61746ELLU, // wtf_Latn_PG + 0x9E7641554C61746ELLU, // wth_Latn_AU + 0xA27645544C61746ELLU, // wti_Latn_ET + 0xAA7650474C61746ELLU, // wtk_Latn_PG 0xB276494E44657661LLU, // wtm_Deva_IN + 0xDA7649444C61746ELLU, // wtw_Latn_ID + 0x829641554C61746ELLU, // wua_Latn_AU + 0x869641554C61746ELLU, // wub_Latn_AU + 0x8E9654474C61746ELLU, // wud_Latn_TG + 0xAE9649444C61746ELLU, // wul_Latn_ID + 0xB29647414C61746ELLU, // wum_Latn_GA + 0xB696545A4C61746ELLU, // wun_Latn_TZ + 0xC69641554C61746ELLU, // wur_Latn_AU + 0xCE9650474C61746ELLU, // wut_Latn_PG 0xD296434E48616E73LLU, // wuu_Hans_CN + 0xD69650474C61746ELLU, // wuv_Latn_PG + 0xDE9641554C61746ELLU, // wux_Latn_AU + 0xE29649444C61746ELLU, // wuy_Latn_ID + 0x82D6424A4C61746ELLU, // wwa_Latn_BJ + 0x86D641554C61746ELLU, // wwb_Latn_AU + 0xBAD656554C61746ELLU, // wwo_Latn_VU + 0xC6D641554C61746ELLU, // wwr_Latn_AU + 0xDAD6434D4C61746ELLU, // www_Latn_CM + 0xDAF641554C61746ELLU, // wxw_Latn_AU + 0x871641554C61746ELLU, // wyb_Latn_AU + 0xA31641554C61746ELLU, // wyi_Latn_AU + 0xB316504C4C61746ELLU, // wym_Latn_PL + 0xB71655534C61746ELLU, // wyn_Latn_US + 0xC71642524C61746ELLU, // wyr_Latn_BR + 0xE316464A4C61746ELLU, // wyy_Latn_FJ + 0x801745534C61746ELLU, // xaa_Latn_ES + 0x84174E474C61746ELLU, // xab_Latn_NG + 0x9817415A41676862LLU, // xag_Aghb_AZ + 0xA01742524C61746ELLU, // xai_Latn_BR + 0xA41742524C61746ELLU, // xaj_Latn_BR + 0xA81756454C61746ELLU, // xak_Latn_VE + 0xAC1752554379726CLLU, // xal_Cyrl_RU + 0xB0175A414C61746ELLU, // xam_Latn_ZA + 0xB417455445746869LLU, // xan_Ethi_ET + 0xB817564E4C61746ELLU, // xao_Latn_VN + 0xC41750474C61746ELLU, // xar_Latn_PG + 0xC81752554379726CLLU, // xas_Cyrl_RU + 0xCC1742524C61746ELLU, // xat_Latn_BR + 0xD01749444C61746ELLU, // xau_Latn_ID 0xD41742524C61746ELLU, // xav_Latn_BR + 0xD81755534C61746ELLU, // xaw_Latn_US + 0xE01749444C61746ELLU, // xay_Latn_ID + 0x843741554C61746ELLU, // xbb_Latn_AU + 0x8C3741554C61746ELLU, // xbd_Latn_AU + 0x903741554C61746ELLU, // xbe_Latn_AU + 0x983741554C61746ELLU, // xbg_Latn_AU + 0xA03750474C61746ELLU, // xbi_Latn_PG + 0xA43741554C61746ELLU, // xbj_Latn_AU + 0xB03746524C61746ELLU, // xbm_Latn_FR + 0xB4374D594C61746ELLU, // xbn_Latn_MY + 0xBC3741554C61746ELLU, // xbp_Latn_AU + 0xC43749444C61746ELLU, // xbr_Latn_ID + 0xD83742524C61746ELLU, // xbw_Latn_BR + 0xE03741554C61746ELLU, // xby_Latn_AU + 0x9C5755534C61746ELLU, // xch_Latn_US 0xB857555A43687273LLU, // xco_Chrs_UZ 0xC457545243617269LLU, // xcr_Cari_TR + 0x807741554C61746ELLU, // xda_Latn_AU + 0xA87741554C61746ELLU, // xdk_Latn_AU + 0xB877414F4C61746ELLU, // xdo_Latn_AO + 0xC07752554379726CLLU, // xdq_Cyrl_RU + 0xE07749444C61746ELLU, // xdy_Latn_ID + 0x8C97434D4C61746ELLU, // xed_Latn_CM + 0x98975A414C61746ELLU, // xeg_Latn_ZA + 0xB09749444C61746ELLU, // xem_Latn_ID + 0xC49742524C61746ELLU, // xer_Latn_BR + 0xC89750474C61746ELLU, // xes_Latn_PG + 0xCC9742524C61746ELLU, // xet_Latn_BR + 0xD09750474C61746ELLU, // xeu_Latn_PG + 0x84D743494C61746ELLU, // xgb_Latn_CI + 0x8CD741554C61746ELLU, // xgd_Latn_AU + 0x98D741554C61746ELLU, // xgg_Latn_AU + 0xA0D741554C61746ELLU, // xgi_Latn_AU + 0xB0D741554C61746ELLU, // xgm_Latn_AU + 0xD0D741554C61746ELLU, // xgu_Latn_AU + 0xD8D741554C61746ELLU, // xgw_Latn_AU 0x78685A414C61746ELLU, // xh_Latn_ZA + 0x90F7504B41726162LLU, // xhe_Arab_PK + 0xB0F74B484B686D72LLU, // xhm_Khmr_KH + 0xD4F7564E4C61746ELLU, // xhv_Latn_VN + 0xA1175A414C61746ELLU, // xii_Latn_ZA + 0xB51747544C61746ELLU, // xin_Latn_GT + 0xC51742524C61746ELLU, // xir_Latn_BR + 0xC917494E4F727961LLU, // xis_Orya_IN + 0xE11742524C61746ELLU, // xiy_Latn_BR + 0x853741554C61746ELLU, // xjb_Latn_AU + 0xCD3741554C61746ELLU, // xjt_Latn_AU + 0x8157504B41726162LLU, // xka_Arab_PK + 0x8557424A4C61746ELLU, // xkb_Latn_BJ + 0x8957495241726162LLU, // xkc_Arab_IR + 0x8D5749444C61746ELLU, // xkd_Latn_ID + 0x915749444C61746ELLU, // xke_Latn_ID + 0x9557425454696274LLU, // xkf_Tibt_BT + 0x99574D4C4C61746ELLU, // xkg_Latn_ML + 0xA557495241726162LLU, // xkj_Arab_IR + 0xAD5749444C61746ELLU, // xkl_Latn_ID + 0xB55749444C61746ELLU, // xkn_Latn_ID + 0xBD57495241726162LLU, // xkp_Arab_IR + 0xC15749444C61746ELLU, // xkq_Latn_ID + 0xC55742524C61746ELLU, // xkr_Latn_BR + 0xC95749444C61746ELLU, // xks_Latn_ID + 0xCD5747484C61746ELLU, // xkt_Latn_GH + 0xD15743474C61746ELLU, // xku_Latn_CG + 0xD55742574C61746ELLU, // xkv_Latn_BW + 0xD95749444C61746ELLU, // xkw_Latn_ID + 0xDD5750474C61746ELLU, // xkx_Latn_PG + 0xE1574D594C61746ELLU, // xky_Latn_MY + 0xE55742544C61746ELLU, // xkz_Latn_BT + 0x817750474C61746ELLU, // xla_Latn_PG 0x897754524C796369LLU, // xlc_Lyci_TR 0x8D7754524C796469LLU, // xld_Lydi_TR + 0xE1774952456C796DLLU, // xly_Elym_IR + 0x8197534F4C61746ELLU, // xma_Latn_SO + 0x8597434D4C61746ELLU, // xmb_Latn_CM + 0x89974D5A4C61746ELLU, // xmc_Latn_MZ + 0x8D97434D4C61746ELLU, // xmd_Latn_CM 0x9597474547656F72LLU, // xmf_Geor_GE + 0x9997434D4C61746ELLU, // xmg_Latn_CM + 0x9D9741554C61746ELLU, // xmh_Latn_AU + 0xA597434D4C61746ELLU, // xmj_Latn_CM + 0xB19749444C61746ELLU, // xmm_Latn_ID 0xB597434E4D616E69LLU, // xmn_Mani_CN + 0xB99742524C61746ELLU, // xmo_Latn_BR + 0xBD9741554C61746ELLU, // xmp_Latn_AU + 0xC19741554C61746ELLU, // xmq_Latn_AU 0xC59753444D657263LLU, // xmr_Merc_SD + 0xCD9749444C61746ELLU, // xmt_Latn_ID + 0xD19741554C61746ELLU, // xmu_Latn_AU + 0xD5974D474C61746ELLU, // xmv_Latn_MG + 0xD9974D474C61746ELLU, // xmw_Latn_MG + 0xDD9749444C61746ELLU, // xmx_Latn_ID + 0xE19741554C61746ELLU, // xmy_Latn_AU + 0xE59749444C61746ELLU, // xmz_Latn_ID 0x81B753414E617262LLU, // xna_Narb_SA + 0x85B754574C61746ELLU, // xnb_Latn_TW + 0xA1B741554C61746ELLU, // xni_Latn_AU + 0xA5B7545A4C61746ELLU, // xnj_Latn_TZ + 0xA9B741554C61746ELLU, // xnk_Latn_AU + 0xB1B741554C61746ELLU, // xnm_Latn_AU + 0xB5B750484C61746ELLU, // xnn_Latn_PH + 0xC1B74D5A4C61746ELLU, // xnq_Latn_MZ 0xC5B7494E44657661LLU, // xnr_Deva_IN + 0xCDB755534C61746ELLU, // xnt_Latn_US + 0xD1B741554C61746ELLU, // xnu_Latn_AU + 0xE1B741554C61746ELLU, // xny_Latn_AU + 0xE5B745474C61746ELLU, // xnz_Latn_EG + 0x89D74E474C61746ELLU, // xoc_Latn_NG + 0x8DD749444C61746ELLU, // xod_Latn_ID 0x99D755474C61746ELLU, // xog_Latn_UG + 0xA1D750474C61746ELLU, // xoi_Latn_PG + 0xA9D742524C61746ELLU, // xok_Latn_BR + 0xB1D753444C61746ELLU, // xom_Latn_SD + 0xB5D747484C61746ELLU, // xon_Latn_GH + 0xB9D742524C61746ELLU, // xoo_Latn_BR + 0xBDD750474C61746ELLU, // xop_Latn_PG + 0xC5D742524C61746ELLU, // xor_Latn_BR + 0xD9D750474C61746ELLU, // xow_Latn_PG + 0x81F741554C61746ELLU, // xpa_Latn_AU + 0x85F741554C61746ELLU, // xpb_Latn_AU + 0x8DF741554C61746ELLU, // xpd_Latn_AU + 0x95F741554C61746ELLU, // xpf_Latn_AU + 0x99F754524772656BLLU, // xpg_Grek_TR + 0x9DF741554C61746ELLU, // xph_Latn_AU + 0xA1F747424F67616DLLU, // xpi_Ogam_GB + 0xA5F741554C61746ELLU, // xpj_Latn_AU + 0xA9F742524C61746ELLU, // xpk_Latn_BR + 0xADF741554C61746ELLU, // xpl_Latn_AU + 0xB1F752554379726CLLU, // xpm_Cyrl_RU + 0xB5F742524C61746ELLU, // xpn_Latn_BR + 0xB9F74D584C61746ELLU, // xpo_Latn_MX + 0xC1F755534C61746ELLU, // xpq_Latn_US 0xC5F7495250727469LLU, // xpr_Prti_IR + 0xCDF741554C61746ELLU, // xpt_Latn_AU + 0xD5F741554C61746ELLU, // xpv_Latn_AU + 0xD9F741554C61746ELLU, // xpw_Latn_AU + 0xDDF741554C61746ELLU, // xpx_Latn_AU + 0xE5F741554C61746ELLU, // xpz_Latn_AU + 0x823742524C61746ELLU, // xra_Latn_BR + 0x863742464C61746ELLU, // xrb_Latn_BF + 0x8E3741554C61746ELLU, // xrd_Latn_AU + 0x923742524C61746ELLU, // xre_Latn_BR + 0x9A3741554C61746ELLU, // xrg_Latn_AU + 0xA23742524C61746ELLU, // xri_Latn_BR + 0xB23752554379726CLLU, // xrm_Cyrl_RU + 0xB63752554379726CLLU, // xrn_Cyrl_RU + 0xC63749544C61746ELLU, // xrr_Latn_IT + 0xD23741554C61746ELLU, // xru_Latn_AU + 0xDA3750474C61746ELLU, // xrw_Latn_PG 0x8257594553617262LLU, // xsa_Sarb_YE + 0x865750484C61746ELLU, // xsb_Latn_PH + 0x925749444C61746ELLU, // xse_Latn_ID + 0x9E574E474C61746ELLU, // xsh_Latn_NG + 0xA25750474C61746ELLU, // xsi_Latn_PG + 0xB25747484C61746ELLU, // xsm_Latn_GH + 0xB6574E474C61746ELLU, // xsn_Latn_NG + 0xBE5750474C61746ELLU, // xsp_Latn_PG + 0xC2574D5A4C61746ELLU, // xsq_Latn_MZ 0xC6574E5044657661LLU, // xsr_Deva_NP + 0xD25756454C61746ELLU, // xsu_Latn_VE + 0xE25754574C61746ELLU, // xsy_Latn_TW + 0x82774D584C61746ELLU, // xta_Latn_MX + 0x86774D584C61746ELLU, // xtb_Latn_MX + 0x8A7753444C61746ELLU, // xtc_Latn_SD + 0x8E774D584C61746ELLU, // xtd_Latn_MX + 0x927749444C61746ELLU, // xte_Latn_ID + 0x9E7741554C61746ELLU, // xth_Latn_AU + 0xA2774D584C61746ELLU, // xti_Latn_MX + 0xA6774D584C61746ELLU, // xtj_Latn_MX + 0xAE774D584C61746ELLU, // xtl_Latn_MX + 0xB2774D584C61746ELLU, // xtm_Latn_MX + 0xB6774D584C61746ELLU, // xtn_Latn_MX + 0xBE774D584C61746ELLU, // xtp_Latn_MX + 0xC277495242726168LLU, // xtq_Brah_IR + 0xCA774D584C61746ELLU, // xts_Latn_MX + 0xCE774D584C61746ELLU, // xtt_Latn_MX + 0xD2774D584C61746ELLU, // xtu_Latn_MX + 0xD67741554C61746ELLU, // xtv_Latn_AU + 0xDA7742524C61746ELLU, // xtw_Latn_BR + 0xE2774D584C61746ELLU, // xty_Latn_MX + 0x8697494E54616D6CLLU, // xub_Taml_IN + 0x8E9741554C61746ELLU, // xud_Latn_AU + 0xA697494E54616D6CLLU, // xuj_Taml_IN + 0xAE9741554C61746ELLU, // xul_Latn_AU + 0xB29749544C61746ELLU, // xum_Latn_IT + 0xB69741554C61746ELLU, // xun_Latn_AU + 0xBA9754444C61746ELLU, // xuo_Latn_TD + 0xCE9741554C61746ELLU, // xut_Latn_AU + 0xD2974E414C61746ELLU, // xuu_Latn_NA + 0x92B749544974616CLLU, // xve_Ital_IT + 0xA2B7414641726162LLU, // xvi_Arab_AF + 0xB6B745534C61746ELLU, // xvn_Latn_ES + 0xBAB749544C61746ELLU, // xvo_Latn_IT + 0xCAB749544C61746ELLU, // xvs_Latn_IT + 0x82D742524C61746ELLU, // xwa_Latn_BR + 0x8ED741554C61746ELLU, // xwd_Latn_AU + 0x92D7424A4C61746ELLU, // xwe_Latn_BJ + 0xA6D741554C61746ELLU, // xwj_Latn_AU + 0xAAD741554C61746ELLU, // xwk_Latn_AU + 0xAED7424A4C61746ELLU, // xwl_Latn_BJ + 0xBAD752554379726CLLU, // xwo_Cyrl_RU + 0xC6D749444C61746ELLU, // xwr_Latn_ID + 0xCED741554C61746ELLU, // xwt_Latn_AU + 0xDAD741554C61746ELLU, // xww_Latn_AU + 0x86F747484C61746ELLU, // xxb_Latn_GH + 0xAAF749444C61746ELLU, // xxk_Latn_ID + 0xB2F741554C61746ELLU, // xxm_Latn_AU + 0xC6F742524C61746ELLU, // xxr_Latn_BR + 0xCEF749444C61746ELLU, // xxt_Latn_ID + 0x831741554C61746ELLU, // xya_Latn_AU + 0x871741554C61746ELLU, // xyb_Latn_AU + 0xA71741554C61746ELLU, // xyj_Latn_AU + 0xAB1741554C61746ELLU, // xyk_Latn_AU + 0xAF1742524C61746ELLU, // xyl_Latn_BR + 0xCF1741554C61746ELLU, // xyt_Latn_AU + 0xE31741554C61746ELLU, // xyy_Latn_AU + 0x9F37434E4D617263LLU, // xzh_Marc_CN + 0xBF374D584C61746ELLU, // xzp_Latn_MX + 0x801850454C61746ELLU, // yaa_Latn_PE + 0x841842524C61746ELLU, // yab_Latn_BR + 0x881849444C61746ELLU, // yac_Latn_ID + 0x8C1850454C61746ELLU, // yad_Latn_PE + 0x901856454C61746ELLU, // yae_Latn_VE + 0x941843444C61746ELLU, // yaf_Latn_CD + 0x9818434C4C61746ELLU, // yag_Latn_CL + 0x9C18544A4C61746ELLU, // yah_Latn_TJ + 0xA018544A4379726CLLU, // yai_Cyrl_TJ + 0xA41843464C61746ELLU, // yaj_Latn_CF + 0xA81855534C61746ELLU, // yak_Latn_US + 0xAC18474E4C61746ELLU, // yal_Latn_GN + 0xB018434D4C61746ELLU, // yam_Latn_CM + 0xB4184E494C61746ELLU, // yan_Latn_NI 0xB8184D5A4C61746ELLU, // yao_Latn_MZ 0xBC18464D4C61746ELLU, // yap_Latn_FM + 0xC0184D584C61746ELLU, // yaq_Latn_MX + 0xC41856454C61746ELLU, // yar_Latn_VE + 0xC818434D4C61746ELLU, // yas_Latn_CM + 0xCC18434D4C61746ELLU, // yat_Latn_CM + 0xD01856454C61746ELLU, // yau_Latn_VE 0xD418434D4C61746ELLU, // yav_Latn_CM + 0xD81842524C61746ELLU, // yaw_Latn_BR + 0xDC18414F4C61746ELLU, // yax_Latn_AO + 0xE0184E474C61746ELLU, // yay_Latn_NG + 0xE4184E474C61746ELLU, // yaz_Latn_NG + 0x80384E474C61746ELLU, // yba_Latn_NG 0x8438434D4C61746ELLU, // ybb_Latn_CM + 0x9038434E4C61746ELLU, // ybe_Latn_CN + 0x9C384E5044657661LLU, // ybh_Deva_NP + 0xA0384E5044657661LLU, // ybi_Deva_NP + 0xA4384E474C61746ELLU, // ybj_Latn_NG + 0xAC384E474C61746ELLU, // ybl_Latn_NG + 0xB03850474C61746ELLU, // ybm_Latn_PG + 0xB43842524C61746ELLU, // ybn_Latn_BR + 0xB83850474C61746ELLU, // ybo_Latn_PG + 0xDC3850474C61746ELLU, // ybx_Latn_PG + 0xE03850474C61746ELLU, // yby_Latn_PG + 0xAC58434E4C61746ELLU, // ycl_Latn_CN + 0xB458434F4C61746ELLU, // ycn_Latn_CO + 0xC45854574C61746ELLU, // ycr_Latn_TW + 0x807841554C61746ELLU, // yda_Latn_AU + 0x907850474C61746ELLU, // yde_Latn_PG + 0x9878504B41726162LLU, // ydg_Arab_PK + 0xA87850474C61746ELLU, // ydk_Latn_PG + 0x8098494E4D6C796DLLU, // yea_Mlym_IN + 0x889844454C61746ELLU, // yec_Latn_DE + 0x909850474C61746ELLU, // yee_Latn_PG + 0xA098434D4C61746ELLU, // yei_Latn_CM + 0xA49847524772656BLLU, // yej_Grek_GR + 0xAC9843444C61746ELLU, // yel_Latn_CD + 0xC4984E474C61746ELLU, // yer_Latn_NG + 0xC8984E474C61746ELLU, // yes_Latn_NG + 0xCC9849444C61746ELLU, // yet_Latn_ID + 0xD098494E54656C75LLU, // yeu_Telu_IN + 0xD49850474C61746ELLU, // yev_Latn_PG + 0xE09842574C61746ELLU, // yey_Latn_BW + 0x80D841554C61746ELLU, // yga_Latn_AU + 0xA0D841554C61746ELLU, // ygi_Latn_AU + 0xACD850474C61746ELLU, // ygl_Latn_PG + 0xB0D850474C61746ELLU, // ygm_Latn_PG + 0xBCD8434E506C7264LLU, // ygp_Plrd_CN + 0xC4D850474C61746ELLU, // ygr_Latn_PG + 0xD0D841554C61746ELLU, // ygu_Latn_AU + 0xD8D850474C61746ELLU, // ygw_Latn_PG + 0x8CF8494C48656272LLU, // yhd_Hebr_IL + 0x7969554148656272LLU, // yi_Hebr_UA + 0x811841554C61746ELLU, // yia_Latn_AU + 0x9918434E59696969LLU, // yig_Yiii_CN + 0x9D18444548656272LLU, // yih_Hebr_DE + 0xA11841554C61746ELLU, // yii_Latn_AU + 0xA51841554C61746ELLU, // yij_Latn_AU + 0xAD1841554C61746ELLU, // yil_Latn_AU + 0xB118494E4C61746ELLU, // yim_Latn_IN + 0xC51849444C61746ELLU, // yir_Latn_ID + 0xC91850474C61746ELLU, // yis_Latn_PG + 0xD518434E59696969LLU, // yiv_Yiii_CN + 0x815850484C61746ELLU, // yka_Latn_PH + 0x995852554379726CLLU, // ykg_Cyrl_RU + 0x9D584D4E4379726CLLU, // ykh_Cyrl_MN + 0xA15849444C61746ELLU, // yki_Latn_ID + 0xA95850474C61746ELLU, // ykk_Latn_PG + 0xB15850474C61746ELLU, // ykm_Latn_PG + 0xB958434D4C61746ELLU, // yko_Latn_CM + 0xC55850474C61746ELLU, // ykr_Latn_PG + 0xE15843464C61746ELLU, // yky_Latn_CF + 0x817850474C61746ELLU, // yla_Latn_PG + 0x857850474C61746ELLU, // ylb_Latn_PG + 0x917850474C61746ELLU, // yle_Latn_PG + 0x997850474C61746ELLU, // ylg_Latn_PG + 0xA17849444C61746ELLU, // yli_Latn_ID + 0xAD7850474C61746ELLU, // yll_Latn_PG + 0xC57841554C61746ELLU, // ylr_Latn_AU + 0xD17850474C61746ELLU, // ylu_Latn_PG + 0xE1784E434C61746ELLU, // yly_Latn_NC + 0x859850474C61746ELLU, // ymb_Latn_PG + 0x919850454C61746ELLU, // yme_Latn_PE + 0x999843444C61746ELLU, // ymg_Latn_CD + 0xA9984D5A4C61746ELLU, // ymk_Latn_MZ + 0xAD9850474C61746ELLU, // yml_Latn_PG + 0xB198534F4C61746ELLU, // ymm_Latn_SO + 0xB59849444C61746ELLU, // ymn_Latn_ID + 0xB99850474C61746ELLU, // ymo_Latn_PG + 0xBD9850474C61746ELLU, // ymp_Latn_PG + 0x81B8434E506C7264LLU, // yna_Plrd_CN + 0x8DB841554C61746ELLU, // ynd_Latn_AU + 0x99B843444C61746ELLU, // yng_Latn_CD + 0xA9B852554379726CLLU, // ynk_Cyrl_RU + 0xADB850474C61746ELLU, // ynl_Latn_PG + 0xC1B84E474C61746ELLU, // ynq_Latn_NG + 0xC9B843444C61746ELLU, // yns_Latn_CD + 0xD1B8434F4C61746ELLU, // ynu_Latn_CO 0x796F4E474C61746ELLU, // yo_Latn_NG + 0x85D850474C61746ELLU, // yob_Latn_PG + 0x99D850484C61746ELLU, // yog_Latn_PH + 0xA1D84A504A70616ELLU, // yoi_Jpan_JP + 0xA9D855534C61746ELLU, // yok_Latn_US + 0xADD849454C61746ELLU, // yol_Latn_IE + 0xB1D843444C61746ELLU, // yom_Latn_CD + 0xB5D850474C61746ELLU, // yon_Latn_PG + 0xCDD84E474C61746ELLU, // yot_Latn_NG + 0xE1D8544854686169LLU, // yoy_Thai_TH + 0x823850474C61746ELLU, // yra_Latn_PG + 0x863850474C61746ELLU, // yrb_Latn_PG + 0x923843494C61746ELLU, // yre_Latn_CI + 0xAA3852554379726CLLU, // yrk_Cyrl_RU 0xAE3842524C61746ELLU, // yrl_Latn_BR + 0xB23841554C61746ELLU, // yrm_Latn_AU + 0xBA3842524C61746ELLU, // yro_Latn_BR + 0xCA3849444C61746ELLU, // yrs_Latn_ID + 0xDA3850474C61746ELLU, // yrw_Latn_PG + 0xE23841554C61746ELLU, // yry_Latn_AU + 0x8E58434E59696969LLU, // ysd_Yiii_CN + 0xB658434E59696969LLU, // ysn_Yiii_CN + 0xBE58434E59696969LLU, // ysp_Yiii_CN + 0xC65852554379726CLLU, // ysr_Cyrl_RU + 0xCA5850474C61746ELLU, // yss_Latn_PG + 0xE258434E506C7264LLU, // ysy_Plrd_CN + 0xDA7850474C61746ELLU, // ytw_Latn_PG + 0xE27841554C61746ELLU, // yty_Latn_AU 0x82984D584C61746ELLU, // yua_Latn_MX + 0x869841554C61746ELLU, // yub_Latn_AU + 0x8A9855534C61746ELLU, // yuc_Latn_US + 0x8E98494C48656272LLU, // yud_Hebr_IL 0x9298434E48616E73LLU, // yue_Hans_CN 0x9298484B48616E74LLU, // yue_Hant_HK + 0x969855534C61746ELLU, // yuf_Latn_US + 0x9A9852554379726CLLU, // yug_Cyrl_RU + 0xA298434F4C61746ELLU, // yui_Latn_CO + 0xA69850474C61746ELLU, // yuj_Latn_PG + 0xAE9843464C61746ELLU, // yul_Latn_CF + 0xB29855534C61746ELLU, // yum_Latn_US + 0xB6984E474C61746ELLU, // yun_Latn_NG + 0xBE98434F4C61746ELLU, // yup_Latn_CO + 0xC298424F4C61746ELLU, // yuq_Latn_BO + 0xC69855534C61746ELLU, // yur_Latn_US + 0xCE9850474C61746ELLU, // yut_Latn_PG + 0xDA9850474C61746ELLU, // yuw_Latn_PG + 0xDE9852554379726CLLU, // yux_Cyrl_RU + 0xE698424F4C61746ELLU, // yuz_Latn_BO + 0x82B849444C61746ELLU, // yva_Latn_ID + 0xCEB856454C61746ELLU, // yvt_Latn_VE + 0x82D850474C61746ELLU, // ywa_Latn_PG + 0x9AD841554C61746ELLU, // ywg_Latn_AU + 0xB6D842524C61746ELLU, // ywn_Latn_BR + 0xC2D8434E506C7264LLU, // ywq_Plrd_CN + 0xC6D841554C61746ELLU, // ywr_Latn_AU + 0xD2D8434E506C7264LLU, // ywu_Plrd_CN + 0xDAD841554C61746ELLU, // yww_Latn_AU + 0x82F841554C61746ELLU, // yxa_Latn_AU + 0x9AF841554C61746ELLU, // yxg_Latn_AU + 0xAEF841554C61746ELLU, // yxl_Latn_AU + 0xB2F841554C61746ELLU, // yxm_Latn_AU + 0xD2F841554C61746ELLU, // yxu_Latn_AU + 0xE2F841554C61746ELLU, // yxy_Latn_AU + 0xC71841554C61746ELLU, // yyr_Latn_AU + 0xD31850474C61746ELLU, // yyu_Latn_PG 0x7A61434E4C61746ELLU, // za_Latn_CN + 0x80194D584C61746ELLU, // zaa_Latn_MX + 0x84194D584C61746ELLU, // zab_Latn_MX + 0x88194D584C61746ELLU, // zac_Latn_MX + 0x8C194D584C61746ELLU, // zad_Latn_MX + 0x90194D584C61746ELLU, // zae_Latn_MX + 0x94194D584C61746ELLU, // zaf_Latn_MX 0x981953444C61746ELLU, // zag_Latn_SD + 0x9C194E474C61746ELLU, // zah_Latn_NG + 0xA419545A4C61746ELLU, // zaj_Latn_TZ + 0xA819545A4C61746ELLU, // zak_Latn_TZ + 0xB0194D584C61746ELLU, // zam_Latn_MX + 0xB8194D584C61746ELLU, // zao_Latn_MX + 0xBC194D584C61746ELLU, // zap_Latn_MX + 0xC0194D584C61746ELLU, // zaq_Latn_MX + 0xC4194D584C61746ELLU, // zar_Latn_MX + 0xC8194D584C61746ELLU, // zas_Latn_MX + 0xCC194D584C61746ELLU, // zat_Latn_MX + 0xD019494E54696274LLU, // zau_Tibt_IN + 0xD4194D584C61746ELLU, // zav_Latn_MX + 0xD8194D584C61746ELLU, // zaw_Latn_MX + 0xDC194D584C61746ELLU, // zax_Latn_MX + 0xE01945544C61746ELLU, // zay_Latn_ET + 0xE4194E474C61746ELLU, // zaz_Latn_NG + 0x88394D594C61746ELLU, // zbc_Latn_MY + 0x90394D594C61746ELLU, // zbe_Latn_MY + 0xCC3949444C61746ELLU, // zbt_Latn_ID + 0xD0394E474C61746ELLU, // zbu_Latn_NG + 0xD8394D594C61746ELLU, // zbw_Latn_MY + 0x80594D584C61746ELLU, // zca_Latn_MX + 0x9C59434E48616E69LLU, // zch_Hani_CN 0xA4794B4D41726162LLU, // zdj_Arab_KM 0x80994E4C4C61746ELLU, // zea_Latn_NL + 0x989950474C61746ELLU, // zeg_Latn_PG + 0x9C99434E48616E69LLU, // zeh_Hani_CN + 0xB0994E474C61746ELLU, // zem_Latn_NG + 0xB4994D5254666E67LLU, // zen_Tfng_MR + 0x80D9545A4C61746ELLU, // zga_Latn_TZ + 0x84D9434E48616E69LLU, // zgb_Hani_CN 0x9CD94D4154666E67LLU, // zgh_Tfng_MA + 0xB0D9434E48616E69LLU, // zgm_Hani_CN + 0xB4D9434E48616E69LLU, // zgn_Hani_CN + 0xC4D950474C61746ELLU, // zgr_Latn_PG 0x7A685457426F706FLLU, // zh_Bopo_TW 0x7A68545748616E62LLU, // zh_Hanb_TW 0x7A68434E48616E73LLU, // zh_Hans_CN 0x7A68545748616E74LLU, // zh_Hant_TW + 0x8CF9434E48616E69LLU, // zhd_Hani_CN + 0xA0F94E474C61746ELLU, // zhi_Latn_NG + 0xB4F9434E4C61746ELLU, // zhn_Latn_CN + 0xD8F9434D4C61746ELLU, // zhw_Latn_CM 0xDCF9434E4E736875LLU, // zhx_Nshu_CN + 0x811950474C61746ELLU, // zia_Latn_PG + 0xA91950474C61746ELLU, // zik_Latn_PG + 0xAD19474E4C61746ELLU, // zil_Latn_GN + 0xB11954444C61746ELLU, // zim_Latn_TD + 0xB519545A4C61746ELLU, // zin_Latn_TZ + 0xD919545A4C61746ELLU, // ziw_Latn_TZ + 0xE5194E474C61746ELLU, // ziz_Latn_NG + 0x815949444C61746ELLU, // zka_Latn_ID + 0x8D594D4D4C61746ELLU, // zkd_Latn_MM + 0xB95952554379726CLLU, // zko_Cyrl_RU + 0xBD5942524C61746ELLU, // zkp_Latn_BR 0xCD59434E4B697473LLU, // zkt_Kits_CN + 0xD15941554C61746ELLU, // zku_Latn_AU + 0xE55952554379726CLLU, // zkz_Cyrl_RU + 0x817943444C61746ELLU, // zla_Latn_CD + 0xA579434E48616E69LLU, // zlj_Hani_CN 0xB17954474C61746ELLU, // zlm_Latn_TG + 0xB579434E48616E69LLU, // zln_Hani_CN + 0xC179434E48616E69LLU, // zlq_Hani_CN + 0xD1794E474C61746ELLU, // zlu_Latn_NG + 0x819941554C61746ELLU, // zma_Latn_AU + 0x859943444C61746ELLU, // zmb_Latn_CD + 0x899941554C61746ELLU, // zmc_Latn_AU + 0x8D9941554C61746ELLU, // zmd_Latn_AU + 0x919941554C61746ELLU, // zme_Latn_AU + 0x959943444C61746ELLU, // zmf_Latn_CD + 0x999941554C61746ELLU, // zmg_Latn_AU + 0x9D9950474C61746ELLU, // zmh_Latn_PG 0xA1994D594C61746ELLU, // zmi_Latn_MY + 0xA59941554C61746ELLU, // zmj_Latn_AU + 0xA99941554C61746ELLU, // zmk_Latn_AU + 0xAD9941554C61746ELLU, // zml_Latn_AU + 0xB19941554C61746ELLU, // zmm_Latn_AU + 0xB59947414C61746ELLU, // zmn_Latn_GA + 0xB99953444C61746ELLU, // zmo_Latn_SD + 0xBD9943444C61746ELLU, // zmp_Latn_CD + 0xC19943444C61746ELLU, // zmq_Latn_CD + 0xC59941554C61746ELLU, // zmr_Latn_AU + 0xC99943444C61746ELLU, // zms_Latn_CD + 0xCD9941554C61746ELLU, // zmt_Latn_AU + 0xD19941554C61746ELLU, // zmu_Latn_AU + 0xD59941554C61746ELLU, // zmv_Latn_AU + 0xD99943444C61746ELLU, // zmw_Latn_CD + 0xDD9943474C61746ELLU, // zmx_Latn_CG + 0xE19941554C61746ELLU, // zmy_Latn_AU + 0xE59943444C61746ELLU, // zmz_Latn_CD + 0x81B954444C61746ELLU, // zna_Latn_TD + 0x91B943444C61746ELLU, // zne_Latn_CD + 0x99B9564E4C61746ELLU, // zng_Latn_VN + 0xA9B941554C61746ELLU, // znk_Latn_AU + 0xC9B94E474C61746ELLU, // zns_Latn_NG + 0x89D94D584C61746ELLU, // zoc_Latn_MX + 0x9DD94D584C61746ELLU, // zoh_Latn_MX + 0xB1D9494E4C61746ELLU, // zom_Latn_IN + 0xB9D94D584C61746ELLU, // zoo_Latn_MX + 0xC1D94D584C61746ELLU, // zoq_Latn_MX + 0xC5D94D584C61746ELLU, // zor_Latn_MX + 0xC9D94D584C61746ELLU, // zos_Latn_MX + 0x81F94D584C61746ELLU, // zpa_Latn_MX + 0x85F94D584C61746ELLU, // zpb_Latn_MX + 0x89F94D584C61746ELLU, // zpc_Latn_MX + 0x8DF94D584C61746ELLU, // zpd_Latn_MX + 0x91F94D584C61746ELLU, // zpe_Latn_MX + 0x95F94D584C61746ELLU, // zpf_Latn_MX + 0x99F94D584C61746ELLU, // zpg_Latn_MX + 0x9DF94D584C61746ELLU, // zph_Latn_MX + 0xA1F94D584C61746ELLU, // zpi_Latn_MX + 0xA5F94D584C61746ELLU, // zpj_Latn_MX + 0xA9F94D584C61746ELLU, // zpk_Latn_MX + 0xADF94D584C61746ELLU, // zpl_Latn_MX + 0xB1F94D584C61746ELLU, // zpm_Latn_MX + 0xB5F94D584C61746ELLU, // zpn_Latn_MX + 0xB9F94D584C61746ELLU, // zpo_Latn_MX + 0xBDF94D584C61746ELLU, // zpp_Latn_MX + 0xC1F94D584C61746ELLU, // zpq_Latn_MX + 0xC5F94D584C61746ELLU, // zpr_Latn_MX + 0xC9F94D584C61746ELLU, // zps_Latn_MX + 0xCDF94D584C61746ELLU, // zpt_Latn_MX + 0xD1F94D584C61746ELLU, // zpu_Latn_MX + 0xD5F94D584C61746ELLU, // zpv_Latn_MX + 0xD9F94D584C61746ELLU, // zpw_Latn_MX + 0xDDF94D584C61746ELLU, // zpx_Latn_MX + 0xE1F94D584C61746ELLU, // zpy_Latn_MX + 0xE5F94D584C61746ELLU, // zpz_Latn_MX + 0x9219434E48616E69LLU, // zqe_Hani_CN + 0x9A39494E4F727961LLU, // zrg_Orya_IN + 0xB63954444C61746ELLU, // zrn_Latn_TD + 0xBA3945434C61746ELLU, // zro_Latn_EC + 0xBE39465248656272LLU, // zrp_Hebr_FR + 0xCA3949444C61746ELLU, // zrs_Latn_ID + 0x825950474C61746ELLU, // zsa_Latn_PG + 0xC6594D584C61746ELLU, // zsr_Latn_MX + 0xD25950474C61746ELLU, // zsu_Latn_PG + 0x92794D584C61746ELLU, // zte_Latn_MX + 0x9A794D584C61746ELLU, // ztg_Latn_MX + 0xAE794D584C61746ELLU, // ztl_Latn_MX + 0xB2794D584C61746ELLU, // ztm_Latn_MX + 0xB6794D584C61746ELLU, // ztn_Latn_MX + 0xBE794D584C61746ELLU, // ztp_Latn_MX + 0xC2794D584C61746ELLU, // ztq_Latn_MX + 0xCA794D584C61746ELLU, // zts_Latn_MX + 0xCE794D584C61746ELLU, // ztt_Latn_MX + 0xD2794D584C61746ELLU, // ztu_Latn_MX + 0xDE794D584C61746ELLU, // ztx_Latn_MX + 0xE2794D584C61746ELLU, // zty_Latn_MX 0x7A755A414C61746ELLU, // zu_Latn_ZA + 0x9E9950474C61746ELLU, // zuh_Latn_PG + 0xB2994F4D41726162LLU, // zum_Arab_OM + 0xB69955534C61746ELLU, // zun_Latn_US + 0xE299434D4C61746ELLU, // zuy_Latn_CM + 0x82D9455445746869LLU, // zwa_Ethi_ET + 0x9B19434E48616E69LLU, // zyg_Hani_CN + 0xA719434E4C61746ELLU, // zyj_Latn_CN + 0xB719434E48616E69LLU, // zyn_Hani_CN + 0xBF194D4D4C61746ELLU, // zyp_Latn_MM 0x833954524C61746ELLU, // zza_Latn_TR + 0xA739434E48616E69LLU, // zzj_Hani_CN }); const std::unordered_map<uint32_t, uint32_t> ARAB_PARENTS({ @@ -2348,6 +14637,7 @@ const std::unordered_map<uint32_t, uint32_t> LATN_PARENTS({ {0x656E474Du, 0x656E8400u}, // en-GM -> en-001 {0x656E4759u, 0x656E8400u}, // en-GY -> en-001 {0x656E484Bu, 0x656E8400u}, // en-HK -> en-001 + {0x656E4944u, 0x656E8400u}, // en-ID -> en-001 {0x656E4945u, 0x656E8400u}, // en-IE -> en-001 {0x656E494Cu, 0x656E8400u}, // en-IL -> en-001 {0x656E494Du, 0x656E8400u}, // en-IM -> en-001 @@ -2451,10 +14741,10 @@ const struct { const char script[4]; const std::unordered_map<uint32_t, uint32_t>* map; } SCRIPT_PARENTS[] = { - {{'L', 'a', 't', 'n'}, &LATN_PARENTS}, {{'A', 'r', 'a', 'b'}, &ARAB_PARENTS}, {{'D', 'e', 'v', 'a'}, &DEVA_PARENTS}, {{'H', 'a', 'n', 't'}, &HANT_PARENTS}, + {{'L', 'a', 't', 'n'}, &LATN_PARENTS}, {{'~', '~', '~', 'B'}, &___B_PARENTS}, }; diff --git a/libs/appfunctions/java/com/android/extensions/appfunctions/AppFunctionService.java b/libs/appfunctions/java/com/android/extensions/appfunctions/AppFunctionService.java index 55f579138218..9f3c34575b94 100644 --- a/libs/appfunctions/java/com/android/extensions/appfunctions/AppFunctionService.java +++ b/libs/appfunctions/java/com/android/extensions/appfunctions/AppFunctionService.java @@ -22,6 +22,7 @@ import static com.android.extensions.appfunctions.SidecarConverter.getPlatformEx import android.annotation.MainThread; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SdkConstant; import android.app.Service; import android.content.Intent; import android.os.Binder; @@ -64,6 +65,7 @@ public abstract class AppFunctionService extends Service { * service must also require the {@link BIND_APP_FUNCTION_SERVICE} permission so that other * applications can not abuse it. */ + @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION) @NonNull public static final String SERVICE_INTERFACE = "android.app.appfunctions.AppFunctionService"; diff --git a/media/java/android/media/quality/AmbientBacklightEvent.java b/media/java/android/media/quality/AmbientBacklightEvent.java index b1483c685fdb..a582c28fdbcb 100644 --- a/media/java/android/media/quality/AmbientBacklightEvent.java +++ b/media/java/android/media/quality/AmbientBacklightEvent.java @@ -37,7 +37,7 @@ public final class AmbientBacklightEvent implements Parcelable { /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef({AMBIENT_BACKLIGHT_EVENT_ENABLED, AMBIENT_BACKLIGHT_EVENT_DISABLED, - AMBIENT_BACKLIGHT_EVENT_METADATA, + AMBIENT_BACKLIGHT_EVENT_METADATA_AVAILABLE, AMBIENT_BACKLIGHT_EVENT_INTERRUPTED}) public @interface Type {} @@ -55,7 +55,7 @@ public final class AmbientBacklightEvent implements Parcelable { * Event type for ambient backlight events. The ambient backlight metadata is * available. */ - public static final int AMBIENT_BACKLIGHT_EVENT_METADATA = 3; + public static final int AMBIENT_BACKLIGHT_EVENT_METADATA_AVAILABLE = 3; /** * Event type for ambient backlight events. The ambient backlight event is preempted by another @@ -93,7 +93,7 @@ public final class AmbientBacklightEvent implements Parcelable { * Gets ambient backlight metadata. * * @return the metadata of the event. It's non-null only for - * {@link #AMBIENT_BACKLIGHT_EVENT_METADATA}. + * {@link #AMBIENT_BACKLIGHT_EVENT_METADATA_AVAILABLE}. */ @Nullable public AmbientBacklightMetadata getMetadata() { diff --git a/media/java/android/media/quality/AmbientBacklightMetadata.java b/media/java/android/media/quality/AmbientBacklightMetadata.java index c295946e50aa..64eb8d901a27 100644 --- a/media/java/android/media/quality/AmbientBacklightMetadata.java +++ b/media/java/android/media/quality/AmbientBacklightMetadata.java @@ -17,6 +17,7 @@ package android.media.quality; import android.annotation.FlaggedApi; +import android.annotation.IntDef; import android.annotation.IntRange; import android.graphics.PixelFormat; import android.media.tv.flags.Flags; @@ -25,16 +26,34 @@ import android.os.Parcelable; import androidx.annotation.NonNull; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.Arrays; /** * Metadata of ambient backlight. * * <p>A metadata instance is sent from ambient backlight hardware in a {@link AmbientBacklightEvent} - * with {@link AmbientBacklightEvent#AMBIENT_BACKLIGHT_EVENT_METADATA}. + * with {@link AmbientBacklightEvent#AMBIENT_BACKLIGHT_EVENT_METADATA_AVAILABLE}. */ @FlaggedApi(Flags.FLAG_MEDIA_QUALITY_FW) public final class AmbientBacklightMetadata implements Parcelable { + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({ALGORITHM_NONE, ALGORITHM_RLE}) + public @interface CompressionAlgorithm {} + + /** + * The compress algorithm is disabled. + */ + public static final int ALGORITHM_NONE = 0; + + /** + * The compress algorithm is run length encoding (RLE). + */ + public static final int ALGORITHM_RLE = 1; + @NonNull private final String mPackageName; private final int mCompressAlgorithm; @@ -50,7 +69,7 @@ public final class AmbientBacklightMetadata implements Parcelable { */ public AmbientBacklightMetadata( @NonNull String packageName, - @AmbientBacklightSettings.CompressAlgorithm int compressAlgorithm, + @CompressionAlgorithm int compressAlgorithm, @AmbientBacklightSettings.Source int source, @PixelFormat.Format int colorFormat, int horizontalZonesNumber, @@ -86,8 +105,8 @@ public final class AmbientBacklightMetadata implements Parcelable { /** * Gets compress algorithm. */ - @AmbientBacklightSettings.CompressAlgorithm - public int getCompressAlgorithm() { + @CompressionAlgorithm + public int getCompressionAlgorithm() { return mCompressAlgorithm; } @@ -114,7 +133,7 @@ public final class AmbientBacklightMetadata implements Parcelable { * larger than 128. */ @IntRange(from = 0, to = 128) - public int getHorizontalZonesNumber() { + public int getHorizontalZonesCount() { return mHorizontalZonesNumber; } @@ -125,7 +144,7 @@ public final class AmbientBacklightMetadata implements Parcelable { * larger than 80. */ @IntRange(from = 0, to = 80) - public int getVerticalZonesNumber() { + public int getVerticalZonesCount() { return mVerticalZonesNumber; } @@ -137,11 +156,11 @@ public final class AmbientBacklightMetadata implements Parcelable { * @return an array of color data, in row by row (left-to-right then top-to-bottom) order of the * color zones. * - * @see #getHorizontalZonesNumber() - * @see #getVerticalZonesNumber() + * @see #getHorizontalZonesCount() + * @see #getVerticalZonesCount() */ @NonNull - public int[] getZonesColors() { + public int[] getZoneColors() { return mZonesColors; } diff --git a/media/java/android/media/quality/AmbientBacklightSettings.java b/media/java/android/media/quality/AmbientBacklightSettings.java index aa06341977fe..bd73f76411c1 100644 --- a/media/java/android/media/quality/AmbientBacklightSettings.java +++ b/media/java/android/media/quality/AmbientBacklightSettings.java @@ -60,21 +60,6 @@ public final class AmbientBacklightSettings implements Parcelable { public static final int SOURCE_AUDIO_VIDEO = 3; - /** @hide */ - @Retention(RetentionPolicy.SOURCE) - @IntDef({ALGORITHM_NONE, ALGORITHM_RLE}) - public @interface CompressAlgorithm {} - - /** - * The compress algorithm is disabled. - */ - public static final int ALGORITHM_NONE = 0; - - /** - * The compress algorithm is run length encoding (RLE). - */ - public static final int ALGORITHM_RLE = 1; - /** * The source of the ambient backlight. */ @@ -170,7 +155,7 @@ public final class AmbientBacklightSettings implements Parcelable { * <p>A color zone is a group of lights that always display the same color. */ @IntRange(from = 0) - public int getHorizontalZonesNumber() { + public int getHorizontalZonesCount() { return mHorizontalZonesNumber; } @@ -180,7 +165,7 @@ public final class AmbientBacklightSettings implements Parcelable { * <p>A color zone is a group of lights that always display the same color. */ @IntRange(from = 0) - public int getVerticalZonesNumber() { + public int getVerticalZonesCount() { return mVerticalZonesNumber; } diff --git a/media/java/android/media/quality/IMediaQualityManager.aidl b/media/java/android/media/quality/IMediaQualityManager.aidl index 253c2d896d63..6e9fa1dcf93d 100644 --- a/media/java/android/media/quality/IMediaQualityManager.aidl +++ b/media/java/android/media/quality/IMediaQualityManager.aidl @@ -20,11 +20,12 @@ import android.media.quality.AmbientBacklightSettings; import android.media.quality.IAmbientBacklightCallback; import android.media.quality.IPictureProfileCallback; import android.media.quality.ISoundProfileCallback; -import android.media.quality.ParamCapability; +import android.media.quality.ParameterCapability; import android.media.quality.PictureProfileHandle; import android.media.quality.PictureProfile; import android.media.quality.SoundProfileHandle; import android.media.quality.SoundProfile; +import android.os.Bundle; import android.os.UserHandle; /** @@ -37,10 +38,10 @@ interface IMediaQualityManager { void removePictureProfile(in String id, in UserHandle user); boolean setDefaultPictureProfile(in String id, in UserHandle user); PictureProfile getPictureProfile( - in int type, in String name, in boolean includeParams, in UserHandle user); + in int type, in String name, in Bundle options, in UserHandle user); List<PictureProfile> getPictureProfilesByPackage( - in String packageName, in boolean includeParams, in UserHandle user); - List<PictureProfile> getAvailablePictureProfiles(in boolean includeParams, in UserHandle user); + in String packageName, in Bundle options, in UserHandle user); + List<PictureProfile> getAvailablePictureProfiles(in Bundle options, in UserHandle user); List<String> getPictureProfilePackageNames(in UserHandle user); List<String> getPictureProfileAllowList(in UserHandle user); void setPictureProfileAllowList(in List<String> packages, in UserHandle user); @@ -51,10 +52,10 @@ interface IMediaQualityManager { void removeSoundProfile(in String id, in UserHandle user); boolean setDefaultSoundProfile(in String id, in UserHandle user); SoundProfile getSoundProfile( - in int type, in String name, in boolean includeParams, in UserHandle user); + in int type, in String name, in Bundle options, in UserHandle user); List<SoundProfile> getSoundProfilesByPackage( - in String packageName, in boolean includeParams, in UserHandle user); - List<SoundProfile> getAvailableSoundProfiles(in boolean includeParams, in UserHandle user); + in String packageName, in Bundle options, in UserHandle user); + List<SoundProfile> getAvailableSoundProfiles(in Bundle options, in UserHandle user); List<String> getSoundProfilePackageNames(in UserHandle user); List<String> getSoundProfileAllowList(in UserHandle user); void setSoundProfileAllowList(in List<String> packages, in UserHandle user); @@ -64,7 +65,7 @@ interface IMediaQualityManager { void registerSoundProfileCallback(in ISoundProfileCallback cb); void registerAmbientBacklightCallback(in IAmbientBacklightCallback cb); - List<ParamCapability> getParamCapabilities(in List<String> names, in UserHandle user); + List<ParameterCapability> getParameterCapabilities(in List<String> names, in UserHandle user); boolean isSupported(in UserHandle user); void setAutoPictureQualityEnabled(in boolean enabled, in UserHandle user); diff --git a/media/java/android/media/quality/IPictureProfileCallback.aidl b/media/java/android/media/quality/IPictureProfileCallback.aidl index 7071a1684fa2..eed77f695416 100644 --- a/media/java/android/media/quality/IPictureProfileCallback.aidl +++ b/media/java/android/media/quality/IPictureProfileCallback.aidl @@ -17,7 +17,7 @@ package android.media.quality; -import android.media.quality.ParamCapability; +import android.media.quality.ParameterCapability; import android.media.quality.PictureProfile; /** @@ -28,6 +28,6 @@ oneway interface IPictureProfileCallback { void onPictureProfileAdded(in String id, in PictureProfile p); void onPictureProfileUpdated(in String id, in PictureProfile p); void onPictureProfileRemoved(in String id, in PictureProfile p); - void onParamCapabilitiesChanged(in String id, in List<ParamCapability> caps); + void onParameterCapabilitiesChanged(in String id, in List<ParameterCapability> caps); void onError(in String id, in int err); } diff --git a/media/java/android/media/quality/ISoundProfileCallback.aidl b/media/java/android/media/quality/ISoundProfileCallback.aidl index 30bb106ef34c..3871fb212259 100644 --- a/media/java/android/media/quality/ISoundProfileCallback.aidl +++ b/media/java/android/media/quality/ISoundProfileCallback.aidl @@ -17,7 +17,7 @@ package android.media.quality; -import android.media.quality.ParamCapability; +import android.media.quality.ParameterCapability; import android.media.quality.SoundProfile; /** @@ -28,6 +28,6 @@ oneway interface ISoundProfileCallback { void onSoundProfileAdded(in String id, in SoundProfile p); void onSoundProfileUpdated(in String id, in SoundProfile p); void onSoundProfileRemoved(in String id, in SoundProfile p); - void onParamCapabilitiesChanged(in String id, in List<ParamCapability> caps); + void onParameterCapabilitiesChanged(in String id, in List<ParameterCapability> caps); void onError(in String id, in int err); } diff --git a/media/java/android/media/quality/MediaQualityContract.java b/media/java/android/media/quality/MediaQualityContract.java index 6a52bcba547a..d1f63404dbff 100644 --- a/media/java/android/media/quality/MediaQualityContract.java +++ b/media/java/android/media/quality/MediaQualityContract.java @@ -18,8 +18,12 @@ package android.media.quality; import android.annotation.FlaggedApi; +import android.annotation.StringDef; import android.media.tv.flags.Flags; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * The contract between the media quality service and applications. Contains definitions for the * commonly used parameter names. @@ -27,6 +31,48 @@ import android.media.tv.flags.Flags; @FlaggedApi(Flags.FLAG_MEDIA_QUALITY_FW) public class MediaQualityContract { + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @StringDef(prefix = "LEVEL_", value = { + LEVEL_LOW, + LEVEL_MEDIUM, + LEVEL_HIGH, + LEVEL_OFF + }) + public @interface Level {} + + /** + * Low level option for a parameter. + * + * <p>This level represents that the corresponding feature is turned on with the low level + * option. + */ + public static final String LEVEL_LOW = "level_low"; + + /** + * Medium level option for a parameter. + * + * <p>This level represents that the corresponding feature is turned on with the medium level + * option. + */ + public static final String LEVEL_MEDIUM = "level_medium"; + + /** + * High level option for a parameter. + * + * <p>This level represents that the corresponding feature is turned on with the high level + * option. + */ + public static final String LEVEL_HIGH = "level_high"; + + /** + * Off level for parameters. + * + * <p>This level represents that the corresponding feature is turned off. + */ + public static final String LEVEL_OFF = "level_off"; + + /** * @hide */ @@ -46,14 +92,22 @@ public class MediaQualityContract { /** * The brightness. * - * <p>Type: INTEGER + * <p>Brightness value range are from 0.0 to 1.0 (inclusive), where 0.0 represents the + * minimum brightness and 1.0 represents the maximum brightness. The content-unmodified + * value is 0.5. + * + * <p>Type: FLOAT */ public static final String PARAMETER_BRIGHTNESS = "brightness"; /** * The contrast. * - * <p>The ratio between the luminance of the brightest white and the darkest black. + * <p>This value represents the image contrast on an arbitrary scale from 0 to 100, + * where 0 represents the darkest black (black screen) and 100 represents the brightest + * white (brighter). + * The default/unmodified value for contrast is 50. + * * <p>Type: INTEGER */ public static final String PARAMETER_CONTRAST = "contrast"; @@ -61,7 +115,12 @@ public class MediaQualityContract { /** * The sharpness. * - * <p>Sharpness indicates the clarity of detail. + * <p>Sharpness value range are from 0 to 100 (inclusive), where 0 represents the minimum + * sharpness that makes the image appear softer with less defined edges, 100 represents the + * maximum sharpness that makes the image appear halos around objects due to excessive + * edges. + * The default/unmodified value for sharpness is 50. + * * <p>Type: INTEGER */ public static final String PARAMETER_SHARPNESS = "sharpness"; @@ -69,7 +128,11 @@ public class MediaQualityContract { /** * The saturation. * - * <p>Saturation indicates the intensity of the color. + * <p>Saturation value controls the intensity or purity of colors. + * Saturation values are from 0 to 100, where 0 represents grayscale (no color) and 100 + * represents the most vivid colors. + * The default/unmodified value for saturation is 50. + * * <p>Type: INTEGER */ public static final String PARAMETER_SATURATION = "saturation"; @@ -77,20 +140,23 @@ public class MediaQualityContract { /** * The hue. * + * <p>Hue affects the balance between red, green and blue primary colors on the screen. + * Hue values are from -50 to 50, where -50 represents cooler and 50 represents warmer. + * The default/unmodified value for hue is 0. + * * <p>Type: INTEGER */ public static final String PARAMETER_HUE = "hue"; /** - * @hide - */ - public static final String PARAMETER_BACKLIGHT = "backlight"; - - /** * Adjust brightness in advance color engine. Similar to a "brightness" control on a TV * but acts at a lower level. * + * <p>The range is from 0 to 100 (inclusive), where 0 represents the minimum brightness and + * 100 represents the maximum brightness. The default/unmodified value is 50. + * * <p>Type: INTEGER + * @see #PARAMETER_BRIGHTNESS */ public static final String PARAMETER_COLOR_TUNER_BRIGHTNESS = "color_tuner_brightness"; @@ -98,7 +164,11 @@ public class MediaQualityContract { * Adjust saturation in advance color engine. Similar to a "saturation" control on a TV * but acts at a lower level. * + * <p>The range is from 0 to 100 (inclusive), where 0 being completely desaturated/grayscale + * and 100 being the most saturated. The default/unmodified value is 50. + * * <p>Type: INTEGER + * @see #PARAMETER_SATURATION */ public static final String PARAMETER_COLOR_TUNER_SATURATION = "color_tuner_saturation"; @@ -106,14 +176,21 @@ public class MediaQualityContract { * Adjust hue in advance color engine. Similar to a "hue" control on a TV but acts at a * lower level. * + * <p>The range is from -50 to 50 (inclusive), where -50 represents cooler setting for a + * specific color and 50 represents warmer setting for a specific color. The + * default/unmodified value is 0. + * * <p>Type: INTEGER + * @see #PARAMETER_HUE */ public static final String PARAMETER_COLOR_TUNER_HUE = "color_tuner_hue"; /** - * Advance setting for red offset. Adjust the black level of red color channels, it - * controls the minimum intensity of each color, affecting the shadows and - * dark areas of the image. + * Advance setting for red offset. Adjust the black level of red color channels, it controls + * the minimum intensity of each color, affecting the shadows and dark areas of the image. + * + * <p>The range is from 0 to 100 (inclusive), where 0 makes shadows darker and 100 makes + * shadows brighter. The default/unmodified value is 50. * * <p>Type: INTEGER */ @@ -121,8 +198,11 @@ public class MediaQualityContract { /** * Advance setting for green offset. Adjust the black level of green color channels, it - * controls the minimum intensity of each color, affecting the shadows and dark - * areas of the image. + * controls the minimum intensity of each color, affecting the shadows and dark areas of the + * image. + * + * <p>The range is from 0 to 100 (inclusive), where 0 makes shadows darker and 100 makes + * shadows brighter. The default/unmodified value is 50. * * <p>Type: INTEGER */ @@ -130,8 +210,11 @@ public class MediaQualityContract { /** * Advance setting for blue offset. Adjust the black level of blue color channels, it - * controls the minimum intensity of each color, affecting the shadows and dark areas - * of the image. + * controls the minimum intensity of each color, affecting the shadows and dark areas of the + * image. + * + * <p>The range is from 0 to 100 (inclusive), where 0 makes shadows darker and 100 makes + * shadows brighter. The default/unmodified value is 50. * * <p>Type: INTEGER */ @@ -141,6 +224,9 @@ public class MediaQualityContract { * Advance setting for red gain. Adjust the gain or amplification of the red color channels. * They control the overall intensity and white balance of red. * + * <p>The range is from 0 to 100 (inclusive), where 0 makes the red dimmer and 100 makes the + * red brighter. The default/unmodified value is 50. + * * <p>Type: INTEGER */ public static final String PARAMETER_COLOR_TUNER_RED_GAIN = "color_tuner_red_gain"; @@ -149,49 +235,67 @@ public class MediaQualityContract { * Advance setting for green gain. Adjust the gain or amplification of the green color * channels. They control the overall intensity and white balance of green. * + * <p>The range is from 0 to 100 (inclusive), where 0 makes the green dimmer and 100 makes + * the green brighter. The default/unmodified value is 50. + * * <p>Type: INTEGER */ public static final String PARAMETER_COLOR_TUNER_GREEN_GAIN = "color_tuner_green_gain"; /** * Advance setting for blue gain. Adjust the gain or amplification of the blue color - * channels.They control the overall intensity and white balance of blue. + * channels. They control the overall intensity and white balance of blue. + * + * <p>The range is from 0 to 100 (inclusive), where 0 makes the blue dimmer and 100 makes + * the blue brighter. The default/unmodified value is 50. * * <p>Type: INTEGER */ public static final String PARAMETER_COLOR_TUNER_BLUE_GAIN = "color_tuner_blue_gain"; /** - * @hide - */ - public static final String PARAMETER_AI_PQ = "ai_pq"; - - /** - * @hide - */ - public static final String PARAMETER_AI_SUPER_RESOLUTION = "ai_super_resolution"; - - /** Noise reduction. - * (Off, Low, Medium, High) - * @see android.hardware.tv.mediaquality.QualityLevel + * Noise reduction. + * + * <p>Possible values: + * <ul> + * <li>{@link #LEVEL_LOW} + * <li>{@link #LEVEL_MEDIUM} + * <li>{@link #LEVEL_HIGH} + * <li>{@link #LEVEL_OFF} + * </ul> + * The default value is {@link #LEVEL_OFF}. * * <p>Type: STRING */ public static final String PARAMETER_NOISE_REDUCTION = "noise_reduction"; /** - * MPEG (moving picture experts group) noise reduction - * (Off, Low, Medium, High) - * @see android.hardware.tv.mediaquality.QualityLevel + * MPEG (moving picture experts group) noise reduction. * - * <p>Type: STRING - * */ + * <p>Possible values: + * <ul> + * <li>{@link #LEVEL_LOW} + * <li>{@link #LEVEL_MEDIUM} + * <li>{@link #LEVEL_HIGH} + * <li>{@link #LEVEL_OFF} + * </ul> + * The default value is {@link #LEVEL_OFF}. + * + * <p>Type: STRING + */ public static final String PARAMETER_MPEG_NOISE_REDUCTION = "mpeg_noise_reduction"; /** * Refine the flesh colors in the pictures without affecting the other colors on the screen. - * (Off, Low, Medium, High) - * @see android.hardware.tv.mediaquality.QualityLevel + * + * <p>Possible values: + * <ul> + * <li>{@link #LEVEL_LOW} + * <li>{@link #LEVEL_MEDIUM} + * <li>{@link #LEVEL_HIGH} + * <li>{@link #LEVEL_OFF} + * </ul> + * The default value is {@link #LEVEL_OFF}. * * <p>Type: STRING */ @@ -199,66 +303,75 @@ public class MediaQualityContract { /** * Contour noise reduction. - * (Off, Low, Medium, High) - * @see android.hardware.tv.mediaquality.QualityLevel + * + * <p>Possible values: + * <ul> + * <li>{@link #LEVEL_LOW} + * <li>{@link #LEVEL_MEDIUM} + * <li>{@link #LEVEL_HIGH} + * <li>{@link #LEVEL_OFF} + * </ul> + * The default value is {@link #LEVEL_OFF}. * * <p>Type: STRING */ public static final String PARAMETER_DECONTOUR = "decontour"; /** - * Dynamically change picture luma to enhance contrast. - * (Off, Low, Medium, High) - * @see android.hardware.tv.mediaquality.QualityLevel + * Dynamically change picture luma to enhance contrast. + * + * <p>Possible values: + * <ul> + * <li>{@link #LEVEL_LOW} + * <li>{@link #LEVEL_MEDIUM} + * <li>{@link #LEVEL_HIGH} + * <li>{@link #LEVEL_OFF} + * </ul> + * The default value is {@link #LEVEL_OFF}. * - * <p>Type: STRING + * <p>Type: STRING */ public static final String PARAMETER_DYNAMIC_LUMA_CONTROL = "dynamic_luma_control"; /** - * Enable/disable film mode + * Enable/disable film mode. * - * <p>Type: BOOLEAN + * <p>Type: BOOLEAN */ public static final String PARAMETER_FILM_MODE = "film_mode"; /** - * @hide - */ - public static final String PARAMETER_BLACK_STRETCH = "black_stretch"; - - /** - * Enable/disable blue color auto stretch + * Enable/disable blue color auto stretch * - * <p>Type: BOOLEAN + * <p>Type: BOOLEAN */ public static final String PARAMETER_BLUE_STRETCH = "blue_stretch"; /** - * Enable/disable the overall color tuning feature. + * Enable/disable the overall color tuning feature. * - * <p>Type: BOOLEAN + * <p>Type: BOOLEAN */ public static final String PARAMETER_COLOR_TUNE = "color_tune"; /** - * Adjust color temperature type + * Adjust color temperature type * - * <p>Type: INTEGER + * <p>Type: STRING */ public static final String PARAMETER_COLOR_TEMPERATURE = "color_temperature"; /** - * Enable/disable globe dimming. + * Enable/disable globe dimming. * - * <p>Type: BOOLEAN + * <p>Type: BOOLEAN */ public static final String PARAMETER_GLOBAL_DIMMING = "global_dimming"; /** - * Enable/disable auto adjust picture parameter based on the TV content. + * Enable/disable auto adjust picture parameter based on the TV content. * - * <p>Type: BOOLEAN + * <p>Type: BOOLEAN */ public static final String PARAMETER_AUTO_PICTURE_QUALITY_ENABLED = "auto_picture_quality_enabled"; @@ -283,6 +396,12 @@ public class MediaQualityContract { /** * The audio volume balance. * + * <p>This parameter controls the balance between the left and right speakers. + * The valid range is -50 to 50 (inclusive), where: + * - Negative values shift the balance towards the left speaker. + * - Positive values shift the balance towards the right speaker. + * - 0 represents a balanced output. + * * <p>Type: INTEGER */ public static final String PARAMETER_BALANCE = "balance"; @@ -290,7 +409,9 @@ public class MediaQualityContract { /** * The bass. * - * <p>Bass setting adjust the low sound frequencies. + * <p>Bass controls the intensity of low-frequency sounds. + * The valid range is 0 - 100 (inclusive). + * * <p>Type: INTEGER */ public static final String PARAMETER_BASS = "bass"; @@ -298,18 +419,17 @@ public class MediaQualityContract { /** * The treble. * - * <p>Treble setting adjust the high sound frequencies. + * <p>Treble controls the intensity of high-frequency sounds. + * The valid range is 0 - 100 (inclusive). + * * <p>Type: INTEGER */ public static final String PARAMETER_TREBLE = "treble"; /** - * @hide - */ - public static final String PARAMETER_SOUND_MODE = "sound_mode"; - - /** - * @hide + * Enable/disable surround sound. + * + * <p>Type: BOOLEAN */ public static final String PARAMETER_SURROUND_SOUND = "surround_sound"; @@ -319,32 +439,46 @@ public class MediaQualityContract { public static final String PARAMETER_EQUALIZER_DETAIL = "equalizer_detail"; /** - * @hide + * Enable/disable speaker output. + * + * <p>Type: BOOLEAN */ public static final String PARAMETER_SPEAKERS = "speakers"; /** - * @hide + * Speaker delay in milliseconds. + * + * <p>Type: INTEGER */ - public static final String PARAMETER_SPEAKERS_DELAY = "speakers_delay"; + public static final String PARAMETER_SPEAKERS_DELAY_MILLIS = "speakers_delay_millis"; /** - * @hide + * Enable/disable enhanced audio return channel (eARC). + * + * <p>eARC allows for higher bandwidth audio transmission over HDMI. + * + * <p>Type: BOOLEAN */ public static final String PARAMETER_EARC = "earc"; /** - * @hide + * Enable/disable auto volume control sound effect. + * + * <p>Type: BOOLEAN */ public static final String PARAMETER_AUTO_VOLUME_CONTROL = "auto_volume_control"; /** - * @hide + * Downmix mode. + * + * <p>Type: STRING */ public static final String PARAMETER_DOWN_MIX_MODE = "down_mix_mode"; /** - * @hide + * Enable/disable dynamic range compression (DRC) of digital theater system (DTS). + * + * <p>Type: BOOLEAN */ public static final String PARAMETER_DTS_DRC = "dts_drc"; @@ -354,31 +488,67 @@ public class MediaQualityContract { public static final String PARAMETER_DOLBY_AUDIO_PROCESSING = "dolby_audio_processing"; /** - * @hide + * Sound mode for dolby audio processing. + * + * <p>Type: STRING */ public static final String PARAMETER_DOLBY_AUDIO_PROCESSING_SOUND_MODE = "dolby_audio_processing_sound_mode"; /** - * @hide + * Enable/disable Volume Leveler. + * + * <p>Volume Leveler helps to maintain a consistent volume level across different + * types of content and even within the same program. It minimizes the jarring jumps + * between loud commercials or action sequences and quiet dialogue. + * + * <p>Type: BOOLEAN */ public static final String PARAMETER_DOLBY_AUDIO_PROCESSING_VOLUME_LEVELER = "dolby_audio_processing_volume_leveler"; /** - * @hide + * Enable/disable Surround Virtualizer. + * + * <p>Surround Virtualizer creates a virtual surround sound experience from stereo + * content, making it seem like the sound is coming from multiple speakers, even if + * you only have your TV's built-in speakers. It expands the soundstage and adds + * depth to the audio. + * + * <p>Type: BOOLEAN */ public static final String PARAMETER_DOLBY_AUDIO_PROCESSING_SURROUND_VIRTUALIZER = "dolby_audio_processing_surround_virtualizer"; /** - * @hide + * Enable/disable Dolby Atmos. + * + * <p>Dolby Atmos creates a more immersive and realistic sound experience by adding + * a height dimension to surround sound. It allows sound to be placed and moved + * precisely around you, including overhead. + * + * <p>Note: To experience Dolby Atmos, you need content that has been specifically + * mixed in Dolby Atmos and a compatible sound system with upward-firing speakers + * or a Dolby Atmos soundbar. + * + * <p>Type: BOOLEAN */ public static final String PARAMETER_DOLBY_AUDIO_PROCESSING_DOLBY_ATMOS = "dolby_audio_processing_dolby_atmos"; /** - * @hide + * Dialogue enhancer. + * + * <p>Possible values: + * <ul> + * <li>{@link #LEVEL_LOW} + * <li>{@link #LEVEL_MEDIUM} + * <li>{@link #LEVEL_HIGH} + * <li>{@link #LEVEL_OFF} + * </ul> + * The default value is {@link #LEVEL_OFF}. + * + * <p>Type: STRING */ public static final String PARAMETER_DIALOGUE_ENHANCER = "dialogue_enhancer"; @@ -388,43 +558,89 @@ public class MediaQualityContract { public static final String PARAMETER_DTS_VIRTUAL_X = "dts_virtual_x"; /** - * @hide + * Enable/disable Total Bass Harmonic Distortion (X). + * + * <p>TBHDX bass enhancement provides a richer low-frequency experience, simulating deeper + * bass. + * + * <p>Type: BOOLEAN */ public static final String PARAMETER_DTS_VIRTUAL_X_TBHDX = "dts_virtual_x_tbhdx"; /** - * @hide + * Enable/disable audio limiter. + * + * <p>It prevents excessive volume peaks that could cause distortion or speaker damage. + * + * <p>Type: BOOLEAN */ public static final String PARAMETER_DTS_VIRTUAL_X_LIMITER = "dts_virtual_x_limiter"; /** - * @hide + * Enable/disable the core DTS Virtual:X surround sound processing. + * + * <p>It creates an immersive, multi-channel audio experience from the speaker + * configuration. + * + * <p>Type: BOOLEAN */ public static final String PARAMETER_DTS_VIRTUAL_X_TRU_SURROUND_X = "dts_virtual_x_tru_surround_x"; /** - * @hide + * Enable/disable DTS TruVolume HD. + * + * <p>It reduces the dynamic range of audio, minimizing loudness variations between content + * and channels. + * + * <p>Type: BOOLEAN */ public static final String PARAMETER_DTS_VIRTUAL_X_TRU_VOLUME_HD = "dts_virtual_x_tru_volume_hd"; /** - * @hide + * Enable/disable dialog clarity. + * + * <p>It enhances the clarity and intelligibility of speech in audio content. + * + * <p>Type: BOOLEAN */ public static final String PARAMETER_DTS_VIRTUAL_X_DIALOG_CLARITY = "dts_virtual_x_dialog_clarity"; /** - * @hide + * Enable/disable virtual X definition. + * + * <p>It applies audio processing to improve overall sound definition and clarity. + * + * <p>Type: BOOLEAN */ public static final String PARAMETER_DTS_VIRTUAL_X_DEFINITION = "dts_virtual_x_definition"; /** - * @hide + * Enable/disable the processing of virtual height channels. + * + * <p>It creates a more immersive audio experience by simulating sounds from above. + * + * <p>Type: BOOLEAN */ public static final String PARAMETER_DTS_VIRTUAL_X_HEIGHT = "dts_virtual_x_height"; + /** + * Digital output delay in milliseconds. + * + * <p>Type: INTEGER + */ + public static final String PARAMETER_DIGITAL_OUTPUT_DELAY_MILLIS = + "digital_output_delay_millis"; + + /** + * Digital output mode. + * + * <p>Type: STRING + */ + public static final String PARAMETER_DIGITAL_OUTPUT_MODE = "digital_output_mode"; + private SoundQuality() { } diff --git a/media/java/android/media/quality/MediaQualityManager.java b/media/java/android/media/quality/MediaQualityManager.java index 166b388d9b7b..191b938b2e26 100644 --- a/media/java/android/media/quality/MediaQualityManager.java +++ b/media/java/android/media/quality/MediaQualityManager.java @@ -25,6 +25,9 @@ import android.annotation.SystemApi; import android.annotation.SystemService; import android.content.Context; import android.media.tv.flags.Flags; +import android.os.Bundle; +import android.os.Parcel; +import android.os.Parcelable; import android.os.RemoteException; import android.os.UserHandle; @@ -36,6 +39,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.concurrent.Executor; +import java.util.function.Consumer; /** * Central system API to the overall media quality, which arbitrates interaction between @@ -61,6 +65,12 @@ public final class MediaQualityManager { private final List<ActiveProcessingPictureListenerRecord> mApListenerRecords = new ArrayList<>(); + /** + * A query option to include parameters in the profile. The default value is {@code false}. + * @hide + */ + public static final String OPTION_INCLUDE_PARAMETERS = "include_parameters"; + /** * @hide @@ -98,11 +108,12 @@ public final class MediaQualityManager { } } @Override - public void onParamCapabilitiesChanged(String profileId, List<ParamCapability> caps) { + public void onParameterCapabilitiesChanged( + String profileId, List<ParameterCapability> caps) { synchronized (mLock) { for (PictureProfileCallbackRecord record : mPpCallbackRecords) { // TODO: filter callback record - record.postParamCapabilitiesChanged(profileId, caps); + record.postParameterCapabilitiesChanged(profileId, caps); } } } @@ -145,11 +156,12 @@ public final class MediaQualityManager { } } @Override - public void onParamCapabilitiesChanged(String profileId, List<ParamCapability> caps) { + public void onParameterCapabilitiesChanged( + String profileId, List<ParameterCapability> caps) { synchronized (mLock) { for (SoundProfileCallbackRecord record : mSpCallbackRecords) { // TODO: filter callback record - record.postParamCapabilitiesChanged(profileId, caps); + record.postParameterCapabilitiesChanged(profileId, caps); } } } @@ -218,18 +230,25 @@ public final class MediaQualityManager { /** * Gets picture profile by given profile type and name. * + * <p>If {@link ProfileQueryParams#areParametersIncluded()} is {@code false}, + * {@link PictureProfile#getParameters()} of the returned profile is an empty bundle. + * * @param type the type of the profile. * @param name the name of the profile. - * @param includeParams {@code true} to include parameters in the profile; {@code false} - * otherwise. + * @param options the options of the query. {@code null} if default options are used. + * * @return the corresponding picture profile if available; {@code null} if the name doesn't * exist. */ @Nullable public PictureProfile getPictureProfile( - @PictureProfile.ProfileType int type, @NonNull String name, boolean includeParams) { + @PictureProfile.ProfileType int type, + @NonNull String name, + @Nullable ProfileQueryParams options) { try { - return mService.getPictureProfile(type, name, includeParams, mUserHandle); + Bundle optionsBundle = options == null + ? ProfileQueryParams.DEFAULT.toBundle() : options.toBundle(); + return mService.getPictureProfile(type, name, optionsBundle, mUserHandle); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -239,18 +258,23 @@ public final class MediaQualityManager { /** * Gets profiles that available to the given package. * + * <p>If {@link ProfileQueryParams#areParametersIncluded()} is {@code false}, + * {@link PictureProfile#getParameters()} of the returned profiles are empty bundles. + * * @param packageName the package name of the profiles. - * @param includeParams {@code true} to include parameters in the profile; {@code false} - * otherwise. + * @param options the options of the query. {@code null} if default options are used. * @hide */ @SystemApi @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_GLOBAL_PICTURE_QUALITY_SERVICE) public List<PictureProfile> getPictureProfilesByPackage( - @NonNull String packageName, boolean includeParams) { + @NonNull String packageName, @Nullable ProfileQueryParams options) { try { - return mService.getPictureProfilesByPackage(packageName, includeParams, mUserHandle); + Bundle optionsBundle = options == null + ? ProfileQueryParams.DEFAULT.toBundle() : options.toBundle(); + return mService.getPictureProfilesByPackage( + packageName, optionsBundle, mUserHandle); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -259,15 +283,19 @@ public final class MediaQualityManager { /** * Gets profiles that available to the caller. * - * @param includeParams {@code true} to include parameters in the profile; {@code false} - * otherwise. + * <p>If {@link ProfileQueryParams#areParametersIncluded()} is {@code false}, + * {@link PictureProfile#getParameters()} of the returned profiles are empty bundles. + * + * @param options the options of the query. {@code null} if default options are used. * @return the corresponding picture profile if available; {@code null} if the name doesn't * exist. */ @NonNull - public List<PictureProfile> getAvailablePictureProfiles(boolean includeParams) { + public List<PictureProfile> getAvailablePictureProfiles(@Nullable ProfileQueryParams options) { try { - return mService.getAvailablePictureProfiles(includeParams, mUserHandle); + Bundle optionsBundle = options == null + ? ProfileQueryParams.DEFAULT.toBundle() : options.toBundle(); + return mService.getAvailablePictureProfiles(optionsBundle, mUserHandle); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -413,17 +441,24 @@ public final class MediaQualityManager { /** * Gets sound profile by given profile type and name. * + * <p>If {@link ProfileQueryParams#areParametersIncluded()} is {@code false}, + * {@link SoundProfile#getParameters()} of the returned profile is an empty bundle. + * * @param type the type of the profile. * @param name the name of the profile. - * @param includeParams {@code true} to include parameters in the profile; {@code false} - * otherwise. + * @param options the options of the query. {@code null} if default options are used. + * * @return the corresponding sound profile if available; {@code null} if the name doesn't exist. */ @Nullable public SoundProfile getSoundProfile( - @SoundProfile.ProfileType int type, @NonNull String name, boolean includeParams) { + @SoundProfile.ProfileType int type, + @NonNull String name, + @Nullable ProfileQueryParams options) { try { - return mService.getSoundProfile(type, name, includeParams, mUserHandle); + Bundle optionsBundle = options == null + ? ProfileQueryParams.DEFAULT.toBundle() : options.toBundle(); + return mService.getSoundProfile(type, name, optionsBundle, mUserHandle); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -433,18 +468,23 @@ public final class MediaQualityManager { /** * Gets profiles that available to the given package. * + * <p>If {@link ProfileQueryParams#areParametersIncluded()} is {@code false}, + * {@link SoundProfile#getParameters()} of the returned profiles are empty bundles. + * * @param packageName the package name of the profiles. - * @param includeParams {@code true} to include parameters in the profile; {@code false} - * otherwise. + * @param options the options of the query. {@code null} if default options are used. + * * @hide */ @SystemApi @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_GLOBAL_SOUND_QUALITY_SERVICE) public List<SoundProfile> getSoundProfilesByPackage( - @NonNull String packageName, boolean includeParams) { + @NonNull String packageName, @Nullable ProfileQueryParams options) { try { - return mService.getSoundProfilesByPackage(packageName, includeParams, mUserHandle); + Bundle optionsBundle = options == null + ? ProfileQueryParams.DEFAULT.toBundle() : options.toBundle(); + return mService.getSoundProfilesByPackage(packageName, optionsBundle, mUserHandle); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -453,15 +493,19 @@ public final class MediaQualityManager { /** * Gets profiles that available to the caller package. * - * @param includeParams {@code true} to include parameters in the profile; {@code false} - * otherwise. + * <p>If {@link ProfileQueryParams#areParametersIncluded()} is {@code false}, + * {@link SoundProfile#getParameters()} of the returned profiles are empty bundles. + * + * @param options the options of the query. {@code null} if default options are used. * * @return the corresponding sound profile if available; {@code null} if the none available. */ @NonNull - public List<SoundProfile> getAvailableSoundProfiles(boolean includeParams) { + public List<SoundProfile> getAvailableSoundProfiles(@Nullable ProfileQueryParams options) { try { - return mService.getAvailableSoundProfiles(includeParams, mUserHandle); + Bundle optionsBundle = options == null + ? ProfileQueryParams.DEFAULT.toBundle() : options.toBundle(); + return mService.getAvailableSoundProfiles(optionsBundle, mUserHandle); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -554,11 +598,17 @@ public final class MediaQualityManager { /** * Gets capability information of the given parameters. + * + * <p>If a name isn't found, a corresponding {@link ParameterCapability} instance is in the + * return list, and {@link ParameterCapability#isSupported()} is {@code false}. + * + * @param names the parameter names. Commonly used names can be found in + * {@link MediaQualityContract}. Vendor-defined names are also permitted. */ @NonNull - public List<ParamCapability> getParamCapabilities(@NonNull List<String> names) { + public List<ParameterCapability> getParameterCapabilities(@NonNull List<String> names) { try { - return mService.getParamCapabilities(names, mUserHandle); + return mService.getParameterCapabilities(names, mUserHandle); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -842,11 +892,12 @@ public final class MediaQualityManager { }); } - public void postParamCapabilitiesChanged(final String id, List<ParamCapability> caps) { + public void postParameterCapabilitiesChanged( + final String id, List<ParameterCapability> caps) { mExecutor.execute(new Runnable() { @Override public void run() { - mCallback.onParamCapabilitiesChanged(id, caps); + mCallback.onParameterCapabilitiesChanged(id, caps); } }); } @@ -902,11 +953,12 @@ public final class MediaQualityManager { }); } - public void postParamCapabilitiesChanged(final String id, List<ParamCapability> caps) { + public void postParameterCapabilitiesChanged( + final String id, List<ParameterCapability> caps) { mExecutor.execute(new Runnable() { @Override public void run() { - mCallback.onParamCapabilitiesChanged(id, caps); + mCallback.onParameterCapabilitiesChanged(id, caps); } }); } @@ -996,8 +1048,8 @@ public final class MediaQualityManager { * is no associated profile * @param updatedCaps the updated capabilities. */ - public void onParamCapabilitiesChanged( - @Nullable String profileId, @NonNull List<ParamCapability> updatedCaps) { + public void onParameterCapabilitiesChanged( + @Nullable String profileId, @NonNull List<ParameterCapability> updatedCaps) { } } @@ -1053,33 +1105,19 @@ public final class MediaQualityManager { * is no associated profile * @param updatedCaps the updated capabilities. */ - public void onParamCapabilitiesChanged( - @Nullable String profileId, @NonNull List<ParamCapability> updatedCaps) { + public void onParameterCapabilitiesChanged( + @Nullable String profileId, @NonNull List<ParameterCapability> updatedCaps) { } } /** * Callback used to monitor status of ambient backlight. */ - public abstract static class AmbientBacklightCallback { + public interface AmbientBacklightCallback { /** * Called when new ambient backlight event is emitted. */ - public void onAmbientBacklightEvent(@NonNull AmbientBacklightEvent event) { - } - } - - /** - * Listener used to monitor status of active pictures. - */ - public interface ActiveProcessingPictureListener { - /** - * Called when active pictures are changed. - * - * @param activeProcessingPictures contents currently undergoing picture processing. - */ - void onActiveProcessingPicturesChanged( - @NonNull List<ActiveProcessingPicture> activeProcessingPictures); + void onAmbientBacklightEvent(@NonNull AmbientBacklightEvent event); } /** @@ -1087,7 +1125,7 @@ public final class MediaQualityManager { */ public void addActiveProcessingPictureListener( @CallbackExecutor @NonNull Executor executor, - @NonNull ActiveProcessingPictureListener listener) { + @NonNull Consumer<List<ActiveProcessingPicture>> listener) { Preconditions.checkNotNull(listener); Preconditions.checkNotNull(executor); synchronized (mLock) { @@ -1106,7 +1144,7 @@ public final class MediaQualityManager { @RequiresPermission(android.Manifest.permission.MANAGE_GLOBAL_PICTURE_QUALITY_SERVICE) public void addGlobalActiveProcessingPictureListener( @NonNull Executor executor, - @NonNull ActiveProcessingPictureListener listener) { + @NonNull Consumer<List<ActiveProcessingPicture>> listener) { Preconditions.checkNotNull(listener); Preconditions.checkNotNull(executor); synchronized (mLock) { @@ -1120,7 +1158,7 @@ public final class MediaQualityManager { * Removes an active picture listener for the contents. */ public void removeActiveProcessingPictureListener( - @NonNull ActiveProcessingPictureListener listener) { + @NonNull Consumer<List<ActiveProcessingPicture>> listener) { Preconditions.checkNotNull(listener); synchronized (mLock) { for (Iterator<ActiveProcessingPictureListenerRecord> it = mApListenerRecords.iterator(); @@ -1135,19 +1173,107 @@ public final class MediaQualityManager { } private static final class ActiveProcessingPictureListenerRecord { - private final ActiveProcessingPictureListener mListener; + private final Consumer<List<ActiveProcessingPicture>> mListener; private final Executor mExecutor; private final boolean mIsGlobal; ActiveProcessingPictureListenerRecord( - ActiveProcessingPictureListener listener, Executor executor, boolean isGlobal) { + Consumer<List<ActiveProcessingPicture>> listener, + Executor executor, + boolean isGlobal) { mListener = listener; mExecutor = executor; mIsGlobal = isGlobal; } - public ActiveProcessingPictureListener getListener() { + public Consumer<List<ActiveProcessingPicture>> getListener() { return mListener; } } + + /** + * Options for profile queries. + */ + public static final class ProfileQueryParams implements Parcelable { + + private final boolean mParametersIncluded; + private static final ProfileQueryParams DEFAULT = new Builder().build(); + + private ProfileQueryParams(Parcel in) { + mParametersIncluded = in.readBoolean(); + } + + /** @hide */ + public ProfileQueryParams(boolean parametersIncluded) { + mParametersIncluded = parametersIncluded; + } + + @NonNull + public static final Creator<ProfileQueryParams> CREATOR = + new Creator<ProfileQueryParams>() { + @Override + public ProfileQueryParams createFromParcel(Parcel in) { + return new ProfileQueryParams(in); + } + + @Override + public ProfileQueryParams[] newArray(int size) { + return new ProfileQueryParams[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeBoolean(mParametersIncluded); + } + + /** + * Returns {@code true} if the parameters need to be included in query results. + * {@code false} otherwise. + */ + public boolean areParametersIncluded() { + return mParametersIncluded; + } + + private Bundle toBundle() { + Bundle bundle = new Bundle(); + bundle.putBoolean(OPTION_INCLUDE_PARAMETERS, mParametersIncluded); + return bundle; + } + + /** + * A builder for {@link ProfileQueryParams}. + */ + public static final class Builder { + private boolean mParametersIncluded; + + /** + * Sets the query option to include parameters in the profile or not. + * + * <p>The default value is {@code false}. + * + * @see ProfileQueryParams#areParametersIncluded() + */ + @SuppressLint("MissingGetterMatchingBuilder") + @NonNull + public Builder setParametersIncluded(boolean included) { + mParametersIncluded = included; + return this; + } + + + /** + * Builds the instance. + */ + @NonNull + public ProfileQueryParams build() { + return new ProfileQueryParams(mParametersIncluded); + } + } + } } diff --git a/media/java/android/media/quality/ParamCapability.aidl b/media/java/android/media/quality/ParameterCapability.aidl index b43409d039f2..eb2ac97916f3 100644 --- a/media/java/android/media/quality/ParamCapability.aidl +++ b/media/java/android/media/quality/ParameterCapability.aidl @@ -16,4 +16,4 @@ package android.media.quality; -parcelable ParamCapability; +parcelable ParameterCapability; diff --git a/media/java/android/media/quality/ParamCapability.java b/media/java/android/media/quality/ParameterCapability.java index ed11abd28379..7a28a3657cfd 100644 --- a/media/java/android/media/quality/ParamCapability.java +++ b/media/java/android/media/quality/ParameterCapability.java @@ -33,17 +33,23 @@ import java.lang.annotation.RetentionPolicy; * Capability info of media quality parameters */ @FlaggedApi(Flags.FLAG_MEDIA_QUALITY_FW) -public final class ParamCapability implements Parcelable { +public final class ParameterCapability implements Parcelable { /** @hide */ @IntDef(flag = true, prefix = { "TYPE_" }, value = { + TYPE_NONE, TYPE_INT, TYPE_LONG, TYPE_DOUBLE, TYPE_STRING, }) @Retention(RetentionPolicy.SOURCE) - public @interface ParamType {} + public @interface ParameterType {} + + /** + * None parameter type. It's used when a parameter is not supported. + */ + public static final int TYPE_NONE = 0; /** * Integer parameter type @@ -98,13 +104,13 @@ public final class ParamCapability implements Parcelable { @NonNull private final String mName; private final boolean mIsSupported; - @ParamType + @ParameterType private final int mType; @NonNull private final Bundle mCaps; /** @hide */ - protected ParamCapability(Parcel in) { + protected ParameterCapability(Parcel in) { mName = in.readString(); mIsSupported = in.readBoolean(); mType = in.readInt(); @@ -125,25 +131,25 @@ public final class ParamCapability implements Parcelable { } @NonNull - public static final Creator<ParamCapability> CREATOR = new Creator<ParamCapability>() { + public static final Creator<ParameterCapability> CREATOR = new Creator<ParameterCapability>() { @Override - public ParamCapability createFromParcel(Parcel in) { - return new ParamCapability(in); + public ParameterCapability createFromParcel(Parcel in) { + return new ParameterCapability(in); } @Override - public ParamCapability[] newArray(int size) { - return new ParamCapability[size]; + public ParameterCapability[] newArray(int size) { + return new ParameterCapability[size]; } }; /** - * Creates a new ParamCapability. + * Creates a new ParameterCapability. * * @hide */ - public ParamCapability( + public ParameterCapability( @NonNull String name, boolean isSupported, int type, @@ -158,7 +164,7 @@ public final class ParamCapability implements Parcelable { * Gets parameter name. */ @NonNull - public String getParamName() { + public String getParameterName() { return mName; } @@ -171,9 +177,11 @@ public final class ParamCapability implements Parcelable { /** * Gets parameter type. + * + * <p>It's {@link #TYPE_NONE} if {@link #isSupported()} is {@code false}. */ - @ParamType - public int getParamType() { + @ParameterType + public int getParameterType() { return mType; } diff --git a/media/java/android/media/quality/PictureProfile.java b/media/java/android/media/quality/PictureProfile.java index 6064485c1c38..8a585efe032c 100644 --- a/media/java/android/media/quality/PictureProfile.java +++ b/media/java/android/media/quality/PictureProfile.java @@ -181,7 +181,7 @@ public final class PictureProfile implements Parcelable { * Gets profile ID. * * <p>A profile ID is a globally unique ID generated and assigned by the system. For profile - * objects retrieved from system (e.g {@link MediaQualityManager#getAvailablePictureProfiles()}) + * objects retrieved from system (e.g {@link MediaQualityManager#getAvailablePictureProfiles}) * this profile ID is non-null; For profiles built locally with {@link Builder}, it's * {@code null}. * @@ -249,6 +249,8 @@ public final class PictureProfile implements Parcelable { * * <p>The keys of commonly used parameters can be found in * {@link MediaQualityContract.PictureQuality}. + * + * @return The profile parameters. Empty bundle if parameters are not included in a query. */ @NonNull public PersistableBundle getParameters() { diff --git a/media/java/android/media/quality/SoundProfile.java b/media/java/android/media/quality/SoundProfile.java index 1dd59ab0903b..971aa6f49f93 100644 --- a/media/java/android/media/quality/SoundProfile.java +++ b/media/java/android/media/quality/SoundProfile.java @@ -50,6 +50,7 @@ public final class SoundProfile implements Parcelable { private final PersistableBundle mParams; private final SoundProfileHandle mHandle; + /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(flag = false, prefix = "TYPE_", value = { @@ -180,7 +181,7 @@ public final class SoundProfile implements Parcelable { * Gets profile ID. * * <p>A profile ID is a globally unique ID generated and assigned by the system. For profile - * objects retrieved from system (e.g {@link MediaQualityManager#getAvailableSoundProfiles()}) + * objects retrieved from system (e.g {@link MediaQualityManager#getAvailableSoundProfiles}) * this profile ID is non-null; For profiles built locally with {@link Builder}, it's * {@code null}. * @@ -248,6 +249,8 @@ public final class SoundProfile implements Parcelable { * * <p>The keys of commonly used parameters can be found in * {@link MediaQualityContract.SoundQuality}. + * + * @return The profile parameters. Empty bundle if parameters are not included in a query. */ @NonNull public PersistableBundle getParameters() { diff --git a/media/java/android/media/tv/TvInputServiceExtensionManager.java b/media/java/android/media/tv/TvInputServiceExtensionManager.java index b876bcf8cd7e..d33ac9256a21 100644 --- a/media/java/android/media/tv/TvInputServiceExtensionManager.java +++ b/media/java/android/media/tv/TvInputServiceExtensionManager.java @@ -22,7 +22,6 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.StringDef; -import android.annotation.SystemApi; import android.media.tv.flags.Flags; import android.os.IBinder; import android.os.RemoteException; @@ -45,7 +44,6 @@ import java.util.Set; * * @hide */ -@SystemApi @FlaggedApi(Flags.FLAG_TIF_EXTENSION_STANDARDIZATION) public final class TvInputServiceExtensionManager { private static final String TAG = "TvInputServiceExtensionManager"; @@ -65,7 +63,6 @@ public final class TvInputServiceExtensionManager { private static final String ANALOG_PACKAGE = "android.media.tv.extension.analog."; private static final String TUNE_PACKAGE = "android.media.tv.extension.tune."; - /** @hide */ @IntDef(prefix = {"REGISTER_"}, value = { REGISTER_SUCCESS, REGISTER_FAIL_NAME_NOT_STANDARDIZED, @@ -93,7 +90,6 @@ public final class TvInputServiceExtensionManager { */ public static final int REGISTER_FAIL_REMOTE_EXCEPTION = 3; - /** @hide */ @StringDef({ ISCAN_INTERFACE, ISCAN_SESSION, @@ -685,8 +681,6 @@ public final class TvInputServiceExtensionManager { /** * Function to return available extension interface names - * - * @hide */ public static @NonNull List<String> getStandardExtensionInterfaceNames() { return new ArrayList<>(sTisExtensions); @@ -711,10 +705,7 @@ public final class TvInputServiceExtensionManager { * {@link #REGISTER_FAIL_IMPLEMENTATION_NOT_STANDARDIZED} on failure due to IBinder not * implementing standardized AIDL interface * {@link #REGISTER_FAIL_REMOTE_EXCEPTION} on failure due to remote exception - * - * @hide */ - @SystemApi @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE) @RegisterResult public int registerExtensionIBinder(@StandardizedExtensionName @NonNull String extensionName, diff --git a/packages/CompanionDeviceManager/res/anim/progress_indeterminate_horizontal_rect1.xml b/packages/CompanionDeviceManager/res/anim/progress_indeterminate_horizontal_rect1.xml new file mode 100644 index 000000000000..a9fd55f77a9c --- /dev/null +++ b/packages/CompanionDeviceManager/res/anim/progress_indeterminate_horizontal_rect1.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<set xmlns:android="http://schemas.android.com/apk/res/android" > + <objectAnimator + android:duration="2000" + android:propertyXName="translateX" + android:pathData="M -522.59998,0 c 48.89972,0 166.02656,0 301.21729,0 c 197.58128,0 420.9827,0 420.9827,0 " + android:interpolator="@interpolator/progress_indeterminate_horizontal_rect1_translatex" + android:repeatCount="infinite" /> + <objectAnimator + android:duration="2000" + android:propertyYName="scaleX" + android:pathData="M 0 0.1 L 1 0.826849212646 L 2 0.1" + android:interpolator="@interpolator/progress_indeterminate_horizontal_rect1_scalex" + android:repeatCount="infinite" /> +</set>
\ No newline at end of file diff --git a/packages/CompanionDeviceManager/res/anim/progress_indeterminate_horizontal_rect2.xml b/packages/CompanionDeviceManager/res/anim/progress_indeterminate_horizontal_rect2.xml new file mode 100644 index 000000000000..7b5b6a93473d --- /dev/null +++ b/packages/CompanionDeviceManager/res/anim/progress_indeterminate_horizontal_rect2.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<set xmlns:android="http://schemas.android.com/apk/res/android" > + <objectAnimator + android:duration="2000" + android:propertyXName="translateX" + android:pathData="M -197.60001,0 c 14.28182,0 85.07782,0 135.54689,0 c 54.26191,0 90.42461,0 168.24331,0 c 144.72154,0 316.40982,0 316.40982,0 " + android:interpolator="@interpolator/progress_indeterminate_horizontal_rect2_translatex" + android:repeatCount="infinite" /> + <objectAnimator + android:duration="2000" + android:propertyYName="scaleX" + android:pathData="M 0.0,0.1 L 1.0,0.571379510698 L 2.0,0.909950256348 L 3.0,0.1" + android:interpolator="@interpolator/progress_indeterminate_horizontal_rect2_scalex" + android:repeatCount="infinite" /> +</set>
\ No newline at end of file diff --git a/packages/CompanionDeviceManager/res/drawable/indeterminate_progress_drawable.xml b/packages/CompanionDeviceManager/res/drawable/indeterminate_progress_drawable.xml new file mode 100644 index 000000000000..1029590796c1 --- /dev/null +++ b/packages/CompanionDeviceManager/res/drawable/indeterminate_progress_drawable.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" + android:drawable="@drawable/indeterminate_progress_vector" > + <target + android:name="rect2_grp" + android:animation="@anim/progress_indeterminate_horizontal_rect2" /> + <target + android:name="rect1_grp" + android:animation="@anim/progress_indeterminate_horizontal_rect1" /> +</animated-vector>
\ No newline at end of file diff --git a/packages/CompanionDeviceManager/res/drawable/indeterminate_progress_vector.xml b/packages/CompanionDeviceManager/res/drawable/indeterminate_progress_vector.xml new file mode 100644 index 000000000000..4db3356176e7 --- /dev/null +++ b/packages/CompanionDeviceManager/res/drawable/indeterminate_progress_vector.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:height="10dp" + android:width="360dp" + android:viewportHeight="10" + android:viewportWidth="360" > + <group + android:name="progress_group" + android:translateX="180" + android:translateY="5" > + <path + android:name="background_track" + android:pathData="M -180.0,-5.0 l 360.0,0 l 0,10.0 l -360.0,0 Z" + android:fillColor="@color/progress_bg" /> + <group + android:name="rect2_grp" + android:translateX="-197.60001" + android:scaleX="0.1" > + <path + android:name="rect2" + android:pathData="M -144.0,-5.0 l 288.0,0 l 0,10.0 l -288.0,0 Z" + android:fillColor="@color/progress_fg" /> + </group> + <group + android:name="rect1_grp" + android:translateX="-522.59998" + android:scaleX="0.1" > + <path + android:name="rect1" + android:pathData="M -144.0,-5.0 l 288.0,0 l 0,10.0 l -288.0,0 Z" + android:fillColor="@color/progress_fg" /> + </group> + </group> +</vector>
\ No newline at end of file diff --git a/packages/CompanionDeviceManager/res/interpolator/progress_indeterminate_horizontal_rect1_scalex.xml b/packages/CompanionDeviceManager/res/interpolator/progress_indeterminate_horizontal_rect1_scalex.xml new file mode 100644 index 000000000000..453e0928a2b6 --- /dev/null +++ b/packages/CompanionDeviceManager/res/interpolator/progress_indeterminate_horizontal_rect1_scalex.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0 0 L 0.3665 0 C 0.47252618112021,0.062409910275 0.61541608570164,0.5 0.68325,0.5 C 0.75475061236836,0.5 0.75725829093844,0.814510098964 1.0,1.0" /> diff --git a/packages/CompanionDeviceManager/res/interpolator/progress_indeterminate_horizontal_rect1_translatex.xml b/packages/CompanionDeviceManager/res/interpolator/progress_indeterminate_horizontal_rect1_translatex.xml new file mode 100644 index 000000000000..a6da0eb77fc5 --- /dev/null +++ b/packages/CompanionDeviceManager/res/interpolator/progress_indeterminate_horizontal_rect1_translatex.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0.0,0.0 L 0.2 0 C 0.3958333333336,0.0 0.474845090492,0.206797621729 0.5916666666664,0.417082932942 C 0.7151610251224,0.639379624869 0.81625,0.974556908664 1.0,1.0 " /> diff --git a/packages/CompanionDeviceManager/res/interpolator/progress_indeterminate_horizontal_rect2_scalex.xml b/packages/CompanionDeviceManager/res/interpolator/progress_indeterminate_horizontal_rect2_scalex.xml new file mode 100644 index 000000000000..785d7abfe51d --- /dev/null +++ b/packages/CompanionDeviceManager/res/interpolator/progress_indeterminate_horizontal_rect2_scalex.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0,0 C 0.06834272400867,0.01992566661414 0.19220331656133,0.15855429260523 0.33333333333333,0.34926160892842 C 0.38410433133433,0.41477913453861 0.54945792615267,0.68136029463551 0.66666666666667,0.68279962777002 C 0.752586273196,0.68179620963216 0.737253971954,0.878896194318 1,1" /> diff --git a/packages/CompanionDeviceManager/res/interpolator/progress_indeterminate_horizontal_rect2_translatex.xml b/packages/CompanionDeviceManager/res/interpolator/progress_indeterminate_horizontal_rect2_translatex.xml new file mode 100644 index 000000000000..931dff1c3236 --- /dev/null +++ b/packages/CompanionDeviceManager/res/interpolator/progress_indeterminate_horizontal_rect2_translatex.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android" + android:pathData="M 0.0,0.0 C 0.0375,0.0 0.128764607715,0.0895380946618 0.25,0.218553507947 C 0.322410320025,0.295610602487 0.436666666667,0.417591408114 0.483333333333,0.489826169306 C 0.69,0.80972296795 0.793333333333,0.950016125212 1.0,1.0 " /> diff --git a/packages/CompanionDeviceManager/res/layout/activity_confirmation.xml b/packages/CompanionDeviceManager/res/layout/activity_confirmation.xml index 5805332418d0..afece5fac0fb 100644 --- a/packages/CompanionDeviceManager/res/layout/activity_confirmation.xml +++ b/packages/CompanionDeviceManager/res/layout/activity_confirmation.xml @@ -71,6 +71,13 @@ android:layout_height="wrap_content" android:visibility="gone"> + <TextView + android:id="@+id/timeout_message" + android:layout_width="match_parent" + android:layout_height="100dp" + android:visibility="gone" + style="@style/TimeoutMessage" /> + <androidx.recyclerview.widget.RecyclerView android:id="@+id/device_list" android:layout_width="match_parent" @@ -87,9 +94,9 @@ app:layout_constraintHeight_max="220dp" android:visibility="gone" /> - <View - android:id="@+id/border_top" - style="@style/DeviceListBorder" /> + <ProgressBar + android:id="@+id/progress_bar" + style="@style/HorizontalProgressBar" /> <View android:id="@+id/border_bottom" @@ -98,10 +105,6 @@ </androidx.constraintlayout.widget.ConstraintLayout> - <ProgressBar - android:id="@+id/spinner_multiple_device" - android:visibility="gone" - style="@style/Spinner" /> </RelativeLayout> @@ -135,7 +138,8 @@ android:layout_marginEnd="16dp" android:layout_marginBottom="16dp"> - <!-- Do NOT change the IDs of the buttons: they are referenced in CTS tests. --> + <!-- Do NOT change the IDs of the buttons: they are referenced in CTS tests. + Legacy name before the change that added single-device dialog.--> <LinearLayout android:id="@+id/negative_multiple_devices_layout" android:layout_width="wrap_content" @@ -159,18 +163,6 @@ </LinearLayout> - <RelativeLayout - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_weight="1" - android:importantForAccessibility="noHideDescendants"> - - <ProgressBar - android:id="@+id/spinner_single_device" - android:visibility="gone" - style="@style/Spinner" /> - </RelativeLayout>> - </LinearLayout> </ScrollView>
\ No newline at end of file diff --git a/packages/CompanionDeviceManager/res/values/colors.xml b/packages/CompanionDeviceManager/res/values/colors.xml new file mode 100644 index 000000000000..8782250f3bba --- /dev/null +++ b/packages/CompanionDeviceManager/res/values/colors.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2024 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> +<resources> + <color name="border">@android:color/system_neutral1_200</color> + <color name="progress_bg">@android:color/system_neutral1_600</color> + <color name="progress_fg">@android:color/system_neutral1_0</color> +</resources> diff --git a/packages/CompanionDeviceManager/res/values/strings.xml b/packages/CompanionDeviceManager/res/values/strings.xml index 2a6d68d1ee35..20ede5ff91d3 100644 --- a/packages/CompanionDeviceManager/res/values/strings.xml +++ b/packages/CompanionDeviceManager/res/values/strings.xml @@ -22,6 +22,21 @@ <!-- Title of the device association confirmation dialog. --> <string name="confirmation_title">Allow the app <strong><xliff:g id="app_name" example="Android Wear">%1$s</xliff:g></strong> to access <strong><xliff:g id="device_name" example="ASUS ZenWatch 2">%2$s</xliff:g></strong>?</string> + <!-- Description of soft discovery timeout. [CHAR LIMIT= NONE] --> + <string name="message_discovery_soft_timeout">Make sure this <xliff:g id="device_type" example="phone">%1$s</xliff:g> has <xliff:g id="discovery_method" example="Bluetooth">%2$s</xliff:g> turned on, and keep your <xliff:g id="profile_name" example="watch">%3$s</xliff:g> nearby.</string> + + <!-- Description of hard discovery timeout. [CHAR LIMIT= NONE] --> + <string name="message_discovery_hard_timeout">No devices found. Please try again later.</string> + + <!-- The discovery method name for Bluetooth [CHAR LIMIT=30] --> + <string name="discovery_bluetooth">Bluetooth</string> + + <!-- The discovery method name for Wi-Fi [CHAR LIMIT=30] --> + <string name="discovery_wifi">Wi-Fi</string> + + <!-- The discovery method name for both Bluetooth and Wi-Fi [CHAR LIMIT=50] --> + <string name="discovery_mixed">Bluetooth and Wi-Fi</string> + <!-- ================= DEVICE_PROFILE_WATCH and null profile ================= --> <!-- The name of the "watch" device type [CHAR LIMIT=30] --> @@ -30,9 +45,12 @@ <!-- Title of the device selection dialog. --> <string name="chooser_title_non_profile">Choose a device to be managed by <strong><xliff:g id="app_name" example="Android Wear">%1$s</xliff:g></strong></string> - <!-- Tile of the multiple devices' dialog. --> + <!-- Title of the multiple devices' dialog. --> <string name="chooser_title">Choose a <xliff:g id="profile_name" example="watch">%1$s</xliff:g> to set up</string> + <!-- Title of the single device scan dialog. --> + <string name="single_device_title">Looking for a <xliff:g id="profile_name" example="watch">%1$s</xliff:g></string> + <!-- Description of the privileges the application will get if associated with the companion device of WATCH profile [CHAR LIMIT=NONE] --> <string name="summary_watch">This app will be allowed to sync info, like the name of someone calling, and access these permissions on your <xliff:g id="device_type" example="phone">%1$s</xliff:g></string> diff --git a/packages/CompanionDeviceManager/res/values/styles.xml b/packages/CompanionDeviceManager/res/values/styles.xml index a161a505a0ac..30813baa6e4a 100644 --- a/packages/CompanionDeviceManager/res/values/styles.xml +++ b/packages/CompanionDeviceManager/res/values/styles.xml @@ -59,6 +59,43 @@ <item name="android:textColor">?android:attr/textColorSecondary</item> </style> + <style name="HorizontalProgressBar" + parent="@android:style/Widget.Material.ProgressBar.Horizontal"> + <item name="android:layout_width">match_parent</item> + <item name="android:layout_height">1dp</item> + <item name="android:layout_marginStart">32dp</item> + <item name="android:layout_marginEnd">32dp</item> + <item name="android:progress">100</item> + <item name="android:indeterminate">true</item> + <item name="android:indeterminateOnly">false</item> + <item name="android:progressTint">@color/border</item> + <item name="android:indeterminateDrawable">@drawable/indeterminate_progress_drawable</item> + </style> + + <style name="DeviceListBorder"> + <item name="android:layout_width">match_parent</item> + <item name="android:layout_height">1dp</item> + <item name="android:layout_marginStart">32dp</item> + <item name="android:layout_marginEnd">32dp</item> + <item name="android:background">@color/border</item> + </style> + + <style name="TimeoutMessage" + parent="@android:style/TextAppearance.DeviceDefault.Medium"> + <item name="android:layout_width">match_parent</item> + <item name="android:layout_height">wrap_content</item> + <item name="android:layout_marginStart">32dp</item> + <item name="android:layout_marginEnd">32dp</item> + <item name="android:paddingEnd">8dp</item> + <item name="android:paddingStart">8dp</item> + <item name="android:paddingTop">18dp</item> + <item name="android:paddingBottom">18dp</item> + <item name="android:textDirection">locale</item> + <item name="android:textSize">14sp</item> + <item name="android:lineSpacingExtra">2dp</item> + <item name="android:textColor">?android:attr/textColorSecondary</item> + </style> + <style name="VendorHelperBackButton" parent="@android:style/Widget.Material.Button.Borderless.Colored"> <item name="android:layout_width">wrap_content</item> @@ -111,22 +148,6 @@ <item name="android:textAppearance">@android:style/TextAppearance.DeviceDefault.Medium</item> </style> - <style name="DeviceListBorder"> - <item name="android:layout_width">match_parent</item> - <item name="android:layout_height">1dp</item> - <item name="android:layout_marginStart">32dp</item> - <item name="android:layout_marginEnd">32dp</item> - <item name="android:background">@android:color/system_neutral1_200</item> - </style> - - <style name="Spinner" - parent="@android:style/Widget.Material.Light.ProgressBar.Large"> - <item name="android:layout_width">56dp</item> - <item name="android:layout_height">56dp</item> - <item name="android:indeterminate">true</item> - <item name="android:layout_centerInParent">true</item> - </style> - <style name="ScrollViewStyle"> <item name="android:scrollbars">none</item> <item name="android:fillViewport">true</item> diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionAssociationActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionAssociationActivity.java index 50419f7368be..ea40e13fdcc9 100644 --- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionAssociationActivity.java +++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionAssociationActivity.java @@ -17,14 +17,12 @@ package com.android.companiondevicemanager; import static android.companion.CompanionDeviceManager.RESULT_CANCELED; -import static android.companion.CompanionDeviceManager.RESULT_DISCOVERY_TIMEOUT; import static android.companion.CompanionDeviceManager.RESULT_INTERNAL_ERROR; import static android.companion.CompanionDeviceManager.RESULT_SECURITY_ERROR; import static android.companion.CompanionDeviceManager.RESULT_USER_REJECTED; import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import static com.android.companiondevicemanager.CompanionDeviceDiscoveryService.DiscoveryState; -import static com.android.companiondevicemanager.CompanionDeviceDiscoveryService.DiscoveryState.FINISHED_TIMEOUT; import static com.android.companiondevicemanager.CompanionDeviceDiscoveryService.LOCK; import static com.android.companiondevicemanager.CompanionDeviceDiscoveryService.sDiscoveryStarted; import static com.android.companiondevicemanager.CompanionDeviceResources.PROFILE_ICONS; @@ -48,11 +46,13 @@ import static java.util.Objects.requireNonNull; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.StringRes; import android.annotation.SuppressLint; import android.companion.AssociatedDevice; import android.companion.AssociationInfo; import android.companion.AssociationRequest; import android.companion.CompanionDeviceManager; +import android.companion.DeviceFilter; import android.companion.Flags; import android.companion.IAssociationRequestCallback; import android.content.Intent; @@ -139,22 +139,19 @@ public class CompanionAssociationActivity extends FragmentActivity implements private TextView mVendorHeaderName; private ImageButton mVendorHeaderButton; - // Progress indicator is only shown while we are looking for the first suitable device for a - // multiple device association. - private ProgressBar mMultipleDeviceSpinner; - // Progress indicator is only shown while we are looking for the first suitable device for a - // single device association. - private ProgressBar mSingleDeviceSpinner; + // Message to be displayed when device hasn't been discovered for a certain duration + private TextView mTimeoutMessage; + + // Horizontal progress indicator is always shown as long as the scanner is searching for devices + private ProgressBar mProgressBar; // Present for self-managed association requests and "single-device" regular association // regular. private Button mButtonAllow; private Button mButtonNotAllow; - // Present for multiple devices' association requests only. - private Button mButtonNotAllowMultipleDevices; + private Button mButtonCancelScan; - // Present for top and bottom borders for permissions list and device list. - private View mBorderTop; + // Bottom border for permissions list and device list. The progress bar acts as the top border. private View mBorderBottom; private LinearLayout mAssociationConfirmationDialog; @@ -162,9 +159,9 @@ public class CompanionAssociationActivity extends FragmentActivity implements private ConstraintLayout mConstraintList; // Only present for self-managed association requests. private RelativeLayout mVendorHeader; - // A linearLayout for mButtonNotAllowMultipleDevices, user will press this layout instead + // A linearLayout for mButtonCancelScan, user will press this layout instead // of the button for accessibility. - private LinearLayout mNotAllowMultipleDevicesLayout; + private LinearLayout mCancelScanLayout; // The recycler view is only shown for multiple-device regular association request, after // at least one matching device is found. @@ -297,7 +294,6 @@ public class CompanionAssociationActivity extends FragmentActivity implements mAssociationConfirmationDialog = findViewById(R.id.association_confirmation); mVendorHeader = findViewById(R.id.vendor_header); - mBorderTop = findViewById(R.id.border_top); mBorderBottom = findViewById(R.id.border_bottom); mTitle = findViewById(R.id.title); @@ -311,43 +307,90 @@ public class CompanionAssociationActivity extends FragmentActivity implements mDeviceIcon = findViewById(R.id.device_icon); + mTimeoutMessage = findViewById(R.id.timeout_message); mDeviceListRecyclerView = findViewById(R.id.device_list); - mMultipleDeviceSpinner = findViewById(R.id.spinner_multiple_device); - mSingleDeviceSpinner = findViewById(R.id.spinner_single_device); + mProgressBar = findViewById(R.id.progress_bar); + mProgressBar.getIndeterminateDrawable().clearColorFilter(); mPermissionListRecyclerView = findViewById(R.id.permission_list); mPermissionListAdapter = new PermissionListAdapter(this); mButtonAllow = findViewById(R.id.btn_positive); mButtonNotAllow = findViewById(R.id.btn_negative); - mButtonNotAllowMultipleDevices = findViewById(R.id.btn_negative_multiple_devices); - mNotAllowMultipleDevicesLayout = findViewById(R.id.negative_multiple_devices_layout); + mButtonCancelScan = findViewById(R.id.btn_negative_multiple_devices); + mCancelScanLayout = findViewById(R.id.negative_multiple_devices_layout); mButtonAllow.setOnClickListener(this::onPositiveButtonClick); mButtonNotAllow.setOnClickListener(this::onNegativeButtonClick); - mNotAllowMultipleDevicesLayout.setOnClickListener(this::onNegativeButtonClick); + mCancelScanLayout.setOnClickListener(this::onNegativeButtonClick); mVendorHeaderButton.setOnClickListener(this::onShowHelperDialog); if (mRequest.isSelfManaged()) { initUiForSelfManagedAssociation(); - } else if (mRequest.isSingleDevice()) { - initUiForSingleDevice(); } else { - initUiForMultipleDevices(); + initUiForDeviceDiscovery(); } } private void onDiscoveryStateChanged(DiscoveryState newState) { - if (newState == FINISHED_TIMEOUT - && CompanionDeviceDiscoveryService.getScanResult().getValue().isEmpty()) { - synchronized (LOCK) { - if (sDiscoveryStarted) { - cancel(RESULT_DISCOVERY_TIMEOUT, null); + switch (newState) { + case IN_PROGRESS: { + mTimeoutMessage.setText(null); + mProgressBar.setIndeterminate(true); + break; + } + case IN_PROGRESS_EXTENDED: { + final String deviceType = getString(R.string.device_type); + final String discoveryType = getString(getDiscoveryMethod()); + final String profile = getString(PROFILE_NAMES.get(mRequest.getDeviceProfile())); + final Spanned message = getHtmlFromResources(this, + R.string.message_discovery_soft_timeout, + deviceType, discoveryType, profile); + mTimeoutMessage.setText(message); + break; + } + case FINISHED_STOPPED: { + if (CompanionDeviceDiscoveryService.getScanResult().getValue().isEmpty()) { + // If the scan times out, do NOT close the activity automatically and let the + // user manually cancel the flow. + synchronized (LOCK) { + if (sDiscoveryStarted) { + stopDiscovery(); + } + } + mTimeoutMessage.setText(getString(R.string.message_discovery_hard_timeout)); } + mProgressBar.setIndeterminate(false); + break; + } + } + } + + @StringRes + private int getDiscoveryMethod() { + // If no filter was given or at least one bluetooth filter was provided, then + // display message for Bluetooth. + // If filter is _only_ for Wi-Fi devices, then display message for Wi-Fi. + // e.g. "Make sure Bluetooth is on" vs "Make sure Wi-Fi is on" + boolean hasBluetooth = false; + boolean hasWifi = false; + for (DeviceFilter<?> filter : mRequest.getDeviceFilters()) { + if (filter.getMediumType() == DeviceFilter.MEDIUM_TYPE_BLUETOOTH + || filter.getMediumType() == DeviceFilter.MEDIUM_TYPE_BLUETOOTH_LE) { + hasBluetooth = true; + } else if (filter.getMediumType() == DeviceFilter.MEDIUM_TYPE_WIFI) { + hasWifi = true; } } + if (hasBluetooth == hasWifi) { + return R.string.discovery_mixed; + } else if (hasBluetooth) { + return R.string.discovery_bluetooth; + } else { + return R.string.discovery_wifi; + } } private void onUserSelectedDevice(@NonNull DeviceFilterPair<?> selectedDevice) { @@ -392,9 +435,7 @@ public class CompanionAssociationActivity extends FragmentActivity implements mCancelled = true; // Stop discovery service if it was used. - if (!mRequest.isSelfManaged()) { - CompanionDeviceDiscoveryService.stop(this); - } + stopDiscovery(); // First send callback to the app directly... try { @@ -408,6 +449,12 @@ public class CompanionAssociationActivity extends FragmentActivity implements setResultAndFinish(null, errorCode); } + private void stopDiscovery() { + if (!mRequest.isSelfManaged()) { + CompanionDeviceDiscoveryService.stop(this); + } + } + private void setResultAndFinish(@Nullable AssociationInfo association, int resultCode) { Slog.i(TAG, "setResultAndFinish(), association=" + (association == null ? "null" : association) @@ -479,41 +526,14 @@ public class CompanionAssociationActivity extends FragmentActivity implements mVendorHeader.setVisibility(View.VISIBLE); mProfileIcon.setVisibility(View.GONE); mDeviceListRecyclerView.setVisibility(View.GONE); - // Top and bottom borders should be gone for selfManaged dialog. - mBorderTop.setVisibility(View.GONE); + mProgressBar.setVisibility(View.GONE); mBorderBottom.setVisibility(View.GONE); } - private void initUiForSingleDevice() { - Slog.d(TAG, "initUiForSingleDevice()"); - - final String deviceProfile = mRequest.getDeviceProfile(); - - if (!SUPPORTED_PROFILES.contains(deviceProfile)) { - throw new RuntimeException("Unsupported profile " + deviceProfile); - } - - final Drawable profileIcon = getIcon(this, PROFILE_ICONS.get(deviceProfile)); - mProfileIcon.setImageDrawable(profileIcon); - - CompanionDeviceDiscoveryService.getScanResult().observe(this, deviceFilterPairs -> { - if (deviceFilterPairs.isEmpty()) { - return; - } - mSelectedDevice = requireNonNull(deviceFilterPairs.get(0)); - updateSingleDeviceUi(); - }); - - mSingleDeviceSpinner.setVisibility(View.VISIBLE); - // Hide permission list and confirmation dialog first before the - // first matched device is found. - mPermissionListRecyclerView.setVisibility(View.GONE); - mDeviceListRecyclerView.setVisibility(View.GONE); - mAssociationConfirmationDialog.setVisibility(View.GONE); - } - - private void initUiForMultipleDevices() { - Slog.d(TAG, "initUiForMultipleDevices()"); + private void initUiForDeviceDiscovery() { + Slog.d(TAG, "initUiForDeviceDiscovery() " + + "single-device=" + mRequest.isSingleDevice() + + ", profile=" + mRequest.getDeviceProfile()); final Drawable profileIcon; final Spanned title; @@ -525,41 +545,59 @@ public class CompanionAssociationActivity extends FragmentActivity implements profileIcon = getIcon(this, PROFILE_ICONS.get(deviceProfile)); - if (deviceProfile == null) { + if (mRequest.isSingleDevice()) { + title = getHtmlFromResources(this, + R.string.single_device_title, getString(PROFILE_NAMES.get(deviceProfile))); + } else if (deviceProfile == null) { title = getHtmlFromResources(this, R.string.chooser_title_non_profile, mAppLabel); - mButtonNotAllowMultipleDevices.setText(R.string.consent_no); } else { title = getHtmlFromResources(this, R.string.chooser_title, getString(PROFILE_NAMES.get(deviceProfile))); } - mDeviceAdapter = new DeviceListAdapter(this, this::onDeviceClicked); - mTitle.setText(title); mProfileIcon.setImageDrawable(profileIcon); - mDeviceListRecyclerView.setAdapter(mDeviceAdapter); - mDeviceListRecyclerView.setLayoutManager(new LinearLayoutManager(this)); - - CompanionDeviceDiscoveryService.getScanResult().observe(this, - deviceFilterPairs -> { - // Dismiss the progress bar once there's one device found for multiple devices. - if (deviceFilterPairs.size() >= 1) { - mMultipleDeviceSpinner.setVisibility(View.GONE); + if (mRequest.isSingleDevice()) { + mBorderBottom.setVisibility(View.GONE); + CompanionDeviceDiscoveryService.getScanResult().observe(this, deviceFilterPairs -> { + if (deviceFilterPairs.isEmpty()) { + return; + } + mSelectedDevice = requireNonNull(deviceFilterPairs.get(0)); + updateUiForAssociationConsent(); + }); + } else { + mDeviceAdapter = new DeviceListAdapter(this, this::onDeviceClicked); + mDeviceListRecyclerView.setAdapter(mDeviceAdapter); + mDeviceListRecyclerView.setLayoutManager(new LinearLayoutManager(this)); + + CompanionDeviceDiscoveryService.getScanResult().observe(this, deviceFilterPairs -> { + if (deviceFilterPairs.size() >= 1) { + // Dismiss the timeout message once there's at least one device found. + mTimeoutMessage.setText(null); + + // Update profile-less cancel scan button to read "Don't allow" to indicate + // that selecting a device implies user consent. + if (deviceProfile == null) { + mButtonCancelScan.setText(R.string.consent_no); } + } - mDeviceAdapter.setDevices(deviceFilterPairs); - }); + mDeviceAdapter.setDevices(deviceFilterPairs); + }); + + mDeviceListRecyclerView.setVisibility(View.VISIBLE); + } mSummary.setVisibility(View.GONE); - // "Remove" consent button: users would need to click on the list item. mButtonAllow.setVisibility(View.GONE); mButtonNotAllow.setVisibility(View.GONE); - mDeviceListRecyclerView.setVisibility(View.VISIBLE); - mButtonNotAllowMultipleDevices.setVisibility(View.VISIBLE); - mNotAllowMultipleDevicesLayout.setVisibility(View.VISIBLE); + + mTimeoutMessage.setVisibility(View.VISIBLE); + mButtonCancelScan.setVisibility(View.VISIBLE); + mCancelScanLayout.setVisibility(View.VISIBLE); mConstraintList.setVisibility(View.VISIBLE); - mMultipleDeviceSpinner.setVisibility(View.VISIBLE); } private void onDeviceClicked(int position) { @@ -586,15 +624,10 @@ public class CompanionAssociationActivity extends FragmentActivity implements } // The permission consent dialog should be displayed for the multiple device // dialog if a device profile exists. - updateSingleDeviceUi(); - mSummary.setVisibility(View.VISIBLE); - mButtonAllow.setVisibility(View.VISIBLE); - mButtonNotAllow.setVisibility(View.VISIBLE); - mDeviceListRecyclerView.setVisibility(View.GONE); - mNotAllowMultipleDevicesLayout.setVisibility(View.GONE); + updateUiForAssociationConsent(); } - private void updateSingleDeviceUi() { + private void updateUiForAssociationConsent() { // No need to show permission consent dialog if it is a isSkipPrompt(true) // AssociationRequest. See AssociationRequestsProcessor#mayAssociateWithoutPrompt. if (mRequest.isSkipPrompt()) { @@ -603,9 +636,14 @@ public class CompanionAssociationActivity extends FragmentActivity implements return; } - mSingleDeviceSpinner.setVisibility(View.GONE); mAssociationConfirmationDialog.setVisibility(View.VISIBLE); + mProgressBar.setIndeterminate(false); // Keep as border but remove animation + mBorderBottom.setVisibility(View.VISIBLE); + mTimeoutMessage.setVisibility(View.GONE); + mDeviceListRecyclerView.setVisibility(View.GONE); + mCancelScanLayout.setVisibility(View.GONE); + final String deviceProfile = mRequest.getDeviceProfile(); final int summaryResourceId = PROFILE_SUMMARIES.get(deviceProfile); final String remoteDeviceName = mSelectedDevice.getDisplayName(); @@ -624,6 +662,10 @@ public class CompanionAssociationActivity extends FragmentActivity implements mTitle.setText(title); mSummary.setText(summary); + + mSummary.setVisibility(View.VISIBLE); + mButtonAllow.setVisibility(View.VISIBLE); + mButtonNotAllow.setVisibility(View.VISIBLE); } private void onPositiveButtonClick(View v) { diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java index f586e3dedf9a..50a01b3bc7c9 100644 --- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java +++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java @@ -76,7 +76,8 @@ public class CompanionDeviceDiscoveryService extends Service { private static final String TAG = "CDM_CompanionDeviceDiscoveryService"; private static final String SYS_PROP_DEBUG_TIMEOUT = "debug.cdm.discovery_timeout"; - private static final long TIMEOUT_DEFAULT = 20_000L; // 20 seconds + private static final long TIMEOUT_SOFT = 20_000L; // 20 seconds + private static final long TIMEOUT_HARD = 180_000L; // 3 minutes private static final long TIMEOUT_MIN = 1_000L; // 1 sec private static final long TIMEOUT_MAX = 60_000L; // 1 min @@ -102,7 +103,8 @@ public class CompanionDeviceDiscoveryService extends Service { private final List<DeviceFilterPair<?>> mDevicesFound = new ArrayList<>(); - private final Runnable mTimeoutRunnable = this::timeout; + private final Runnable mSoftTimeoutRunnable = this::softTimeout; + private final Runnable mHardTimeoutRunnable = this::stopDiscoveryAndFinish; private boolean mStopAfterFirstMatch; @@ -116,8 +118,8 @@ public class CompanionDeviceDiscoveryService extends Service { enum DiscoveryState { NOT_STARTED, IN_PROGRESS, + IN_PROGRESS_EXTENDED, FINISHED_STOPPED, - FINISHED_TIMEOUT } static boolean startForRequest( @@ -175,7 +177,7 @@ public class CompanionDeviceDiscoveryService extends Service { break; case ACTION_STOP_DISCOVERY: - stopDiscoveryAndFinish(/* timeout */ false); + stopDiscoveryAndFinish(); break; } return START_NOT_STICKY; @@ -223,9 +225,17 @@ public class CompanionDeviceDiscoveryService extends Service { } @MainThread - private void stopDiscoveryAndFinish(boolean timeout) { - Slog.d(TAG, "stopDiscoveryAndFinish(" + timeout + ")"); + private void softTimeout() { + // If no device is found at this point, display a message and continue discovery + if (mDevicesFound.isEmpty()) { + sStateLiveData.setValue(DiscoveryState.IN_PROGRESS_EXTENDED); + } else { + stopDiscoveryAndFinish(); + } + } + @MainThread + private void stopDiscoveryAndFinish() { synchronized (LOCK) { if (!sDiscoveryStarted) { stopSelf(); @@ -260,13 +270,10 @@ public class CompanionDeviceDiscoveryService extends Service { mBleScanner.stopScan(mBleScanCallback); } - Handler.getMain().removeCallbacks(mTimeoutRunnable); + Handler.getMain().removeCallbacks(mSoftTimeoutRunnable); + Handler.getMain().removeCallbacks(mHardTimeoutRunnable); - if (timeout) { - sStateLiveData.setValue(DiscoveryState.FINISHED_TIMEOUT); - } else { - sStateLiveData.setValue(DiscoveryState.FINISHED_STOPPED); - } + sStateLiveData.setValue(DiscoveryState.FINISHED_STOPPED); synchronized (LOCK) { sDiscoveryStarted = false; @@ -379,7 +386,7 @@ public class CompanionDeviceDiscoveryService extends Service { sScanResultsLiveData.setValue(mDevicesFound); // Stop discovery when there's one device found for singleDevice. if (mStopAfterFirstMatch) { - stopDiscoveryAndFinish(/* timeout */ false); + stopDiscoveryAndFinish(); } }); } @@ -396,20 +403,17 @@ public class CompanionDeviceDiscoveryService extends Service { } private void scheduleTimeout() { - long timeout = SystemProperties.getLong(SYS_PROP_DEBUG_TIMEOUT, -1); - if (timeout <= 0) { + long softTimeout = SystemProperties.getLong(SYS_PROP_DEBUG_TIMEOUT, -1); + if (softTimeout <= 0) { // 0 or negative values indicate that the sysprop was never set or should be ignored. - timeout = TIMEOUT_DEFAULT; + softTimeout = TIMEOUT_SOFT; } else { - timeout = min(timeout, TIMEOUT_MAX); // should be <= 1 min (TIMEOUT_MAX) - timeout = max(timeout, TIMEOUT_MIN); // should be >= 1 sec (TIMEOUT_MIN) + softTimeout = min(softTimeout, TIMEOUT_MAX); // should be <= 1 min (TIMEOUT_MAX) + softTimeout = max(softTimeout, TIMEOUT_MIN); // should be >= 1 sec (TIMEOUT_MIN) } - Handler.getMain().postDelayed(mTimeoutRunnable, timeout); - } - - private void timeout() { - stopDiscoveryAndFinish(/* timeout */ true); + Handler.getMain().postDelayed(mSoftTimeoutRunnable, softTimeout); + Handler.getMain().postDelayed(mHardTimeoutRunnable, TIMEOUT_HARD); } @Override diff --git a/packages/SettingsLib/SearchWidget/res/values-mn/strings.xml b/packages/SettingsLib/SearchWidget/res/values-mn/strings.xml index 01a7797e4829..bb9cf49607ca 100644 --- a/packages/SettingsLib/SearchWidget/res/values-mn/strings.xml +++ b/packages/SettingsLib/SearchWidget/res/values-mn/strings.xml @@ -17,5 +17,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="search_menu" msgid="1914043873178389845">"Тохиргоог хайх"</string> + <string name="search_menu" msgid="1914043873178389845">"Тохиргооноос хайх"</string> </resources> diff --git a/packages/SettingsLib/aconfig/settingslib.aconfig b/packages/SettingsLib/aconfig/settingslib.aconfig index cc996c5a2120..2f91097b04a6 100644 --- a/packages/SettingsLib/aconfig/settingslib.aconfig +++ b/packages/SettingsLib/aconfig/settingslib.aconfig @@ -9,10 +9,10 @@ flag { } flag { - name: "bluetooth_qs_tile_dialog_auto_on_toggle" - namespace: "bluetooth" - description: "Displays the auto on toggle in the bluetooth QS tile dialog" - bug: "316985153" + name: "bluetooth_qs_tile_dialog_auto_on_toggle" + namespace: "bluetooth" + description: "Displays the auto on toggle in the bluetooth QS tile dialog" + bug: "316985153" } flag { @@ -23,24 +23,24 @@ flag { } flag { - name: "enable_le_audio_sharing" - namespace: "pixel_cross_device_control" - description: "Gates whether to enable LE audio sharing" - bug: "323125723" + name: "enable_le_audio_sharing" + namespace: "pixel_cross_device_control" + description: "Gates whether to enable LE audio sharing" + bug: "323125723" } flag { - name: "enable_le_audio_qr_code_private_broadcast_sharing" - namespace: "pixel_cross_device_control" - description: "Gates whether to enable LE audio private broadcast sharing via QR code" - bug: "323125723" + name: "enable_le_audio_qr_code_private_broadcast_sharing" + namespace: "pixel_cross_device_control" + description: "Gates whether to enable LE audio private broadcast sharing via QR code" + bug: "323125723" } flag { - name: "enable_hide_exclusively_managed_bluetooth_device" - namespace: "dck_framework" - description: "Hide exclusively managed Bluetooth devices in BT settings menu." - bug: "324475542" + name: "enable_hide_exclusively_managed_bluetooth_device" + namespace: "dck_framework" + description: "Hide exclusively managed Bluetooth devices in BT settings menu." + bug: "324475542" } flag { @@ -89,7 +89,7 @@ flag { description: "the battery saver can pause all non-essential apps and their corresponding notification when device is in locked state to introduce the security vulnerability" bug: "346513692" metadata { - purpose: PURPOSE_BUGFIX + purpose: PURPOSE_BUGFIX } } @@ -113,13 +113,13 @@ flag { } flag { - name: "asha_profile_access_profile_enabled_true" - namespace: "accessibility" - description: "Changes the return value of HearingAidProfile.accessProfileEnabled() to true" - bug: "356530795" - metadata { - purpose: PURPOSE_BUGFIX - } + name: "asha_profile_access_profile_enabled_true" + namespace: "accessibility" + description: "Changes the return value of HearingAidProfile.accessProfileEnabled() to true" + bug: "356530795" + metadata { + purpose: PURPOSE_BUGFIX + } } flag { diff --git a/packages/SettingsLib/aconfig/settingslib_media_flag_declarations.aconfig b/packages/SettingsLib/aconfig/settingslib_media_flag_declarations.aconfig index 6f614b372ea6..065a61c74811 100644 --- a/packages/SettingsLib/aconfig/settingslib_media_flag_declarations.aconfig +++ b/packages/SettingsLib/aconfig/settingslib_media_flag_declarations.aconfig @@ -2,17 +2,17 @@ package: "com.android.settingslib.media.flags" container: "system" flag { - name: "use_media_router2_for_info_media_manager" - namespace: "media_solutions" - description: "Gates whether to use a MediaRouter2-based implementation of InfoMediaManager, instead of the legacy MediaRouter2Manager-based implementation." - bug: "192657812" + name: "use_media_router2_for_info_media_manager" + namespace: "media_solutions" + description: "Gates whether to use a MediaRouter2-based implementation of InfoMediaManager, instead of the legacy MediaRouter2Manager-based implementation." + bug: "192657812" } flag { - name: "enable_tv_media_output_dialog" - namespace: "tv_system_ui" - description: "Gates all the changes for the tv specific media output dialog" - bug: "303205631" + name: "enable_tv_media_output_dialog" + namespace: "tv_system_ui" + description: "Gates all the changes for the tv specific media output dialog" + bug: "303205631" } flag { diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml index 7e9e369c14af..6a169e984e37 100644 --- a/packages/SettingsLib/res/values-af/strings.xml +++ b/packages/SettingsLib/res/values-af/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktief (net links)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktief (net regs)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktief (links en regs)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Kon nie omgewing opdateer nie"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktief (net media). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktiewe (net media). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery"</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Gekoppel (steun oudiodeling). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery"</string> diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml index 616187343d0c..be2daa217b10 100644 --- a/packages/SettingsLib/res/values-am/strings.xml +++ b/packages/SettingsLib/res/values-am/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"ገቢር (ግራ ብቻ)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"ገቢር (ቀኝ ብቻ)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"ገቢር (ግራ እና ቀኝ)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"በዙሪያ ያሉትን ማዘመን አልተቻለም"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"ገቢር (ሚዲያ ብቻ)። <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ባትሪ።"</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"ገቢር (ሚዲያ ብቻ)። ግ፦ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>፣ ቀ፦ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ባትሪ።"</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"ተገናኝቷል (የድምፅ ማጋራት ይደግፋል)፣ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ባትሪ።"</string> diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml index a298294956f5..f334f99fa17f 100644 --- a/packages/SettingsLib/res/values-ar/strings.xml +++ b/packages/SettingsLib/res/values-ar/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"سماعة الأذن الطبية نشطة (اليسرى فقط)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"سماعة الأذن الطبية نشطة (اليمنى فقط)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"سماعتا الأذن الطبيتان نشطتان (اليسرى واليمنى)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"تعذَّر تعديل حالة الأصوات المحيطة"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"البلوتوث نشِط (للوسائط فقط). مستوى شحن البطارية: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"البلوتوث نشِط (للوسائط فقط)، مستوى الشحن في سماعة الرأس اليسرى: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>، مستوى الشحن في سماعة الرأس اليمنى: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"البلوتوث متصل (ميزة \"مشاركة الصوت\" متاحة). مستوى شحن البطارية: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml index addf12b6f5a0..6e676456eb59 100644 --- a/packages/SettingsLib/res/values-as/strings.xml +++ b/packages/SettingsLib/res/values-as/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"সক্ৰিয় হৈ আছে (কেৱল বাওঁফালৰটো)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"সক্ৰিয় হৈ আছে (কেৱল সোঁফালৰটো)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"সক্ৰিয় হৈ আছে (বাওঁফালৰটো আৰু সোঁফালৰটো)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"আশ-পাশ আপডে’ট কৰিব পৰা নগ’ল"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"সক্ৰিয় হৈ আছে (কেৱল মিডিয়া)। <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰী।"</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"সক্ৰিয় হৈ আছে (কেৱল মিডিয়া)। বাওঁ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, সোঁ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> বেটাৰী।"</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"সংযুক্ত হৈ আছে (অডিঅ’ শ্বেয়াৰিং সমৰ্থন কৰে), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰী।"</string> diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml index 6f97c9c19e98..b8e75827c6d7 100644 --- a/packages/SettingsLib/res/values-az/strings.xml +++ b/packages/SettingsLib/res/values-az/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktiv (yalnız sol)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktiv (yalnız sağ)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktiv (sol və sağ)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Ətraf mühit güncəllənmədi"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktiv (yalnız media). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batareya."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktiv (yalnız media). Sol: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Sağ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batareya."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Qoşulub (audio paylaşma dəstəklənir). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batareya."</string> diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml index fc55fff3e8f9..295dd8369af0 100644 --- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml +++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktivno (samo levo)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktivno (samo desno)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktivno (levo i desno)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Ažuriranje okruženja nije uspelo"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktivno (samo za medije). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktivno (samo za medije). Levo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, desno: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterije."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Povezano (podržava deljenje zvuka), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string> diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml index be86aca4da85..90ed686f32e3 100644 --- a/packages/SettingsLib/res/values-be/strings.xml +++ b/packages/SettingsLib/res/values-be/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Выкарыстоўваецца (толькі левы навушнік)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Выкарыстоўваецца (толькі правы навушнік)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Выкарыстоўваецца (левы і правы навушнікі)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Не ўдалося абнавіць стан навакольных гукаў"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Выкарыстоўваецца (толькі для мультымедыя). Зарад акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Выкарыстоўваецца (толькі для мультымедыя). Зарад акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (левы навушнік), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (правы навушнік)."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Падключана (падтрымліваецца абагульванне аўдыя). Зарад акумулятара: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml index 624c55b6bb55..d45068762aac 100644 --- a/packages/SettingsLib/res/values-bg/strings.xml +++ b/packages/SettingsLib/res/values-bg/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Активно (само лявото)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Активно (само дясното)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Активно (лявото и дясното)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Данните за околните звуци не бяха актуализирани"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Активно (само за мултимедия). Батерия – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Активно (само за мултимедия). Л: батерия – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Д: батерия – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Свързано (поддържа споделяне на звука). Батерия – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml index fcc99cadf0f4..8cb1542c39c2 100644 --- a/packages/SettingsLib/res/values-bn/strings.xml +++ b/packages/SettingsLib/res/values-bn/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"চালু আছে (শুধু বাঁদিক)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"চালু আছে (শুধু ডানদিক)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"চালু আছে (বাঁদিক ও ডানদিক)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"সারাউন্ডিং আপডেট করা যায়নি"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"চালু আছে (শুধুমাত্র মিডিয়া)। <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ব্যাটারি।"</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"চালু আছে (শুধুমাত্র মিডিয়া), বাঁদিক: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ডানদিক: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ব্যাটারি।"</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"কানেক্ট করা আছে (অডিও শেয়ারিংয়ে কাজ করে), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ব্যাটারি।"</string> diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml index fea1fa561d98..1847a4669a07 100644 --- a/packages/SettingsLib/res/values-bs/strings.xml +++ b/packages/SettingsLib/res/values-bs/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktivno (samo lijevo)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktivno (samo desno)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktivno (lijevo i desno)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Ažuriranje okruženja nije uspjelo"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktivno (samo za medijski sadržaj). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktivno (samo za medijski sadržaj). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> baterije, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterije."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Povezano (podržava dijeljenje zvuka). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string> diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml index 3f73bccef833..ad9cc351c788 100644 --- a/packages/SettingsLib/res/values-ca/strings.xml +++ b/packages/SettingsLib/res/values-ca/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Actiu (només l\'esquerre)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Actiu (només el dret)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Actiu (esquerre i dret)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"No s\'ha pogut actualitzar l\'entorn"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Actiu (només contingut multimèdia). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Actiu (només contingut multimèdia), E: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Connectat (admet compartició d\'àudio). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string> diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml index 940e2f6200a6..867ddfdaf394 100644 --- a/packages/SettingsLib/res/values-cs/strings.xml +++ b/packages/SettingsLib/res/values-cs/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktivní (pouze levé)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktivní (pouze pravé)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktivní (levé a pravé)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Okolí se nepodařilo aktualizovat"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktivní (pouze média). Baterie: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktivní (pouze média), baterie: L <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, P <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Připojeno (podporuje sdílení zvuku), baterie: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml index 2b3084704bee..aa85c1aadb12 100644 --- a/packages/SettingsLib/res/values-da/strings.xml +++ b/packages/SettingsLib/res/values-da/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktiveret (kun venstre)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktiveret (kun højre)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktiveret (venstre og højre)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Omgivelserne kunne ikke opdateres"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktiveret (kun for medier). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktiveret (kun for medier), V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Forbundet (understøtter lyddeling). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string> diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml index e9e9275fdb7d..62aa4a7214b9 100644 --- a/packages/SettingsLib/res/values-de/strings.xml +++ b/packages/SettingsLib/res/values-de/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktiv (nur links)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktiv (nur rechts)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktiv (links und rechts)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Status der Umgebungsgeräusche konnte nicht aktualisiert werden"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktiv (nur Medien). Akku: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktiv (nur Medien). Akku links: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Akku rechts: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Verbunden (unterstützt Audiofreigabe). Akku: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml index 4662c3ccd67e..ab75a9b42f02 100644 --- a/packages/SettingsLib/res/values-el/strings.xml +++ b/packages/SettingsLib/res/values-el/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Ενεργό (μόνο το αριστερό)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Ενεργό (μόνο το δεξί)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Ενεργό (αριστερό και δεξί)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Δεν ήταν δυνατή η ενημέρωση των ήχων περιβάλλοντος"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Ενεργό (μόνο για μέσα). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> μπαταρία."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Ενεργό (μόνο για μέσα). Α: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Δ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> μπαταρία."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Συνδεδεμένο (υποστηρίζει κοινή χρήση ήχου). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> μπαταρία."</string> diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml index b281f4ceccc2..7573543ece11 100644 --- a/packages/SettingsLib/res/values-en-rAU/strings.xml +++ b/packages/SettingsLib/res/values-en-rAU/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Active (left only)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Active (right only)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Active (left and right)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Couldn\'t update surroundings"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Active (media only). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Active (media only). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Connected (supports audio sharing). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string> diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml index b281f4ceccc2..7573543ece11 100644 --- a/packages/SettingsLib/res/values-en-rGB/strings.xml +++ b/packages/SettingsLib/res/values-en-rGB/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Active (left only)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Active (right only)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Active (left and right)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Couldn\'t update surroundings"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Active (media only). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Active (media only). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Connected (supports audio sharing). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string> diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml index b281f4ceccc2..7573543ece11 100644 --- a/packages/SettingsLib/res/values-en-rIN/strings.xml +++ b/packages/SettingsLib/res/values-en-rIN/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Active (left only)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Active (right only)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Active (left and right)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Couldn\'t update surroundings"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Active (media only). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Active (media only). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> battery."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Connected (supports audio sharing). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> battery."</string> diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml index 6ad60084b622..ae95613df96d 100644 --- a/packages/SettingsLib/res/values-es-rUS/strings.xml +++ b/packages/SettingsLib/res/values-es-rUS/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Activo (solo izquierdo)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Activo (solo derecho)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Activos (izquierdo y derecho)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"No se pudo actualizar el sonido envolvente"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Activado (solo para contenido multimedia). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Activo (solo para contenido multimedia); I: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>; D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Conectado (admite el uso compartido de audio); <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string> diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml index 60197511390b..eb03083c3377 100644 --- a/packages/SettingsLib/res/values-es/strings.xml +++ b/packages/SettingsLib/res/values-es/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Activo (solo izquierdo)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Activo (solo derecho)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Activo (izquierdo y derecho)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"No se han podido actualizar los alrededores"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Activo (solo multimedia). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Activo (solo multimedia). Izquierdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batería. Derecho: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Conectado (permite compartir audio). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string> diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml index 773b1e67b232..9ed48b1c013d 100644 --- a/packages/SettingsLib/res/values-et/strings.xml +++ b/packages/SettingsLib/res/values-et/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktiivne (ainult vasak)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktiivne (ainult parem)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktiivne (vasak ja parem)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Ümbritsevate helide seadeid ei saanud värskendada"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktiivne (ainult meedia). Aku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktiivne (ainult meedia). Aku: V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, P: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Ühendatud (toetab heli jagamist). Aku <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml index 274b9a1c5790..24dafa92ede6 100644 --- a/packages/SettingsLib/res/values-eu/strings.xml +++ b/packages/SettingsLib/res/values-eu/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktibo (ezkerrekoa soilik)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktibo (eskuinekoa soilik)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktibo (ezkerrekoa eta eskuinekoa)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Ezin izan da eguneratu ingurunea"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktibo (multimedia-edukia soilik). Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktibo (multimedia-edukia soilik). L aldearen bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>. R aldearen bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Konektatuta (audioa partekatzeko eginbidea onartzen du). Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml index 6154b8cef78a..60121ccf0055 100644 --- a/packages/SettingsLib/res/values-fa/strings.xml +++ b/packages/SettingsLib/res/values-fa/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"فعال (فقط چپ)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"فعال (فقط راست)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"فعال (چپ و راست)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"پیرامون بهروز نشد"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"فعال (فقط رسانه). باتری: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"فعال (فقط رسانه). باتری چپ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>، باتری راست: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"متصل (از اشتراک صدا پشتیبانی میکند)، باتری: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml index 7baf2a0803fc..d0d90379b2c0 100644 --- a/packages/SettingsLib/res/values-fi/strings.xml +++ b/packages/SettingsLib/res/values-fi/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktiivinen (vain vasen)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktiivinen (vain oikea)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktiivinen (vasen ja oikea)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Ympäristön päivittäminen epäonnistui"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktiivinen (vain media). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> virtaa."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktiivinen (vain media). V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, O: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> virtaa."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Yhdistetty (tukee audionjakoa). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> virtaa."</string> diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml index 699fa7f118d8..27e4906f3d79 100644 --- a/packages/SettingsLib/res/values-fr-rCA/strings.xml +++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Actif (gauche seulement)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Actif (droite seulement)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Actif (gauche et droite)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Impossible de mettre à jour les sons de l\'environnement"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Actif (contenu multimédia uniquement). Pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Actif (contenu multimédia uniquement). G. : pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D. : pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Connecté (prise en charge du partage audio). Pile à <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml index 73dbdbffe2fb..87d768a65761 100644 --- a/packages/SettingsLib/res/values-fr/strings.xml +++ b/packages/SettingsLib/res/values-fr/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Actif (gauche uniquement)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Actif (droit uniquement)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Actifs (gauche et droit)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Impossible de mettre à jour le mode Sons environnants"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Actif (multimédia uniquement). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batterie."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Actif (multimédia uniquement). Gauche : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batterie, droit : <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batterie."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Connecté (compatible avec le partage audio). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batterie."</string> @@ -256,8 +255,8 @@ <string name="adb_wireless_error" msgid="721958772149779856">"Erreur"</string> <string name="adb_wireless_settings" msgid="2295017847215680229">"Débogage sans fil"</string> <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Pour afficher et utiliser les appareils disponibles, activez le débogage sans fil"</string> - <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Associer l\'appareil avec un code QR"</string> - <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"Associer les nouveaux appareils à l\'aide d\'un lecteur de code QR"</string> + <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Associer l\'appareil avec un QR code"</string> + <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"Associer les nouveaux appareils à l\'aide d\'un lecteur de QR code"</string> <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Associer l\'appareil avec un code d\'association"</string> <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Associer les nouveaux appareils à l\'aide d\'un code à six chiffres"</string> <string name="adb_paired_devices_title" msgid="5268997341526217362">"Appareils associés"</string> @@ -271,12 +270,12 @@ <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Code d\'association via le Wi-Fi"</string> <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Échec de l\'association"</string> <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Assurez-vous que l\'appareil est connecté au même réseau."</string> - <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Associer l\'appareil via le Wi‑Fi à l\'aide d\'un code QR"</string> + <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Associer l\'appareil via le Wi‑Fi à l\'aide d\'un QR code"</string> <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Association de l\'appareil…"</string> - <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Échec de l\'association à l\'appareil. Le code QR est incorrect, ou l\'appareil n\'est pas connecté au même réseau."</string> + <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Échec de l\'association à l\'appareil. Le QR code est incorrect, ou l\'appareil n\'est pas connecté au même réseau."</string> <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Adresse IP et port"</string> - <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Scanner un code QR"</string> - <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"Associez l\'appareil via le Wi‑Fi à l\'aide d\'un code QR"</string> + <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Scanner un QR code"</string> + <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"Associez l\'appareil via le Wi‑Fi à l\'aide d\'un QR code"</string> <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Connectez-vous à un réseau Wi-Fi"</string> <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, débogage, dev"</string> <string name="bugreport_in_power" msgid="8664089072534638709">"Raccourci vers rapport de bug"</string> diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml index 9f14f7cc3f71..4e90b53286ca 100644 --- a/packages/SettingsLib/res/values-gl/strings.xml +++ b/packages/SettingsLib/res/values-gl/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Activo (só o esquerdo)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Activo (só o dereito)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Activos (o esquerdo e o dereito)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Non se puido actualizar o ambiente"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Activo (só contido multimedia). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Activo (só contido multimedia). Esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de batería. Dereito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de batería."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Conectado (compatible con audio compartido). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería."</string> diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml index 74b19f609179..bfe68feb5c98 100644 --- a/packages/SettingsLib/res/values-gu/strings.xml +++ b/packages/SettingsLib/res/values-gu/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"ચાલુ છે (માત્ર ડાબી બાજુ)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"ચાલુ છે (માત્ર જમણી બાજુ)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"ચાલુ છે (ડાબી અને જમણી બાજુ)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"આસપાસના અવાજો અપડેટ કરી શક્યા નથી"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"સક્રિય (માત્ર મીડિયા માટે). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"સક્રિય (માત્ર મીડિયા માટે). ડાબી બાજુ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, જમણી બાજુ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> બૅટરી."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"કનેક્ટેડ (ઑડિયો શેરિંગને સપોર્ટ કરે છે). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> બૅટરી."</string> diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml index 8f9229ae6bf0..5146ebc75e81 100644 --- a/packages/SettingsLib/res/values-hi/strings.xml +++ b/packages/SettingsLib/res/values-hi/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"सिर्फ़ बाईं तरफ़ वाला चालू है"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"सिर्फ़ दाईं तरफ़ वाला चालू है"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"बाईं और दाईं तरफ़ वाला चालू है"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"वॉल्यूम को मैनेज करने की सेटिंग नहीं बदली जा सकी"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"चालू है (सिर्फ़ मीडिया के लिए). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बैटरी."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"चालू है (सिर्फ़ मीडिया के लिए). बायां हेडसेट: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, दायां हेडसेट: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> बैटरी."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"कनेक्ट हो गया (ऑडियो शेयर करने की सुविधा काम करती है). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बैटरी."</string> diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml index 3a18da0ff703..4c743a9c6219 100644 --- a/packages/SettingsLib/res/values-hr/strings.xml +++ b/packages/SettingsLib/res/values-hr/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktivno (samo lijevo)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktivno (samo desno)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktivno (lijevo i desno)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Ažuriranje okruženja nije uspjelo"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktivno (samo medijski sadržaji). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktivno (samo medijski sadržaji), L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterije."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Povezano (podržava zajedničko slušanje). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterije."</string> diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml index 00ca5c6a0e21..b17dfff697e4 100644 --- a/packages/SettingsLib/res/values-hu/strings.xml +++ b/packages/SettingsLib/res/values-hu/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktív (csak bal)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktív (csak jobb)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktív (bal és jobb)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Nem sikerült módosítani a környezetet"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktív (csak médiatartalom lejátszása esetén). Akkumulátor töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktív (csak médiatartalom lejátszása esetén). Akkumulátorok töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (bal) és <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (jobb)."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Csatlakoztatva (támogatja a hang megosztását). Akkumulátor töltöttségi szintje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml index 58eca5cd3b7c..abca57c3ca7b 100644 --- a/packages/SettingsLib/res/values-hy/strings.xml +++ b/packages/SettingsLib/res/values-hy/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Ակտիվ է (միայն ձախ)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Ակտիվ է (միայն աջ)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Ակտիվ է (ձախ և աջ)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Չհաջողվեց թարմացնել շրջակայքի կարգավիճակը"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Ակտիվ է (միայն մեդիա)։ Մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>։"</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Ակտիվ է (միայն մեդիա)։ Ձախ ականջակալի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, աջ ականջակալի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>։"</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Միացված է (աջակցում է աուդիոյի փոխանցում)։ Մարտկոցի լիցքը՝ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>։"</string> diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml index 1652ebf66d74..784a7582f962 100644 --- a/packages/SettingsLib/res/values-in/strings.xml +++ b/packages/SettingsLib/res/values-in/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktif (hanya kiri)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktif (hanya kanan)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktif (kiri dan kanan)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Tidak dapat memperbarui suara sekitar"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktif (hanya media). Baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktif (hanya media). Baterai L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Terhubung (mendukung berbagi audio). Baterai <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml index bc766325d871..88f657a17b9d 100644 --- a/packages/SettingsLib/res/values-is/strings.xml +++ b/packages/SettingsLib/res/values-is/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Kveikt (eingöngu vinstra)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Kveikt (eingöngu hægra)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Kveikt (vinstra og hægra)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Ekki var hægt að uppfæra umhverfi"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Virkt (eingöngu margmiðlunarefni). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> rafhlöðuhleðsla."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Virkt (eingöngu margmiðlunarefni), V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> rafhlöðuhleðsla."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Tengt (styður hljóðdeilingu), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> rafhlöðuhleðsla."</string> diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml index f51c9166cca4..0c71a2195538 100644 --- a/packages/SettingsLib/res/values-iw/strings.xml +++ b/packages/SettingsLib/res/values-iw/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"פעיל (שמאל בלבד)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"פעיל (ימין בלבד)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"פעיל (ימין ושמאל)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"לא ניתן לעדכן את עוצמת הרעשים בסביבה"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"פעיל (מדיה בלבד). סוללה: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"פעיל (מדיה בלבד). סוללה בצד שמאל: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, סוללה בצד ימין: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"מחובר (תמיכה בשיתוף אודיו). סוללה: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml index 923054d268b6..10f142743dff 100644 --- a/packages/SettingsLib/res/values-ja/strings.xml +++ b/packages/SettingsLib/res/values-ja/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"アクティブ(左のみ)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"アクティブ(右のみ)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"アクティブ(左と右)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"周囲の音を更新できませんでした"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"有効(メディアのみ)。バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"有効(メディアのみ)。左: バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>、右: バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>。"</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"接続済み(音声の共有をサポート)。バッテリー残量 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string> diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml index e8f1b0769cb6..4473216657ee 100644 --- a/packages/SettingsLib/res/values-ka/strings.xml +++ b/packages/SettingsLib/res/values-ka/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"აქტიური (მხოლოდ მარცხენა)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"აქტიური (მხოლოდ მარჯვენა)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"აქტიური (მარცხენა და მარჯვენა)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"გარემოცვის განახლება ვერ მოხერხდა"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"აქტიური (მხოლოდ მედია). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>%% ბატარეა."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"აქტიური (მხოლოდ მედია), მარცხენა: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, მარჯვენა:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ბატარეა."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"დაკავშირებული (აუდიოს გაზიარება მხარდაჭერილია). ბატარეა <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml index a88517dfe445..a0a91c8089eb 100644 --- a/packages/SettingsLib/res/values-kk/strings.xml +++ b/packages/SettingsLib/res/values-kk/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Істеп тұр (тек сол жағы)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Істеп тұр (тек оң жағы)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Істеп тұр (екі жағы да)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Айналаны жаңарту мүмкін болмады."</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Істеп тұр (тек мультимедиа). Батарея зарядының деңгейі – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Істеп тұр (тек мультимедиа). Сол жақ: батарея зарядының деңгейі — <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>. Оң жақ: батарея зарядының деңгейі — <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Жалғанып тұр (аудио бөлісу мүмкіндігі бар). Батарея зарядының деңгейі – <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml index 41b427a91bf6..bee7772db42b 100644 --- a/packages/SettingsLib/res/values-km/strings.xml +++ b/packages/SettingsLib/res/values-km/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"សកម្ម (ខាងឆ្វេងប៉ុណ្ណោះ)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"សកម្ម (ខាងស្ដាំប៉ុណ្ណោះ)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"សកម្ម (ខាងឆ្វេង និងខាងស្ដាំ)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"មិនអាចប្ដូរមជ្ឈដ្ឋានជុំវិញបានទេ"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"សកម្ម (តែមេឌៀប៉ុណ្ណោះ)។ ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>។"</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"សកម្ម (តែមេឌៀប៉ុណ្ណោះ)។ ឆ្វេង៖ ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ស្ដាំ៖ ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>។"</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"បានភ្ជាប់ (អាចប្រើការស្ដាប់សំឡេងរួមគ្នា)។ ថ្ម <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>។"</string> diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml index 20b4c93eef8f..f11dff5b10c8 100644 --- a/packages/SettingsLib/res/values-kn/strings.xml +++ b/packages/SettingsLib/res/values-kn/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"ಸಕ್ರಿಯವಾಗಿದೆ (ಎಡಕಿವಿಯ ಸಾಧನ ಮಾತ್ರ)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"ಸಕ್ರಿಯವಾಗಿದೆ (ಬಲಕಿವಿಯ ಸಾಧನ ಮಾತ್ರ)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"ಸಕ್ರಿಯವಾಗಿವೆ (ಎಡ ಮತ್ತು ಬಲಕಿವಿಯ ಸಾಧನಗಳು)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"ಆ್ಯಂಬಿಯೆಂಟ್ ಸ್ಥಿತಿಯನ್ನು ಅಪ್ಡೇಟ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"ಸಕ್ರಿಯವಾಗಿದೆ (ಮೀಡಿಯಾ ಮಾತ್ರ). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ಬ್ಯಾಟರಿ ಮಟ್ಟ."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"ಸಕ್ರಿಯವಾಗಿದೆ (ಮೀಡಿಯಾ ಮಾತ್ರ). ಎಡ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ಬಲ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ಬ್ಯಾಟರಿ ಮಟ್ಟ."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"ಕನೆಕ್ಟ್ ಆಗಿದೆ (ಆಡಿಯೋ ಹಂಚಿಕೊಳ್ಳುವಿಕೆಯನ್ನು ಬೆಂಬಲಿಸುತ್ತದೆ). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ಬ್ಯಾಟರಿ ಮಟ್ಟ."</string> diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml index 084ab17845d3..672ad8c1d0a3 100644 --- a/packages/SettingsLib/res/values-ko/strings.xml +++ b/packages/SettingsLib/res/values-ko/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"활성(왼쪽만)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"활성(오른쪽만)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"활성(왼쪽 및 오른쪽)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"주변 소리를 업데이트할 수 없음"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"사용 중입니다(미디어 전용). 배터리는 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>입니다."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"사용 중입니다(미디어 전용). 배터리는 왼쪽 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, 오른쪽 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>입니다."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"연결되었습니다(오디오 공유 지원). 배터리는 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>입니다."</string> diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml index 2d1ea8677934..a9b4a1e7100d 100644 --- a/packages/SettingsLib/res/values-ky/strings.xml +++ b/packages/SettingsLib/res/values-ky/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Иштеп жатат (сол тарап гана)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Иштеп жатат (оң тарап гана)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Иштеп жатат (сол жана оң)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Айланадагы абал жаңыртылган жок"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Жигердүү (медиа үчүн гана). Батарея: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Жигердүү (медиа үчүн гана). Батарея: L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Туташып турат (чогуу уксаңыз болот). Батарея: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml index ec06e5e07e64..cc8e42ca9d8a 100644 --- a/packages/SettingsLib/res/values-lo/strings.xml +++ b/packages/SettingsLib/res/values-lo/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"ນຳໃຊ້ຢູ່ (ຊ້າຍເທົ່ານັ້ນ)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"ນຳໃຊ້ຢູ່ (ຂວາເທົ່ານັ້ນ)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"ນຳໃຊ້ຢູ່ (ຊ້າຍ ແລະ ຂວາ)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"ບໍ່ສາມາດອັບເດດສຽງແວດລ້ອມໄດ້"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"ນຳໃຊ້ຢູ່ (ມີເດຍເທົ່ານັ້ນ). ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"ນຳໃຊ້ຢູ່ (ມີເດຍເທົ່ານັ້ນ). ຊ: ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ຂ: ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"ເຊື່ອມຕໍ່ແລ້ວ (ຮອງຮັບການແບ່ງປັນສຽງ). ແບັດເຕີຣີ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml index f0a82e01c896..f81d52777743 100644 --- a/packages/SettingsLib/res/values-lt/strings.xml +++ b/packages/SettingsLib/res/values-lt/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktyvus (tik kairiojoje pusėje)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktyvus (tik dešiniojoje pusėje)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktyvus (kairiojoje ir dešiniojoje pusėse)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Nepavyko atnaujinti aplinkos"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktyvus (tik medija). Akumuliatorius lygis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktyvus (tik medija), akumuliatoriaus lygis kairėje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, dešinėje: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Prijungta (palaikomas garso įrašų bendrinimas). Akumuliatoriaus lygis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml index 47fe2d952b34..2738a4072efc 100644 --- a/packages/SettingsLib/res/values-lv/strings.xml +++ b/packages/SettingsLib/res/values-lv/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Ierīce aktīva (tikai kreisā auss)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Ierīce aktīva (tikai labā auss)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Ierīces aktīvas (kreisā un labā auss)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Nevarēja atjaunināt apkārtnes skaņas"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktīvs (tikai multividei). Akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktīvs (tikai multividei). Akumulatora uzlādes līmenis kreisajā austiņā: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, labajā austiņā: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Izveidots savienojums (atbalsta audio kopīgošanu). Akumulatora uzlādes līmenis: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml index a8c8d83e3641..9ec3bac71b65 100644 --- a/packages/SettingsLib/res/values-mk/strings.xml +++ b/packages/SettingsLib/res/values-mk/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Активно (само лево)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Активно (само десно)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Активно (лево и десно)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Не можеше да се ажурира опкружувањето"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Активно (само аудиовизуелни содржини). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерија."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Активно (само аудиовизуелни содржини). Л: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> батерија, Д: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батерија."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Поврзано (поддржува споделување аудио). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерија."</string> diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml index 859c67e62ef5..fd8861f09674 100644 --- a/packages/SettingsLib/res/values-ml/strings.xml +++ b/packages/SettingsLib/res/values-ml/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"സജീവമാണ് (ഇടതുഭാഗത്ത് മാത്രം)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"സജീവമാണ് (വലതുഭാഗത്ത് മാത്രം)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"സജീവമാണ് (ഇടതുഭാഗത്തും വലതുഭാഗത്തും)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"സറൗണ്ടിംഗ്സ് അപ്ഡേറ്റ് ചെയ്യാനായില്ല"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"സജീവം (മീഡിയ മാത്രം). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ബാറ്ററി."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"സജീവം (മീഡിയ മാത്രം). ഇടതുവശത്ത്: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> ബാറ്ററി, വലതുവശത്ത്: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ബാറ്ററി."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"കണക്റ്റ് ചെയ്തു (ഓഡിയോ പങ്കിടൽ പിന്തുണയ്ക്കുന്നു). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ബാറ്ററി."</string> diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml index c61bcde5e3df..08dfa7d1a600 100644 --- a/packages/SettingsLib/res/values-mn/strings.xml +++ b/packages/SettingsLib/res/values-mn/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Идэвхтэй (зөвхөн зүүн тал)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Идэвхтэй (зөвхөн баруун тал)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Идэвхтэй (зүүн, баруун тал)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Орчин тойрныг шинэчилж чадсангүй"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Идэвхтэй (зөвхөн медиа). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батарей."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Идэвхтэй (зөвхөн медиа). З: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Б: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батарей."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Холбогдсон (аудио хуваалцахыг дэмждэг). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батарей."</string> diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml index 654b447f89cd..3f88af62f8c7 100644 --- a/packages/SettingsLib/res/values-mr/strings.xml +++ b/packages/SettingsLib/res/values-mr/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"अॅक्टिव्ह आहे (फक्त डावे)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"अॅक्टिव्ह आहे (फक्त उजवे)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"अॅक्टिव्ह आहे (डावे आणि उजवे)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"जवळपासचे आवाज अपडेट करता आले नाहीत"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"अॅक्टिव्ह आहे (फक्त मीडिया). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बॅटरी."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"ॲक्टिव्ह आहे (फक्त मीडिया). डावीकडे: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> बॅटरी, उजवीकडे: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> बॅटरी."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"कनेक्ट केले आहे (ऑडिओ शेअरिंगला सपोर्ट करते). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> बॅटरी."</string> diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml index fcb5d6ef7ebb..97a7b43e0200 100644 --- a/packages/SettingsLib/res/values-ms/strings.xml +++ b/packages/SettingsLib/res/values-ms/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktif (kiri sahaja)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktif (kanan sahaja)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktif (kiri dan kanan)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Tidak dapat mengemaskinikan persekitaran"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktif (media sahaja). Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktif (media sahaja), L: Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Disambungkan (menyokong perkongsian audio). Bateri <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml index 4826c49679e6..9525884488a5 100644 --- a/packages/SettingsLib/res/values-my/strings.xml +++ b/packages/SettingsLib/res/values-my/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"သုံးနေသည် (ဘယ်ဘက်သီးသန့်)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"သုံးနေသည် (ညာဘက်သီးသန့်)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"သုံးနေသည် (ဘယ်နှင့်ညာ)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"ဝန်းကျင်အသံ အပ်ဒိတ်လုပ်၍ မရလိုက်ပါ"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"အသုံးပြုနေသည် (မီဒီယာသီးသန့်)။ ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>။"</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"အသုံးပြုနေသည် (မီဒီယာသီးသန့်)။ ဘက်ထရီ L- <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>၊ R- <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>။"</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"ချိတ်ဆက်ထားသည် (အော်ဒီယို မျှဝေခြင်း ပံ့ပိုးသည်)။ ဘက်ထရီ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>။"</string> diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml index e7be3c942de9..94a701b3f8e2 100644 --- a/packages/SettingsLib/res/values-nb/strings.xml +++ b/packages/SettingsLib/res/values-nb/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktiv (bare venstre)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktiv (bare høyre)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktiv (venstre og høyre)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Kunne ikke oppdatere omgivelsene"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktiv (bare medieinnhold) <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktiv (bare medieinnhold). V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batteri, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Tilkoblet (støtter lyddeling). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string> diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml index 0478d9c8a923..a2ee640ef55e 100644 --- a/packages/SettingsLib/res/values-ne/strings.xml +++ b/packages/SettingsLib/res/values-ne/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"सक्रिय छ (बायाँ मात्र)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"सक्रिय छ (दायाँ मात्र)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"सक्रिय छ (दायाँ र बायाँ)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"वरपरका आवाजसम्बन्धी सेटिङ अपडेट गर्न सकिएन"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"सक्रिय छ (मिडिया मात्र)। <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ब्याट्री।"</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"सक्रिय छ (मिडिया मात्र)। बायाँ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, दायाँ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ब्याट्री।"</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"कनेक्ट गरिएको छ (अडियो सेयर गर्न मिल्छ)। <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ब्याट्री।"</string> diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml index bae7bb9ffda0..63014b60d718 100644 --- a/packages/SettingsLib/res/values-nl/strings.xml +++ b/packages/SettingsLib/res/values-nl/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Actief (alleen links)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Actief (alleen rechts)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Actief (links en rechts)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Kan omgeving niet updaten"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Actief (alleen media). Batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Actief (alleen media), L: batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Verbonden (ondersteunt audio delen), batterijniveau <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml index 7b8f3ccce52d..803309c890b8 100644 --- a/packages/SettingsLib/res/values-or/strings.xml +++ b/packages/SettingsLib/res/values-or/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"ସକ୍ରିୟ (କେବଳ ବାମ)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"ସକ୍ରିୟ (କେବଳ ଡାହାଣ)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"ସକ୍ରିୟ (ବାମ ଏବଂ ଡାହାଣ)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"ପରିପାର୍ଶ୍ୱକୁ ଅପଡେଟ କରାଯାଇପାରିଲା ନାହିଁ"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"ସକ୍ରିୟ (କେବଳ ମିଡିଆ)। <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ବେଟେରୀ।"</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"ସକ୍ରିୟ (କେବଳ ମିଡିଆ)। ବାମ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ଡାହାଣ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ବେଟେରୀ।"</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"କନେକ୍ଟ କରାଯାଇଛି (ଅଡିଓ ସେୟାରିଂକୁ ସପୋର୍ଟ କରେ)। <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ବେଟେରୀ।"</string> diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml index 7e2a50f96a7b..d8726db136bd 100644 --- a/packages/SettingsLib/res/values-pa/strings.xml +++ b/packages/SettingsLib/res/values-pa/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"ਕਿਰਿਆਸ਼ੀਲ (ਸਿਰਫ਼ ਖੱਬਾ)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"ਕਿਰਿਆਸ਼ੀਲ (ਸਿਰਫ਼ ਸੱਜਾ)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"ਕਿਰਿਆਸ਼ੀਲ (ਖੱਬਾ ਅਤੇ ਸੱਜਾ)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"ਆਲੇ-ਦੁਆਲੇ ਨੂੰ ਅੱਪਡੇਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"ਕਿਰਿਆਸ਼ੀਲ (ਸਿਰਫ਼ ਮੀਡੀਆ)। <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ਬੈਟਰੀ।"</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"ਕਿਰਿਆਸ਼ੀਲ (ਸਿਰਫ਼ ਮੀਡੀਆ)। ਖੱਬੇ ਪਾਸੇ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ਸੱਜੇ ਪਾਸੇ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ਬੈਟਰੀ।"</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"ਕਨੈਕਟ ਕੀਤਾ (ਆਡੀਓ ਸਾਂਝਾਕਰਨ ਦਾ ਸਮਰਥਨ ਕਰਦਾ ਹੈ)। <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ਬੈਟਰੀ।"</string> diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml index 397cb82061cd..d789c6407812 100644 --- a/packages/SettingsLib/res/values-pl/strings.xml +++ b/packages/SettingsLib/res/values-pl/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktywne (tylko lewa strona)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktywne (tylko prawa strona)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktywne (lewa i prawa strona)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Nie udało się zaktualizować otoczenia"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktywne (tylko multimedia). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> naładowania baterii."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktywne (tylko multimedia), lewa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, prawa: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> naładowania baterii."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Połączone (obsługa udostępniania dźwięku), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> naładowania baterii."</string> diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml index 273c84d66824..bd08415acdea 100644 --- a/packages/SettingsLib/res/values-pt-rBR/strings.xml +++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Ativo (apenas o esquerdo)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Ativo (apenas o direito)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Ativo (esquerdo e direito)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Não foi possível atualizar o som ambiente"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Ativo (apenas mídia). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Ativo (apenas mídia). Lado esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria. Lado direito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Conectado (aceita compartilhamento de áudio). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string> diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml index 273c84d66824..bd08415acdea 100644 --- a/packages/SettingsLib/res/values-pt/strings.xml +++ b/packages/SettingsLib/res/values-pt/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Ativo (apenas o esquerdo)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Ativo (apenas o direito)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Ativo (esquerdo e direito)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Não foi possível atualizar o som ambiente"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Ativo (apenas mídia). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Ativo (apenas mídia). Lado esquerdo: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> de bateria. Lado direito: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> de bateria."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Conectado (aceita compartilhamento de áudio). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de bateria."</string> diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml index 1d77583d02e2..1b6614591624 100644 --- a/packages/SettingsLib/res/values-ro/strings.xml +++ b/packages/SettingsLib/res/values-ro/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Activ (numai stânga)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Activ (numai dreapta)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Activ (stânga și dreapta)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Nu s-a putut actualiza zona din jur"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Activ (numai pentru conținut media). Nivelul bateriei <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Activ (numai pentru conținut media): nivelul bateriei din stânga: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, nivelul bateriei din dreapta: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Conectat (acceptă permiterea accesului la audio). Nivelul bateriei: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml index d69778034323..56748fbaef63 100644 --- a/packages/SettingsLib/res/values-ru/strings.xml +++ b/packages/SettingsLib/res/values-ru/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Используется (только левый)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Используется (только правый)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Используется (левый и правый)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Не удалось отрегулировать окружающие звуки."</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Используется (только для медиа), заряд: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Используется (только для медиа), заряд: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (Л), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (П)."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Подключено (поддерживается отправка аудио), заряд: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml index df22ba72518d..5030450771a5 100644 --- a/packages/SettingsLib/res/values-si/strings.xml +++ b/packages/SettingsLib/res/values-si/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"සක්රිය (වම පමණි)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"සක්රිය (දකුණ පමණි)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"සක්රිය (වම සහ දකුණ)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"වටපිටාව යාවත්කාලීන කළ නොහැකි විය"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"ක්රියාත්මකයි (මාධ්ය පමණයි). බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"ක්රියාත්මකයි (මාධ්ය පමණයි), බැටරිය ව: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ද: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"සම්බන්ධයි (ශ්රව්ය බෙදා ගැනීමට සහය දක්වයි). බැටරිය <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml index 7af38252c8f9..b4787f2fd337 100644 --- a/packages/SettingsLib/res/values-sk/strings.xml +++ b/packages/SettingsLib/res/values-sk/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktívne (iba ľavé)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktívne (iba pravé)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktívne (ľavé aj pravé)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Okolie sa nepodarilo aktualizovať"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktívne (iba médiá). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batérie."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktívne (iba médiá). Ľ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> batérie, P: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batérie."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Pripojené (podporuje zdieľanie zvuku). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batérie."</string> diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml index e82feb4674d9..b6eacf879c0f 100644 --- a/packages/SettingsLib/res/values-sl/strings.xml +++ b/packages/SettingsLib/res/values-sl/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktivno (samo levo)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktivno (samo desno)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktivno (levo in desno)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Okolice ni bilo mogoče posodobiti"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktivno (samo predstavnost). Baterija: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktivno (samo predstavnost), baterija – L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, D: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Povezano (podpira deljenje zvoka), baterija: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml index f8573098175f..ee31c29300d1 100644 --- a/packages/SettingsLib/res/values-sq/strings.xml +++ b/packages/SettingsLib/res/values-sq/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktive (vetëm majtas)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktive (vetëm djathtas)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktive (majtas dhe djathtas)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Ambienti rrethues nuk mund të përditësohej"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktiv (vetëm për media). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> bateri."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktiv (vetëm për media). Majtas: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> bateri, djathtas: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> bateri."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Lidhur (mbështet ndarjen e audios). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> bateri."</string> diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml index ad15dd4eda3c..fcf1e4ffe2ec 100644 --- a/packages/SettingsLib/res/values-sr/strings.xml +++ b/packages/SettingsLib/res/values-sr/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Активно (само лево)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Активно (само десно)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Активно (лево и десно)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Ажурирање окружења није успело"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Активно (само за медије). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерије."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Активно (само за медије). Лево: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, десно: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> батерије."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Повезано (подржава дељење звука), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> батерије."</string> diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml index 7f172dbefe7c..c66242beee37 100644 --- a/packages/SettingsLib/res/values-sv/strings.xml +++ b/packages/SettingsLib/res/values-sv/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktiv (endast vänster)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktiv (endast höger)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktiv (vänster och höger)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Det gick inte att uppdatera omgivningsläget"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktiv (endast media). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktiv (endast media). V: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, H: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> batteri."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Ansluten (ljuddelning stöds). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> batteri."</string> diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml index bf95f4e0e8f7..d84d3555526c 100644 --- a/packages/SettingsLib/res/values-sw/strings.xml +++ b/packages/SettingsLib/res/values-sw/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Inatumika (kushoto pekee)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Inatumika (kulia pekee)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Inatumika (kushoto na kulia)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Imeshindwa kusasisha mazingira"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Inatumika (maudhui pekee). Chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Inatumika (maudhui pekee), Kushoto: chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Kulia: chaji ya betri imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Imeunganishwa (inaweza kutumia kipengele cha kusikiliza pamoja). Chaji imefika <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml index 24c2244f6052..b0c25d05138e 100644 --- a/packages/SettingsLib/res/values-ta/strings.xml +++ b/packages/SettingsLib/res/values-ta/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"செயலில் உள்ளது (இடதுபுறம் மட்டும்)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"செயலில் உள்ளது (வலதுபுறம் மட்டும்)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"செயலில் உள்ளது (இடது மற்றும் வலதுபுறம்)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"சுற்றுப்புறங்களைப் புதுப்பிக்க முடியவில்லை"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"செயலிலுள்ளது (மீடியா மட்டும்). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> பேட்டரி."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"செயலிலுள்ளது (மீடியா மட்டும்). இடது பேட்டரி: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, வலது பேட்டரி: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"இணைக்கப்பட்டுள்ளது (ஆடியோ பகிர்வை ஆதரிக்கிறது). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> பேட்டரி."</string> diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml index abee83647fea..aae20b22e30f 100644 --- a/packages/SettingsLib/res/values-te/strings.xml +++ b/packages/SettingsLib/res/values-te/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"యాక్టివ్గా ఉంది (ఎడమ వైపు మాత్రమే)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"యాక్టివ్గా ఉంది (కుడి వైపు మాత్రమే)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"యాక్టివ్గా ఉంది (ఎడమ వైపు, కుడి వైపు)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"పరిసరాలను అప్డేట్ చేయడం సాధ్యం కాలేదు"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"యాక్టివ్ (మీడియా మాత్రమే). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> బ్యాటరీ."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"యాక్టివ్ (మీడియా మాత్రమే). ఎడమ వైపు: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> బ్యాటరీ, కుడివైపు: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> బ్యాటరీ."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"కనెక్ట్ చేయబడింది (ఆడియో షేరింగ్కు సపోర్ట్ చేస్తుంది). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> బ్యాటరీ."</string> diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml index f8f6af2a5c50..a228e6b24150 100644 --- a/packages/SettingsLib/res/values-th/strings.xml +++ b/packages/SettingsLib/res/values-th/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"ใช้งานอยู่ (เฉพาะข้างซ้าย)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"ใช้งานอยู่ (เฉพาะข้างขวา)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"ใช้งานอยู่ (ข้างซ้ายและขวา)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"อัปเดตเสียงแวดล้อมไม่ได้"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"ใช้งานอยู่ (สื่อเท่านั้น) แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"ใช้งานอยู่ (สื่อเท่านั้น) แบตเตอรี่ข้างซ้าย: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, ข้างขวา: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>"</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"เชื่อมต่อแล้ว (รองรับการแชร์เสียง) แบตเตอรี่ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml index 853621904d48..655347904b66 100644 --- a/packages/SettingsLib/res/values-tl/strings.xml +++ b/packages/SettingsLib/res/values-tl/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Aktibo (kaliwa lang)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Aktibo (kanan lang)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Aktibo (kaliwa at kanan)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Hindi ma-update ang paligid"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Aktibo (media lang). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterya."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Aktibo (media lang). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> baterya."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Nakakonekta (sinusuportahan ang pag-share ng audio), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> baterya."</string> diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml index 8168d534d057..6a8158bae647 100644 --- a/packages/SettingsLib/res/values-tr/strings.xml +++ b/packages/SettingsLib/res/values-tr/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Etkin (yalnızca sol taraf)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Etkin (yalnızca sağ taraf)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Etkin (sol ve sağ taraf)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Çevredeki sesler güncellenemedi"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Etkin (yalnızca medya). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pil seviyesi."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Etkin (yalnızca medya). Sol: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, Sağ: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> pil seviyesi."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Bağlı (ses paylaşımını destekler). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pil seviyesi."</string> diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml index 3167290603a4..d599fb4cb82b 100644 --- a/packages/SettingsLib/res/values-uk/strings.xml +++ b/packages/SettingsLib/res/values-uk/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Активовано (лише лівий)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Активовано (лише правий)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Активовано (лівий і правий)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Не вдалось оновити стан оточення"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Активне з’єднання (лише для мультимедіа). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> заряду акумулятора."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Активне з’єднання (лише для мультимедіа). Рівень заряду: лівий <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, правий: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Підключено (підтримує надсилання аудіо). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> заряду акумулятора."</string> diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml index fe3dc059eab7..f0588efc1bad 100644 --- a/packages/SettingsLib/res/values-ur/strings.xml +++ b/packages/SettingsLib/res/values-ur/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"فعال ہے (صرف بایاں)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"فعال ہے (صرف دایاں)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"فعال ہے (بایاں اور دایاں)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"اطراف کو اپ ڈیٹ نہیں کیا جا سکا"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"فعال (صرف میڈیا)۔ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> بیٹری۔"</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"فعال (صرف میڈیا)۔ L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>، R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> بیٹری۔"</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"منسلک ہے (آڈیو کے اشتراک کو سپورٹ کرتا ہے)۔ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> بیٹری۔"</string> diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml index d046effa4e7b..6930278ac13b 100644 --- a/packages/SettingsLib/res/values-uz/strings.xml +++ b/packages/SettingsLib/res/values-uz/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Faol (faqat chap)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Faol (faqat oʻng)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Faol (chap va oʻng)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Atrof-muhit yangilanmadi"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Faol (faqat media uchun) Quvvat: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Faol (faqat media uchun), quvvat: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> (L), <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> (R)"</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Ulangan (audio yuborish mumkin), quvvat: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml index b9617f7fd3f8..ffdd479f1bd4 100644 --- a/packages/SettingsLib/res/values-vi/strings.xml +++ b/packages/SettingsLib/res/values-vi/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Đang hoạt động (chỉ tai trái)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Đang hoạt động (chỉ tai phải)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Đang hoạt động (cả tai phải và tai trái)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Không cập nhật được âm lượng xung quanh"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Đang hoạt động (chỉ phát nội dung đa phương tiện). Còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pin."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Đang hoạt động (chỉ phát nội dung đa phương tiện). Bên trái: Còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> pin. Bên phải: Còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> pin."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Đã kết nối (có hỗ trợ tính năng chia sẻ âm thanh). Còn <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> pin."</string> diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml index 905b221d90e3..3b42efd2443e 100644 --- a/packages/SettingsLib/res/values-zh-rCN/strings.xml +++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"使用中(仅左耳助听器)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"使用中(仅右耳助听器)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"使用中(左右耳助听器)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"无法更新周围声音"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"使用中(仅限媒体)。电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"使用中(仅限媒体)。左侧电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>,右侧电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>。"</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"已连接(支持音频分享)。电池电量为 <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string> diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml index ccac068bbab4..a6de0d982cd9 100644 --- a/packages/SettingsLib/res/values-zh-rHK/strings.xml +++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"使用中 (僅左側)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"使用中 (僅右側)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"使用中 (左右兩側)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"無法更新環境聲音"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"啟用 (只限媒體)。<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> 電量。"</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"啟用 (只限媒體),左側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> 電量,右側:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> 電量。"</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"已連線 (支援音訊分享功能),<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> 電量。"</string> diff --git a/packages/SettingsLib/res/values-zh-rTW/arrays.xml b/packages/SettingsLib/res/values-zh-rTW/arrays.xml index b851f46016d0..c4d820c50549 100644 --- a/packages/SettingsLib/res/values-zh-rTW/arrays.xml +++ b/packages/SettingsLib/res/values-zh-rTW/arrays.xml @@ -296,7 +296,7 @@ <string-array name="shade_display_awareness_summaries"> <item msgid="2964753205732912921">"只在裝置螢幕顯示通知欄"</item> <item msgid="7795034287069726554">"在單一外接螢幕顯示通知欄"</item> - <item msgid="5280431949814340475">"在上一次使用的螢幕顯示通知欄"</item> + <item msgid="5280431949814340475">"在最新使用的螢幕顯示通知欄"</item> </string-array> <string-array name="shade_display_awareness_values"> <item msgid="3055776101992426514">"預設螢幕"</item> diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml index 3bd35648bd5d..e4d95e831137 100644 --- a/packages/SettingsLib/res/values-zh-rTW/strings.xml +++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"使用中 (僅左側)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"使用中 (僅右側)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"使用中 (左右兩側)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"無法更新環境狀態"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"已啟用 (僅限媒體)。電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"已啟用 (僅限媒體)。左側電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>,右側電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g>。"</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"已連線 (支援音訊分享)。電量:<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>。"</string> diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml index 7d964232485d..1f9eca4dd2e5 100644 --- a/packages/SettingsLib/res/values-zu/strings.xml +++ b/packages/SettingsLib/res/values-zu/strings.xml @@ -110,8 +110,7 @@ <string name="bluetooth_hearing_aid_left_active" msgid="8330226430756799572">"Iyasebenza (ngakwesokunxele kuphela)"</string> <string name="bluetooth_hearing_aid_right_active" msgid="2244728507170385397">"Iyasebenza (ngakwesokudla kuphela)"</string> <string name="bluetooth_hearing_aid_left_and_right_active" msgid="4294571497939983181">"Iyasebenza (ngakwesokunxele nakwesokudla)"</string> - <!-- no translation found for bluetooth_hearing_device_ambient_error (6035857289108813878) --> - <skip /> + <string name="bluetooth_hearing_device_ambient_error" msgid="6035857289108813878">"Ayikwazanga ukubuyekeza izindawo ezizungezile"</string> <string name="bluetooth_active_media_only_battery_level" msgid="7772517511061834073">"Iyasebenza (imidiya kuphela). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ibhethri."</string> <string name="bluetooth_active_media_only_battery_level_untethered" msgid="7444753133664620926">"Iyasebenza (imidiya kuphela). L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g>, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> ibhethri."</string> <string name="bluetooth_battery_level_lea_support" msgid="5968584103507988820">"Ixhunyiwe (isekela ukwabelana ngokuqoshiwe). <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> ibhethri."</string> diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.kt b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.kt index e01f27964733..c71b19c9235f 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.kt +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.kt @@ -501,7 +501,7 @@ open class WifiUtils { val wifiManager = context.getSystemService(WifiManager::class.java) ?: return@launch val aapmManager = context.getSystemService(AdvancedProtectionManager::class.java) if (isAdvancedProtectionEnabled(aapmManager)) { - val intent = aapmManager.createSupportIntent( + val intent = AdvancedProtectionManager.createSupportIntent( AdvancedProtectionManager.FEATURE_ID_DISALLOW_WEP, AdvancedProtectionManager.SUPPORT_DIALOG_TYPE_BLOCKED_INTERACTION) onStartActivity(intent) diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig index 7d201c18a141..715d22328f2b 100644 --- a/packages/SystemUI/aconfig/systemui.aconfig +++ b/packages/SystemUI/aconfig/systemui.aconfig @@ -457,6 +457,13 @@ flag { } flag { + name: "status_bar_signal_policy_refactor_ethernet" + namespace: "systemui" + description: "Use recommended architecture for ethernet icon in status bar" + bug: "291321279" +} + +flag { name: "status_bar_swipe_over_chip" namespace: "systemui" description: "Allow users to swipe over the status bar chip to open the shade" @@ -675,6 +682,16 @@ flag { } flag { + name: "clipboard_overlay_multiuser" + namespace: "systemui" + description: "Fix clipboard overlay for secondary users" + bug: "217922018" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { name: "clipboard_shared_transitions" namespace: "systemui" description: "Show shared transitions from clipboard" diff --git a/packages/SystemUI/animation/lib/src/com/android/systemui/animation/OriginRemoteTransition.java b/packages/SystemUI/animation/lib/src/com/android/systemui/animation/OriginRemoteTransition.java index 7d27a562f536..91fad4fb6dc2 100644 --- a/packages/SystemUI/animation/lib/src/com/android/systemui/animation/OriginRemoteTransition.java +++ b/packages/SystemUI/animation/lib/src/com/android/systemui/animation/OriginRemoteTransition.java @@ -43,6 +43,7 @@ import com.android.wm.shell.shared.TransitionUtil; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; /** * An implementation of {@link IRemoteTransition} that accepts a {@link UIComponent} as the origin @@ -52,6 +53,7 @@ import java.util.List; */ public class OriginRemoteTransition extends IRemoteTransition.Stub { private static final String TAG = "OriginRemoteTransition"; + private static final long FINISH_ANIMATION_TIMEOUT_MS = 100; private final Context mContext; private final boolean mIsEntry; @@ -248,23 +250,20 @@ public class OriginRemoteTransition extends IRemoteTransition.Stub { if (mIsEntry) { if (!closingSurfaces.isEmpty()) { - tmpTransaction - .setRelativeLayer(mOriginLeash, closingSurfaces.get(0), 1); + tmpTransaction.setRelativeLayer(mOriginLeash, closingSurfaces.get(0), 1); } else { logW("Missing closing surface is entry transition"); } if (!openingSurfaces.isEmpty()) { - tmpTransaction - .setRelativeLayer( - openingSurfaces.get(openingSurfaces.size() - 1), mOriginLeash, 1); + tmpTransaction.setRelativeLayer( + openingSurfaces.get(openingSurfaces.size() - 1), mOriginLeash, 1); } else { logW("Missing opening surface is entry transition"); } } else { if (!openingSurfaces.isEmpty()) { - tmpTransaction - .setRelativeLayer(mOriginLeash, openingSurfaces.get(0), 1); + tmpTransaction.setRelativeLayer(mOriginLeash, openingSurfaces.get(0), 1); } else { logW("Missing opening surface is exit transition"); } @@ -293,12 +292,26 @@ public class OriginRemoteTransition extends IRemoteTransition.Stub { private void finishAnimation(boolean finished) { logD("finishAnimation: finished=" + finished); + OneShotRunnable finishInternalRunnable = new OneShotRunnable(this::finishInternal); + Runnable timeoutRunnable = + () -> { + Log.w(TAG, "Timeout waiting for surface transaction!"); + finishInternalRunnable.run(); + }; + Runnable committedRunnable = + () -> { + // Remove the timeout runnable. + mHandler.removeCallbacks(timeoutRunnable); + finishInternalRunnable.run(); + }; if (mAnimator == null) { // The transition didn't start. Ensure we apply the start transaction and report // finish afterwards. mStartTransaction - .addTransactionCommittedListener(mHandler::post, this::finishInternal) + .addTransactionCommittedListener(mHandler::post, committedRunnable::run) .apply(); + // Call finishInternal() anyway after the timeout. + mHandler.postDelayed(timeoutRunnable, FINISH_ANIMATION_TIMEOUT_MS); return; } mAnimator = null; @@ -306,8 +319,10 @@ public class OriginRemoteTransition extends IRemoteTransition.Stub { mPlayer.onEnd(finished); // Detach the origin from the transition leash and report finish after it's done. mOriginTransaction - .detachFromTransitionLeash(mOrigin, mHandler::post, this::finishInternal) + .detachFromTransitionLeash(mOrigin, mHandler::post, committedRunnable) .commit(); + // Call finishInternal() anyway after the timeout. + mHandler.postDelayed(timeoutRunnable, FINISH_ANIMATION_TIMEOUT_MS); } private void finishInternal() { @@ -423,6 +438,23 @@ public class OriginRemoteTransition extends IRemoteTransition.Stub { return out; } + /** A {@link Runnable} that will only run once. */ + private static class OneShotRunnable implements Runnable { + private final AtomicBoolean mDone = new AtomicBoolean(); + private final Runnable mRunnable; + + OneShotRunnable(Runnable runnable) { + this.mRunnable = runnable; + } + + @Override + public void run() { + if (!mDone.getAndSet(true)) { + mRunnable.run(); + } + } + } + /** * An interface that represents an origin transitions. * diff --git a/packages/SystemUI/animation/lib/src/com/android/systemui/animation/ViewUIComponent.java b/packages/SystemUI/animation/lib/src/com/android/systemui/animation/ViewUIComponent.java index d0404ec02306..7c219c6ca921 100644 --- a/packages/SystemUI/animation/lib/src/com/android/systemui/animation/ViewUIComponent.java +++ b/packages/SystemUI/animation/lib/src/com/android/systemui/animation/ViewUIComponent.java @@ -29,6 +29,7 @@ import android.view.Surface; import android.view.SurfaceControl; import android.view.View; import android.view.ViewGroup; +import android.view.ViewRootImpl; import android.view.ViewTreeObserver.OnDrawListener; import java.util.ArrayList; @@ -131,7 +132,6 @@ public class ViewUIComponent implements UIComponent { mView.getViewTreeObserver().removeOnDrawListener(mOnDrawListener); // Restore view visibility mView.setVisibility(mVisibleOverride ? View.VISIBLE : View.INVISIBLE); - mView.invalidate(); // Clean up surfaces. SurfaceControl.Transaction t = new SurfaceControl.Transaction(); t.reparent(sc, null) @@ -142,8 +142,16 @@ public class ViewUIComponent implements UIComponent { sc.release(); executor.execute(onDone); }); - // Apply transaction AFTER the view is drawn. - mView.getRootSurfaceControl().applyTransactionOnDraw(t); + ViewRootImpl viewRoot = mView.getViewRootImpl(); + if (viewRoot == null) { + t.apply(); + } else { + // Apply transaction AFTER the view is drawn. + viewRoot.applyTransactionOnDraw(t); + // Request layout to force redrawing the entire view tree, so that the transaction is + // guaranteed to be applied. + viewRoot.requestLayout(); + } } @Override diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/ShortcutHelperCoreStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/ShortcutHelperCoreStartableTest.kt new file mode 100644 index 000000000000..b417616425c4 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/ShortcutHelperCoreStartableTest.kt @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2025 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.keyboard.shortcut + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.keyboard.shortcut.shared.model.ShortcutHelperState +import com.android.systemui.kosmos.testScope +import com.android.systemui.plugins.ActivityStarter +import com.android.systemui.plugins.activityStarter +import com.android.systemui.testKosmos +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.kotlin.any +import org.mockito.kotlin.doNothing +import org.mockito.kotlin.eq +import org.mockito.kotlin.whenever + +@SmallTest +@RunWith(AndroidJUnit4::class) +@OptIn(ExperimentalCoroutinesApi::class) +class ShortcutHelperCoreStartableTest : SysuiTestCase() { + private val kosmos = testKosmos() + private val repo = kosmos.shortcutHelperStateRepository + private val helper = kosmos.shortcutHelperTestHelper + private val testScope = kosmos.testScope + private val activityStarter = kosmos.activityStarter + + @Test + fun shortcutHelperState_whenToggled_doesNotBecomeActive_ifDeviceIsLocked() { + testScope.runTest { + assumedKeyguardIsNotDismissed() + + val state by collectLastValue(repo.state) + helper.toggle(deviceId = 456) + + assertThat(state).isEqualTo(ShortcutHelperState.Inactive) + } + } + + @Test + fun shortcutHelperState_whenToggled_becomesActive_ifDeviceIsUnlocked() { + testScope.runTest { + assumeKeyguardIsDismissed() + + val state by collectLastValue(repo.state) + helper.toggle(deviceId = 456) + + assertThat(state).isEqualTo(ShortcutHelperState.Active(deviceId = 456)) + } + } + + private fun assumeKeyguardIsDismissed(){ + whenever(activityStarter.dismissKeyguardThenExecute(any(), any(), eq(true))).then { + (it.arguments[0] as ActivityStarter.OnDismissAction).onDismiss() + } + } + + private fun assumedKeyguardIsNotDismissed(){ + // Do nothing, simulating keyguard not being dismissed and action not being not executed + doNothing().whenever(activityStarter).dismissKeyguardThenExecute(any(), any(), eq(true)) + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModelTest.kt index 78fce276a5f9..3fc46b973959 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModelTest.kt @@ -55,15 +55,15 @@ import com.android.systemui.keyboard.shortcut.shortcutHelperViewModel import com.android.systemui.keyboard.shortcut.ui.model.IconSource import com.android.systemui.keyboard.shortcut.ui.model.ShortcutCategoryUi import com.android.systemui.keyboard.shortcut.ui.model.ShortcutsUiState -import com.android.systemui.kosmos.Kosmos -import com.android.systemui.kosmos.testCase import com.android.systemui.kosmos.testDispatcher import com.android.systemui.kosmos.testScope +import com.android.systemui.kosmos.useUnconfinedTestDispatcher import com.android.systemui.model.sysUiState import com.android.systemui.settings.FakeUserTracker import com.android.systemui.settings.fakeUserTracker import com.android.systemui.settings.userTracker import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SHORTCUT_HELPER_SHOWING +import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.UnconfinedTestDispatcher @@ -89,8 +89,7 @@ class ShortcutHelperViewModelTest : SysuiTestCase() { private val mockApplicationInfo: ApplicationInfo = mock() private val kosmos = - Kosmos().also { - it.testCase = this + testKosmos().useUnconfinedTestDispatcher().also { it.testDispatcher = UnconfinedTestDispatcher() it.shortcutHelperSystemShortcutsSource = fakeSystemSource it.shortcutHelperMultiTaskingShortcutsSource = fakeMultiTaskingSource @@ -108,7 +107,6 @@ class ShortcutHelperViewModelTest : SysuiTestCase() { private val inputManager = kosmos.fakeInputManager.inputManager private val viewModel = kosmos.shortcutHelperViewModel - @Before fun setUp() { fakeSystemSource.setGroups(TestShortcuts.systemGroups) @@ -433,6 +431,28 @@ class ShortcutHelperViewModelTest : SysuiTestCase() { assertThat(activeUiState.shouldShowResetButton).isTrue() } + @Test + fun shortcutsUiState_searchQuery_isResetAfterHelperIsClosedAndReOpened() = + testScope.runTest{ + val uiState by collectLastValue(viewModel.shortcutsUiState) + + openHelperAndSearchForFooString() + assertThat((uiState as? ShortcutsUiState.Active)?.searchQuery).isEqualTo("foo") + + closeAndReopenShortcutHelper() + assertThat((uiState as? ShortcutsUiState.Active)?.searchQuery).isEqualTo("") + } + + private fun openHelperAndSearchForFooString(){ + testHelper.showFromActivity() + viewModel.onSearchQueryChanged("foo") + } + + private fun closeAndReopenShortcutHelper() { + viewModel.onViewClosed() + testHelper.showFromActivity() + } + private fun groupWithShortcutLabels( vararg shortcutLabels: String, groupLabel: String = FIRST_SIMPLE_GROUP_LABEL, diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/CommandQueueTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/CommandQueueTest.java index b730b3703515..2020d0dcb041 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/CommandQueueTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/CommandQueueTest.java @@ -18,6 +18,8 @@ import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE; import static android.inputmethodservice.InputMethodService.BACK_DISPOSITION_ADJUST_NOTHING; import static android.inputmethodservice.InputMethodService.BACK_DISPOSITION_DEFAULT; import static android.inputmethodservice.InputMethodService.IME_ACTIVE; +import static android.service.quickaccesswallet.Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP; +import static android.service.quickaccesswallet.Flags.FLAG_LAUNCH_WALLET_VIA_SYSUI_CALLBACKS; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.WindowInsetsController.BEHAVIOR_DEFAULT; @@ -367,6 +369,15 @@ public class CommandQueueTest extends SysuiTestCase { } @Test + @EnableFlags({FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP, + FLAG_LAUNCH_WALLET_VIA_SYSUI_CALLBACKS}) + public void testWalletLaunchGesture() { + mCommandQueue.onWalletLaunchGestureDetected(); + waitForIdleSync(); + verify(mCallbacks).onWalletLaunchGestureDetected(); + } + + @Test public void testShowPipMenu() { mCommandQueue.showPictureInPictureMenu(); waitForIdleSync(); diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/StatusBarSignalPolicyTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/StatusBarSignalPolicyTest.kt index 173055364018..bb9141afe404 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/StatusBarSignalPolicyTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/StatusBarSignalPolicyTest.kt @@ -25,104 +25,97 @@ import com.android.settingslib.mobile.TelephonyIcons import com.android.systemui.Flags.FLAG_STATUS_BAR_SIGNAL_POLICY_REFACTOR import com.android.systemui.SysuiTestCase import com.android.systemui.kosmos.Kosmos -import com.android.systemui.kosmos.testCase +import com.android.systemui.kosmos.runTest +import com.android.systemui.kosmos.testScope +import com.android.systemui.kosmos.useUnconfinedTestDispatcher import com.android.systemui.statusbar.connectivity.IconState import com.android.systemui.statusbar.connectivity.NetworkController import com.android.systemui.statusbar.phone.StatusBarSignalPolicy -import com.android.systemui.statusbar.phone.StatusBarSignalPolicy_Factory import com.android.systemui.statusbar.phone.ui.StatusBarIconController import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.airplaneModeInteractor +import com.android.systemui.statusbar.pipeline.ethernet.domain.ethernetInteractor +import com.android.systemui.statusbar.pipeline.ethernet.shared.StatusBarSignalPolicyRefactorEthernet +import com.android.systemui.statusbar.pipeline.shared.data.repository.connectivityRepository +import com.android.systemui.statusbar.pipeline.shared.data.repository.fake import com.android.systemui.statusbar.policy.SecurityController -import com.android.systemui.tuner.TunerService -import com.android.systemui.util.CarrierConfigTracker +import com.android.systemui.testKosmos +import com.android.systemui.tuner.tunerService import com.android.systemui.util.kotlin.JavaAdapter -import com.android.systemui.util.mockito.mock -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.test.TestScope -import kotlinx.coroutines.test.runCurrent -import kotlinx.coroutines.test.runTest +import kotlin.test.Test import org.junit.Before import org.junit.runner.RunWith import org.mockito.Mockito.verify import org.mockito.kotlin.clearInvocations +import org.mockito.kotlin.mock import org.mockito.kotlin.verifyNoMoreInteractions -import kotlin.test.Test -@OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWith(AndroidJUnit4::class) class StatusBarSignalPolicyTest : SysuiTestCase() { - private val kosmos = Kosmos().also { it.testCase = this } - - private lateinit var underTest: StatusBarSignalPolicy - - private val testScope = TestScope() - - private val javaAdapter = JavaAdapter(testScope.backgroundScope) - private val airplaneModeInteractor = kosmos.airplaneModeInteractor + private val kosmos = testKosmos().useUnconfinedTestDispatcher() + private val javaAdapter = JavaAdapter(kosmos.testScope.backgroundScope) private val securityController = mock<SecurityController>() - private val tunerService = mock<TunerService>() private val statusBarIconController = mock<StatusBarIconController>() private val networkController = mock<NetworkController>() - private val carrierConfigTracker = mock<CarrierConfigTracker>() - - private var slotAirplane: String? = null - @Before - fun setup() { - underTest = - StatusBarSignalPolicy_Factory.newInstance( + private val Kosmos.underTest by + Kosmos.Fixture { + StatusBarSignalPolicy( mContext, statusBarIconController, - carrierConfigTracker, networkController, securityController, tunerService, javaAdapter, airplaneModeInteractor, + ethernetInteractor, ) + } + private lateinit var slotAirplane: String + private lateinit var slotEthernet: String + + @Before + fun setup() { slotAirplane = mContext.getString(R.string.status_bar_airplane) + slotEthernet = mContext.getString(R.string.status_bar_ethernet) } @Test @EnableFlags(FLAG_STATUS_BAR_SIGNAL_POLICY_REFACTOR) fun airplaneModeViaInteractor_statusBarSignalPolicyRefactorFlagEnabled_iconUpdated() = - testScope.runTest { + kosmos.runTest { underTest.start() + clearInvocations(statusBarIconController) + airplaneModeInteractor.setIsAirplaneMode(true) - runCurrent() verify(statusBarIconController).setIconVisibility(slotAirplane, true) airplaneModeInteractor.setIsAirplaneMode(false) - runCurrent() verify(statusBarIconController).setIconVisibility(slotAirplane, false) } @Test @EnableFlags(FLAG_STATUS_BAR_SIGNAL_POLICY_REFACTOR) fun airplaneModeViaSignalCallback_statusBarSignalPolicyRefactorFlagEnabled_iconNotUpdated() = - testScope.runTest { + kosmos.runTest { underTest.start() - runCurrent() clearInvocations(statusBarIconController) // Make sure the legacy code path does not change airplane mode when the refactor // flag is enabled. underTest.setIsAirplaneMode(IconState(true, TelephonyIcons.FLIGHT_MODE_ICON, "")) - runCurrent() verifyNoMoreInteractions(statusBarIconController) underTest.setIsAirplaneMode(IconState(false, TelephonyIcons.FLIGHT_MODE_ICON, "")) - runCurrent() verifyNoMoreInteractions(statusBarIconController) } @Test @EnableFlags(FLAG_STATUS_BAR_SIGNAL_POLICY_REFACTOR) fun statusBarSignalPolicyInitialization_statusBarSignalPolicyRefactorFlagEnabled_initNoOp() = - testScope.runTest { + kosmos.runTest { // Make sure StatusBarSignalPolicy.init does no initialization when // the refactor flag is disabled. underTest.init() @@ -132,42 +125,126 @@ class StatusBarSignalPolicyTest : SysuiTestCase() { @Test @DisableFlags(FLAG_STATUS_BAR_SIGNAL_POLICY_REFACTOR) fun airplaneModeViaSignalCallback_statusBarSignalPolicyRefactorFlagDisabled_iconUpdated() = - testScope.runTest { + kosmos.runTest { underTest.init() underTest.setIsAirplaneMode(IconState(true, TelephonyIcons.FLIGHT_MODE_ICON, "")) - runCurrent() verify(statusBarIconController).setIconVisibility(slotAirplane, true) underTest.setIsAirplaneMode(IconState(false, TelephonyIcons.FLIGHT_MODE_ICON, "")) - runCurrent() verify(statusBarIconController).setIconVisibility(slotAirplane, false) } @Test @DisableFlags(FLAG_STATUS_BAR_SIGNAL_POLICY_REFACTOR) fun airplaneModeViaInteractor_statusBarSignalPolicyRefactorFlagDisabled_iconNotUpdated() = - testScope.runTest { + kosmos.runTest { underTest.init() // Make sure changing airplane mode from airplaneModeRepository does nothing // if the StatusBarSignalPolicyRefactor is not enabled. airplaneModeInteractor.setIsAirplaneMode(true) - runCurrent() verifyNoMoreInteractions(statusBarIconController) airplaneModeInteractor.setIsAirplaneMode(false) - runCurrent() verifyNoMoreInteractions(statusBarIconController) } @Test @DisableFlags(FLAG_STATUS_BAR_SIGNAL_POLICY_REFACTOR) fun statusBarSignalPolicyInitialization_statusBarSignalPolicyRefactorFlagDisabled_startNoOp() = - testScope.runTest { + kosmos.runTest { // Make sure StatusBarSignalPolicy.start does no initialization when // the refactor flag is disabled. underTest.start() verifyNoMoreInteractions(securityController, networkController, tunerService) } + + @Test + @EnableFlags(FLAG_STATUS_BAR_SIGNAL_POLICY_REFACTOR) + @DisableFlags(StatusBarSignalPolicyRefactorEthernet.FLAG_NAME) + fun ethernetIconViaSignalCallback_refactorFlagDisabled_iconUpdated() = + kosmos.runTest { + underTest.start() + clearInvocations(statusBarIconController) + + underTest.setEthernetIndicators( + IconState(/* visible= */ true, /* icon= */ 1, /* contentDescription= */ "Ethernet") + ) + verify(statusBarIconController).setIconVisibility(slotEthernet, true) + + underTest.setEthernetIndicators( + IconState( + /* visible= */ false, + /* icon= */ 0, + /* contentDescription= */ "No ethernet", + ) + ) + verify(statusBarIconController).setIconVisibility(slotEthernet, false) + } + + @Test + @EnableFlags( + FLAG_STATUS_BAR_SIGNAL_POLICY_REFACTOR, + StatusBarSignalPolicyRefactorEthernet.FLAG_NAME, + ) + fun ethernetIconViaSignalCallback_refactorFlagEnabled_iconNotUpdated() = + kosmos.runTest { + underTest.start() + clearInvocations(statusBarIconController) + + underTest.setEthernetIndicators( + IconState(/* visible= */ true, /* icon= */ 1, /* contentDescription= */ "Ethernet") + ) + verifyNoMoreInteractions(statusBarIconController) + + underTest.setEthernetIndicators( + IconState( + /* visible= */ false, + /* icon= */ 0, + /* contentDescription= */ "No ethernet", + ) + ) + verifyNoMoreInteractions(statusBarIconController) + } + + @Test + @EnableFlags(FLAG_STATUS_BAR_SIGNAL_POLICY_REFACTOR) + @DisableFlags(StatusBarSignalPolicyRefactorEthernet.FLAG_NAME) + fun ethernetIconViaInteractor_refactorFlagDisabled_iconNotUpdated() = + kosmos.runTest { + underTest.start() + clearInvocations(statusBarIconController) + + connectivityRepository.fake.setEthernetConnected(default = true, validated = true) + verifyNoMoreInteractions(statusBarIconController) + + connectivityRepository.fake.setEthernetConnected(default = false, validated = false) + verifyNoMoreInteractions(statusBarIconController) + + connectivityRepository.fake.setEthernetConnected(default = true, validated = false) + verifyNoMoreInteractions(statusBarIconController) + } + + @Test + @EnableFlags( + FLAG_STATUS_BAR_SIGNAL_POLICY_REFACTOR, + StatusBarSignalPolicyRefactorEthernet.FLAG_NAME, + ) + fun ethernetIconViaInteractor_refactorFlagEnabled_iconUpdated() = + kosmos.runTest { + underTest.start() + clearInvocations(statusBarIconController) + + connectivityRepository.fake.setEthernetConnected(default = true, validated = true) + verify(statusBarIconController).setIconVisibility(slotEthernet, true) + + connectivityRepository.fake.setEthernetConnected(default = false, validated = false) + verify(statusBarIconController).setIconVisibility(slotEthernet, false) + + clearInvocations(statusBarIconController) + + connectivityRepository.fake.setEthernetConnected(default = true, validated = false) + verify(statusBarIconController).setIconVisibility(slotEthernet, true) + } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/demo/ui/viewmodel/DemoNotifChipViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/demo/ui/viewmodel/DemoNotifChipViewModelTest.kt deleted file mode 100644 index 69a76271f726..000000000000 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/demo/ui/viewmodel/DemoNotifChipViewModelTest.kt +++ /dev/null @@ -1,146 +0,0 @@ -/* - * 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.chips.notification.demo.ui.viewmodel - -import android.content.packageManager -import android.graphics.drawable.BitmapDrawable -import android.platform.test.annotations.DisableFlags -import android.platform.test.annotations.EnableFlags -import androidx.test.filters.SmallTest -import com.android.systemui.SysuiTestCase -import com.android.systemui.coroutines.collectLastValue -import com.android.systemui.kosmos.testScope -import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips -import com.android.systemui.statusbar.chips.ui.model.ColorsModel -import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel -import com.android.systemui.statusbar.commandline.CommandRegistry -import com.android.systemui.statusbar.commandline.commandRegistry -import com.android.systemui.testKosmos -import com.google.common.truth.Truth.assertThat -import java.io.PrintWriter -import java.io.StringWriter -import kotlin.test.Test -import kotlinx.coroutines.test.runTest -import org.junit.Before -import org.mockito.kotlin.any -import org.mockito.kotlin.whenever - -@SmallTest -class DemoNotifChipViewModelTest : SysuiTestCase() { - private val kosmos = testKosmos() - private val testScope = kosmos.testScope - private val commandRegistry = kosmos.commandRegistry - private val pw = PrintWriter(StringWriter()) - - private val underTest = kosmos.demoNotifChipViewModel - - @Before - fun setUp() { - underTest.start() - whenever(kosmos.packageManager.getApplicationIcon(any<String>())) - .thenReturn(BitmapDrawable()) - } - - @Test - @DisableFlags(StatusBarNotifChips.FLAG_NAME) - fun chip_flagOff_hidden() = - testScope.runTest { - val latest by collectLastValue(underTest.chip) - - addDemoNotifChip() - - assertThat(latest).isInstanceOf(OngoingActivityChipModel.Hidden::class.java) - } - - @Test - @EnableFlags(StatusBarNotifChips.FLAG_NAME) - fun chip_noPackage_hidden() = - testScope.runTest { - val latest by collectLastValue(underTest.chip) - - commandRegistry.onShellCommand(pw, arrayOf("demo-notif")) - - assertThat(latest).isInstanceOf(OngoingActivityChipModel.Hidden::class.java) - } - - @Test - @EnableFlags(StatusBarNotifChips.FLAG_NAME) - fun chip_hasPackage_shown() = - testScope.runTest { - val latest by collectLastValue(underTest.chip) - - commandRegistry.onShellCommand(pw, arrayOf("demo-notif", "-p", "com.android.systemui")) - - assertThat(latest).isInstanceOf(OngoingActivityChipModel.Shown::class.java) - } - - @Test - @EnableFlags(StatusBarNotifChips.FLAG_NAME) - fun chip_hasText_shownWithText() = - testScope.runTest { - val latest by collectLastValue(underTest.chip) - - commandRegistry.onShellCommand( - pw, - arrayOf("demo-notif", "-p", "com.android.systemui", "-t", "test"), - ) - - assertThat(latest).isInstanceOf(OngoingActivityChipModel.Shown.Text::class.java) - } - - @Test - @EnableFlags(StatusBarNotifChips.FLAG_NAME) - fun chip_supportsColor() = - testScope.runTest { - val latest by collectLastValue(underTest.chip) - - commandRegistry.onShellCommand( - pw, - arrayOf("demo-notif", "-p", "com.android.systemui", "-c", "#434343"), - ) - - assertThat(latest).isInstanceOf(OngoingActivityChipModel.Shown::class.java) - assertThat((latest as OngoingActivityChipModel.Shown).colors) - .isInstanceOf(ColorsModel.Custom::class.java) - } - - @Test - @EnableFlags(StatusBarNotifChips.FLAG_NAME) - fun chip_hasHideArg_hidden() = - testScope.runTest { - val latest by collectLastValue(underTest.chip) - - // First, show a chip - addDemoNotifChip() - assertThat(latest).isInstanceOf(OngoingActivityChipModel.Shown::class.java) - - // Then, hide the chip - commandRegistry.onShellCommand(pw, arrayOf("demo-notif", "--hide")) - - assertThat(latest).isInstanceOf(OngoingActivityChipModel.Hidden::class.java) - } - - private fun addDemoNotifChip() { - addDemoNotifChip(commandRegistry, pw) - } - - companion object { - fun addDemoNotifChip(commandRegistry: CommandRegistry, pw: PrintWriter) { - commandRegistry.onShellCommand(pw, arrayOf("demo-notif", "-p", "com.android.systemui")) - } - } -} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/domain/interactor/SingleNotificationChipInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/domain/interactor/SingleNotificationChipInteractorTest.kt index 9ad1f409a8ea..0d033a4098ec 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/domain/interactor/SingleNotificationChipInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/domain/interactor/SingleNotificationChipInteractorTest.kt @@ -52,7 +52,7 @@ class SingleNotificationChipInteractorTest : SysuiTestCase() { promotedContent = PROMOTED_CONTENT, ) - val underTest = factory.create(startingNotif) + val underTest = factory.create(startingNotif, creationTime = 1) val latest by collectLastValue(underTest.notificationChip) @@ -71,7 +71,8 @@ class SingleNotificationChipInteractorTest : SysuiTestCase() { key = "notif1", statusBarChipIcon = originalIconView, promotedContent = PROMOTED_CONTENT, - ) + ), + creationTime = 1, ) val latest by collectLastValue(underTest.notificationChip) @@ -99,7 +100,8 @@ class SingleNotificationChipInteractorTest : SysuiTestCase() { key = "notif1", statusBarChipIcon = originalIconView, promotedContent = PROMOTED_CONTENT, - ) + ), + creationTime = 1, ) val latest by collectLastValue(underTest.notificationChip) @@ -127,7 +129,8 @@ class SingleNotificationChipInteractorTest : SysuiTestCase() { key = "notif1", statusBarChipIcon = originalIconView, promotedContent = PROMOTED_CONTENT, - ) + ), + creationTime = 1, ) val latest by collectLastValue(underTest.notificationChip) @@ -153,7 +156,8 @@ class SingleNotificationChipInteractorTest : SysuiTestCase() { key = "notif1", statusBarChipIcon = null, promotedContent = PROMOTED_CONTENT, - ) + ), + creationTime = 1, ) val latest by collectLastValue(underTest.notificationChip) @@ -171,7 +175,8 @@ class SingleNotificationChipInteractorTest : SysuiTestCase() { key = "notif1", statusBarChipIcon = null, promotedContent = PROMOTED_CONTENT, - ) + ), + creationTime = 1, ) val latest by collectLastValue(underTest.notificationChip) @@ -189,7 +194,7 @@ class SingleNotificationChipInteractorTest : SysuiTestCase() { statusBarChipIcon = mock(), promotedContent = PROMOTED_CONTENT, ) - val underTest = factory.create(startingNotif) + val underTest = factory.create(startingNotif, creationTime = 1) val latest by collectLastValue(underTest.notificationChip) assertThat(latest).isNotNull() @@ -214,7 +219,7 @@ class SingleNotificationChipInteractorTest : SysuiTestCase() { statusBarChipIcon = mock(), promotedContent = PROMOTED_CONTENT, ) - val underTest = factory.create(startingNotif) + val underTest = factory.create(startingNotif, creationTime = 1) val latest by collectLastValue(underTest.notificationChip) assertThat(latest).isNotNull() @@ -239,7 +244,8 @@ class SingleNotificationChipInteractorTest : SysuiTestCase() { key = "notif1", statusBarChipIcon = mock(), promotedContent = null, - ) + ), + creationTime = 1, ) val latest by collectLastValue(underTest.notificationChip) @@ -259,7 +265,8 @@ class SingleNotificationChipInteractorTest : SysuiTestCase() { uid = UID, statusBarChipIcon = mock(), promotedContent = PROMOTED_CONTENT, - ) + ), + creationTime = 1, ) val latest by collectLastValue(underTest.notificationChip) @@ -279,7 +286,8 @@ class SingleNotificationChipInteractorTest : SysuiTestCase() { uid = UID, statusBarChipIcon = mock(), promotedContent = PROMOTED_CONTENT, - ) + ), + creationTime = 1, ) val latest by collectLastValue(underTest.notificationChip) @@ -297,7 +305,8 @@ class SingleNotificationChipInteractorTest : SysuiTestCase() { uid = UID, statusBarChipIcon = mock(), promotedContent = PROMOTED_CONTENT, - ) + ), + creationTime = 1, ) val latest by collectLastValue(underTest.notificationChip) @@ -330,7 +339,8 @@ class SingleNotificationChipInteractorTest : SysuiTestCase() { uid = hiddenUid, statusBarChipIcon = mock(), promotedContent = PROMOTED_CONTENT, - ) + ), + creationTime = 1, ) val latest by collectLastValue(underTest.notificationChip) assertThat(latest).isNotNull() diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/domain/interactor/StatusBarNotificationChipsInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/domain/interactor/StatusBarNotificationChipsInteractorTest.kt index 5a894ca895c3..f703d785ceac 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/domain/interactor/StatusBarNotificationChipsInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/notification/domain/interactor/StatusBarNotificationChipsInteractorTest.kt @@ -23,7 +23,10 @@ import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue import com.android.systemui.coroutines.collectValues -import com.android.systemui.kosmos.testScope +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.collectLastValue +import com.android.systemui.kosmos.collectValues +import com.android.systemui.kosmos.runTest import com.android.systemui.kosmos.useUnconfinedTestDispatcher import com.android.systemui.statusbar.StatusBarIconView import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips @@ -33,6 +36,7 @@ import com.android.systemui.statusbar.notification.data.repository.activeNotific import com.android.systemui.statusbar.notification.promoted.shared.model.PromotedNotificationContentModel import com.android.systemui.statusbar.notification.shared.ActiveNotificationModel import com.android.systemui.testKosmos +import com.android.systemui.util.time.fakeSystemClock import com.google.common.truth.Truth.assertThat import kotlin.test.Test import kotlinx.coroutines.test.runTest @@ -43,17 +47,14 @@ import org.mockito.kotlin.mock @RunWith(AndroidJUnit4::class) class StatusBarNotificationChipsInteractorTest : SysuiTestCase() { private val kosmos = testKosmos().useUnconfinedTestDispatcher() - private val testScope = kosmos.testScope - private val activeNotificationListRepository = kosmos.activeNotificationListRepository - private val underTest by lazy { - kosmos.statusBarNotificationChipsInteractor.also { it.start() } - } + private val Kosmos.underTest by + Kosmos.Fixture { statusBarNotificationChipsInteractor.also { it.start() } } @Test @DisableFlags(StatusBarNotifChips.FLAG_NAME) fun notificationChips_flagOff_noNotifs() = - testScope.runTest { + kosmos.runTest { val latest by collectLastValue(underTest.notificationChips) setNotifs( @@ -72,7 +73,7 @@ class StatusBarNotificationChipsInteractorTest : SysuiTestCase() { @Test @EnableFlags(StatusBarNotifChips.FLAG_NAME) fun notificationChips_noNotifs_empty() = - testScope.runTest { + kosmos.runTest { val latest by collectLastValue(underTest.notificationChips) setNotifs(emptyList()) @@ -83,7 +84,7 @@ class StatusBarNotificationChipsInteractorTest : SysuiTestCase() { @Test @EnableFlags(StatusBarNotifChips.FLAG_NAME) fun notificationChips_notifMissingStatusBarChipIconView_empty() = - testScope.runTest { + kosmos.runTest { val latest by collectLastValue(underTest.notificationChips) setNotifs( @@ -102,7 +103,7 @@ class StatusBarNotificationChipsInteractorTest : SysuiTestCase() { @Test @EnableFlags(StatusBarNotifChips.FLAG_NAME) fun notificationChips_onePromotedNotif_statusBarIconViewMatches() = - testScope.runTest { + kosmos.runTest { val latest by collectLastValue(underTest.notificationChips) val icon = mock<StatusBarIconView>() @@ -124,7 +125,7 @@ class StatusBarNotificationChipsInteractorTest : SysuiTestCase() { @Test @EnableFlags(StatusBarNotifChips.FLAG_NAME) fun notificationChips_onlyForPromotedNotifs() = - testScope.runTest { + kosmos.runTest { val latest by collectLastValue(underTest.notificationChips) val firstIcon = mock<StatusBarIconView>() @@ -159,7 +160,7 @@ class StatusBarNotificationChipsInteractorTest : SysuiTestCase() { @Test @EnableFlags(StatusBarNotifChips.FLAG_NAME) fun notificationChips_notifUpdatesGoThrough() = - testScope.runTest { + kosmos.runTest { val latest by collectLastValue(underTest.notificationChips) val firstIcon = mock<StatusBarIconView>() @@ -209,7 +210,7 @@ class StatusBarNotificationChipsInteractorTest : SysuiTestCase() { @Test @EnableFlags(StatusBarNotifChips.FLAG_NAME) fun notificationChips_promotedNotifDisappearsThenReappears() = - testScope.runTest { + kosmos.runTest { val latest by collectLastValue(underTest.notificationChips) setNotifs( @@ -250,8 +251,95 @@ class StatusBarNotificationChipsInteractorTest : SysuiTestCase() { @Test @EnableFlags(StatusBarNotifChips.FLAG_NAME) + fun notificationChips_sortedBasedOnFirstAppearanceTime() = + kosmos.runTest { + val latest by collectLastValue(underTest.notificationChips) + + val firstIcon = mock<StatusBarIconView>() + val secondIcon = mock<StatusBarIconView>() + + // First, add notif1 at t=1000 + fakeSystemClock.setCurrentTimeMillis(1000) + val notif1 = + activeNotificationModel( + key = "notif1", + statusBarChipIcon = firstIcon, + promotedContent = PromotedNotificationContentModel.Builder("notif1").build(), + ) + setNotifs(listOf(notif1)) + assertThat(latest).hasSize(1) + assertThat(latest!![0].key).isEqualTo("notif1") + + // WHEN we add notif2 at t=2000 + fakeSystemClock.advanceTime(1000) + val notif2 = + activeNotificationModel( + key = "notif2", + statusBarChipIcon = secondIcon, + promotedContent = PromotedNotificationContentModel.Builder("notif2").build(), + ) + setNotifs(listOf(notif1, notif2)) + + // THEN notif2 is ranked above notif1 because it appeared later + assertThat(latest).hasSize(2) + assertThat(latest!![0].key).isEqualTo("notif2") + assertThat(latest!![1].key).isEqualTo("notif1") + + // WHEN notif1 and notif2 swap places + setNotifs(listOf(notif2, notif1)) + + // THEN notif2 is still ranked above notif1 to preserve chip ordering + assertThat(latest).hasSize(2) + assertThat(latest!![0].key).isEqualTo("notif2") + assertThat(latest!![1].key).isEqualTo("notif1") + + // WHEN notif1 and notif2 swap places again + setNotifs(listOf(notif1, notif2)) + + // THEN notif2 is still ranked above notif1 to preserve chip ordering + assertThat(latest).hasSize(2) + assertThat(latest!![0].key).isEqualTo("notif2") + assertThat(latest!![1].key).isEqualTo("notif1") + + // WHEN notif1 gets an update + val notif1NewPromotedContent = + PromotedNotificationContentModel.Builder("notif1").apply { + this.shortCriticalText = "Arrived" + } + setNotifs( + listOf( + activeNotificationModel( + key = "notif1", + statusBarChipIcon = firstIcon, + promotedContent = notif1NewPromotedContent.build(), + ), + notif2, + ) + ) + + // THEN notif2 is still ranked above notif1 to preserve chip ordering + assertThat(latest).hasSize(2) + assertThat(latest!![0].key).isEqualTo("notif2") + assertThat(latest!![1].key).isEqualTo("notif1") + + // WHEN notif1 disappears and then reappears + fakeSystemClock.advanceTime(1000) + setNotifs(listOf(notif2)) + assertThat(latest).hasSize(1) + + fakeSystemClock.advanceTime(1000) + setNotifs(listOf(notif2, notif1)) + + // THEN notif1 is now ranked first + assertThat(latest).hasSize(2) + assertThat(latest!![0].key).isEqualTo("notif1") + assertThat(latest!![1].key).isEqualTo("notif2") + } + + @Test + @EnableFlags(StatusBarNotifChips.FLAG_NAME) fun notificationChips_notifChangesKey() = - testScope.runTest { + kosmos.runTest { val latest by collectLastValue(underTest.notificationChips) val firstIcon = mock<StatusBarIconView>() @@ -291,7 +379,7 @@ class StatusBarNotificationChipsInteractorTest : SysuiTestCase() { @Test @EnableFlags(StatusBarNotifChips.FLAG_NAME) fun onPromotedNotificationChipTapped_emitsKeys() = - testScope.runTest { + kosmos.runTest { val latest by collectValues(underTest.promotedNotificationChipTapEvent) underTest.onPromotedNotificationChipTapped("fakeKey") @@ -308,7 +396,7 @@ class StatusBarNotificationChipsInteractorTest : SysuiTestCase() { @Test @EnableFlags(StatusBarNotifChips.FLAG_NAME) fun onPromotedNotificationChipTapped_sameKeyTwice_emitsTwice() = - testScope.runTest { + kosmos.runTest { val latest by collectValues(underTest.promotedNotificationChipTapEvent) underTest.onPromotedNotificationChipTapped("fakeKey") @@ -319,7 +407,7 @@ class StatusBarNotificationChipsInteractorTest : SysuiTestCase() { assertThat(latest[1]).isEqualTo("fakeKey") } - private fun setNotifs(notifs: List<ActiveNotificationModel>) { + private fun Kosmos.setNotifs(notifs: List<ActiveNotificationModel>) { activeNotificationListRepository.activeNotifications.value = ActiveNotificationsStore.Builder() .apply { notifs.forEach { addIndividualNotif(it) } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt index c5c2a94cf0ea..4fb42e94adb2 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt @@ -38,7 +38,6 @@ import com.android.systemui.screenrecord.data.model.ScreenRecordModel import com.android.systemui.screenrecord.data.repository.screenRecordRepository import com.android.systemui.statusbar.chips.mediaprojection.domain.interactor.MediaProjectionChipInteractorTest.Companion.NORMAL_PACKAGE import com.android.systemui.statusbar.chips.mediaprojection.domain.interactor.MediaProjectionChipInteractorTest.Companion.setUpPackageManagerForMediaProjection -import com.android.systemui.statusbar.chips.notification.demo.ui.viewmodel.demoNotifChipViewModel import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer @@ -97,7 +96,6 @@ class OngoingActivityChipsViewModelTest : SysuiTestCase() { @Before fun setUp() { setUpPackageManagerForMediaProjection(kosmos) - kosmos.demoNotifChipViewModel.start() val icon = BitmapDrawable( context.resources, diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsWithNotifsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsWithNotifsViewModelTest.kt index b2e7febd1743..0050ebee64d6 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsWithNotifsViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsWithNotifsViewModelTest.kt @@ -37,8 +37,6 @@ import com.android.systemui.screenrecord.data.repository.screenRecordRepository import com.android.systemui.statusbar.StatusBarIconView import com.android.systemui.statusbar.chips.mediaprojection.domain.interactor.MediaProjectionChipInteractorTest.Companion.NORMAL_PACKAGE import com.android.systemui.statusbar.chips.mediaprojection.domain.interactor.MediaProjectionChipInteractorTest.Companion.setUpPackageManagerForMediaProjection -import com.android.systemui.statusbar.chips.notification.demo.ui.viewmodel.DemoNotifChipViewModelTest.Companion.addDemoNotifChip -import com.android.systemui.statusbar.chips.notification.demo.ui.viewmodel.demoNotifChipViewModel import com.android.systemui.statusbar.chips.notification.domain.interactor.statusBarNotificationChipsInteractor import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips import com.android.systemui.statusbar.chips.notification.ui.viewmodel.NotifChipsViewModelTest.Companion.assertIsNotifChip @@ -112,7 +110,6 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() { @Before fun setUp() { setUpPackageManagerForMediaProjection(kosmos) - kosmos.demoNotifChipViewModel.start() kosmos.statusBarNotificationChipsInteractor.start() val icon = BitmapDrawable( @@ -255,20 +252,6 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() { } @Test - fun chips_threeActiveChips_topTwoShown() = - testScope.runTest { - screenRecordState.value = ScreenRecordModel.Recording - callRepo.setOngoingCallState(inCallModel(startTimeMs = 34)) - addDemoNotifChip(commandRegistry, pw) - - val latest by collectLastValue(underTest.chips) - - assertIsScreenRecordChip(latest!!.primary) - assertIsCallChip(latest!!.secondary) - // Demo notif chip is dropped - } - - @Test fun primaryChip_onlyCallShown_callShown() = testScope.runTest { screenRecordState.value = ScreenRecordModel.DoingNothing @@ -433,7 +416,16 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() { fun primaryChip_higherPriorityChipAdded_lowerPriorityChipReplaced() = testScope.runTest { // Start with just the lowest priority chip shown - addDemoNotifChip(commandRegistry, pw) + val notifIcon = mock<StatusBarIconView>() + setNotifs( + listOf( + activeNotificationModel( + key = "notif", + statusBarChipIcon = notifIcon, + promotedContent = PromotedNotificationContentModel.Builder("notif").build(), + ) + ) + ) // And everything else hidden callRepo.setOngoingCallState(OngoingCallModel.NoCall) mediaProjectionState.value = MediaProjectionState.NotProjecting @@ -441,7 +433,7 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() { val latest by collectLastValue(underTest.primaryChip) - assertIsDemoNotifChip(latest) + assertIsNotifChip(latest, notifIcon) // WHEN the higher priority call chip is added callRepo.setOngoingCallState(inCallModel(startTimeMs = 34)) @@ -475,7 +467,16 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() { mediaProjectionState.value = MediaProjectionState.Projecting.EntireScreen(NORMAL_PACKAGE) callRepo.setOngoingCallState(inCallModel(startTimeMs = 34)) - addDemoNotifChip(commandRegistry, pw) + val notifIcon = mock<StatusBarIconView>() + setNotifs( + listOf( + activeNotificationModel( + key = "notif", + statusBarChipIcon = notifIcon, + promotedContent = PromotedNotificationContentModel.Builder("notif").build(), + ) + ) + ) val latest by collectLastValue(underTest.primaryChip) @@ -497,15 +498,24 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() { // WHEN the higher priority call is removed callRepo.setOngoingCallState(OngoingCallModel.NoCall) - // THEN the lower priority demo notif is used - assertIsDemoNotifChip(latest) + // THEN the lower priority notif is used + assertIsNotifChip(latest, notifIcon) } @Test fun chips_movesChipsAroundAccordingToPriority() = testScope.runTest { // Start with just the lowest priority chip shown - addDemoNotifChip(commandRegistry, pw) + val notifIcon = mock<StatusBarIconView>() + setNotifs( + listOf( + activeNotificationModel( + key = "notif", + statusBarChipIcon = notifIcon, + promotedContent = PromotedNotificationContentModel.Builder("notif").build(), + ) + ) + ) // And everything else hidden callRepo.setOngoingCallState(OngoingCallModel.NoCall) mediaProjectionState.value = MediaProjectionState.NotProjecting @@ -513,16 +523,16 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() { val latest by collectLastValue(underTest.chips) - assertIsDemoNotifChip(latest!!.primary) + assertIsNotifChip(latest!!.primary, notifIcon) assertThat(latest!!.secondary).isInstanceOf(OngoingActivityChipModel.Hidden::class.java) // WHEN the higher priority call chip is added callRepo.setOngoingCallState(inCallModel(startTimeMs = 34)) - // THEN the higher priority call chip is used as primary and demo notif is demoted to + // THEN the higher priority call chip is used as primary and notif is demoted to // secondary assertIsCallChip(latest!!.primary) - assertIsDemoNotifChip(latest!!.secondary) + assertIsNotifChip(latest!!.secondary, notifIcon) // WHEN the higher priority media projection chip is added mediaProjectionState.value = @@ -533,7 +543,7 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() { ) // THEN the higher priority media projection chip is used as primary and call is demoted - // to secondary (and demo notif is dropped altogether) + // to secondary (and notif is dropped altogether) assertIsShareToAppChip(latest!!.primary) assertIsCallChip(latest!!.secondary) @@ -547,15 +557,15 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() { screenRecordState.value = ScreenRecordModel.DoingNothing callRepo.setOngoingCallState(OngoingCallModel.NoCall) - // THEN media projection and demo notif remain + // THEN media projection and notif remain assertIsShareToAppChip(latest!!.primary) - assertIsDemoNotifChip(latest!!.secondary) + assertIsNotifChip(latest!!.secondary, notifIcon) // WHEN media projection is dropped mediaProjectionState.value = MediaProjectionState.NotProjecting - // THEN demo notif is promoted to primary - assertIsDemoNotifChip(latest!!.primary) + // THEN notif is promoted to primary + assertIsNotifChip(latest!!.primary, notifIcon) assertThat(latest!!.secondary).isInstanceOf(OngoingActivityChipModel.Hidden::class.java) } @@ -669,12 +679,6 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() { assertThat(latest).isEqualTo(OngoingActivityChipModel.Hidden(shouldAnimate = false)) } - private fun assertIsDemoNotifChip(latest: OngoingActivityChipModel?) { - assertThat(latest).isInstanceOf(OngoingActivityChipModel.Shown::class.java) - assertThat((latest as OngoingActivityChipModel.Shown).icon) - .isInstanceOf(OngoingActivityChipModel.ChipIcon.FullColorAppIcon::class.java) - } - private fun setNotifs(notifs: List<ActiveNotificationModel>) { activeNotificationListRepository.activeNotifications.value = ActiveNotificationsStore.Builder() diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java index f502cabc21ec..809df4196ac6 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java @@ -676,14 +676,6 @@ public class NetworkControllerBaseTest extends SysuiTestCase { } } - protected void verifyLastCallStrength(int icon) { - ArgumentCaptor<IconState> iconArg = ArgumentCaptor.forClass(IconState.class); - verify(mCallbackHandler, Mockito.atLeastOnce()).setCallIndicator( - iconArg.capture(), - anyInt()); - assertEquals("Call strength, in status bar", icon, (int) iconArg.getValue().icon); - } - protected void assertNetworkNameEquals(String expected) { assertEquals("Network name", expected, mMobileSignalController.getState().networkName); } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/core/StatusBarOrchestratorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/core/StatusBarOrchestratorTest.kt index 659e53f4addd..04c5bd930e72 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/core/StatusBarOrchestratorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/core/StatusBarOrchestratorTest.kt @@ -38,9 +38,9 @@ import com.android.systemui.statusbar.data.model.StatusBarMode.LIGHTS_OUT_TRANSP import com.android.systemui.statusbar.data.model.StatusBarMode.OPAQUE import com.android.systemui.statusbar.data.model.StatusBarMode.TRANSPARENT import com.android.systemui.statusbar.data.repository.fakeStatusBarModePerDisplayRepository -import com.android.systemui.statusbar.window.data.model.StatusBarWindowState import com.android.systemui.statusbar.window.data.repository.fakeStatusBarWindowStatePerDisplayRepository import com.android.systemui.statusbar.window.fakeStatusBarWindowController +import com.android.systemui.statusbar.window.shared.model.StatusBarWindowState import com.android.systemui.testKosmos import com.android.wm.shell.bubbles.bubbles import com.google.common.truth.Truth.assertThat diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java index 7f139bd69a37..f318c74e0584 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacksTest.java @@ -65,6 +65,7 @@ import com.android.systemui.statusbar.notification.stack.NotificationStackScroll import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler; +import com.android.systemui.wallet.controller.QuickAccessWalletController; import org.junit.Before; import org.junit.Test; @@ -111,6 +112,7 @@ public class CentralSurfacesCommandQueueCallbacksTest extends SysuiTestCase { @Mock private EmergencyGestureIntentFactory mEmergencyGestureIntentFactory; @Mock private KeyguardInteractor mKeyguardInteractor; @Mock private QSPanelController mQSPanelController; + @Mock private QuickAccessWalletController mQuickAccessWalletController; CentralSurfacesCommandQueueCallbacks mSbcqCallbacks; @@ -149,7 +151,8 @@ public class CentralSurfacesCommandQueueCallbacksTest extends SysuiTestCase { mQSHost, mActivityStarter, mKeyguardInteractor, - mEmergencyGestureIntentFactory); + mEmergencyGestureIntentFactory, + mQuickAccessWalletController); when(mUserTracker.getUserHandle()).thenReturn( UserHandle.of(ActivityManager.getCurrentUser())); diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.kt index b815c6ce0c51..92318b9820b8 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewControllerTest.kt @@ -560,7 +560,6 @@ class KeyguardStatusBarViewControllerTest : SysuiTestCase() { updateStateToKeyguard() controller.setDozing(true) - controller.updateViewState() Truth.assertThat(keyguardStatusBarView.visibility).isEqualTo(View.INVISIBLE) } @@ -573,7 +572,6 @@ class KeyguardStatusBarViewControllerTest : SysuiTestCase() { updateStateToKeyguard() controller.setDozing(false) - controller.updateViewState() Truth.assertThat(keyguardStatusBarView.visibility).isEqualTo(View.VISIBLE) } @@ -633,7 +631,6 @@ class KeyguardStatusBarViewControllerTest : SysuiTestCase() { Truth.assertThat(keyguardStatusBarView.visibility).isEqualTo(View.VISIBLE) controller.setDozing(true) - controller.updateViewState() // setDozing(true) should typically cause the view to hide. But since the flag is on, we // should ignore these set dozing calls and stay the same visibility. diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/ethernet/domain/EthernetInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/ethernet/domain/EthernetInteractorTest.kt index f9ae5ff9bbc3..e7bfa0d50498 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/ethernet/domain/EthernetInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/ethernet/domain/EthernetInteractorTest.kt @@ -19,39 +19,40 @@ package com.android.systemui.statusbar.pipeline.ethernet.domain import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.settingslib.AccessibilityContentDescriptions -import com.android.systemui.res.R import com.android.systemui.SysuiTestCase import com.android.systemui.common.shared.model.ContentDescription import com.android.systemui.common.shared.model.Icon -import com.android.systemui.coroutines.collectLastValue -import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.collectLastValue +import com.android.systemui.kosmos.runTest +import com.android.systemui.kosmos.useUnconfinedTestDispatcher +import com.android.systemui.res.R +import com.android.systemui.statusbar.pipeline.shared.data.repository.connectivityRepository +import com.android.systemui.statusbar.pipeline.shared.data.repository.fake +import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat -import kotlinx.coroutines.test.TestScope -import kotlinx.coroutines.test.runTest import org.junit.Test import org.junit.runner.RunWith @SmallTest @RunWith(AndroidJUnit4::class) class EthernetInteractorTest : SysuiTestCase() { - private val connectivityRepository = FakeConnectivityRepository() - private val underTest = EthernetInteractor(connectivityRepository) - - private val testScope = TestScope() + private val kosmos = testKosmos().useUnconfinedTestDispatcher() + private val Kosmos.underTest by Kosmos.Fixture { ethernetInteractor } @Test fun icon_default_validated() = - testScope.runTest { + kosmos.runTest { val latest by collectLastValue(underTest.icon) - connectivityRepository.setEthernetConnected(default = true, validated = true) + connectivityRepository.fake.setEthernetConnected(default = true, validated = true) val expected = Icon.Resource( R.drawable.stat_sys_ethernet_fully, ContentDescription.Resource( AccessibilityContentDescriptions.ETHERNET_CONNECTION_VALUES[1] - ) + ), ) assertThat(latest).isEqualTo(expected) @@ -59,17 +60,17 @@ class EthernetInteractorTest : SysuiTestCase() { @Test fun icon_default_notValidated() = - testScope.runTest { + kosmos.runTest { val latest by collectLastValue(underTest.icon) - connectivityRepository.setEthernetConnected(default = true, validated = false) + connectivityRepository.fake.setEthernetConnected(default = true, validated = false) val expected = Icon.Resource( R.drawable.stat_sys_ethernet, ContentDescription.Resource( AccessibilityContentDescriptions.ETHERNET_CONNECTION_VALUES[0] - ) + ), ) assertThat(latest).isEqualTo(expected) @@ -77,20 +78,20 @@ class EthernetInteractorTest : SysuiTestCase() { @Test fun icon_notDefault_validated() = - testScope.runTest { + kosmos.runTest { val latest by collectLastValue(underTest.icon) - connectivityRepository.setEthernetConnected(default = false, validated = true) + connectivityRepository.fake.setEthernetConnected(default = false, validated = true) assertThat(latest).isNull() } @Test fun icon_notDefault_notValidated() = - testScope.runTest { + kosmos.runTest { val latest by collectLastValue(underTest.icon) - connectivityRepository.setEthernetConnected(default = false, validated = false) + connectivityRepository.fake.setEthernetConnected(default = false, validated = false) assertThat(latest).isNull() } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelTest.kt index e686edec8514..07d088bbb3d6 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/ui/dialog/viewmodel/ModesDialogViewModelTest.kt @@ -80,7 +80,7 @@ class ModesDialogViewModelTest : SysuiTestCase() { kosmos.mockModesDialogEventLogger, ) - timeScheduleInfo = ZenModeConfig.ScheduleInfo() + timeScheduleInfo = ScheduleInfo() timeScheduleInfo.days = intArrayOf(Calendar.MONDAY, Calendar.TUESDAY, Calendar.WEDNESDAY) timeScheduleInfo.startHour = 11 timeScheduleInfo.endHour = 15 @@ -126,7 +126,7 @@ class ModesDialogViewModelTest : SysuiTestCase() { ) runCurrent() - assertThat(tiles?.size).isEqualTo(3) + assertThat(tiles).hasSize(3) with(tiles?.elementAt(0)!!) { assertThat(this.text).isEqualTo("Disabled by other") assertThat(this.subtext).isEqualTo("Not set") @@ -176,7 +176,7 @@ class ModesDialogViewModelTest : SysuiTestCase() { ) runCurrent() - assertThat(tiles?.size).isEqualTo(3) + assertThat(tiles).hasSize(3) with(tiles?.elementAt(0)!!) { assertThat(this.text).isEqualTo("Active without manual") assertThat(this.subtext).isEqualTo("On") @@ -226,7 +226,7 @@ class ModesDialogViewModelTest : SysuiTestCase() { ) runCurrent() - assertThat(tiles?.size).isEqualTo(3) + assertThat(tiles).hasSize(3) // Check that tile is initially present with(tiles?.elementAt(0)!!) { @@ -239,7 +239,7 @@ class ModesDialogViewModelTest : SysuiTestCase() { runCurrent() } // Check that tile is still present at the same location, but turned off - assertThat(tiles?.size).isEqualTo(3) + assertThat(tiles).hasSize(3) with(tiles?.elementAt(0)!!) { assertThat(this.text).isEqualTo("Active without manual") assertThat(this.subtext).isEqualTo("Manage in settings") @@ -252,7 +252,7 @@ class ModesDialogViewModelTest : SysuiTestCase() { runCurrent() // Check that tile is now gone - assertThat(tiles2?.size).isEqualTo(2) + assertThat(tiles2).hasSize(2) assertThat(tiles2?.elementAt(0)!!.text).isEqualTo("Active with manual") assertThat(tiles2?.elementAt(1)!!.text).isEqualTo("Inactive with manual") } @@ -287,22 +287,22 @@ class ModesDialogViewModelTest : SysuiTestCase() { ) runCurrent() - assertThat(tiles?.size).isEqualTo(3) + assertThat(tiles).hasSize(3) repository.removeMode("A") runCurrent() - assertThat(tiles?.size).isEqualTo(2) + assertThat(tiles).hasSize(2) repository.removeMode("B") runCurrent() - assertThat(tiles?.size).isEqualTo(1) + assertThat(tiles).hasSize(1) repository.removeMode("C") runCurrent() - assertThat(tiles?.size).isEqualTo(0) + assertThat(tiles).hasSize(0) } @Test @@ -439,8 +439,11 @@ class ModesDialogViewModelTest : SysuiTestCase() { with(tiles?.elementAt(6)!!) { assertThat(this.stateDescription).isEqualTo("Off") assertThat(this.subtextDescription) - .isEqualTo(SystemZenRules.getDaysOfWeekFull(context, timeScheduleInfo) - + ", " + SystemZenRules.getTimeSummary(context, timeScheduleInfo)) + .isEqualTo( + SystemZenRules.getDaysOfWeekFull(context, timeScheduleInfo) + + ", " + + SystemZenRules.getTimeSummary(context, timeScheduleInfo) + ) } // All tiles have the same long click info @@ -464,7 +467,7 @@ class ModesDialogViewModelTest : SysuiTestCase() { ) runCurrent() - assertThat(tiles?.size).isEqualTo(1) + assertThat(tiles).hasSize(1) assertThat(tiles?.elementAt(0)?.enabled).isFalse() // Trigger onClick @@ -497,13 +500,13 @@ class ModesDialogViewModelTest : SysuiTestCase() { ) runCurrent() - assertThat(tiles?.size).isEqualTo(1) + assertThat(tiles).hasSize(1) // Click tile to toggle it off tiles?.elementAt(0)!!.onClick() runCurrent() - assertThat(tiles?.size).isEqualTo(1) + assertThat(tiles).hasSize(1) with(tiles?.elementAt(0)!!) { assertThat(this.text).isEqualTo("Active without manual") assertThat(this.subtext).isEqualTo("Manage in settings") @@ -538,7 +541,7 @@ class ModesDialogViewModelTest : SysuiTestCase() { ) runCurrent() - assertThat(tiles?.size).isEqualTo(1) + assertThat(tiles).hasSize(1) with(tiles?.elementAt(0)!!) { assertThat(this.text).isEqualTo("Disabled by other") assertThat(this.subtext).isEqualTo("Not set") @@ -590,7 +593,7 @@ class ModesDialogViewModelTest : SysuiTestCase() { ) runCurrent() - assertThat(tiles?.size).isEqualTo(2) + assertThat(tiles).hasSize(2) // Trigger onLongClick for A tiles?.first()?.onLongClick?.let { it() } @@ -641,7 +644,7 @@ class ModesDialogViewModelTest : SysuiTestCase() { ) runCurrent() - assertThat(tiles?.size).isEqualTo(3) + assertThat(tiles).hasSize(3) // Trigger onClick for each tile in sequence tiles?.forEach { it.onClick.invoke() } @@ -682,7 +685,7 @@ class ModesDialogViewModelTest : SysuiTestCase() { ) runCurrent() - assertThat(tiles?.size).isEqualTo(2) + assertThat(tiles).hasSize(2) val modeCaptor = argumentCaptor<ZenMode>() // long click manual DND and then automatic mode diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/window/data/repository/StatusBarWindowStatePerDisplayRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/window/data/repository/StatusBarWindowStatePerDisplayRepositoryTest.kt index c7c7fdc40acb..42ebaf7e0c59 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/window/data/repository/StatusBarWindowStatePerDisplayRepositoryTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/window/data/repository/StatusBarWindowStatePerDisplayRepositoryTest.kt @@ -28,7 +28,7 @@ import com.android.systemui.coroutines.collectLastValue import com.android.systemui.kosmos.testScope import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.commandQueue -import com.android.systemui.statusbar.window.data.model.StatusBarWindowState +import com.android.systemui.statusbar.window.shared.model.StatusBarWindowState import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/window/data/repository/StatusBarWindowStateRepositoryStoreTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/window/data/repository/StatusBarWindowStateRepositoryStoreTest.kt index e23e88cc2e4a..e36178cb99d5 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/window/data/repository/StatusBarWindowStateRepositoryStoreTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/window/data/repository/StatusBarWindowStateRepositoryStoreTest.kt @@ -27,7 +27,7 @@ import com.android.systemui.kosmos.testScope import com.android.systemui.settings.displayTracker import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.commandQueue -import com.android.systemui.statusbar.window.data.model.StatusBarWindowState +import com.android.systemui.statusbar.window.shared.model.StatusBarWindowState import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlin.test.Test diff --git a/packages/SystemUI/res/drawable/volume_dialog_background.xml b/packages/SystemUI/res/drawable/volume_dialog_background.xml index b527506e28f5..cd0e2c076cef 100644 --- a/packages/SystemUI/res/drawable/volume_dialog_background.xml +++ b/packages/SystemUI/res/drawable/volume_dialog_background.xml @@ -17,7 +17,6 @@ <shape xmlns:android="http://schemas.android.com/apk/res/android" xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" android:shape="rectangle"> - <corners android:bottomLeftRadius="@dimen/volume_dialog_background_corner_radius" - android:bottomRightRadius="@dimen/volume_dialog_background_corner_radius"/> + <corners android:radius="@dimen/volume_dialog_background_corner_radius"/> <solid android:color="@androidprv:color/materialColorSurface" /> </shape> diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml index 0ec668012cfc..0b624e1687a6 100644 --- a/packages/SystemUI/res/layout/volume_dialog.xml +++ b/packages/SystemUI/res/layout/volume_dialog.xml @@ -26,7 +26,7 @@ android:id="@+id/volume_dialog_background" android:layout_width="@dimen/volume_dialog_width" android:layout_height="0dp" - android:layout_marginTop="@dimen/volume_dialog_background_vertical_margin" + android:layout_marginTop="@dimen/volume_dialog_background_top_margin" android:layout_marginBottom="@dimen/volume_dialog_background_vertical_margin" android:background="@drawable/volume_dialog_background" app:layout_constraintBottom_toBottomOf="@id/volume_dialog_settings" @@ -40,7 +40,7 @@ android:layout_width="0dp" android:layout_height="0dp" android:layout_marginEnd="@dimen/volume_dialog_ringer_drawer_diff_end_margin" - android:layout_marginBottom="@dimen/volume_dialog_background_vertical_margin" + android:layout_marginBottom="@dimen/volume_dialog_components_spacing" app:layout_constraintBottom_toTopOf="@id/volume_dialog_main_slider_container" app:layout_constraintEnd_toEndOf="@id/volume_dialog_main_slider_container" app:layout_constraintStart_toStartOf="parent" diff --git a/packages/SystemUI/res/layout/volume_dialog_slider.xml b/packages/SystemUI/res/layout/volume_dialog_slider.xml index 0acf4109bbb5..967cb3fd68de 100644 --- a/packages/SystemUI/res/layout/volume_dialog_slider.xml +++ b/packages/SystemUI/res/layout/volume_dialog_slider.xml @@ -14,15 +14,17 @@ limitations under the License. --> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="wrap_content" - android:layout_height="wrap_content"> + android:layout_width="@dimen/volume_dialog_slider_width" + android:layout_height="@dimen/volume_dialog_slider_height"> <com.google.android.material.slider.Slider android:id="@+id/volume_dialog_slider" style="@style/SystemUI.Material3.Slider.Volume" - android:layout_width="@dimen/volume_dialog_slider_width" - android:layout_height="@dimen/volume_dialog_slider_height" + android:layout_width="match_parent" + android:layout_height="match_parent" android:layout_gravity="center" + android:layout_marginTop="-20dp" + android:layout_marginBottom="-20dp" android:orientation="vertical" android:theme="@style/Theme.Material3.DayNight" /> </FrameLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/volume_ringer_drawer.xml b/packages/SystemUI/res/layout/volume_ringer_drawer.xml index 983603a95833..8f51dbca2774 100644 --- a/packages/SystemUI/res/layout/volume_ringer_drawer.xml +++ b/packages/SystemUI/res/layout/volume_ringer_drawer.xml @@ -29,6 +29,7 @@ android:id="@+id/ringer_buttons_background" android:layout_width="@dimen/volume_dialog_width" android:layout_height="0dp" + android:visibility="gone" android:layout_marginTop="@dimen/volume_dialog_background_vertical_margin" android:layout_marginBottom="@dimen/volume_dialog_background_vertical_margin" android:background="@drawable/volume_dialog_ringer_background" /> diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index ebc19350805a..0e8b2d53598e 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Deurlopende kennisgewing vir \'n skermopnamesessie"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Neem jou skerm op?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Neem een app op"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Neem hierdie skerm op"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Neem %s op"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Wanneer jy jou hele skerm opneem, word enigiets wat op jou skerm wys, opgeneem. Wees dus versigtig met dinge soos wagwoorde, betalingbesonderhede, boodskappe, foto’s, en oudio en video."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Wanneer jy ’n app opneem, word enigiets wat in daardie app gewys of gespeel word, opgeneem. Wees dus versigtig met dinge soos wagwoorde, betalingbesonderhede, boodskappe, foto’s, en oudio en video."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Neem skerm op"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Kon nie voorafstelling opdateer nie"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Voorafstelling"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Gekies"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Omgewing"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Links"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Regs"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Vou uit na links- en regsgeskeide kontroles"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Vou in na verenigde kontrole"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Demp omgewing"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Ontdemp omgewing"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Nutsgoed"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Intydse Onderskrifte"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Nota"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Wys laeprioriteit-kennisgewingikone"</string> <string name="other" msgid="429768510980739978">"Ander"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"verwyder teël"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"voeg teël by die laaste posisie"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Skuif teël"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Voeg teël by die verlangde posisie"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Skuif na <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Voeg by posisie <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Posisie is ongeldig."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"kies gebruiker"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Geen internet nie"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Maak <xliff:g id="ID_1">%s</xliff:g>-instellings oop."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Wysig volgorde van Kitsinstellings."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Aan/af-kieslys"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Bladsy <xliff:g id="ID_1">%1$d</xliff:g> van <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Sluitskerm"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"gaan by toestel in"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Gebruik vingerafdruk om oop te maak"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Stawing word vereis. Raak die vingerafdruksensor om te staaf."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Oproep aan die gang"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiele data"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Gekoppel"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Tydelik gekoppel"</string> diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index 18bffac51025..15286a6aaea2 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"ለአንድ የማያ ገፅ ቀረጻ ክፍለ-ጊዜ በመካሄድ ያለ ማሳወቂያ"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"ማያ ገፅዎን ይቀዳሉ?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"አንድ መተግበሪያ ቅዳ"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"ይህን ማያ ገፅ ይቅዱ"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"%s ይቅዱ"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"መላው ማያ ገፅዎን በሚቀዱበት ጊዜ፣ በማያ ገፅዎ ላይ የሚታየው ማንኛውም ነገር ይቀዳል። ስለዚህ እንደ የይለፍ ቃላት፣ የክፍያ ዝርዝሮች፣ መልዕክቶች፣ ፎቶዎች እና ኦዲዮ እና ቪድዮ ላሉ ነገሮች ጥንቃቄ ያድርጉ።"</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"መተግበሪያን ሲቀዱ በዚያ መተግበሪያ ውስጥ የሚታይ ወይም የሚጫወት ማንኛውም ነገር ይቀዳል። ስለዚህ እንደ የይለፍ ቃላት፣ የክፍያ ዝርዝሮች፣ መልዕክቶች፣ ፎቶዎች እና ኦዲዮ እና ቪድዮ ላሉ ነገሮች ጥንቃቄ ያድርጉ።"</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"ማያ ገፅን ቅረጽ"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"ቅድመ-ቅምጥን ማዘመን አልተቻለም"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"ቅድመ-ቅምጥ"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"ተመርጧል"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"በዙሪያ ያሉ"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"ግራ"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"ቀኝ"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"ወደ ግራ እና ቀኝ የተለያዩ ቁጥጥሮች ዘርጋ"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"ወደ የተዋሃደ ቁጥጥር ሰብስብ"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"በዙሪያ ያሉትን ድምፀ-ከል አድርግ"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"በዙሪያ ያሉትን ድምፅ-ከል አንሳ"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"መሣሪያዎች"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"የቀጥታ መግለጫ ጽሑፍ"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"ማስታወሻ"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"አነስተኛ ቅድሚያ ያላቸው የማሳወቂያ አዶዎችን አሳይ"</string> <string name="other" msgid="429768510980739978">"ሌላ"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"ሰቅ አስወግድ"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"በመጨረሻው ቦታ ላይ ሰቅ ያክሉ"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"ሰቁን ውሰድ"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"ወደተፈለገው ቦታ ሰቅ ያክሉ"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"ወደ <xliff:g id="POSITION">%1$d</xliff:g> ውሰድ"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"ወደ <xliff:g id="POSITION">%1$d</xliff:g> ቦታ አክል"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"አቀማመጡ ተቀባይነት የለውም።"</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"ተጠቃሚ ይምረጡ"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"ምንም በይነመረብ የለም"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"የ<xliff:g id="ID_1">%s</xliff:g> ቅንብሮችን ክፈት።"</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"የፈጣን ቅንብሮችን ቅደም ተከተል ያርትዑ።"</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"የኃይል ምናሌ"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"ገፅ <xliff:g id="ID_1">%1$d</xliff:g> ከ <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"ማያ ገፅ ቁልፍ"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"መሣሪያን ያስገቡ"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ለመክፈት የጣት አሻራ ይጠቀሙ"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ማረጋገጥ ያስፈልጋል። ለማረጋገጥ የጣት አሻራ ዳሳሹን ይንኩ።"</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"በመካሄድ ላይ የስልክ ጥሪ"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"የተንቀሳቃሽ ስልክ ውሂብ"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"ተገናኝቷል"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"በጊዜያዊነት ተገናኝቷል"</string> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index 20668f821c9d..d68c43281908 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"إشعار مستمر لجلسة تسجيل شاشة"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"هل تريد تسجيل الشاشة؟"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"تسجيل شاشة تطبيق واحد"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"تسجيل محتوى هذه الشاشة"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"تسجيل محتوى \"%s\""</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"أثناء تسجيل محتوى الشاشة بالكامل، يتم تسجيل كل المحتوى المعروض على شاشتك، لذا يُرجى توخي الحذر بشأن المعلومات الظاهرة، مثل كلمات المرور وتفاصيل الدفع والرسائل والصور والمقاطع الصوتية والفيديوهات."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"سيتم تسجيل كل المحتوى المعروض أو المشغَّل على شاشة التطبيق، لذا يُرجى توخي الحذر بشأن المعلومات الظاهرة، مثل كلمات المرور وتفاصيل الدفع والرسائل والصور والمقاطع الصوتية والفيديوهات."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"تسجيل الشاشة"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"تعذَّر تعديل الإعداد المسبق"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"الإعدادات المسبقة"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"تمّ اختياره"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"الأصوات المحيطة"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"الجهاز الأيسر"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"الجهاز الأيمن"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"توسيع لوحة التحكّم الموحّدة إلى عناصر تحكُّم منفصلة على اليسار واليمين"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"تصغير عناصر التحكّم في الصوت إلى لوحة تحكُّم موحّدة"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"كتم الأصوات المحيطة"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"إعادة الأصوات المحيطة"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"الأدوات"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"النسخ النصي التلقائي"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"ملاحظات"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"إظهار رموز الإشعارات ذات الأولوية المنخفضة"</string> <string name="other" msgid="429768510980739978">"غير ذلك"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"إزالة بطاقة"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"إضافة مربّع إلى الموضع الأخير"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"نقل بطاقة"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"إضافة مربّع إلى الموضع المطلوب"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"الانتقال إلى <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"الإضافة إلى الموضع <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"الموضِع غير صالح."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"اختيار مستخدم"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"لا يتوفر اتصال إنترنت."</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"فتح إعدادات <xliff:g id="ID_1">%s</xliff:g>."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"تعديل ترتيب الإعدادات السريعة"</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"قائمة زر التشغيل"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"الصفحة <xliff:g id="ID_1">%1$d</xliff:g> من <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"شاشة القفل"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"الدخول إلى الجهاز"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"يمكنك استخدام بصمة الإصبع للفتح"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"المصادقة مطلوبة. المس مستشعر بصمات الإصبع للمصادقة."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"مكالمة هاتفية جارية"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"بيانات الجوّال"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"متصلة بالإنترنت"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"متصلة مؤقتًا"</string> diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml index fb0030f28ed8..4c4579f8e42d 100644 --- a/packages/SystemUI/res/values-as/strings.xml +++ b/packages/SystemUI/res/values-as/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"স্ক্রীন ৰেকৰ্ডিং ছেশ্বন চলি থকা সময়ত পোৱা জাননী"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"আপোনাৰ স্ক্ৰীনখন ৰেকৰ্ড কৰিবনে?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"এটা এপ্ ৰেকৰ্ড কৰক"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"এই স্ক্ৰীনখন ৰেকর্ড কৰক"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"%s ৰেকর্ড কৰক"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"আপুনি গোটেই স্ক্ৰীনখন ৰেকৰ্ডিং কৰিলে, আপোনাৰ স্ক্ৰীনখনত দেখুওৱা যিকোনো বস্তু ৰেকৰ্ড কৰা হয়। গতিকে, পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, বাৰ্তা, ফট’ আৰু অডিঅ’ আৰু ভিডিঅ’ৰ ক্ষেত্ৰত সাৱধান হওক।"</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"আপুনি কোনো এপ্ ৰেকৰ্ড কৰিলে, সেই এপত দেখুওৱা বা প্লে’ কৰা যিকোনো বস্তু ৰেকৰ্ড কৰা হয়। গতিকে, পাছৱৰ্ড, পৰিশোধৰ সবিশেষ, বাৰ্তা, ফট’ আৰু অডিঅ’ আৰু ভিডিঅ’ৰ ক্ষেত্ৰত সাৱধান হওক।"</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"স্ক্ৰীনখন ৰেকৰ্ড কৰক"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"প্ৰিছেট আপডে’ট কৰিব পৰা নগ’ল"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"প্ৰিছেট"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"বাছনি কৰা হৈছে"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"আশ-পাশ"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"বাওঁফাল"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"সোঁফাল"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"বাওঁ আৰু সোঁফালৰ পৃথক কৰা নিয়ন্ত্ৰণলৈ সংকোচন কৰক"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"একত্ৰিত নিয়ন্ত্ৰণলৈ সংকোচন কৰক"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"আশ-পাশৰ ধ্বনি মিউট কৰক"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"আশ-পাশৰ ধ্বনি আনমিউট কৰক"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"সঁজুলি"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"লাইভ কেপশ্বন"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"টোকা"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"কম গুৰুত্বপূৰ্ণ জাননীৰ আইকনসমূহ দেখুৱাওক"</string> <string name="other" msgid="429768510980739978">"অন্যান্য"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"টাইল আঁতৰাবলৈ"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"অন্তিম স্থানত টাইল যোগ দিয়ক"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"টাইল স্থানান্তৰ কৰক"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"বিচৰা স্থানত টাইল যোগ দিয়ক"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> নম্বৰলৈ স্থানান্তৰ কৰক"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> নম্বৰ স্থানত যোগ দিয়ক"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"স্থান অমান্য।"</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"ব্যৱহাৰকাৰী বাছনি কৰক"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"ইণ্টাৰনেট সংযোগ নাই"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"<xliff:g id="ID_1">%s</xliff:g>ৰ ছেটিং খোলক।"</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"ক্ষিপ্ৰ ছেটিঙৰ ক্ৰম সম্পাদনা কৰক।"</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"পাৱাৰ মেনু"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g>ৰ পৃষ্ঠা <xliff:g id="ID_1">%1$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"লক স্ক্ৰীন"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"ডিভাইচ আনলক কৰক"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"খুলিবলৈ ফিংগাৰপ্ৰিণ্ট ব্যৱহাৰ কৰক"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"বিশ্বাসযোগ্যতা প্ৰমাণীকৰণৰ আৱশ্যক। বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ কৰিবলৈ ফিংগাৰপ্ৰিণ্ট ছেন্সৰটো স্পৰ্শ কৰক।"</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"চলি থকা ফ’ন কল"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"ম’বাইল ডেটা"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"সংযোজিত হৈ আছে"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"অস্থায়ীভাৱে সংযোগ কৰা হৈছে"</string> diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml index 532fcebf7ef3..08452d353765 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ekranın video çəkimi ərzində silinməyən bildiriş"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Ekran qeydə alınsın?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Bir tətbiqi qeydə alın"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Bu ekranı qeydə alın"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Qeydə alın: %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Bütün ekranı qeydə alarkən ekranda göstərilən bütün kontent qeydə alınır. Parol, ödəniş detalları, mesaj, foto, habelə audio və video kimi məlumatlarla bağlı diqqətli olun."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Tətbiq qeydə aldıqda həmin tətbiqdə göstərilən və ya işə salınan bütün kontent qeydə alınır. Parol, ödəniş detalları, mesaj, foto, habelə audio və video kimi məlumatlarla bağlı diqqətli olun."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Ekranı qeydə alın"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Hazır ayar güncəllənmədi"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Hazır Ayar"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Seçilib"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Ətraf mühit"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Sol"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Sağ"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Sola və sağa ayrılmış idarəetmələr üçün genişləndirin"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Vahid nəzarət üçün yığcamlaşdırın"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Ətraf mühiti səssiz edin"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Ətraf mühiti səssiz rejimdən çıxarın"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Alətlər"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Canlı Altyazı"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Qeyd"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Aşağı prioritet bildiriş işarələrini göstərin"</string> <string name="other" msgid="429768510980739978">"Digər"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"lövhəni silin"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"son mövqeyə mozaik əlavə edin"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Lövhəni köçürün"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"İstənilən mövqeyə mozaik əlavə edin"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> mövqeyinə köçürün"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> mövqeyinə əlavə edin"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Mövqe yanlışdır."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"istifadəçi seçin"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"İnternet yoxdur"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"<xliff:g id="ID_1">%s</xliff:g> ayarlarını açın."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Sürətli Ayarlarda ardıcıllığı redaktə edin."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Qidalanma düyməsi menyusu"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g> səhifədən <xliff:g id="ID_1">%1$d</xliff:g> səhifə"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Ekran kilidi"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"cihaz daxil edin"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Açmaq üçün barmaq izindən istifadə edin"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Doğrulanma tələb olunur. Doğrulamaq üçün barmaq izi sensoruna toxunun."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Davam edən zəng"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobil data"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Qoşulub"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Müvəqqəti qoşulub"</string> diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml index d0c3fa33f398..8d9495a1a4e7 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Obaveštenje o sesiji snimanja ekrana je aktivno"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Želite da snimite ekran?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Snimi jednu aplikaciju"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Snimi ovaj ekran"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Snimi %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Kada snimate ceo ekran, snima se sve što je na njemu. Zato pazite na lozinke, informacije o plaćanju, poruke, slike, audio i video sadržaj."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Kada snimate aplikaciju, snima se sav sadržaj koji se prikazuje ili pušta u njoj. Zato pazite na lozinke, informacije o plaćanju, poruke, slike, audio i video sadržaj."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Snimi ekran"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Ažuriranje zadatih podešavanja nije uspelo"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Unapred određena podešavanja"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Izabrano"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Okruženje"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Levo"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Desno"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Proširi na kontrole razdvojene na levu i desnu stranu"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Skupi u jedinstvenu kontrolu"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Isključi zvuk okruženja"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Uključi zvuk okruženja"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Alatke"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Titl uživo"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Beleška"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Prikaži ikone obaveštenja niskog prioriteta"</string> <string name="other" msgid="429768510980739978">"Drugo"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"uklonili pločicu"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"dodali pločicu na poslednju poziciju"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Premestite pločicu"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Dodajte pločicu na željenu poziciju"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Premestite na <xliff:g id="POSITION">%1$d</xliff:g>. poziciju"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Dodajte na <xliff:g id="POSITION">%1$d</xliff:g>. poziciju"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Pozicija je nevažeća."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"odabrali korisnika"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Nema interneta"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Otvori podešavanja za <xliff:g id="ID_1">%s</xliff:g>."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Izmenite redosled Brzih podešavanja."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Meni dugmeta za uključivanje"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_1">%1$d</xliff:g>. strana od <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Zaključan ekran"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"unesite uređaj"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Otvorite pomoću otiska prsta"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Potrebna je potvrda identiteta. Dodirnite senzor za otisak prsta da biste potvrdili identitet."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Aktuelni telefonski poziv"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilni podaci"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Povezano"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Privremeno povezano"</string> diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml index b40801dcd09a..3431862c77fc 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Бягучае апавяшчэнне для сеанса запісу экрана"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Запісаць экран?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Запісаць адну праграму"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Запісаць гэты экран"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Запісаць: %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Пры запісе ўсяго экрана запісваецца ўсё, што паказваецца на экране. Таму прадухіліце паказ пароляў, плацежных рэквізітаў, паведамленняў, фота, відэа і аўдыя."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Пры запісе праграмы запісваецца ўсё, што паказваецца або прайграецца ў гэтай праграме. Таму прадухіліце паказ пароляў, плацежных рэквізітаў, паведамленняў, фота, відэа і аўдыя."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Запісаць экран"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Не ўдалося абнавіць набор налад"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Набор налад"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Выбрана"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Навакольныя гукі"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Левы бок"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Правы бок"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Зрабіць левую і правую панэлі кіравання"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Зрабіць адну панэль кіравання"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Выключыць навакольныя гукі"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Уключыць навакольныя гукі"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Інструменты"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Аўтаматычныя субцітры"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Нататка"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Паказваць значкі апавяшчэнняў з нізкім прыярытэтам"</string> <string name="other" msgid="429768510980739978">"Іншае"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"выдаліць плітку"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"дадаць плітку ў апошнюю пазіцыю"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Перамясціць плітку"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Дадаць плітку ў патрэбную пазіцыю"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Перамясціць на пазіцыю <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Дадаць на пазіцыю <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Няправільнае месца."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"выбраць карыстальніка"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Няма падключэння да інтэрнэту"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Адкрыць налады <xliff:g id="ID_1">%s</xliff:g>."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Змяніць парадак хуткіх налад."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Меню кнопкі сілкавання"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Старонка <xliff:g id="ID_1">%1$d</xliff:g> з <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Экран блакіроўкі"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"адкрыць галоўны экран прылады"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Каб адкрыць, скарыстайце адбітак пальца"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Патрабуецца аўтэнтыфікацыя. Дакраніцеся да сканера адбіткаў пальцаў."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Бягучы тэлефонны выклік"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мабільная перадача даных"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Падключана"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Падключана часова"</string> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index 83aa4e57b911..1128d03595e1 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Текущо известие за сесия за записване на екрана"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Да се записва ли екранът?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Записване на едно приложение"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Записване на този екран"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Записване на %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Когато записвате целия си екран, се записва всичко, което се показва на него. Затова бъдете внимателни с неща като пароли, подробности за начини на плащане, съобщения, снимки, аудио и видео."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Когато записвате приложение, се записва всичко, което се показва или възпроизвежда в него. Затова бъдете внимателни с неща като пароли, подробности за начини на плащане, съобщения, снимки, аудио и видео."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Записване на екрана"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Предварително зададените настройки не бяха актуализирани"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Предварително зададено"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Избрано"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Околни звуци"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Ляво"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Дясно"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Разгъване до отделни контроли за ляво и дясно"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Свиване до обединена контрола"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Спиране на околните звуци"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Включване на околните звуци"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Инструменти"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Надписи на живо"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Бележка"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Показване на иконите за известията с нисък приоритет"</string> <string name="other" msgid="429768510980739978">"Друго"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"премахване на панел"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"добавяне на панела на последната позиция"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Преместване на панел"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Добавяне на панела на желаната позиция"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Преместване към позиция <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Добавяне към позиция <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Невалидна позиция."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"изберете потребител"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Няма връзка с интернет"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Отваряне на настройките за <xliff:g id="ID_1">%s</xliff:g>."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Редактиране на подредбата на бързите настройки."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Меню за включване/изключване"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Страница <xliff:g id="ID_1">%1$d</xliff:g> от <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Заключен екран"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"вход в устройството"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Използвайте отпечатък за отваряне"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Изисква се удостоверяване на самоличността. За целта докоснете сензора за отпечатъци."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Текущо телефонно обаждане"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобилни данни"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Свързано"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Установена е временна връзка"</string> diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index b927ad19283a..23a693b9840e 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"স্ক্রিন রেকর্ডিং সেশন চলার বিজ্ঞপ্তি"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"আপনার স্ক্রিন রেকর্ড করবেন?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"একটি অ্যাপ রেকর্ড করুন"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"এই স্ক্রিন রেকর্ড করুন"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"%s রেকর্ড করুন"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"আপনার সম্পূর্ণ স্ক্রিন রেকর্ড করার সময়, আপনার স্ক্রিনে দেখানো সব কিছু রেকর্ড করা হয়। তাই পাসওয়ার্ড, পেমেন্টের বিবরণ, মেসেজ, ফটো এবং অডিও ও ভিডিওর মতো বিষয়ের ক্ষেত্রে সতর্ক থাকুন।"</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"আপনি কোনও অ্যাপ রেকর্ড করার সময়, সেই অ্যাপে দেখানো বা চালানো সব কিছু রেকর্ড করা হয়। তাই পাসওয়ার্ড, পেমেন্টের বিবরণ, মেসেজ, ফটো এবং অডিও ও ভিডিওর মতো বিষয়ের ক্ষেত্রে সতর্ক থাকুন।"</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"স্ক্রিন রেকর্ড করুন"</string> @@ -355,7 +353,7 @@ <string name="quick_settings_color_correction_label" msgid="5636617913560474664">"রঙ সংশোধন"</string> <string name="quick_settings_font_scaling_label" msgid="5289001009876936768">"ফন্ট সাইজ"</string> <string name="quick_settings_more_user_settings" msgid="7634653308485206306">"ব্যবহারকারীদের ম্যানেজ করুন"</string> - <string name="quick_settings_done" msgid="2163641301648855793">"সম্পন্ন হয়েছে"</string> + <string name="quick_settings_done" msgid="2163641301648855793">"হয়ে গেছে"</string> <string name="quick_settings_close_user_panel" msgid="5599724542275896849">"বন্ধ করুন"</string> <string name="quick_settings_connected" msgid="3873605509184830379">"সংযুক্ত হয়েছে"</string> <string name="quick_settings_connected_battery_level" msgid="1322075669498906959">"সংযুক্ত হয়েছে, ব্যাটারি <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"প্রিসেট আপডেট করা যায়নি"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"প্রিসেট"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"বেছে নেওয়া হয়েছে"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"সারাউন্ডিং"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"বাঁদিক"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"ডানদিক"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"বাঁদিক ও ডানদিকের আলাদা করা কন্ট্রোল বড় করুন"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"ইউনিফায়েড কন্ট্রোল আড়াল করুন"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"সারাউন্ডিং মিউট করুন"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"সারাউন্ডিং আনমিউট করুন"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"টুল"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"লাইভ ক্যাপশন"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"মনে রাখবেন"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"কম-গুরুত্বপূর্ণ বিজ্ঞপ্তির আইকন দেখুন"</string> <string name="other" msgid="429768510980739978">"অন্যান্য"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"টাইল সরান"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"শেষ জায়গাতে টাইল যোগ করুন"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"টাইল সরান"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"আপনার পছন্দের জায়গাতে টাইল যোগ করুন"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g>-এ সরান"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"অবস্থান <xliff:g id="POSITION">%1$d</xliff:g>-এ যোগ করুন"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"পজিশন সঠিক নয়।"</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"ব্যবহারকারী বেছে নিন"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"ইন্টারনেট কানেকশন নেই"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"<xliff:g id="ID_1">%s</xliff:g> সেটিংস খুলুন৷"</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"দ্রুত সেটিংসের ক্রম এডিট করুন"</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"পাওয়ার মেনু"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g>টির মধ্যে <xliff:g id="ID_1">%1$d</xliff:g> নং পৃষ্ঠা"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"লক স্ক্রিন"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"ডিভাইস আনলক করুন"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"খুলতে ফিঙ্গারপ্রিন্ট ব্যবহার করুন"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"যাচাইকরণ করতে হবে। যাচাইকরণ করতে আঙুলের ছাপের সেন্সরে টাচ করুন।"</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ব্যবহারকারী এখন ফোনে কথা বলছেন"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"মোবাইল ডেটা"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"কানেক্ট করা আছে"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"সাময়িকভাবে কানেক্ট করা হয়েছে"</string> diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml index defc62e084c9..d7b3f60edb03 100644 --- a/packages/SystemUI/res/values-bs/strings.xml +++ b/packages/SystemUI/res/values-bs/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Obavještenje za sesiju snimanja ekrana je u toku"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Snimati ekran?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Snimaj jednu aplikaciju"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Snimaj ovaj ekran"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Snimaj ekran %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Kada snimate cijeli ekran, snimat će se sve što se prikazuje na ekranu. Stoga budite oprezni s informacijama kao što su lozinke, podaci o plaćanju, poruke, fotografije, audio i videozapisi."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Kada snimate aplikaciju, snimat će se sve što se prikazuje ili reproducira u toj aplikaciji. Stoga budite oprezni s informacijama kao što su lozinke, podaci o plaćanju, poruke, fotografije, audio i videozapisi."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Snimaj ekran"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Ažuriranje zadane postavke nije uspjelo"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Zadana postavka"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Odabrano"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Okruženje"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Lijevo"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Desno"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Proširivanje u zasebne kontrole ulijevo i udesno"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Sužavanje u objedinjenu kontrolu"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Isključivanje zvuka okruženja"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Uključivanje zvuka okruženja"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Alati"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Automatski titlovi"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Bilješka"</string> @@ -978,7 +969,7 @@ <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"uklanjanje kartice"</string> <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"dodavanje kartice na posljednji položaj"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Pomjeranje kartice"</string> - <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Dodajte karticu na željeni položaj"</string> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Dodavanje kartice na željeni položaj"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Pomjeranje u položaj <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Dodavanje u položaj <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Nevažeći položaj."</string> @@ -994,7 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"odaberete korisnika"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Nema internetske veze"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Otvori postavke za: <xliff:g id="ID_1">%s</xliff:g>."</string> - <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Uredite redoslijed brzih postavki."</string> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Uređivanje redoslijeda Brzih postavki."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Meni napajanja"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Stranica <xliff:g id="ID_1">%1$d</xliff:g> od <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Zaključani ekran"</string> @@ -1298,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"pristup uređaju"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Otvorite pomoću otiska prsta"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Potrebna je autentifikacija. Dodirnite senzor za otisak prsta da autentificirate."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Telefonski poziv u toku"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Prijenos podataka na mobilnoj mreži"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Povezano"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Privremeno povezano"</string> @@ -1444,7 +1436,7 @@ <string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Prečice aplikacije"</string> <string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Trenutna aplikacija"</string> <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Pristupačnost"</string> - <string name="shortcut_helper_title" msgid="8567500639300970049">"Prečice tastature"</string> + <string name="shortcut_helper_title" msgid="8567500639300970049">"Prečice na tastaturi"</string> <string name="shortcut_helper_customize_mode_title" msgid="1467657117101096033">"Prilagodite prečice na tastaturi"</string> <string name="shortcut_customize_mode_remove_shortcut_dialog_title" msgid="7106420484940737208">"Ukloniti prečicu?"</string> <string name="shortcut_customize_mode_reset_shortcut_dialog_title" msgid="8131184731313717780">"Vratiti na zadano?"</string> @@ -1456,7 +1448,7 @@ <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ikona sužavanja"</string> <string name="shortcut_helper_content_description_meta_key" msgid="3989315044342124818">"Ikona tipke radnji ili meta tipka"</string> <string name="shortcut_helper_content_description_plus_icon" msgid="6152683734278299020">"Ikona znaka plus"</string> - <string name="shortcut_helper_customize_button_text" msgid="3124983502748069338">"Prilagođavanje"</string> + <string name="shortcut_helper_customize_button_text" msgid="3124983502748069338">"Prilagodite"</string> <string name="shortcut_helper_reset_button_text" msgid="2548243844050633472">"Poništavanje"</string> <string name="shortcut_helper_done_button_text" msgid="7249905942125386191">"Gotovo"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Ikona proširivanja"</string> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index 05c9d8162021..09f63c551f01 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificació en curs d\'una sessió de gravació de la pantalla"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Vols gravar la pantalla?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Grava una aplicació"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Grava aquesta pantalla"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Grava %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Quan graves tota la pantalla, es grava tot el que es mostra en pantalla. Per aquest motiu, ves amb compte amb elements com les contrasenyes, les dades de pagament, els missatges, les fotos, i l\'àudio i el vídeo."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Quan graves una aplicació, es grava tot el que es mostra o es reprodueix en aquesta aplicació. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges, les fotos, i l\'àudio i el vídeo."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Grava la pantalla"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"No s\'ha pogut actualitzar el valor predefinit"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Valors predefinits"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Seleccionat"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Entorn"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Esquerra"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Dreta"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Desplega els controls separats d\'esquerra i dreta"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Replega per unificar el control"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Silencia l\'entorn"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Deixa de silenciar l\'entorn"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Eines"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Subtítols instantanis"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Nota"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Mostra les icones de notificació amb prioritat baixa"</string> <string name="other" msgid="429768510980739978">"Altres"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"suprimir el mosaic"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"afegir una icona a la darrera posició"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Mou el mosaic"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Afegeix una icona a la posició que vulguis"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Mou a la posició <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Afegeix a la posició <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"La posició no és vàlida."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"triar un usuari"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Sense connexió a Internet"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Obre la configuració per a <xliff:g id="ID_1">%s</xliff:g>."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Edita l\'ordre de la configuració ràpida."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menú d\'engegada"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Pàgina <xliff:g id="ID_1">%1$d</xliff:g> (<xliff:g id="ID_2">%2$d</xliff:g> en total)"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Pantalla de bloqueig"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"accedir al dispositiu"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Utilitza l\'empremta digital per obrir"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticació necessària. Toca el sensor d\'empremtes digitals per autenticar-te."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Trucada en curs"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Dades mòbils"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Connectat"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Connexió temporal"</string> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index 7ae441627e87..07587641802a 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Trvalé oznámení o relaci nahrávání"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Pořídit nahrávku obrazovky?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Nahrát jednu aplikaci"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Nahrávat tuhle obrazovku"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Nahrávat obrazovku %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Při nahrávání celé obrazovky se zaznamenává veškerý obsah na obrazovce. Buďte proto opatrní, když jde o hesla, platební údaje, zprávy, fotografie, zvuk a video."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Při nahrávání aplikace se zaznamenává všechno, co se v dané obrazovce zobrazuje nebo přehrává. Buďte proto opatrní, když jde o hesla, platební údaje, zprávy, fotografie, zvuk a video."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Nahrát obrazovku"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Předvolbu nelze aktualizovat"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Předvolba"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Vybráno"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Okolí"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Vlevo"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Vpravo"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Rozbalit na samostatné ovládání levé a pravé strany"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Sbalit na sjednocené ovládání"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Ztlumit okolí"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Zapnout zvuk okolí"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Nástroje"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Okamžité titulky"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Poznámka"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Zobrazit ikony oznámení s nízkou prioritou"</string> <string name="other" msgid="429768510980739978">"Jiné"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"odstranit dlaždici"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"přidat dlaždici na poslední pozici"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Přesunout dlaždici"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Přidat dlaždici na požadované místo"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Přesunout na pozici <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Přidat dlaždici na pozici <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Pozice není platná."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"zvolit uživatele"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Nejste připojeni k internetu"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Otevřít nastavení aplikace <xliff:g id="ID_1">%s</xliff:g>."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Upravit pořadí Rychlého nastavení."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Nabídka vypínače"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Stránka <xliff:g id="ID_1">%1$d</xliff:g> z <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Obrazovka uzamčení"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"zadáte zařízení"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"K otevření použijte otisk prstu"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Je vyžadováno ověření. Dotkněte se snímače otisků prstů."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Probíhající hovor"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilní data"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Připojeno"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Dočasně připojeno"</string> @@ -1449,7 +1438,7 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Přístupnost"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Klávesové zkratky"</string> <string name="shortcut_helper_customize_mode_title" msgid="1467657117101096033">"Přizpůsobení klávesových zkratek"</string> - <string name="shortcut_customize_mode_remove_shortcut_dialog_title" msgid="7106420484940737208">"Odstrabit zkratku?"</string> + <string name="shortcut_customize_mode_remove_shortcut_dialog_title" msgid="7106420484940737208">"Odstranit zkratku?"</string> <string name="shortcut_customize_mode_reset_shortcut_dialog_title" msgid="8131184731313717780">"Resetovat do výchozího nastavení?"</string> <string name="shortcut_customize_mode_add_shortcut_description" msgid="6866025005347407696">"Nastavte zkratku stisknutím klávesy"</string> <string name="shortcut_customize_mode_remove_shortcut_description" msgid="6851287900585057128">"Vlastní zkratka se trvale smaže."</string> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index c168a306b4cd..bcf93657caa7 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Konstant notifikation om skærmoptagelse"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Vil du optage din skærm?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Optag én app"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Optag denne skærm"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Optag %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Når du optager hele skærmen, bliver alt det, der vises på skærmen, optaget. Vær derfor forsigtig med ting såsom adgangskoder, betalingsoplysninger, beskeder, billeder, lyd og video."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Når du optager en app, optages alt det, der vises eller afspilles i den pågældende app. Vær derfor forsigtig med ting såsom adgangskoder, betalingsoplysninger, beskeder, billeder, lyd og video."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Optag skærm"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Forindstillingen kunne ikke opdateres"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Forindstilling"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Valgt"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Omgivelser"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Venstre"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Højre"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Udvid til adskilte styringselementer til venstre og højre"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Minimer til samlet styringselement"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Ignorer omgivelser"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Ignorer ikke omgivelser"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Værktøjer"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Livetekstning"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Note"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Vis ikoner for notifikationer med lav prioritet"</string> <string name="other" msgid="429768510980739978">"Andet"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"fjern felt"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"føj handlingsfeltet til den sidste position"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Flyt felt"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Føj handlingsfeltet til den ønskede placering"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Flyt til <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Føj til lokation <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Positionen er ugyldig."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"vælge bruger"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Intet internet"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Åbn <xliff:g id="ID_1">%s</xliff:g>-indstillinger."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Rediger rækkefølgen af kvikmenuen."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menu for afbryderknappen"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Side <xliff:g id="ID_1">%1$d</xliff:g> af <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Låseskærm"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"få adgang til enheden"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Brug fingeraftryk for at åbne"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Godkendelse er påkrævet. Sæt fingeren på fingeraftrykssensoren for at godkende."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Igangværende telefonopkald"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobildata"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Forbundet"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Midlertidigt forbundet"</string> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index eaa849db64b1..670f5a712c4a 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Fortlaufende Benachrichtigung für eine Bildschirmaufzeichnung"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Bildschirm aufnehmen?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Einzelne App aufnehmen"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Diesen Bildschirm aufnehmen"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"%s aufnehmen"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Wenn du den gesamten Bildschirm aufnimmst, ist in der Aufnahme alles zu sehen, was auf dem Bildschirm angezeigt wird. Sei also vorsichtig mit Informationen wie Passwörtern, Zahlungsdetails, Nachrichten, Fotos sowie Audio- und Videoinhalten."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Wenn du eine App aufnimmst, ist in der Aufnahme alles zu sehen, was in dieser App angezeigt oder abgespielt wird. Sei also vorsichtig mit Informationen wie Passwörtern, Zahlungsdetails, Nachrichten, Fotos sowie Audio- und Videoinhalten."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Bildschirm aufnehmen"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Voreinstellung konnte nicht aktualisiert werden"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Voreinstellung"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Ausgewählt"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Umgebungsgeräusche"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Links"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Rechts"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"In ein linkes und ein rechtes Steuerfeld maximieren"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Zu einem einzigen Steuerfeld minimieren"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Umgebungsgeräusche stummschalten"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Stummschaltung der Umgebungsgeräusche aufheben"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Tools"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Automatische Untertitel"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Notiz"</string> @@ -839,7 +830,7 @@ <string name="keyboard_key_button_template" msgid="8005673627272051429">"Taste <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="3734400625170020657">"Pos1"</string> <string name="keyboard_key_back" msgid="4185420465469481999">"Zurück"</string> - <string name="keyboard_key_tab" msgid="4592772350906496730">"Tabulatortaste"</string> + <string name="keyboard_key_tab" msgid="4592772350906496730">"Tab"</string> <string name="keyboard_key_space" msgid="6980847564173394012">"Leertaste"</string> <string name="keyboard_key_enter" msgid="8633362970109751646">"Eingabetaste"</string> <string name="keyboard_key_backspace" msgid="4095278312039628074">"Rücktaste"</string> @@ -885,7 +876,7 @@ <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Tastenkürzel anzeigen"</string> <string name="group_system_go_back" msgid="2730322046244918816">"Zurück"</string> <string name="group_system_access_home_screen" msgid="4130366993484706483">"Zum Startbildschirm wechseln"</string> - <string name="group_system_overview_open_apps" msgid="5659958952937994104">"Letzte Apps aufrufen"</string> + <string name="group_system_overview_open_apps" msgid="5659958952937994104">"Zuletzt verwendete Apps aufrufen"</string> <string name="group_system_cycle_forward" msgid="5478663965957647805">"Zuletzt verwendete Apps vorwärts durchgehen"</string> <string name="group_system_cycle_back" msgid="8194102916946802902">"Zuletzt verwendete Apps rückwärts durchgehen"</string> <string name="group_system_access_all_apps_search" msgid="1553588630154197469">"Liste der Apps öffnen"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Symbole für Benachrichtigungen mit einer niedrigen Priorität anzeigen"</string> <string name="other" msgid="429768510980739978">"Sonstiges"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"Entfernen der Kachel"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"Kachel an letzter Position hinzufügen"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Kachel verschieben"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Kachel an gewünschter Position hinzufügen"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Auf Position <xliff:g id="POSITION">%1$d</xliff:g> verschieben"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Zur Position <xliff:g id="POSITION">%1$d</xliff:g> hinzufügen"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Position ist ungültig."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"Auswählen des Nutzers"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Kein Internet"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Einstellungen für <xliff:g id="ID_1">%s</xliff:g> öffnen."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Reihenfolge der Schnelleinstellungen bearbeiten"</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Ein-/Aus-Menü"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Seite <xliff:g id="ID_1">%1$d</xliff:g> von <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Sperrbildschirm"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"Eingeben des Geräts"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Mit Fingerabdruck öffnen"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentifizierung erforderlich. Tippe dazu einfach auf den Fingerabdrucksensor."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Aktiver Anruf"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile Daten"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Verbunden"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Vorübergehend verbunden"</string> @@ -1444,16 +1433,16 @@ <string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Multitasking"</string> <string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Splitscreen"</string> <string name="shortcut_helper_category_input" msgid="8674018654124839566">"Eingabe"</string> - <string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"App-Verknüpfungen"</string> + <string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Tastaturkürzel für Apps"</string> <string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Aktuelle App"</string> <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Bedienungshilfen"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Tastenkürzel"</string> - <string name="shortcut_helper_customize_mode_title" msgid="1467657117101096033">"Tastenkombinationen anpassen"</string> - <string name="shortcut_customize_mode_remove_shortcut_dialog_title" msgid="7106420484940737208">"Tastenkombination entfernen?"</string> + <string name="shortcut_helper_customize_mode_title" msgid="1467657117101096033">"Tastenkürzel anpassen"</string> + <string name="shortcut_customize_mode_remove_shortcut_dialog_title" msgid="7106420484940737208">"Tastaturkürzel entfernen?"</string> <string name="shortcut_customize_mode_reset_shortcut_dialog_title" msgid="8131184731313717780">"Auf Standardeinstellung zurücksetzen?"</string> - <string name="shortcut_customize_mode_add_shortcut_description" msgid="6866025005347407696">"Drücke eine Taste, um eine Tastenkombination festzulegen"</string> - <string name="shortcut_customize_mode_remove_shortcut_description" msgid="6851287900585057128">"Dadurch wird die benutzerdefinierte Tastenkombination endgültig gelöscht."</string> - <string name="shortcut_customize_mode_reset_shortcut_description" msgid="2081849715634358684">"Dadurch werden alle deine benutzerdefinierten Tastenkombinationen endgültig gelöscht."</string> + <string name="shortcut_customize_mode_add_shortcut_description" msgid="6866025005347407696">"Drücke eine Taste, um das Tastaturkürzel einzurichten"</string> + <string name="shortcut_customize_mode_remove_shortcut_description" msgid="6851287900585057128">"Das benutzerdefinierte Tastenkürzel wird endgültig gelöscht."</string> + <string name="shortcut_customize_mode_reset_shortcut_description" msgid="2081849715634358684">"Alle deine benutzerdefinierten Tastenkürzel werden endgültig gelöscht."</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Tastenkürzel suchen"</string> <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Keine Suchergebnisse"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Symbol „Minimieren“"</string> @@ -1468,7 +1457,7 @@ <string name="shortcut_helper_key_combinations_forward_slash" msgid="1238652537199346970">"Schrägstrich"</string> <string name="shortcut_helper_content_description_drag_handle" msgid="5092426406009848110">"Ziehpunkt"</string> <string name="shortcut_helper_keyboard_settings_buttons_label" msgid="6720967595915985259">"Tastatureinstellungen"</string> - <string name="shortcut_helper_customize_dialog_set_shortcut_button_label" msgid="4754492225010429382">"Tastenkombination festlegen"</string> + <string name="shortcut_helper_customize_dialog_set_shortcut_button_label" msgid="4754492225010429382">"Speichern"</string> <string name="shortcut_helper_customize_dialog_remove_button_label" msgid="6546386970440176552">"Entfernen"</string> <string name="shortcut_helper_customize_dialog_reset_button_label" msgid="7645535254306312685">"Ja, zurücksetzen"</string> <string name="shortcut_helper_customize_dialog_cancel_button_label" msgid="5595546460431741178">"Abbrechen"</string> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index dab393cffe56..31e356797f68 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ειδοποίηση σε εξέλιξη για μια περίοδο λειτουργίας εγγραφής οθόνης"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Να γίνει εγγραφή της οθόνης σας;"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Εγγραφή μίας εφαρμογής"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Εγγραφή αυτής της οθόνης"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Εγγραφή %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Όταν κάνετε εγγραφή ολόκληρης της οθόνη σας, καταγράφεται οτιδήποτε εμφανίζεται σε αυτήν. Επομένως, να είστε προσεκτικοί με τους κωδικούς πρόσβασης, τα στοιχεία πληρωμής, τα μηνύματα, τις φωτογραφίες, τον ήχο και το βίντεο."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Όταν κάνετε εγγραφή μιας εφαρμογής, καταγράφεται οτιδήποτε εμφανίζεται ή αναπαράγεται στη συγκεκριμένη εφαρμογή. Επομένως, να είστε προσεκτικοί με τους κωδικούς πρόσβασης, τα στοιχεία πληρωμής, τα μηνύματα, τις φωτογραφίες, τον ήχο και το βίντεο."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Εγγραφή οθόνης"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Δεν ήταν δυνατή η ενημέρωση της προεπιλογής"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Προεπιλογή"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Έχει επιλεγεί"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Ήχοι περιβάλλοντος"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Αριστερά"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Δεξιά"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Ανάπτυξη σε ξεχωριστά στοιχεία ελέγχου αριστερά και δεξιά"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Σύμπτυξη σε ενοποιημένο στοιχείο ελέγχου"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Σίγαση ήχων περιβάλλοντος"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Κατάργηση σίγασης ήχων περιβάλλοντος"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Εργαλεία"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Ζωντανοί υπότιτλοι"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Σημείωση"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Εμφάνιση εικονιδίων ειδοποιήσεων χαμηλής προτεραιότητας"</string> <string name="other" msgid="429768510980739978">"Άλλο"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"κατάργηση πλακιδίου"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"προσθήκη πλακιδίου στην τελευταία θέση"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Μετακίνηση πλακιδίου"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Προσθήκη πλακιδίου στην επιθυμητή θέση"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Μετακίνηση στη θέση <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Προσθήκη στη θέση <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Μη έγκυρη θέση."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"επιλογή χρήστη"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Δεν υπάρχει σύνδεση στο διαδίκτυο"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Άνοιγμα ρυθμίσεων <xliff:g id="ID_1">%s</xliff:g>."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Επεξεργασία σειράς Γρήγορων ρυθμίσεων."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Μενού λειτουργίας"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Σελίδα <xliff:g id="ID_1">%1$d</xliff:g> από <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Οθόνη κλειδώματος"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"εισαγωγή συσκευής"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Χρήση δακτυλικού αποτυπώματος για άνοιγμα"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Απαιτείται έλεγχος ταυτότητας. Αγγίξτε τον αισθητήρα δακτυλικών αποτυπωμάτων για έλεγχο ταυτότητας."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Τηλεφωνική κλήση σε εξέλιξη"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Δεδομένα κινητής τηλεφωνίας"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Συνδέθηκε"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Προσωρινή σύνδεση"</string> diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml index efab948b12bb..30eb21f9308f 100644 --- a/packages/SystemUI/res/values-en-rAU/strings.xml +++ b/packages/SystemUI/res/values-en-rAU/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Record your screen?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Record one app"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Record this screen"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Record %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"When you\'re recording your entire screen, anything displayed on your screen is recorded. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"When you\'re recording an app, anything displayed or played in that app is recorded. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Record screen"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Couldn\'t update preset"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Preset"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Selected"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Surroundings"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Left"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Right"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Expand to left and right separated controls"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Collapse to unified control"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Mute surroundings"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Unmute surroundings"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Tools"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Live Caption"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Note"</string> @@ -1298,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"enter device"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Use fingerprint to open"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentication required. Touch the fingerprint sensor to authenticate."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ongoing phone call"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Connected"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Temporarily connected"</string> diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml index 8486688cbf8d..4b4b7b8e4575 100644 --- a/packages/SystemUI/res/values-en-rCA/strings.xml +++ b/packages/SystemUI/res/values-en-rCA/strings.xml @@ -1289,7 +1289,7 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"enter device"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Use fingerprint to open"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentication required. Touch the fingerprint sensor to authenticate."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ongoing phone call"</string> + <string name="ongoing_call_content_description" msgid="6394763878322348560">"Ongoing call"</string> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Connected"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Temporarily connected"</string> diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index efab948b12bb..30eb21f9308f 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Record your screen?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Record one app"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Record this screen"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Record %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"When you\'re recording your entire screen, anything displayed on your screen is recorded. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"When you\'re recording an app, anything displayed or played in that app is recorded. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Record screen"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Couldn\'t update preset"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Preset"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Selected"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Surroundings"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Left"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Right"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Expand to left and right separated controls"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Collapse to unified control"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Mute surroundings"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Unmute surroundings"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Tools"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Live Caption"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Note"</string> @@ -1298,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"enter device"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Use fingerprint to open"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentication required. Touch the fingerprint sensor to authenticate."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ongoing phone call"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Connected"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Temporarily connected"</string> diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml index efab948b12bb..30eb21f9308f 100644 --- a/packages/SystemUI/res/values-en-rIN/strings.xml +++ b/packages/SystemUI/res/values-en-rIN/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ongoing notification for a screen record session"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Record your screen?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Record one app"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Record this screen"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Record %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"When you\'re recording your entire screen, anything displayed on your screen is recorded. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"When you\'re recording an app, anything displayed or played in that app is recorded. So be careful with things like passwords, payment details, messages, photos, audio and video."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Record screen"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Couldn\'t update preset"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Preset"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Selected"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Surroundings"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Left"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Right"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Expand to left and right separated controls"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Collapse to unified control"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Mute surroundings"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Unmute surroundings"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Tools"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Live Caption"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Note"</string> @@ -1298,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"enter device"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Use fingerprint to open"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentication required. Touch the fingerprint sensor to authenticate."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ongoing phone call"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Connected"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Temporarily connected"</string> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index e9786e309aa9..2b3c54d9e280 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificación constante para una sesión de grabación de pantalla"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"¿Quieres grabar la pantalla?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Grabar una app"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Grabar esta pantalla"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Grabar %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Cuando grabes toda la pantalla, se grabará todo lo que se muestre en ella. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes, fotos, audios y videos."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Cuando grabes una app, se grabará todo lo que se muestre o reproduzca en ella. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes, fotos, audios y videos."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Grabar pantalla"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"No se pudo actualizar el ajuste predeterminado"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Ajuste predeterminado"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Seleccionado"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Sonido envolvente"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Izquierda"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Derecha"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Expandir los controles separados a la izquierda y a la derecha"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Contraer al control unificado"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Silenciar el sonido envolvente"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Activar el sonido envolvente"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Herramientas"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Subtitulado instantáneo"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Nota"</string> @@ -886,8 +877,8 @@ <string name="group_system_go_back" msgid="2730322046244918816">"Atrás"</string> <string name="group_system_access_home_screen" msgid="4130366993484706483">"Ir a la pantalla principal"</string> <string name="group_system_overview_open_apps" msgid="5659958952937994104">"Ver apps recientes"</string> - <string name="group_system_cycle_forward" msgid="5478663965957647805">"Desplazar por las apps recientes (adelante)"</string> - <string name="group_system_cycle_back" msgid="8194102916946802902">"Desplazar por las apps recientes (atrás)"</string> + <string name="group_system_cycle_forward" msgid="5478663965957647805">"Desplazarse por las apps recientes (adelante)"</string> + <string name="group_system_cycle_back" msgid="8194102916946802902">"Desplazarse por las apps recientes (atrás)"</string> <string name="group_system_access_all_apps_search" msgid="1553588630154197469">"Abrir lista de apps"</string> <string name="group_system_access_system_settings" msgid="8731721963449070017">"Abrir configuración"</string> <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Abrir Asistente"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Mostrar íconos de notificaciones con prioridad baja"</string> <string name="other" msgid="429768510980739978">"Otros"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"quitar tarjeta"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"agregar tarjeta a la última posición"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Mover la tarjeta"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Agregar tarjeta a la posición deseada"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Mover a <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Agregar a la posición <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Posición no válida"</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"elegir usuario"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Sin Internet"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Abrir configuración de <xliff:g id="ID_1">%s</xliff:g>"</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Editar el orden de la Configuración rápida."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menú de encendido"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Página <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Pantalla de bloqueo"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"ingresar al dispositivo"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Usa la huella dactilar para abrir"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Se requiere de una autenticación. Toca el sensor de huellas dactilares para autenticarte."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Llamada en curso"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Datos móviles"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Conexión establecida"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Conectado temporalmente"</string> @@ -1449,11 +1438,11 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Accesibilidad"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Combinaciones de teclas"</string> <string name="shortcut_helper_customize_mode_title" msgid="1467657117101096033">"Personaliza las combinaciones de teclas"</string> - <string name="shortcut_customize_mode_remove_shortcut_dialog_title" msgid="7106420484940737208">"¿Quieres quitar el acceso directo?"</string> + <string name="shortcut_customize_mode_remove_shortcut_dialog_title" msgid="7106420484940737208">"¿Quieres quitar la combinación?"</string> <string name="shortcut_customize_mode_reset_shortcut_dialog_title" msgid="8131184731313717780">"¿Quieres restablecer la configuración predeterminada?"</string> - <string name="shortcut_customize_mode_add_shortcut_description" msgid="6866025005347407696">"Presiona la tecla para asignar el acceso directo"</string> - <string name="shortcut_customize_mode_remove_shortcut_description" msgid="6851287900585057128">"Esta acción borrará tu acceso directo personalizado de forma permanente."</string> - <string name="shortcut_customize_mode_reset_shortcut_description" msgid="2081849715634358684">"Esta acción borrará todos tus accesos directos personalizados de forma permanente."</string> + <string name="shortcut_customize_mode_add_shortcut_description" msgid="6866025005347407696">"Presiona una tecla para asignar la combinación"</string> + <string name="shortcut_customize_mode_remove_shortcut_description" msgid="6851287900585057128">"Esta acción borrará tu combinación personalizada de forma permanente."</string> + <string name="shortcut_customize_mode_reset_shortcut_description" msgid="2081849715634358684">"Esta acción borrará todas tus combinaciones personalizadas de forma permanente."</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Buscar combinaciones de teclas"</string> <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"La búsqueda no arrojó resultados"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ícono de contraer"</string> @@ -1468,7 +1457,7 @@ <string name="shortcut_helper_key_combinations_forward_slash" msgid="1238652537199346970">"barra diagonal"</string> <string name="shortcut_helper_content_description_drag_handle" msgid="5092426406009848110">"Controlador de arrastre"</string> <string name="shortcut_helper_keyboard_settings_buttons_label" msgid="6720967595915985259">"Configuración del teclado"</string> - <string name="shortcut_helper_customize_dialog_set_shortcut_button_label" msgid="4754492225010429382">"Establecer combinación de teclas"</string> + <string name="shortcut_helper_customize_dialog_set_shortcut_button_label" msgid="4754492225010429382">"Establecer"</string> <string name="shortcut_helper_customize_dialog_remove_button_label" msgid="6546386970440176552">"Quitar"</string> <string name="shortcut_helper_customize_dialog_reset_button_label" msgid="7645535254306312685">"Sí, restablecer"</string> <string name="shortcut_helper_customize_dialog_cancel_button_label" msgid="5595546460431741178">"Cancelar"</string> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index 946087472777..69fab5ac89db 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificación continua de una sesión de grabación de la pantalla"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"¿Grabar la pantalla?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Grabar una aplicación"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Grabar esta pantalla"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Grabar %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Cuando grabas toda la pantalla, se graba todo lo que se muestre en ella. Debes tener cuidado con elementos como contraseñas, detalles de pagos, mensajes, fotos, audio y vídeo."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Cuando grabas una aplicación, se graba todo lo que se muestre o reproduzca en ella. Debes tener cuidado con elementos como contraseñas, detalles de pagos, mensajes, fotos, audio y vídeo."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Grabar pantalla"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"No se ha podido actualizar el preajuste"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Preajuste"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Seleccionado"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Alrededores"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Izquierda"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Derecha"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Expandir a los controles separados de izquierda y derecha"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Contraer al control unificado"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Silenciar alrededores"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Dejar de silenciar alrededores"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Herramientas"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Subtítulos automáticos"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Nota"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Mostrar iconos de notificaciones con prioridad baja"</string> <string name="other" msgid="429768510980739978">"Otros"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"quitar recuadro"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"añadir el recuadro a la última posición"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Mover recuadro"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Añadir recuadro a la posición deseada"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Mover a <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Añadir a la posición <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Posición no válida."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"elegir un usuario"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Sin Internet"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Abrir ajustes de <xliff:g id="ID_1">%s</xliff:g>."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Editar orden de los ajustes rápidos."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menú de encendido"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Página <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Pantalla de bloqueo"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"acceder al dispositivo"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Usa la huella digital para abrir"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticación obligatoria. Toca el sensor de huellas digitales para autenticarte."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Llamada en curso"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Datos móviles"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Conectado"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Conectada temporalmente"</string> @@ -1454,7 +1443,7 @@ <string name="shortcut_customize_mode_add_shortcut_description" msgid="6866025005347407696">"Pulsa una tecla para asignar una combinación de teclas"</string> <string name="shortcut_customize_mode_remove_shortcut_description" msgid="6851287900585057128">"Se eliminará tu combinación de teclas personalizada de forma permanente."</string> <string name="shortcut_customize_mode_reset_shortcut_description" msgid="2081849715634358684">"Se eliminarán todos tus accesos directos personalizados de forma permanente."</string> - <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Atajos de búsqueda"</string> + <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Buscar accesos directos"</string> <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"No hay resultados de búsqueda"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Icono de contraer"</string> <string name="shortcut_helper_content_description_meta_key" msgid="3989315044342124818">"Icono de la tecla de acción o de la tecla Meta"</string> diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml index 3999042fdd2d..2ba50051b6ab 100644 --- a/packages/SystemUI/res/values-et/strings.xml +++ b/packages/SystemUI/res/values-et/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Pooleli märguanne ekraanikuva salvestamise seansi puhul"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Kas salvestada ekraanikuvast video?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Ühe rakenduse salvestamine"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Ekraanikuva jäädvustamine"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Kuva %s jäädvustamine"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Kui salvestate kogu ekraani, salvestatakse kõik ekraanil kuvatud andmed. Seega olge ettevaatlik selliste andmetega nagu paroolid, makseteave, sõnumid, fotod ning heli ja video."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Kui salvestate rakendust, salvestatakse kõik, mida selles rakenduses näidatakse või esitatakse. Seega olge ettevaatlik selliste andmetega nagu paroolid, makseteave, sõnumid, fotod ning heli ja video."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Salvesta ekraanikuva"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Eelseadistust ei saanud värskendada"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Eelseadistus"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Valitud"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Ümbritsevad helid"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Vasakule"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Paremale"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Vasaku ja parema poole eraldi juhtimine"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Mõlema poole ühtne juhtimine"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Ümbritsevate helide vaigistamine"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Ümbritsevate helide vaigistuse tühistamine"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Tööriistad"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Reaalajas subtiitrid"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Märkus"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Kuva madala prioriteediga märguande ikoonid"</string> <string name="other" msgid="429768510980739978">"Muu"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"paani eemaldamiseks"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"lisage paan viimasesse asukohta"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Teisalda paan"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Lisage paan soovitud asukohta"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Teisaldamine asendisse <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Lisamine asendisse <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Sobimatu asukoht."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"valige kasutaja"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Interneti-ühendus puudub"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Ava teenuse <xliff:g id="ID_1">%s</xliff:g> seaded."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Muutke kiirseadete järjekorda"</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Toitemenüü"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Leht <xliff:g id="ID_1">%1$d</xliff:g>/<xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Lukustuskuva"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"seadmesse sisenemiseks"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Kasutage avamiseks sõrmejälge"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Vajalik on autentimine. Puudutage autentimiseks sõrmejäljeandurit."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Käimasolev telefonikõne"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiilne andmeside"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Ühendatud"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Ajutiselt ühendatud"</string> @@ -1459,7 +1448,7 @@ <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Ahendamisikoon"</string> <string name="shortcut_helper_content_description_meta_key" msgid="3989315044342124818">"Toiming või metaklahv"</string> <string name="shortcut_helper_content_description_plus_icon" msgid="6152683734278299020">"Pluss-ikoon"</string> - <string name="shortcut_helper_customize_button_text" msgid="3124983502748069338">"Kohandamine"</string> + <string name="shortcut_helper_customize_button_text" msgid="3124983502748069338">"Kohanda"</string> <string name="shortcut_helper_reset_button_text" msgid="2548243844050633472">"Lähtesta"</string> <string name="shortcut_helper_done_button_text" msgid="7249905942125386191">"Valmis"</string> <string name="shortcut_helper_content_description_expand_icon" msgid="1084435697860417390">"Laiendamisikoon"</string> @@ -1468,12 +1457,12 @@ <string name="shortcut_helper_key_combinations_forward_slash" msgid="1238652537199346970">"kaldkriips"</string> <string name="shortcut_helper_content_description_drag_handle" msgid="5092426406009848110">"Lohistamispide"</string> <string name="shortcut_helper_keyboard_settings_buttons_label" msgid="6720967595915985259">"Klaviatuuri seaded"</string> - <string name="shortcut_helper_customize_dialog_set_shortcut_button_label" msgid="4754492225010429382">"Määrake otsetee"</string> + <string name="shortcut_helper_customize_dialog_set_shortcut_button_label" msgid="4754492225010429382">"Määra otsetee"</string> <string name="shortcut_helper_customize_dialog_remove_button_label" msgid="6546386970440176552">"Eemalda"</string> - <string name="shortcut_helper_customize_dialog_reset_button_label" msgid="7645535254306312685">"Jah, lähtesta"</string> + <string name="shortcut_helper_customize_dialog_reset_button_label" msgid="7645535254306312685">"Lähtesta"</string> <string name="shortcut_helper_customize_dialog_cancel_button_label" msgid="5595546460431741178">"Tühista"</string> <string name="shortcut_helper_add_shortcut_dialog_placeholder" msgid="9154297849458741995">"Vajutage klahvi"</string> - <string name="shortcut_customizer_key_combination_in_use_error_message" msgid="7693234470526626327">"Klahvikombinatsioon on juba kasutusel. Proovige mõnda muud klahvi."</string> + <string name="shortcut_customizer_key_combination_in_use_error_message" msgid="7693234470526626327">"Kombinatsioon on juba kasutusel. Proovige mõnda muud klahvi."</string> <string name="shortcut_customizer_generic_error_message" msgid="3128454624049722741">"Otseteed ei saa seadistada."</string> <string name="shortcut_helper_plus_symbol" msgid="4534843157353732011">"+"</string> <string name="launch_keyboard_tutorial_notification_title" msgid="8849933155160522519">"Navigeerige klaviatuuri abil"</string> diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml index 88a46c19bb83..89ec1dda2435 100644 --- a/packages/SystemUI/res/values-eu/strings.xml +++ b/packages/SystemUI/res/values-eu/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Pantailaren grabaketa-saioaren jakinarazpen jarraitua"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Pantaila grabatu nahi duzu?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Grabatu aplikazio bat"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Grabatu pantaila hau"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Grabatu %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Pantaila osoa grabatzen ari zarenean, pantailan agertzen den guztia grabatzen da. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin, argazkiekin, audioekin eta bideoekin, besteak beste."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Aplikazio bat grabatzen ari zarenean, aplikazio horretan agertzen den edo bertan erreproduzitzen ari den guztia grabatzen da. Beraz, kontuz ibili pasahitzekin, ordainketen xehetasunekin, mezuekin, argazkiekin, audioekin eta bideoekin, besteak beste."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Grabatu pantaila"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Ezin izan da eguneratu aurrezarpena"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Aurrezarpena"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Hautatuta"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Ingurunea"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Ezkerrekoa"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Eskuinekoa"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Zabaldu ezkerreko eta eskuineko kontrolatzeko aukerak bereiz erabiltzeko"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Tolestu kontrolatzeko aukerak bateratuta erabiltzeko"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Desaktibatu ingurunearen audioa"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Aktibatu ingurunearen audioa"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Tresnak"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Istanteko azpitituluak"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Oharra"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Erakutsi lehentasun txikiko jakinarazpenen ikonoak"</string> <string name="other" msgid="429768510980739978">"Beste bat"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"kendu lauza"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"gehitu lauza azken posizioan"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Mugitu lauza"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Gehitu lauza nahi duzun posizioan"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Eraman <xliff:g id="POSITION">%1$d</xliff:g>garren lekura"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Gehitu <xliff:g id="POSITION">%1$d</xliff:g>garren lekuan"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Kokapenak ez du balio."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"erabiltzailea aukeratzeko"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Ez dago Interneteko konexiorik"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Ireki <xliff:g id="ID_1">%s</xliff:g> ezarpenak."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Editatu ezarpen bizkorren ordena."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Itzaltzeko menua"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_1">%1$d</xliff:g>/<xliff:g id="ID_2">%2$d</xliff:g> orria"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Pantaila blokeatua"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"sartu gailuan"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Erabili hatz-marka irekitzeko"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autentifikazioa behar da. Autentifikatzeko, ukitu hatz-marken sentsorea."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Telefono-dei bat abian da"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Datu-konexioa"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Konektatuta"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Aldi baterako konektatuta"</string> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index 5e851dc5db52..ae15b2ffe203 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"اعلان درحال انجام برای جلسه ضبط صفحهنمایش"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"صفحهنمایش ضبط شود؟"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"ضبط یک برنامه"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"ضبط کردن این صفحه"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"ضبط کردن %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"وقتی کل صفحهنمایش را ضبط میکنید، هر چیزی که در صفحهنمایش نشان داده شود ضبط خواهد شد. درنتیجه مراقب چیزهایی مثل گذرواژهها، جزئیات پرداخت، پیامها، عکسها، و صدا و تصویر باشید."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"وقتی برنامهای را ضبط میکنید، هر چیزی که در آن برنامه نشان داده شود یا پخش شود ضبط خواهد شد. درنتیجه مراقب چیزهایی مثل گذرواژهها، جزئیات پرداخت، پیامها، عکسها، و صدا و تصویر باشید."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"ضبط صفحهنمایش"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"پیشتنظیم بهروزرسانی نشد"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"پیشتنظیم"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"انتخابشده"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"پیرامون"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"چپ"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"راست"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"ازهم بازکردن برای کنترلهای جداگانه چپ و راست"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"جمع کردن برای کنترل یکپارچه"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"بیصدا کردن پیرامون"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"صدادار کردن پیرامون"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"ابزارها"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"زیرنویس زنده ناشنوایان"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"یادداشت"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"نمایش نمادهای اعلان کماهمیت"</string> <string name="other" msgid="429768510980739978">"موارد دیگر"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"برداشتن کاشی"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"افزودن کاشی به آخرین جایگاه"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"انتقال کاشی"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"افزودن کاشی به جایگاه دلخواه"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"انتقال به <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"افزودن به موقعیت <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"موقعیت نامعتبر است."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"انتخاب کاربر"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"عدم اتصال به اینترنت"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"باز کردن تنظیمات <xliff:g id="ID_1">%s</xliff:g>."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"ویرایش ترتیب «تنظیمات فوری»."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"منوی روشن/خاموش"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"صفحه <xliff:g id="ID_1">%1$d</xliff:g> از <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"صفحه قفل"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"وارد شدن به دستگاه"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"از اثر انگشت برای باز کردن قفل استفاده کنید"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"اصالتسنجی لازم است. برای اصالتسنجی، حسگر اثر انگشت را لمس کنید."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"تماس تلفنی درحال انجام"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"داده تلفن همراه"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"متصل است"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"موقتاً متصل است"</string> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index b257a89f6e26..3220bfcb8d65 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -111,8 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Pysyvä ilmoitus näytön tallentamisesta"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Tallennetaanko näytön toimintaa?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Tallenna yhdestä sovelluksesta"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Tallenna tämä näyttö"</string> + <!-- String.format failed for translation --> <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> <skip /> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Kun tallennat koko näyttöä, kaikki näytöllä näkyvä sisältö tallennetaan. Ole siis varovainen, kun lisäät salasanoja, maksutietoja, viestejä, kuvia, audiota tai videoita."</string> @@ -417,20 +417,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Esiasetusta ei voitu muuttaa"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Esiasetus"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Valittu"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Ympäristö"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Vasen"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Oikea"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Laajenna vasemmalle ja oikealle erilliset ohjaimet"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Tiivistä yhtenäiseksi säätimeksi"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Mykistä ympäristö"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Poista ympäristön mykistys"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Työkalut"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Livetekstitys"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Muistiinpano"</string> @@ -976,11 +969,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Näytä vähemmän tärkeät ilmoituskuvakkeet"</string> <string name="other" msgid="429768510980739978">"Muu"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"poista kiekko"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"lisää laatta viimeiseen kohtaan"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Siirrä kiekkoa"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Lisää laatta haluttuun kohtaan"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Siirrä paikkaan <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Lisää paikkaan <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Virheellinen sijainti."</string> @@ -996,8 +987,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"valitse käyttäjä"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Ei internetyhteyttä"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Avaa kohteen <xliff:g id="ID_1">%s</xliff:g> asetukset."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Muokkaa pika-asetusten järjestystä."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Virtavalikko"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Sivu <xliff:g id="ID_1">%1$d</xliff:g>/<xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Lukitusnäyttö"</string> @@ -1301,7 +1291,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"avataksesi laitteen"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Avaa sormenjäljellä"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Todennus vaaditaan. Todenna koskettamalla sormenjälkitunnistinta."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Puhelu käynnissä"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiilidata"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Yhdistetty"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Väliaikaisesti yhdistetty"</string> diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index 8481f0fbb790..367c7591a2b7 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notification en cours pour une session d\'enregistrement d\'écran"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Enregistrer votre écran?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Enregistrer une appli"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Enregistrer cet écran"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Enregistrer %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Lorsque vous enregistrez l\'intégralité de votre écran, tout ce qui s\'affiche sur votre écran est enregistré. Par conséquent, soyez prudent avec les mots de passe, les détails du mode de paiement, les messages, les photos et les contenus audio et vidéo."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Lorsque vous enregistrez une appli, tout ce qui est affiché ou lu dans cette appli est enregistré. Par conséquent, soyez prudent avec les mots de passe, les détails du mode de paiement, les messages, les photos et les contenus audio et vidéo."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Enregistrer l\'écran"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Impossible de mettre à jour le préréglage"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Préréglage"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Sélectionné"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Environnement"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Gauche"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Droit"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Développer les commandes distinctes à gauche et à droite"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Passer au contrôle unifié"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Ignorer les sons de l\'environnement"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Réactiver les sons de l\'environnement"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Outils"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Sous-titres instantanés"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Note"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Afficher les icônes de notification de faible priorité"</string> <string name="other" msgid="429768510980739978">"Autre"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"retirer la tuile"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"Ajouter une tuile à la dernière position"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Déplacer la tuile"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Ajouter une tuile à la position désirée"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Déplacer vers <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Ajouter à la position <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Position incorrecte."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"choisir un utilisateur"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Aucune connexion Internet"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Ouvrir les paramètres <xliff:g id="ID_1">%s</xliff:g>."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Modifier l\'ordre des Paramètres rapides."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menu de l\'interrupteur"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Page <xliff:g id="ID_1">%1$d</xliff:g> sur <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Écran de verrouillage"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"accéder à l\'appareil"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Servez-vous de votre empreinte digitale pour ouvrir"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentification requise. Touchez le capteur d\'empreintes digitales pour vous authentifier."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Appel téléphonique en cours…"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Données cellulaires"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Connexion active"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Connectée temporairement"</string> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index 80f9cd9adffe..dc10bcbf74be 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notification en cours pour une session d\'enregistrement de l\'écran"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Enregistrer l\'écran ?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Enregistrer une appli"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Enregistrer cet écran"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Enregistrer %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Lorsque vous enregistrez l\'intégralité de votre écran, tout ce qui s\'y affiche est enregistré. Faites donc attention aux éléments tels que les mots de passe, les détails de mode de paiement, les messages, les photos, et les contenus audio et vidéo."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Lorsque vous enregistrez une appli, tout ce qui est affiché ou lu dans celle-ci est enregistré. Faites donc attention aux éléments tels que les mots de passe, détails de mode de paiement, messages, photos et contenus audio et vidéo."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Enregistrer l\'écran"</string> @@ -180,7 +178,7 @@ <string name="accessibility_phone_button" msgid="4256353121703100427">"Téléphoner"</string> <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Assistance vocale"</string> <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string> - <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Lecteur code QR"</string> + <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"Lecteur QR code"</string> <string name="accessibility_unlock_button" msgid="3613812140816244310">"Déverrouillé"</string> <string name="accessibility_lock_icon" msgid="661492842417875775">"Appareil verrouillé"</string> <string name="accessibility_scanning_face" msgid="3093828357921541387">"Analyse du visage en cours"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Impossible de mettre à jour les préréglages"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Préréglage"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Sélectionné"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Sons environnants"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Gauche"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Droite"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Développer les commandes gauche et droite"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Réduire en une commande unifiée"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Couper le mode Sons environnants"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Réactiver le mode Sons environnants"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Outils"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Sous-titres instantanés"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Note"</string> @@ -755,7 +746,7 @@ <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Déverrouiller pour utiliser"</string> <string name="wallet_error_generic" msgid="257704570182963611">"Problème de récupération de vos cartes. Réessayez plus tard"</string> <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Paramètres de l\'écran de verrouillage"</string> - <string name="qr_code_scanner_title" msgid="1938155688725760702">"Lecteur code QR"</string> + <string name="qr_code_scanner_title" msgid="1938155688725760702">"Lecteur QR code"</string> <string name="qr_code_scanner_updating_secondary_label" msgid="8344598017007876352">"Mise à jour"</string> <string name="status_bar_work" msgid="5238641949837091056">"Profil professionnel"</string> <string name="status_bar_airplane" msgid="4848702508684541009">"Mode Avion"</string> @@ -1239,7 +1230,7 @@ <string name="media_output_first_broadcast_title" msgid="6292237789860753022">"Fonctionnement des annonces"</string> <string name="media_output_broadcast" msgid="3555580945878071543">"Annonce"</string> <string name="media_output_first_notify_broadcast_message" msgid="6353857724136398494">"Les personnes à proximité équipées d\'appareils Bluetooth compatibles peuvent écouter le contenu multimédia que vous diffusez"</string> - <string name="media_output_broadcasting_message" msgid="4150299923404886073">"Pour écouter votre annonce, les personnes à proximité équipées d\'appareils Bluetooth compatibles peuvent scanner votre code QR ou utiliser le nom et le mot de passe de votre annonce"</string> + <string name="media_output_broadcasting_message" msgid="4150299923404886073">"Pour écouter votre annonce, les personnes à proximité équipées d\'appareils Bluetooth compatibles peuvent scanner votre QR code ou utiliser le nom et le mot de passe de votre annonce"</string> <string name="media_output_broadcast_name" msgid="8786127091542624618">"Nom de l\'annonce"</string> <string name="media_output_broadcast_code" msgid="870795639644728542">"Mot de passe"</string> <string name="media_output_broadcast_dialog_save" msgid="7910865591430010198">"Enregistrer"</string> @@ -1298,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"accéder à l\'appareil"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Utilisez votre empreinte pour ouvrir"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Authentification requise. Appuyez sur le lecteur d\'empreintes digitales pour vous authentifier."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Appel téléphonique en cours"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Données mobiles"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Connecté"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Connexion temporaire"</string> diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml index 4837954b1161..eef9147bbfab 100644 --- a/packages/SystemUI/res/values-gl/strings.xml +++ b/packages/SystemUI/res/values-gl/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificación de actividade en curso sobre unha sesión de gravación de pantalla"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Queres gravar a túa pantalla?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Gravar unha aplicación"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Gravar esta pantalla"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Gravar %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Cando gravas a pantalla completa, recóllese todo o que se mostra nela. Recomendámosche que teñas coidado con determinada información, como os contrasinais, os detalles de pago, as mensaxes e as fotos, así como co contido de audio e de vídeo."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Cando gravas unha aplicación, recóllese todo o que se mostra ou reproduce nela. Recomendámosche que teñas coidado con determinada información, como os contrasinais, os detalles de pago, as mensaxes e as fotos, así como co contido de audio e de vídeo."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Gravar pantalla"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Non se puido actualizar a configuración predeterminada"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Configuración predeterminada"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Elemento seleccionado"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Ambiente"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Esquerdo"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Dereito"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Despregar para controis separados do lado esquerdo e do dereito"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Contraer para control unificado"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Silenciar o ambiente"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Activar o son ambiental"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Ferramentas"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Subtítulos instantáneos"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Nota"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Mostrar iconas das notificacións que teñan baixa prioridade"</string> <string name="other" msgid="429768510980739978">"Outros"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"quitar tarxeta"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"engadir o atallo á última posición"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Mover tarxeta"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Engadir o atallo á última posición"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Mover a <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Engadir á posición <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Posición non válida."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"escoller usuario"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Non hai conexión a Internet"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Abrir configuración de <xliff:g id="ID_1">%s</xliff:g>."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Editar a orde de Configuración rápida."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menú de acendido"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Páxina <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Pantalla de bloqueo"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"poñer o dispositivo"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Usa a impresión dixital para abrir"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Requírese autenticación. Para autenticarte, toca o sensor de impresión dixital."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Chamada telefónica en curso"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Datos móbiles"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Conectada"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Conectada temporalmente"</string> diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml index ceefccc26312..88b4f34c90c3 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"સ્ક્રીન રેકોર્ડિંગ સત્ર માટે ચાલુ નોટિફિકેશન"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"તમારી સ્ક્રીન રેકોર્ડ કરીએ?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"એક ઍપ રેકોર્ડ કરો"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"આ સ્ક્રીન રેકોર્ડ કરો"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"%s રેકોર્ડ કરો"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"જ્યારે તમે તમારી પૂર્ણ સ્ક્રીન રેકોર્ડ કરી રહ્યાં હો, ત્યારે તમારી સ્ક્રીન પર બતાવવામાં આવતી હોય તેવી બધી વસ્તુ રેકોર્ડ કરવામાં આવે છે. તેથી પાસવર્ડ, ચુકવણીની વિગતો, મેસેજ, ફોટા અને ડિવાઇસ પર વાગી રહેલા ઑડિયો તથા વીડિયો જેવી બાબતોને લઈને સાવચેત રહો."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"જ્યારે તમે કોઈ ઍપને રેકોર્ડ કરી રહ્યાં હો, ત્યારે એ ઍપમાં બતાવવામાં કે ચલાવવામાં આવતી હોય તેવી બધી વસ્તુ રેકોર્ડ કરવામાં આવે છે. તેથી પાસવર્ડ, ચુકવણીની વિગતો, મેસેજ, ફોટા અને ડિવાઇસ પર વાગી રહેલા ઑડિયો તથા વીડિયો જેવી બાબતોને લઈને સાવચેત રહો."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"સ્ક્રીન રેકોર્ડ કરો"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"પ્રીસેટ અપડેટ કરી શક્યા નથી"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"પ્રીસેટ"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"પસંદ કરી છે"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"આસપાસના અવાજો"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"ડાબે"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"જમણે"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"ડાબે અને જમણે અલગ કરેલા નિયંત્રણો સુધી વિસ્તૃત કરો"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"એકીકૃત નિયંત્રણ સુધી નાનું કરો"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"આસપાસના અવાજો મ્યૂટ કરો"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"આસપાસના અવાજો અનમ્યૂટ કરો"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"ટૂલ"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"લાઇવ કૅપ્શન"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"નોંધ"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"ઓછી પ્રાધાન્યતાનું નોટિફિકેશન આઇકન બતાવો"</string> <string name="other" msgid="429768510980739978">"અન્ય"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"ટાઇલ કાઢી નાખો"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"છેલ્લા સ્થાનમાં ટાઇલ ઉમેરો"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"ટાઇલ ખસેડો"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"ઇચ્છિત સ્થાનમાં ટાઇલ ઉમેરો"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> પર ખસેડો"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"જગ્યા પર <xliff:g id="POSITION">%1$d</xliff:g> ઉમેરો"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"સ્થિતિ અમાન્ય છે."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"વપરાશકર્તા પસંદ કરો"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"કોઈ ઇન્ટરનેટ નથી"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"<xliff:g id="ID_1">%s</xliff:g> સેટિંગ ખોલો."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"ઝડપી સેટિંગના ક્રમમાં ફેરફાર કરો."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"પાવર મેનૂ"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g> માંથી <xliff:g id="ID_1">%1$d</xliff:g> પૃષ્ઠ"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"લૉક સ્ક્રીન"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"ડિવાઇસ અનલૉક કરો"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ખોલવા માટે ફિંગરપ્રિન્ટનો ઉપયોગ કરો"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"પ્રમાણીકરણ આવશ્યક છે. પ્રમાણિત કરવા માટે ફિંગરપ્રિન્ટ સેન્સરને ટચ કરો."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ફોન કૉલ ચાલુ છે"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"મોબાઇલ ડેટા"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"કનેક્ટ કરેલું"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"હંગામી રીતે કનેક્ટ કર્યું"</string> @@ -1473,7 +1462,7 @@ <string name="shortcut_helper_customize_dialog_reset_button_label" msgid="7645535254306312685">"હા, રીસેટ કરો"</string> <string name="shortcut_helper_customize_dialog_cancel_button_label" msgid="5595546460431741178">"રદ કરો"</string> <string name="shortcut_helper_add_shortcut_dialog_placeholder" msgid="9154297849458741995">"કી દબાવો"</string> - <string name="shortcut_customizer_key_combination_in_use_error_message" msgid="7693234470526626327">"કી સંયોજન પેહલેથી ઉપયોગમાં છે. અન્ય કી અજમાવી જુઓ."</string> + <string name="shortcut_customizer_key_combination_in_use_error_message" msgid="7693234470526626327">"કી સંયોજન પહેલેલેથી ઉપયોગમાં છે. અન્ય કી અજમાવી જુઓ."</string> <string name="shortcut_customizer_generic_error_message" msgid="3128454624049722741">"શૉર્ટકટ સેટ કરી શકાતો નથી."</string> <string name="shortcut_helper_plus_symbol" msgid="4534843157353732011">"+"</string> <string name="launch_keyboard_tutorial_notification_title" msgid="8849933155160522519">"તમારા કીબોર્ડ વડે નૅવિગેટ કરો"</string> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index 91e17df566d8..1f7066e0d663 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"स्क्रीन रिकॉर्ड सेशन के लिए जारी सूचना"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"क्या आपको स्क्रीन को रिकॉर्ड करना है?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"एक ऐप्लिकेशन रिकॉर्ड करें"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"इस स्क्रीन को रिकॉर्ड करें"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"%s को रिकॉर्ड करें"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"पूरी स्क्रीन रिकॉर्ड करते समय, स्क्रीन पर दिखने वाली हर चीज़ रिकॉर्ड की जाती है. इसलिए पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज, डिवाइस पर चल रहे ऑडियो और वीडियो, और फ़ोटो जैसी चीज़ों को लेकर सावधानी बरतें."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"किसी ऐप्लिकेशन को रिकॉर्ड करने के दौरान, उस पर दिख रहा कॉन्टेंट या चल रहा मीडिया भी रिकॉर्ड होता है. इसलिए, रिकॉर्ड करते समय पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज, फ़ोटो, ऑडियो, और वीडियो को लेकर सावधानी बरतें."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"स्क्रीन रिकॉर्ड करें"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"प्रीसेट अपडेट नहीं किया जा सका"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"प्रीसेट"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"चुना गया"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"आस-पास का वॉल्यूम"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"बाईं ओर के वॉल्यूम के लिए"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"दाईं ओर के वॉल्यूम के लिए"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"दाईं और बाईं ओर के वॉल्यूम को अलग-अलग मैनेज करने के लिए, वॉल्यूम पैनल को बड़ा करें"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"यूनिफ़ाइड कंट्रोल पर जाने के लिए पैनल को छोटा करें"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"आस-पास के वॉल्यूम को म्यूट करें"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"आस-पास के वॉल्यूम को अनम्यूट करें"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"टूल"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"लाइव कैप्शन"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"नोट"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"कम प्राथमिकता वाली सूचना के आइकॉन दिखाएं"</string> <string name="other" msgid="429768510980739978">"अन्य"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"टाइल हटाएं"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"आखिरी जगह पर टाइल जोड़ें"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"टाइल को किसी और पोज़िशन पर ले जाएं"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"अपनी पसंदीदा जगह पर टाइल जोड़ें"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"टाइल को <xliff:g id="POSITION">%1$d</xliff:g> पोज़िशन पर ले जाएं"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"टाइल को <xliff:g id="POSITION">%1$d</xliff:g> पोज़िशन पर जोड़ें"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"मौजूदा जगह अमान्य है."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"उपयोगकर्ता चुनें"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"इंटरनेट कनेक्शन नहीं है"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"<xliff:g id="ID_1">%s</xliff:g> सेटिंग खोलें."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"क्विक सेटिंग के क्रम में बदलाव करें."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"पावर मेन्यू"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"पेज <xliff:g id="ID_2">%2$d</xliff:g> में से <xliff:g id="ID_1">%1$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"लॉक स्क्रीन"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"डिवाइस की होम स्क्रीन पर जाएं"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"खोलने के लिए, फ़िंगरप्रिंट का इस्तेमाल करें"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"पुष्टि करना ज़रूरी है. पुष्टि करने के लिए, फ़िंगरप्रिंट सेंसर को छुएं."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"फ़ोन कॉल चल रहा है"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"मोबाइल डेटा"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"कनेक्ट हो गया"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"इंटरनेट कनेक्शन कुछ समय के लिए है"</string> @@ -1452,8 +1441,8 @@ <string name="shortcut_customize_mode_remove_shortcut_dialog_title" msgid="7106420484940737208">"क्या आपको शॉर्टकट हटाना है?"</string> <string name="shortcut_customize_mode_reset_shortcut_dialog_title" msgid="8131184731313717780">"क्या आपको फिर से डिफ़ॉल्ट सेटिंग चालू करनी है?"</string> <string name="shortcut_customize_mode_add_shortcut_description" msgid="6866025005347407696">"शॉर्टकट असाइन करने के लिए बटन दबाएं"</string> - <string name="shortcut_customize_mode_remove_shortcut_description" msgid="6851287900585057128">"ऐसा करने से, आपका कस्टम शॉर्टकट हमेशा के लिए मिट जाएगा."</string> - <string name="shortcut_customize_mode_reset_shortcut_description" msgid="2081849715634358684">"ऐसा करने पर, आपके सभी कस्टम शॉर्टकट हमेशा के लिए मिट जाएंगे."</string> + <string name="shortcut_customize_mode_remove_shortcut_description" msgid="6851287900585057128">"ऐसा करने पर, पसंद के मुताबिक बनाया गया आपका शॉर्टकट हमेशा के लिए मिट जाएगा."</string> + <string name="shortcut_customize_mode_reset_shortcut_description" msgid="2081849715634358684">"ऐसा करने पर, पसंद के मुताबिक बनाए गए आपके सभी शॉर्टकट हमेशा के लिए मिट जाएंगे."</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"शॉर्टकट खोजें"</string> <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"खोज का कोई नतीजा नहीं मिला"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"छोटा करने का आइकॉन"</string> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index 0696dbfb003a..5c40a5170fa7 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Tekuća obavijest za sesiju snimanja zaslona"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Želite li snimati zaslon?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Snimanje jedne aplikacije"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Snimi ovaj zaslon"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Snimi %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Kad snimate cijeli zaslon, snima se sve što se prikazuje na zaslonu. Stoga pazite na stvari kao što su zaporke, podaci o plaćanju, poruke, fotografije te audio i videozapisi."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Kad snimate aplikaciju, snima se sve što se prikazuje ili reproducira u toj aplikaciji. Stoga pazite na stvari kao što su zaporke, podaci o plaćanju, poruke, fotografije te audio i videozapisi."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Snimanje zaslona"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Ažuriranje unaprijed definiranih postavki nije uspjelo"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Unaprijed definirana postavka"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Odabrano"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Okruženje"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Lijevo"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Desno"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Proširi u zasebne kontrole slijeva i zdesna"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Sažmi u objedinjenu kontrolu"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Isključi zvuk okruženja"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Uključi zvuk okruženja"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Alati"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Automatski titlovi"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Napomena"</string> @@ -884,7 +875,7 @@ <string name="group_system_full_screenshot" msgid="5742204844232667785">"Snimanje zaslona"</string> <string name="group_system_access_system_app_shortcuts" msgid="8562482996626694026">"Prikaz prečaca"</string> <string name="group_system_go_back" msgid="2730322046244918816">"Natrag"</string> - <string name="group_system_access_home_screen" msgid="4130366993484706483">"Otvaranje početnog zaslona"</string> + <string name="group_system_access_home_screen" msgid="4130366993484706483">"Otvori početni zaslon"</string> <string name="group_system_overview_open_apps" msgid="5659958952937994104">"Prikaz nedavnih aplikacija"</string> <string name="group_system_cycle_forward" msgid="5478663965957647805">"Listajte nedavne aplikacije (prema naprijed)"</string> <string name="group_system_cycle_back" msgid="8194102916946802902">"Listajte nedavne aplikacije (unatrag)"</string> @@ -1298,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"pristupili uređaju"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Otvorite pomoću otiska prsta"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Potrebna je autentifikacija. Dodirnite senzor otiska prsta da biste se autentificirali."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Telefonski poziv u tijeku"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilni podaci"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Povezano"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Privremeno povezano"</string> @@ -1467,10 +1459,10 @@ <string name="shortcut_helper_keyboard_settings_buttons_label" msgid="6720967595915985259">"Postavke tipkovnice"</string> <string name="shortcut_helper_customize_dialog_set_shortcut_button_label" msgid="4754492225010429382">"Postavite prečac"</string> <string name="shortcut_helper_customize_dialog_remove_button_label" msgid="6546386970440176552">"Ukloni"</string> - <string name="shortcut_helper_customize_dialog_reset_button_label" msgid="7645535254306312685">"Da, vrati na zadano"</string> + <string name="shortcut_helper_customize_dialog_reset_button_label" msgid="7645535254306312685">"Da, vrati"</string> <string name="shortcut_helper_customize_dialog_cancel_button_label" msgid="5595546460431741178">"Odustani"</string> <string name="shortcut_helper_add_shortcut_dialog_placeholder" msgid="9154297849458741995">"Pritisnite tipku"</string> - <string name="shortcut_customizer_key_combination_in_use_error_message" msgid="7693234470526626327">"Kombinacija tipki već se upotrebljava. Pokušajte s drugom tipkom."</string> + <string name="shortcut_customizer_key_combination_in_use_error_message" msgid="7693234470526626327">"Ta se kombinacija već koristi. Pokušajte s nekom drugom."</string> <string name="shortcut_customizer_generic_error_message" msgid="3128454624049722741">"Prečac se ne može postaviti."</string> <string name="shortcut_helper_plus_symbol" msgid="4534843157353732011">"+"</string> <string name="launch_keyboard_tutorial_notification_title" msgid="8849933155160522519">"Krećite se pomoću tipkovnice"</string> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index d2f6e8fc951c..50c60833574a 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Folyamatban lévő értesítés képernyőrögzítési munkamenethez"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Rögzíti a képernyőt?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Egyetlen alkalmazás rögzítése"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"A képernyő felvétele"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"%s felvétele"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"A teljes képernyő rögzítése esetén a képernyőn megjelenő minden tartalom rögzítésre kerül. Ezért legyen elővigyázatos a jelszavakkal, a fizetési adatokkal, az üzenetekkel, a fotókkal, valamint a hang- és videófelvételekkel."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Alkalmazás rögzítésekor az adott alkalmazásban megjelenített vagy lejátszott minden tartalom rögzítésre kerül. Ezért legyen elővigyázatos a jelszavakkal, a fizetési adatokkal, az üzenetekkel, a fotókkal, valamint a hang- és videófelvételekkel."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Képernyő rögzítése"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Nem sikerült frissíteni a beállításkészletet"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Beállításkészlet"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Kiválasztva"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Környezet"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Bal"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Jobb"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Kibontás a balra és jobbra elválasztott vezérlőkhöz"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Összecsukás az egységes vezérléshez"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Környezet némítása"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Környezet némításának feloldása"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Eszközök"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Élő feliratozás"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Megjegyzés"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Alacsony prioritású értesítési ikonok mutatása"</string> <string name="other" msgid="429768510980739978">"Egyéb"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"mozaik eltávolításához"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"mozaik hozzáadása az utolsó pozícióhoz"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Mozaik áthelyezése"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Mozaik hozzáadása a kívánt pozícióhoz"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Áthelyezés ide: <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Hozzáadás a következő pozícióhoz: <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Érvénytelen pozíció."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"felhasználó kiválasztása"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Nincs internetkapcsolat"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"A(z) <xliff:g id="ID_1">%s</xliff:g> beállításainak megnyitása."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"A Gyorsbeállítások mozaiksorrendjének szerkesztése."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Bekapcsológombhoz tartozó menü"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_1">%1$d</xliff:g>. oldal, összesen: <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Lezárási képernyő"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"eszköz megadásához"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Ujjlenyomat használata a megnyitáshoz"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Hitelesítés szükséges. Érintse meg az ujjlenyomat-érzékelőt a hitelesítéshez."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Folyamatban lévő telefonhívás"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiladat"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Csatlakozva"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Ideiglenesen csatlakoztatva"</string> diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml index f65f604a3aa8..2e42ecd6a25f 100644 --- a/packages/SystemUI/res/values-hy/strings.xml +++ b/packages/SystemUI/res/values-hy/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Էկրանի տեսագրման աշխատաշրջանի ընթացիկ ծանուցում"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Տեսագրե՞լ ձեր էկրանը"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Տեսագրել մեկ հավելված"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Տեսագրել էկրանը"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Տեսագրել %s էկրանը"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Երբ դուք տեսագրում եք ամբողջ էկրանը, էկրանին ցուցադրվող ամեն ինչ տեսագրվում է։ Ուստի ուշադիր եղեք այնպիսի բաների հետ, ինչպիսիք են գաղտնաբառերը, վճարային տվյալները, հաղորդագրությունները, լուսանկարները, աուդիո և վիդեո բովանդակությունը։"</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Երբ դուք որևէ հավելված եք տեսագրում, հավելվածում ցուցադրվող կամ նվագարկվող ամեն ինչ տեսագրվում է։ Ուստի ուշադիր եղեք այնպիսի բաների հետ, ինչպիսիք են գաղտնաբառերը, վճարային տվյալները, հաղորդագրությունները, լուսանկարները, աուդիո և վիդեո բովանդակությունը։"</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Տեսագրել էկրանը"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Չհաջողվեց թարմացնել կարգավորումների հավաքածուն"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Կարգավորումների հավաքածու"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Ընտրված է"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Շրջակայք"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Ձախ"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Աջ"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Ծավալել՝ դարձնելով կառավարման աջ և ձախ առանձնացված տարրեր"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Ծալել՝ դարձնելով կառավարման մեկ միասնական տարր"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Անջատել շրջակայքի ձայները"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Միացնել շրջակայքի ձայները"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Գործիքներ"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Կենդանի ենթագրեր"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Նշում"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Ցուցադրել ցածր առաջնահերթության ծանուցումների պատկերակները"</string> <string name="other" msgid="429768510980739978">"Այլ"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"հեռացնել սալիկը"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"ավելացնել սալիկը վերջին դիրքում"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Տեղափոխել սալիկը"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Ավելացնել սալիկը նախընտրած դիրքում"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Տեղափոխել դիրք <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Ավելացնել դիրք <xliff:g id="POSITION">%1$d</xliff:g>-ում"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Դիրքն անվավեր է։"</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"ընտրել օգտատեր"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Ինտերնետ կապ չկա"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Բացել <xliff:g id="ID_1">%s</xliff:g> կարգավորումները:"</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Փոփոխել Արագ կարգավորումների հերթականությունը"</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Սնուցման կոճակի ընտրացանկ"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Էջ <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Կողպէկրան"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"նշել սարքը"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Բացելու համար օգտագործեք մատնահետքը"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Պահանջվում է նույնականացում։ Դրա համար մատը հպեք մատնահետքի սկաներին։"</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ընթացիկ հեռախոսազանգ"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Բջջային ինտերնետ"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Միացած է"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Ժամանակավոր կապ"</string> @@ -1470,10 +1459,10 @@ <string name="shortcut_helper_keyboard_settings_buttons_label" msgid="6720967595915985259">"Ստեղնաշարի կարգավորումներ"</string> <string name="shortcut_helper_customize_dialog_set_shortcut_button_label" msgid="4754492225010429382">"Ստեղծել դյուրանցում"</string> <string name="shortcut_helper_customize_dialog_remove_button_label" msgid="6546386970440176552">"Հեռացնել"</string> - <string name="shortcut_helper_customize_dialog_reset_button_label" msgid="7645535254306312685">"Այո, վերականգնել"</string> + <string name="shortcut_helper_customize_dialog_reset_button_label" msgid="7645535254306312685">"Վերականգնել"</string> <string name="shortcut_helper_customize_dialog_cancel_button_label" msgid="5595546460431741178">"Չեղարկել"</string> <string name="shortcut_helper_add_shortcut_dialog_placeholder" msgid="9154297849458741995">"Սեղմեք որևէ ստեղն"</string> - <string name="shortcut_customizer_key_combination_in_use_error_message" msgid="7693234470526626327">"Ստեղների համակցությունն արդեն օգտագործվում է։ Ընտրեք այլ ստեղն։"</string> + <string name="shortcut_customizer_key_combination_in_use_error_message" msgid="7693234470526626327">"Ստեղների համակցությունն արդեն օգտագործվում է։ Ընտրեք ուրիշը։"</string> <string name="shortcut_customizer_generic_error_message" msgid="3128454624049722741">"Դյուրանցումը հնարավոր չէ ստեղծել։"</string> <string name="shortcut_helper_plus_symbol" msgid="4534843157353732011">"+"</string> <string name="launch_keyboard_tutorial_notification_title" msgid="8849933155160522519">"Կողմնորոշվեք ձեր ստեղնաշարի օգնությամբ"</string> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index 527c8e8da9bc..2740ce508515 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notifikasi yang sedang berjalan untuk sesi rekaman layar"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Rekam layar Anda?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Rekam satu aplikasi"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Rekam layar ini"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Rekam %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Saat Anda merekam seluruh layar, semua hal yang ditampilkan di layar akan direkam. Jadi, berhati-hatilah saat memasukkan sandi, detail pembayaran, pesan, foto, audio, dan video."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Jika Anda merekam aplikasi, semua hal yang ditampilkan atau diputar di aplikasi tersebut akan direkam. Jadi, berhati-hatilah saat memasukkan sandi, detail pembayaran, pesan, foto, audio, dan video."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Rekam layar"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Tidak dapat memperbarui preset"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Preset"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Dipilih"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Suara sekitar"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Kiri"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Kanan"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Luaskan ke kontrol terpisah kiri dan kanan"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Ciutkan ke kontrol terpadu"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Bisukan suara sekitar"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Bunyikan suara sekitar"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Alat"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Teks Otomatis"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Catatan"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Tampilkan ikon notifikasi prioritas rendah"</string> <string name="other" msgid="429768510980739978">"Lainnya"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"menghapus kartu"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"menambahkan kartu ke posisi terakhir"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Pindahkan kartu"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Tambahkan kartu ke posisi yang diinginkan"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Pindahkan ke <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Tambahkan ke posisi <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Posisi tidak valid."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"memilih pengguna"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Tidak ada internet"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Buka setelan <xliff:g id="ID_1">%s</xliff:g>."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Edit urutan Setelan Cepat."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menu daya"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Halaman <xliff:g id="ID_1">%1$d</xliff:g> dari <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Layar kunci"</string> @@ -1246,7 +1234,7 @@ <string name="media_output_broadcast_name" msgid="8786127091542624618">"Nama Siaran"</string> <string name="media_output_broadcast_code" msgid="870795639644728542">"Sandi"</string> <string name="media_output_broadcast_dialog_save" msgid="7910865591430010198">"Simpan"</string> - <string name="media_output_broadcast_starting" msgid="8130153654166235557">"Memulai …"</string> + <string name="media_output_broadcast_starting" msgid="8130153654166235557">"Memulai…"</string> <string name="media_output_broadcast_start_failed" msgid="3670835946856129775">"Tidak dapat menyiarkan"</string> <string name="media_output_broadcast_update_error" msgid="1420868236079122521">"Tidak dapat menyimpan. Coba lagi."</string> <string name="media_output_broadcast_last_update_error" msgid="5484328807296895491">"Tidak dapat menyimpan."</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"masukkan perangkat"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Gunakan sidik jari untuk membuka"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Perlu autentikasi. Sentuh sensor sidik jari untuk melakukan autentikasi."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Panggilan telepon sedang berlangsung"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Data seluler"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Terhubung"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Terhubung sementara"</string> @@ -1448,7 +1437,7 @@ <string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Aplikasi Saat Ini"</string> <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Aksesibilitas"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Pintasan keyboard"</string> - <string name="shortcut_helper_customize_mode_title" msgid="1467657117101096033">"Menyesuaikan pintasan keyboard"</string> + <string name="shortcut_helper_customize_mode_title" msgid="1467657117101096033">"Sesuaikan pintasan keyboard"</string> <string name="shortcut_customize_mode_remove_shortcut_dialog_title" msgid="7106420484940737208">"Hapus pintasan?"</string> <string name="shortcut_customize_mode_reset_shortcut_dialog_title" msgid="8131184731313717780">"Reset kembali ke pintasan default?"</string> <string name="shortcut_customize_mode_add_shortcut_description" msgid="6866025005347407696">"Tekan tombol untuk menetapkan pintasan"</string> diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml index 3d1b025f8dfa..a6de1d70805e 100644 --- a/packages/SystemUI/res/values-is/strings.xml +++ b/packages/SystemUI/res/values-is/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Áframhaldandi tilkynning fyrir skjáupptökulotu"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Viltu taka upp skjáinn?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Taka upp eitt forrit"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Taka upp þennan skjá"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Taka upp %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Þegar þú tekur upp allan skjáinn verður allt sem er sýnilegt á skjánum tekið upp. Passaðu því upp á aðgangsorð, greiðsluupplýsingar, skilaboð, myndir, hljóð og myndskeið."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Þegar þú tekur upp forrit verður allt sem er sýnilegt eða spilað í forritinu tekið upp. Passaðu því upp á aðgangsorð, greiðsluupplýsingar, skilaboð, myndir, hljóð og myndskeið."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Taka upp skjá"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Tókst ekki að uppfæra forstillingu"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Forstilling"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Valið"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Umhverfi"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Vinstri"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Hægri"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Aðskilja stýringar til vinstri og hægri"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Taka saman í eina stýringu"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Þagga umhverfi"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Kveikja á hljóði umhverfis"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Verkfæri"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Skjátextar í rauntíma"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Glósa"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Sýna tákn fyrir tilkynningar með litlum forgangi"</string> <string name="other" msgid="429768510980739978">"Annað"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"fjarlægja flís"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"bæta reit við síðustu stöðu"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Færa flís"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Bæta reit við óskaða stöðu"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Færa í <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Bæta við í stöðu <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Staða ógild."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"velja notanda"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Engin nettenging"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Opna <xliff:g id="ID_1">%s</xliff:g> stillingar."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Breyta röð flýtistillinga."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Aflrofavalmynd"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Blaðsíða <xliff:g id="ID_1">%1$d</xliff:g> af <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Lásskjár"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"opna tæki"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Opna með fingrafari"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Auðkenningar krafist. Auðkenndu með því að snerta fingrafaralesarann."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Símtal í gangi"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Farsímagögn"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Tengt"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Tímabundin tenging"</string> @@ -1468,7 +1457,7 @@ <string name="shortcut_helper_key_combinations_forward_slash" msgid="1238652537199346970">"rétt skástrik"</string> <string name="shortcut_helper_content_description_drag_handle" msgid="5092426406009848110">"Dragkló"</string> <string name="shortcut_helper_keyboard_settings_buttons_label" msgid="6720967595915985259">"Stillingar lyklaborðs"</string> - <string name="shortcut_helper_customize_dialog_set_shortcut_button_label" msgid="4754492225010429382">"Stilltu flýtileið"</string> + <string name="shortcut_helper_customize_dialog_set_shortcut_button_label" msgid="4754492225010429382">"Stilla flýtileið"</string> <string name="shortcut_helper_customize_dialog_remove_button_label" msgid="6546386970440176552">"Fjarlægja"</string> <string name="shortcut_helper_customize_dialog_reset_button_label" msgid="7645535254306312685">"Já, endurstilla"</string> <string name="shortcut_helper_customize_dialog_cancel_button_label" msgid="5595546460431741178">"Hætta við"</string> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index b6059205bffa..86aeae467b91 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notifica costante per una sessione di registrazione dello schermo"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Registrare lo schermo?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Registra un\'app"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Registra questa schermata"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Registra %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Quando registri l\'intero schermo, tutto ciò che viene mostrato sullo schermo viene registrato. Presta quindi attenzione a password, dati di pagamento, messaggi, foto, audio e video."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Quando registri un\'app, tutto ciò che viene mostrato o riprodotto al suo interno viene registrato. Presta quindi attenzione a password, dati di pagamento, messaggi, foto, audio e video."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Registra lo schermo"</string> @@ -969,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Mostra icone di notifiche con priorità bassa"</string> <string name="other" msgid="429768510980739978">"Altro"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"rimuovere il riquadro"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"aggiungere il riquadro all\'ultima posizione"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Sposta riquadro"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Aggiungi il riquadro alla posizione desiderata"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Sposta nella posizione <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Aggiungi alla posizione <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Posizione non valida."</string> @@ -989,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"selezionare l\'utente"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Nessuna connessione a Internet"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Apri le impostazioni <xliff:g id="ID_1">%s</xliff:g>."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Modifica l\'ordine delle Impostazioni rapide."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menu del tasto di accensione"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Pagina <xliff:g id="ID_1">%1$d</xliff:g> di <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Schermata di blocco"</string> @@ -1294,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"accedere al dispositivo"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Usa l\'impronta per aprire"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticazione obbligatoria. Eseguila toccando il sensore di impronte digitali."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Telefonata in corso"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Dati mobili"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Connessa"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Connessa temporaneamente"</string> @@ -1443,11 +1439,11 @@ <string name="shortcut_helper_title" msgid="8567500639300970049">"Scorciatoie da tastiera"</string> <string name="shortcut_helper_customize_mode_title" msgid="1467657117101096033">"Personalizza scorciatoie da tastiera"</string> <string name="shortcut_customize_mode_remove_shortcut_dialog_title" msgid="7106420484940737208">"Rimuovere scorciatoia?"</string> - <string name="shortcut_customize_mode_reset_shortcut_dialog_title" msgid="8131184731313717780">"Vuoi ripristinare il valore predefinito?"</string> + <string name="shortcut_customize_mode_reset_shortcut_dialog_title" msgid="8131184731313717780">"Vuoi ripristinare le impostazioni predefinite?"</string> <string name="shortcut_customize_mode_add_shortcut_description" msgid="6866025005347407696">"Premi un tasto per assegnare una scorciatoia"</string> <string name="shortcut_customize_mode_remove_shortcut_description" msgid="6851287900585057128">"La scorciatoia personalizzata verrà eliminata definitivamente."</string> <string name="shortcut_customize_mode_reset_shortcut_description" msgid="2081849715634358684">"Tutte le tue scorciatoie personalizzate verranno eliminate definitivamente."</string> - <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Scorciatoie per la ricerca"</string> + <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Cerca scorciatoie"</string> <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Nessun risultato di ricerca"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Icona Comprimi"</string> <string name="shortcut_helper_content_description_meta_key" msgid="3989315044342124818">"Icona tasto Azione o Meta"</string> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index d0f26ba3704b..605a1fb88cc3 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"התראה מתמשכת לסשן הקלטת מסך"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"להקליט את המסך?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"הקלטה של אפליקציה אחת"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"הקלטת המסך שמוצג עכשיו"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"הקלטה של %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"כשמקליטים את כל המסך, כל מה שמופיע במסך מוקלט. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"כשמקליטים אפליקציה, כל מה שרואים או מפעילים בה מוקלט. מומלץ להיזהר עם סיסמאות, פרטי תשלום, הודעות, תמונות, אודיו וסרטונים."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"הקלטת המסך"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"לא ניתן לעדכן את ההגדרה הקבועה מראש"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"הגדרה קבועה מראש"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"נבחר"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"הרעשים בסביבה"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"שמאל"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"ימין"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"הרחבה לאמצעי בקרה נפרדים לצד שמאל ולצד ימין"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"כיווץ לאמצעי בקרה מאוחד"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"השתקת הרעשים בסביבה"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"ביטול השתקת הרעשים בסביבה"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"כלים"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"כתוביות מיידיות"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"פתק"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"הצגת סמלי התראות בעדיפות נמוכה"</string> <string name="other" msgid="429768510980739978">"אחר"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"הסרת הלחצן"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"הוספת הלחצן במיקום האחרון"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"העברת הלחצן"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"הוספת הלחצן במיקום הרצוי"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"העברה למיקום <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"הוספה למיקום <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"המיקום לא תקין."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"בחירת משתמש"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"אין אינטרנט"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"פתיחת הגדרות של <xliff:g id="ID_1">%s</xliff:g>."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"שינוי הסדר של ההגדרות המהירות."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"תפריט הפעלה"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"דף <xliff:g id="ID_1">%1$d</xliff:g> מתוך <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"מסך נעילה"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"הזנת מכשיר"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"שימוש בטביעת אצבע כדי לפתוח"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"נדרש אימות. יש לגעת בחיישן טביעות האצבע כדי לבצע אימות."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"מתקיימת שיחה"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"חבילת גלישה"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"מחובר"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"מחובר באופן זמני"</string> @@ -1452,8 +1441,8 @@ <string name="shortcut_customize_mode_remove_shortcut_dialog_title" msgid="7106420484940737208">"להסיר את קיצור הדרך?"</string> <string name="shortcut_customize_mode_reset_shortcut_dialog_title" msgid="8131184731313717780">"לאפס לברירת המחדל?"</string> <string name="shortcut_customize_mode_add_shortcut_description" msgid="6866025005347407696">"צריך להקיש על מקש כדי להקצות מקש קיצור"</string> - <string name="shortcut_customize_mode_remove_shortcut_description" msgid="6851287900585057128">"קיצור הדרך יימחק באופן סופי."</string> - <string name="shortcut_customize_mode_reset_shortcut_description" msgid="2081849715634358684">"הפעולה הזו תמחק באופן סופי את כל קיצורי הדרך המותאמים אישית."</string> + <string name="shortcut_customize_mode_remove_shortcut_description" msgid="6851287900585057128">"קיצור הדרך יימחק לתמיד."</string> + <string name="shortcut_customize_mode_reset_shortcut_description" msgid="2081849715634358684">"הפעולה הזו תמחק לתמיד את כל קיצורי הדרך שמותאמים אישית."</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"קיצורי דרך לחיפוש"</string> <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"אין תוצאות חיפוש"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"סמל הכיווץ"</string> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index dd9eb2a22857..4634a50c7199 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"画面の録画セッション中の通知"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"画面を録画しますか?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"1 つのアプリを録画"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"この画面の録画"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"%s の録画"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"画面全体を録画すると、画面に表示されるものがすべて録画されます。パスワード、お支払いの詳細、メッセージ、写真、音声、動画などの情報にご注意ください。"</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"アプリを録画すると、そのアプリで表示または再生される内容がすべて録画されます。パスワード、お支払いの詳細、メッセージ、写真、音声、動画などの情報にご注意ください。"</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"画面を録画"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"プリセットを更新できませんでした"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"プリセット"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"選択中"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"周囲の音"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"左"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"右"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"開く - 左右それぞれで制御する"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"閉じる - まとめて制御する"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"周囲の音をミュート"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"周囲の音のミュートを解除"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"ツール"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"自動字幕起こし"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"注"</string> @@ -1298,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"デバイスを入力"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"指紋を使って開いてください"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"認証が必要です。指紋認証センサーをタッチして認証してください。"</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"通話中"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"モバイルデータ"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"接続済み"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"一時的に接続されています"</string> @@ -1445,13 +1437,13 @@ <string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"現在のアプリ"</string> <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"ユーザー補助"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"キーボード ショートカット"</string> - <string name="shortcut_helper_customize_mode_title" msgid="1467657117101096033">"キーボード ショートカットをカスタマイズする"</string> + <string name="shortcut_helper_customize_mode_title" msgid="1467657117101096033">"キーボード ショートカットのカスタマイズ"</string> <string name="shortcut_customize_mode_remove_shortcut_dialog_title" msgid="7106420484940737208">"ショートカットを削除しますか?"</string> <string name="shortcut_customize_mode_reset_shortcut_dialog_title" msgid="8131184731313717780">"デフォルトにリセットしますか?"</string> <string name="shortcut_customize_mode_add_shortcut_description" msgid="6866025005347407696">"ショートカットを割り当てるキーを押してください"</string> <string name="shortcut_customize_mode_remove_shortcut_description" msgid="6851287900585057128">"この操作を行うと、カスタム ショートカットが完全に削除されます。"</string> <string name="shortcut_customize_mode_reset_shortcut_description" msgid="2081849715634358684">"この操作を行うと、すべてのカスタム ショートカットが完全に削除されます。"</string> - <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"検索ショートカット"</string> + <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"ショートカットの検索"</string> <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"検索結果がありません"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"閉じるアイコン"</string> <string name="shortcut_helper_content_description_meta_key" msgid="3989315044342124818">"アクションキーまたはメタキーのアイコン"</string> @@ -1467,7 +1459,7 @@ <string name="shortcut_helper_keyboard_settings_buttons_label" msgid="6720967595915985259">"キーボードの設定"</string> <string name="shortcut_helper_customize_dialog_set_shortcut_button_label" msgid="4754492225010429382">"ショートカットの設定"</string> <string name="shortcut_helper_customize_dialog_remove_button_label" msgid="6546386970440176552">"削除"</string> - <string name="shortcut_helper_customize_dialog_reset_button_label" msgid="7645535254306312685">"リセットする"</string> + <string name="shortcut_helper_customize_dialog_reset_button_label" msgid="7645535254306312685">"リセット"</string> <string name="shortcut_helper_customize_dialog_cancel_button_label" msgid="5595546460431741178">"キャンセル"</string> <string name="shortcut_helper_add_shortcut_dialog_placeholder" msgid="9154297849458741995">"キーを押してください"</string> <string name="shortcut_customizer_key_combination_in_use_error_message" msgid="7693234470526626327">"このキーの組み合わせはすでに使用されています。別のキーを試してください。"</string> diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml index e2459f39c6a8..fc0b81dbcca5 100644 --- a/packages/SystemUI/res/values-ka/strings.xml +++ b/packages/SystemUI/res/values-ka/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"უწყვეტი შეტყობინება ეკრანის ჩაწერის სესიისთვის"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"გსურთ თქვენი ეკრანის ჩაწერა?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"ერთი აპის ჩაწერა"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"ამ ეკრანის ჩაწერა"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"%s-ის ჩანაწერი"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"მთლიანი ეკრანის ჩაწერისას ჩაიწერება ყველაფერი, რაც თქვენს ეკრანზე გამოჩნდება. ამიტომ სიფრთხილე გამოიჩინეთ ისეთ ინფორმაციასთან, როგორიცაა პაროლები, გადახდის დეტალები, შეტყობინებები, ფოტოები, აუდიო და ვიდეო."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"აპის ჩაწერისას ჩაიწერება ყველაფერი, რაც ამ აპში გამოჩნდება ან დაიკვრება. ამიტომ სიფრთხილე გამოიჩინეთ ისეთ ინფორმაციასთან, როგორიცაა პაროლები, გადახდის დეტალები, შეტყობინებები, ფოტოები, აუდიო და ვიდეო."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"ეკრანის ჩაწერა"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"წინასწარ დაყენებული პარამეტრების განახლება ვერ მოხერხდა"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"წინასწარ დაყენებული"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"არჩეულია"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"გარემოცვა"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"მარცხენა"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"მარჯვენა"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"განცალკევებული მართვის საშუალებების გაფართოება მარცხნივ და მარჯვნივ"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"ერთიანი მართვის ჩაკეცვა"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"გარემოცვის დადუმება"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"გარემოცვის დადუმების მოხსნა"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"ხელსაწყოები"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"ავტოსუბტიტრები"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"ჩანიშვნა"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"დაბალი პრიორიტეტის მქონე შეტყობინებების ხატულების ჩვენება"</string> <string name="other" msgid="429768510980739978">"სხვა"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"მოზაიკის ფილის წაშლა"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"მოზაიკის ფილის ბოლო პოზიციაზე დამატება"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"მოზაიკის გადატანა"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"მოზაიკის ფილის სასურველ პოზიციაზე დამატება"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"გადატანა <xliff:g id="POSITION">%1$d</xliff:g>-ზე"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"დამატება პოზიციაზე <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"პოზიცია არასწორია."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"მომხმარებლის არჩევა"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"ინტერნეტ-კავშირი არ არის"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"<xliff:g id="ID_1">%s</xliff:g> პარამეტრების გახსნა."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"სწრაფი პარამეტრების თანმიმდევრობის რედაქტირება"</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"ჩართვის მენიუ"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"გვერდი <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>-დან"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"ჩაკეტილი ეკრანი"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"მოწყობილობის შეყვანა"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"გასახსნელად გამოიყენეთ თითის ანაბეჭდი"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"საჭიროა ავტორიზაცია. ავტორიზაციისთვის შეეხეთ თითის ანაბეჭდის სენსორს."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"მიმდინარე სატელეფონო ზარი"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"მობილური ინტერნეტი"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"დაკავშირებული"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"დროებით დაკავშირებული"</string> diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml index c325c9681287..643a1c27b675 100644 --- a/packages/SystemUI/res/values-kk/strings.xml +++ b/packages/SystemUI/res/values-kk/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Экранды бейнеге жазудың ағымдағы хабарландыруы"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Қолданба экранын жазасыз ба?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Бір қолданба экранын жазу"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Осы экранды жазу"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"%s экранын жазу"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Бүкіл экранды жазған кезде, онда көрінетін барлық нәрсе жазылады. Сондықтан құпия сөздерді, төлем туралы мәліметті, хабарларды немесе басқа құпия ақпаратты енгізген кезде сақ болыңыз."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Қолданбаны жазған кезде, онда көрінетін не ойнатылатын барлық нәрсе жазылады. Сондықтан құпия сөздерді, төлем туралы мәліметті, хабарларды немесе басқа құпия ақпаратты енгізген кезде сақ болыңыз."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Экранды жазу"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Параметрлер жинағын жаңарту мүмкін болмады."</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Параметрлер жинағы"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Таңдалды"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Айнала"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Сол жақ"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Оң жақ"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Сол жақ және оң жақ бөлек бақылау құралдарына жаю"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Біріктірілген бақылау құралына жию"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Айналаның дыбысын өшіру"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Айналаның дыбысын қосу"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Құралдар"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Live Caption"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Ескертпе"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Маңызды емес хабарландыру белгішелерін көрсету"</string> <string name="other" msgid="429768510980739978">"Басқа"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"бөлшекті өшіру"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"соңғы позицияға бөлшек қосу"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Бөлшекті жылжыту"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Қалаған позицияға бөлшек қосу"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> орнына жылжыту"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> орнына қосу"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Орын жарамсыз."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"пайдаланушыны таңдаңыз"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Интернетпен байланыс жоқ"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"<xliff:g id="ID_1">%s</xliff:g> параметрлерін ашу."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Жылдам параметрлердің ретін өзгерту."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Қуат мәзірі"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g> ішінен <xliff:g id="ID_1">%1$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Құлыптаулы экран"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"құрылғыны енгізу"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Ашу үшін саусақ ізін пайдаланыңыз."</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Аутентификациядан өту қажет. Ол үшін саусақ ізін оқу сканерін түртіңіз."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Телефон қоңырауы бар"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобильдік интернет"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Жалғанды"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Уақытша байланыс орнатылды."</string> @@ -1449,11 +1438,11 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Арнайы мүмкіндіктер"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Перне тіркесімдері"</string> <string name="shortcut_helper_customize_mode_title" msgid="1467657117101096033">"Пернелер тіркесімін бейімдеу"</string> - <string name="shortcut_customize_mode_remove_shortcut_dialog_title" msgid="7106420484940737208">"Жылдам пәрменді өшіру керек пе?"</string> - <string name="shortcut_customize_mode_reset_shortcut_dialog_title" msgid="8131184731313717780">"Әдепкі таңбашаларға қайтару керек пе?"</string> - <string name="shortcut_customize_mode_add_shortcut_description" msgid="6866025005347407696">"Жылдам пәрменді тағайындау үшін пернені басыңыз."</string> - <string name="shortcut_customize_mode_remove_shortcut_description" msgid="6851287900585057128">"Арнаулы жылдам пәрменіңіз біржола жойылады."</string> - <string name="shortcut_customize_mode_reset_shortcut_description" msgid="2081849715634358684">"Мұндайда барлық арнаулы таңбашалар біржола жойылады."</string> + <string name="shortcut_customize_mode_remove_shortcut_dialog_title" msgid="7106420484940737208">"Тіркесімді өшіру керек пе?"</string> + <string name="shortcut_customize_mode_reset_shortcut_dialog_title" msgid="8131184731313717780">"Әдепкі тіркесімге қайтару керек пе?"</string> + <string name="shortcut_customize_mode_add_shortcut_description" msgid="6866025005347407696">"Тіркесім тағайындау үшін пернені басыңыз."</string> + <string name="shortcut_customize_mode_remove_shortcut_description" msgid="6851287900585057128">"Арнаулы тіркесіміңіз біржола жойылады."</string> + <string name="shortcut_customize_mode_reset_shortcut_description" msgid="2081849715634358684">"Мұндайда барлық арнаулы тіркесім біржола жойылады."</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Іздеу жылдам пәрмендері"</string> <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Іздеу нәтижелері жоқ."</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Жию белгішесі"</string> diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml index a6e25d1aafda..239e2a9764a0 100644 --- a/packages/SystemUI/res/values-km/strings.xml +++ b/packages/SystemUI/res/values-km/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"ការជូនដំណឹងដែលកំពុងដំណើរការសម្រាប់រយៈពេលប្រើការថតសកម្មភាពអេក្រង់"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"ថតអេក្រង់របស់អ្នកឬ?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"ថតកម្មវិធីទោល"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"ថតអេក្រង់នេះ"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"ថត %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"នៅពេលអ្នកកំពុងថតអេក្រង់ទាំងមូលរបស់អ្នក អ្វីគ្រប់យ៉ាងដែលបង្ហាញនៅលើអេក្រង់របស់អ្នកត្រូវបានថត។ ដូច្នេះ សូមប្រុងប្រយ័ត្នចំពោះអ្វីៗដូចជា ពាក្យសម្ងាត់ ព័ត៌មានលម្អិតអំពីការទូទាត់ប្រាក់ សារ រូបថត ព្រមទាំងសំឡេង និងវីដេអូ។"</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"នៅពេលអ្នកកំពុងថតកម្មវិធីណាមួយ អ្វីគ្រប់យ៉ាងដែលបង្ហាញ ឬចាក់នៅក្នុងកម្មវិធីនោះត្រូវបានថត។ ដូច្នេះ សូមប្រុងប្រយ័ត្នចំពោះអ្វីៗដូចជា ពាក្យសម្ងាត់ ព័ត៌មានលម្អិតអំពីការទូទាត់ប្រាក់ សារ រូបថត ព្រមទាំងសំឡេង និងវីដេអូ។"</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"ថតអេក្រង់"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"មិនអាចប្ដូរការកំណត់ជាមុនបានទេ"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"កំណត់ជាមុន"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"បានជ្រើសរើស"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"មជ្ឈដ្ឋានជុំវិញ"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"ឆ្វេង"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"ស្ដាំ"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"ពង្រីកទៅជាការគ្រប់គ្រងខាងឆ្វេង និងខាងស្ដាំដាច់ដោយឡែកពីគ្នា"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"បង្រួមទៅជាការគ្រប់គ្រងដែលបានរួមបញ្ចូលគ្នា"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"បិទសំឡេងមជ្ឈដ្ឋានជុំវិញ"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"បើកសំឡេងមជ្ឈដ្ឋានជុំវិញ"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"ឧបករណ៍"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"អក្សររត់ក្នុងពេលជាក់ស្ដែង"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"កំណត់ចំណាំ"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"បង្ហាញរូបការជូនដំណឹងដែលមានអាទិភាពទាប"</string> <string name="other" msgid="429768510980739978">"ផ្សេងៗ"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"ដកប្រអប់ចេញ"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"បញ្ចូលប្រអប់ទៅទីតាំងចុងក្រោយ"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"ផ្លាស់ទីប្រអប់"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"បញ្ចូលប្រអប់ទៅទីតាំងដែលចង់បាន"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"ផ្លាស់ទីទៅ <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"បញ្ចូលទៅទីតាំងទី <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"ទីតាំងគ្មានសុពលភាព។"</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"ជ្រើសរើសអ្នកប្រើប្រាស់"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"គ្មានអ៊ីនធឺណិតទេ"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"បើការកំណត់ <xliff:g id="ID_1">%s</xliff:g>"</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"កែលំដាប់នៃការកំណត់រហ័ស។"</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"ម៉ឺនុយថាមពល"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"ទំព័រ <xliff:g id="ID_1">%1$d</xliff:g> នៃ <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"អេក្រង់ចាក់សោ"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"បញ្ចូលឧបករណ៍"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ប្រើស្នាមម្រាមដៃ ដើម្បីបើក"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"តម្រូវឱ្យមានការផ្ទៀងផ្ទាត់។ សូមចុចឧបករណ៍ចាប់ស្នាមម្រាមដៃ ដើម្បីផ្ទៀងផ្ទាត់។"</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ការហៅទូរសព្ទដែលកំពុងដំណើរការ"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"ទិន្នន័យទូរសព្ទចល័ត"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"បានភ្ជាប់"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"បានភ្ជាប់ជាបណ្ដោះអាសន្ន"</string> @@ -1473,7 +1462,7 @@ <string name="shortcut_helper_customize_dialog_reset_button_label" msgid="7645535254306312685">"បាទ/ចាស កំណត់ឡើងវិញ"</string> <string name="shortcut_helper_customize_dialog_cancel_button_label" msgid="5595546460431741178">"បោះបង់"</string> <string name="shortcut_helper_add_shortcut_dialog_placeholder" msgid="9154297849458741995">"ចុចគ្រាប់ចុច"</string> - <string name="shortcut_customizer_key_combination_in_use_error_message" msgid="7693234470526626327">"កំពុងប្រើបន្សំគ្រាប់ចុចស្រាប់ហើយ។ សាកល្បងប្រើគ្រាប់ចុចផ្សេង។"</string> + <string name="shortcut_customizer_key_combination_in_use_error_message" msgid="7693234470526626327">"បន្សំគ្រាប់ចុចនេះត្រូវបានប្រើប្រាស់ហើយ។ សាកល្បងគ្រាប់ចុចផ្សេង។"</string> <string name="shortcut_customizer_generic_error_message" msgid="3128454624049722741">"មិនអាចកំណត់ផ្លូវកាត់បានទេ។"</string> <string name="shortcut_helper_plus_symbol" msgid="4534843157353732011">"+"</string> <string name="launch_keyboard_tutorial_notification_title" msgid="8849933155160522519">"រុករកដោយប្រើក្ដារចុចរបស់អ្នក"</string> diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml index 2ddb1a8e9a92..0b0caa4e51eb 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್ ಸೆಶನ್ಗಾಗಿ ಚಾಲ್ತಿಯಲ್ಲಿರುವ ನೋಟಿಫಿಕೇಶನ್"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಅನ್ನು ರೆಕಾರ್ಡ್ ಮಾಡಬೇಕೇ?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"ಒಂದು ಆ್ಯಪ್ ಅನ್ನು ರೆಕಾರ್ಡ್ ಮಾಡಿ"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"ಸ್ಕ್ರೀನ್ ಅನ್ನು ರೆಕಾರ್ಡ್ ಮಾಡಿ"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"%s ರೆಕಾರ್ಡ್ ಮಾಡಿ"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"ನಿಮ್ಮ ಸಂಪೂರ್ಣ ಸ್ಕ್ರೀನ್ ಅನ್ನು ನೀವು ರೆಕಾರ್ಡ್ ಮಾಡುತ್ತಿರುವಾಗ, ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಮೇಲೆ ಗೋಚರಿಸುವ ಎಲ್ಲವನ್ನೂ ರೆಕಾರ್ಡ್ ಮಾಡಲಾಗುತ್ತದೆ. ಆದ್ದರಿಂದ ಪಾಸ್ವರ್ಡ್ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಸಂದೇಶಗಳು, ಫೋಟೋಗಳು ಮತ್ತು ಆಡಿಯೋ ಮತ್ತು ವೀಡಿಯೊದಂತಹ ವಿಷಯಗಳ ಬಗ್ಗೆ ಜಾಗರೂಕರಾಗಿರಿ."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"ನೀವು ಆ್ಯಪ್ ಅನ್ನು ರೆಕಾರ್ಡ್ ಮಾಡುವಾಗ, ಆ ಆ್ಯಪ್ನಲ್ಲಿ ತೋರಿಸಿರುವ ಅಥವಾ ಪ್ಲೇ ಮಾಡಿದ ಎಲ್ಲವನ್ನೂ ರೆಕಾರ್ಡ್ ಮಾಡಲಾಗುತ್ತದೆ. ಆದ್ದರಿಂದ ಪಾಸ್ವರ್ಡ್ಗಳು, ಪಾವತಿ ವಿವರಗಳು, ಸಂದೇಶಗಳು, ಫೋಟೋಗಳು ಮತ್ತು ಆಡಿಯೋ ಮತ್ತು ವೀಡಿಯೊದಂತಹ ವಿಷಯಗಳ ಬಗ್ಗೆ ಜಾಗರೂಕರಾಗಿರಿ."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡ್ ಮಾಡಿ"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"ಪ್ರಿಸೆಟ್ ಅನ್ನು ಅಪ್ಡೇಟ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"ಪ್ರಿಸೆಟ್"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"ಆಯ್ಕೆಮಾಡಲಾಗಿದೆ"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"ಆ್ಯಂಬಿಯೆಂಟ್ ವಾಲ್ಯೂಮ್"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"ಎಡ"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"ಬಲ"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"ಪ್ರತ್ಯೇಕ ಎಡ ಮತ್ತು ಬಲ ಕಂಟ್ರೋಲ್ಗಳಿಗಾಗಿ ವಿಸ್ತರಿಸಿ"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"ಯೂನಿಫೈಡ್ ಕಂಟ್ರೋಲ್ಗಾಗಿ ಕುಗ್ಗಿಸಿ"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"ಆ್ಯಂಬಿಯೆಂಟ್ ವಾಲ್ಯೂಮ್ ಅನ್ನು ಮ್ಯೂಟ್ ಮಾಡಿ"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"ಆ್ಯಂಬಿಯೆಂಟ್ ವಾಲ್ಯೂಮ್ ಅನ್ನು ಅನ್ಮ್ಯೂಟ್ ಮಾಡಿ"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"ಟೂಲ್ಗಳು"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"ಲೈವ್ ಕ್ಯಾಪ್ಶನ್"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"ಟಿಪ್ಪಣಿ"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"ಕಡಿಮೆ-ಆದ್ಯತೆ ಸೂಚನೆಯ ಐಕಾನ್ಗಳನ್ನು ತೋರಿಸಿ"</string> <string name="other" msgid="429768510980739978">"ಇತರ"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"ಟೈಲ್ ಅನ್ನು ತೆಗೆದುಹಾಕಿ"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"ಕೊನೆಯ ಸ್ಥಾನಕ್ಕೆ ಟೈಲ್ ಅನ್ನು ಸೇರಿಸಿ"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"ಟೈಲ್ ಸರಿಸಿ"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"ಬಯಸಿದ ಸ್ಥಾನಕ್ಕೆ ಟೈಲ್ ಅನ್ನು ಸೇರಿಸಿ"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"ಇಲ್ಲಿಗೆ ಸರಿಸಿ <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> ಸ್ಥಾನಕ್ಕೆ ಸೇರಿಸಿ"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"ಸ್ಥಾನವು ಅಮಾನ್ಯವಾಗಿದೆ."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"ಬಳಕೆದಾರರನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"ಇಂಟರ್ನೆಟ್ ಇಲ್ಲ"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"<xliff:g id="ID_1">%s</xliff:g> ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ತೆರೆಯಿರಿ."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್ಗಳ ಕ್ರಮವನ್ನು ಎಡಿಟ್ ಮಾಡಿ."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"ಪವರ್ ಮೆನು"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g> ರಲ್ಲಿ <xliff:g id="ID_1">%1$d</xliff:g> ಪುಟ"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"ಲಾಕ್ ಸ್ಕ್ರೀನ್"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"ಸಾಧನವನ್ನು ಪ್ರವೇಶಿಸಿ"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ತೆರೆಯುವುದಕ್ಕಾಗಿ ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಅನ್ನು ಬಳಸಿ"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ದೃಢೀಕರಣದ ಅವಶ್ಯಕತೆಯಿದೆ. ದೃಢೀಕರಿಸಲು ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್ ಅನ್ನು ಸ್ಪರ್ಶಿಸಿ."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ಚಾಲ್ತಿಯಲ್ಲಿರುವ ಫೋನ್ ಕರೆ"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"ಮೊಬೈಲ್ ಡೇಟಾ"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"ಕನೆಕ್ಟ್ ಆಗಿದೆ"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"ತಾತ್ಕಾಲಿಕವಾಗಿ ಕನೆಕ್ಟ್ ಮಾಡಲಾಗಿದೆ"</string> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index caa76340dc29..14736604bcf8 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"화면 녹화 세션에 관한 지속적인 알림"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"화면을 녹화하시겠습니까?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"단일 앱 녹화"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"이 화면 녹화"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"%s 녹화"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"전체 화면을 녹화하면 화면에 표시되는 모든 항목이 녹화됩니다. 따라서 비밀번호, 결제 세부정보, 메시지, 사진, 오디오 및 동영상 등이 노출되지 않도록 주의하세요."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"앱을 녹화하면 앱에 표시되거나 앱에서 재생되는 모든 항목이 녹화됩니다. 따라서 비밀번호, 결제 세부정보, 메시지, 사진, 오디오 및 동영상 등이 노출되지 않도록 주의하세요."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"화면 녹화"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"사전 설정을 업데이트할 수 없음"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"미리 설정"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"선택됨"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"주변 소리"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"왼쪽"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"오른쪽"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"왼쪽 및 오른쪽 개별 제어로 확장"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"통합 제어로 축소"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"주변 소리 음소거"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"주변 소리 음소거 해제"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"도구"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"실시간 자막"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"메모"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"우선순위가 낮은 알림 아이콘 표시"</string> <string name="other" msgid="429768510980739978">"기타"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"타일 삭제"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"마지막 위치에 타일 추가"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"타일 이동"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"원하는 위치에 타일 추가"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> 위치로 이동"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> 위치에 추가"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"위치가 잘못되었습니다."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"사용자 선택"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"인터넷 연결 없음"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"<xliff:g id="ID_1">%s</xliff:g> 설정 열기"</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"빠른 설정 순서 수정"</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"전원 메뉴"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g>페이지 중 <xliff:g id="ID_1">%1$d</xliff:g>페이지"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"잠금 화면"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"기기 입력"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"지문으로 열기"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"인증이 필요합니다. 지문 센서를 터치하여 인증하세요."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"진행 중인 전화 통화"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"모바일 데이터"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"연결됨"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"일시적으로 연결됨"</string> @@ -1449,12 +1438,12 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"접근성"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"단축키"</string> <string name="shortcut_helper_customize_mode_title" msgid="1467657117101096033">"단축키 맞춤설정"</string> - <string name="shortcut_customize_mode_remove_shortcut_dialog_title" msgid="7106420484940737208">"바로가기를 제거하시겠습니까?"</string> + <string name="shortcut_customize_mode_remove_shortcut_dialog_title" msgid="7106420484940737208">"단축키를 삭제하시겠어요?"</string> <string name="shortcut_customize_mode_reset_shortcut_dialog_title" msgid="8131184731313717780">"기본값으로 재설정하시겠어요?"</string> <string name="shortcut_customize_mode_add_shortcut_description" msgid="6866025005347407696">"키를 눌러 단축키 지정"</string> - <string name="shortcut_customize_mode_remove_shortcut_description" msgid="6851287900585057128">"맞춤 단축어가 영구적으로 삭제됩니다."</string> - <string name="shortcut_customize_mode_reset_shortcut_description" msgid="2081849715634358684">"모든 맞춤 바로가기가 완전히 삭제됩니다."</string> - <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"검색 바로가기"</string> + <string name="shortcut_customize_mode_remove_shortcut_description" msgid="6851287900585057128">"맞춤 단축키가 영구적으로 삭제됩니다."</string> + <string name="shortcut_customize_mode_reset_shortcut_description" msgid="2081849715634358684">"모든 맞춤 단축키가 완전히 삭제됩니다."</string> + <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"단축키 검색"</string> <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"검색 결과 없음"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"접기 아이콘"</string> <string name="shortcut_helper_content_description_meta_key" msgid="3989315044342124818">"작업 또는 메타 키 아이콘"</string> diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml index 836179edb217..ad70e7961dc6 100644 --- a/packages/SystemUI/res/values-ky/strings.xml +++ b/packages/SystemUI/res/values-ky/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Экранды жаздыруу сеансы боюнча учурдагы билдирме"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Экранды жаздырасызбы?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Бир колдонмону жаздыруу"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Бул экранды жаздыруу"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"%s жаздыруу"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Бүтүндөй экранды жаздырганда, андагы нерселердин баары видеого түшүп калат. Андыктан этият болуп, сырсөздөр, төлөм ыкмалары, билдирүүлөр, сүрөттөр, аудио жана видео материалдар сыяктуу купуя нерселерди көрсөтүп албаңыз."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Колдонмону жаздырганда, андагы нерселердин баары видеого түшүп калат. Андыктан сырсөздөр, төлөмдүн чоо-жайы, билдирүүлөр, сүрөттөр, аудио жана видео сыяктуу нерселер менен этият болуңуз."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Экранды жаздыруу"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Алдын ала коюлган параметрлер жаңыртылган жок"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Алдын ала коюлган параметрлер"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Тандалды"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Айланадагы үндөр"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Сол"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Оң"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Cол жана оң жактагы өзүнчө башкаруу элементтерине жайып көрсөтүү"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Бирдиктүү башкаруу элементине жыйыштыруу"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Айланадагы үндөрдү басуу"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Айланадагы үндөрдү чыгаруу"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Куралдар"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Ыкчам коштомо жазуулар"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Учкай маалымат"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Анча маанилүү эмес билдирменин сүрөтчөлөрүн көрсөтүү"</string> <string name="other" msgid="429768510980739978">"Башка"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"ыкчам баскычты өчүрүү"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"аягына карта кошуу"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Ыкчам баскычты жылдыруу"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Керектүү жерге карта кошуу"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Төмөнкүгө жылдыруу: <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g>-позицияга кошуу"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Абал жараксыз."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"колдонуучуну тандоо"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Интернет жок"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"<xliff:g id="ID_1">%s</xliff:g> параметрлерин ачуу."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Ыкчам параметрлердин иретин өзгөртүү."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Кубат баскычынын менюсу"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g> ичинен <xliff:g id="ID_1">%1$d</xliff:g>-бет"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Кулпуланган экран"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"түзмөккө кирүү"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Манжаңыздын изи менен ачыңыз"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Аныктыкты текшерүү талап кылынат. Аныктыгын текшерүү үчүн манжа изинин сенсоруна тийип коюңуз."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Учурдагы телефон чалуу"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобилдик трафик"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Туташты"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Убактылуу туташып турат"</string> diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml index 47a431b04f0d..1c3d4110b793 100644 --- a/packages/SystemUI/res/values-lo/strings.xml +++ b/packages/SystemUI/res/values-lo/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"ການແຈ້ງເຕືອນສຳລັບເຊດຊັນການບັນທຶກໜ້າຈໍໃດໜຶ່ງ"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"ບັນທຶກໜ້າຈໍຂອງທ່ານບໍ?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"ບັນທຶກແອັບດຽວ"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"ບັນທຶກໜ້າຈໍນີ້"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"ບັນທຶກ %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"ເມື່ອທ່ານບັນທຶກໝົດໜ້າຈໍຂອງທ່ານ, ລະບົບຈະບັນທຶກທຸກສິ່ງທີ່ສະແດງຢູ່ໜ້າຈໍຂອງທ່ານ. ດັ່ງນັ້ນ, ໃຫ້ລະມັດລະວັງສິ່ງຕ່າງໆ ເຊັ່ນ: ລະຫັດຜ່ານ, ລາຍລະອຽດການຈ່າຍເງິນ, ຂໍ້ຄວາມ, ຮູບພາບ, ພ້ອມທັງສຽງ ແລະ ວິດີໂອ."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"ເມື່ອທ່ານບັນທຶກແອັບ, ລະບົບຈະບັນທຶກທຸກສິ່ງທີ່ສະແດງ ຫຼື ຫຼິ້ນຢູ່ໃນແອັບນັ້ນ. ດັ່ງນັ້ນ, ໃຫ້ລະມັດລະວັງສິ່ງຕ່າງໆ ເຊັ່ນ: ລະຫັດຜ່ານ, ລາຍລະອຽດການຈ່າຍເງິນ, ຂໍ້ຄວາມ, ຮູບພາບ, ພ້ອມທັງສຽງ ແລະ ວິດີໂອ."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"ບັນທຶກໜ້າຈໍ"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"ບໍ່ສາມາດອັບເດດການຕັ້ງຄ່າລ່ວງໜ້າໄດ້"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"ຄ່າທີ່ກຳນົດລ່ວງໜ້າ"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"ເລືອກແລ້ວ"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"ສຽງແວດລ້ອມ"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"ຊ້າຍ"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"ຂວາ"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"ຂະຫຍາຍເປັນການຄວບຄຸມທີ່ແຍກເບື້ອງຊ້າຍ ແລະ ຂວາ"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"ຫຍໍ້ລົງເປັນການຄວບຄຸມແບບຮວມ"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"ປິດສຽງແວດລ້ອມ"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"ເຊົາປິດສຽງແວດລ້ອມ"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"ເຄື່ອງມື"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"ຄຳບັນຍາຍສົດ"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"ບັນທຶກ"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"ສະແດງໄອຄອນການແຈ້ງເຕືອນຄວາມສຳຄັນຕ່ຳ"</string> <string name="other" msgid="429768510980739978">"ອື່ນໆ"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"ລຶບແຜ່ນອອກ"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"ເພີ່ມແຜ່ນໃສ່ຕຳແໜ່ງສຸດທ້າຍ"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"ຍ້າຍແຜ່ນ"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"ເພີ່ມແຜ່ນໃສ່ຕຳແໜ່ງທີ່ຕ້ອງການ"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"ຍ້າຍໄປ <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"ເພີ່ມໃສ່ຕຳແໜ່ງ <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"ຕຳແໜ່ງບໍ່ຖືກຕ້ອງ."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"ເລືອກຜູ້ໃຊ້"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"ບໍ່ມີອິນເຕີເນັດ"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"ເປີດການຕັ້ງຄ່າ <xliff:g id="ID_1">%s</xliff:g>."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"ແກ້ໄຂລຳດັບຂອງການຕັ້ງຄ່າດ່ວນ."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"ເມນູເປີດປິດ"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_1">%1$d</xliff:g> ຈາກທັງໝົດ <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"ໜ້າຈໍລັອກ"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"ເຂົ້າອຸປະກອນ"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ໃຊ້ລາຍນິ້ວມືເພື່ອເປີດ"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ຕ້ອງພິສູດຢືນຢັນ. ແຕະໃສ່ເຊັນເຊີລາຍນິ້ວມືເພື່ອພິສູດຢືນຢັນ."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ສາຍໂທອອກ"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"ອິນເຕີເນັດມືຖື"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"ເຊື່ອມຕໍ່ແລ້ວ"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"ເຊື່ອມຕໍ່ແລ້ວຊົ່ວຄາວ"</string> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index 5fba5b2fd43b..eb6fd2d9eea7 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Šiuo metu rodomas ekrano įrašymo sesijos pranešimas"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Įrašyti ekraną?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Įrašyti vieną programą"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Įrašyti šį ekraną"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Įrašyti ekraną „%s“"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Kai įrašote visą ekraną, įrašomas visas ekrane rodomas turinys. Todėl būkite atsargūs naudodami slaptažodžius, išsamią mokėjimo metodo informaciją, pranešimus, nuotraukas ir garso bei vaizdo įrašus."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Kai įrašote programą, įrašomas visas toje programoje rodomas ar leidžiamas turinys. Todėl būkite atsargūs naudodami slaptažodžius, išsamią mokėjimo metodo informaciją, pranešimus, nuotraukas ir garso bei vaizdo įrašus."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Įrašyti ekraną"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Išankstinių nustatymų atnaujinti nepavyko"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Išankstiniai nustatymai"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Pasirinkta"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Aplinka"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Kairė"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Dešinė"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Išskleisti į atskirus kairįjį ir dešinįjį valdiklius"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Sutraukti į bendrą valdiklį"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Nutildyti aplinką"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Įjungti aplinkos garsą"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Įrankiai"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Subtitrai realiuoju laiku"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Pastaba"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Rodyti mažo prioriteto pranešimų piktogramas"</string> <string name="other" msgid="429768510980739978">"Kita"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"pašalintumėte išklotinės elementą"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"pridėti išklotinės elementą paskutinėje pozicijoje"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Perkelti išklotinės elementą"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Pridėti išklotinės elementą norimoje pozicijoje"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Perkelkite į <xliff:g id="POSITION">%1$d</xliff:g> poziciją"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Pridėkite <xliff:g id="POSITION">%1$d</xliff:g> pozicijoje"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Padėtis netinkama."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"pasirinktumėte naudotoją"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Nėra interneto ryšio"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Atidaryti „<xliff:g id="ID_1">%s</xliff:g>“ nustatymus."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Redaguoti sparčiųjų nustatymų tvarką."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Įjungimo meniu"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_1">%1$d</xliff:g> psl. iš <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Užrakinimo ekranas"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"pasiektumėte įrenginį"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Naudokite kontrolinį kodą, kad atidarytumėte"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Reikia nustatyti tapatybę. Nustatykite tapatybę palietę kontrolinio kodo jutiklį."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Vykstantis telefono skambutis"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiliojo ryšio duomenys"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Prisijungta"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Laikinai prijungta"</string> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index a407750fb35f..7740d2d14c0f 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Aktīvs paziņojums par ekrāna ierakstīšanas sesiju"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Vai ierakstīt ekrānu?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Ierakstīt vienu lietotni"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Ierakstīt šo ekrānu"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Ierakstīt ekrānu %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Ierakstot visu ekrānu, viss, kas redzams ekrānā, tiek ierakstīts. Tāpēc piesardzīgi apejieties ar parolēm, maksājumu informāciju, ziņojumiem, fotoattēliem un audio un video saturu."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Ierakstot lietotni, tiek ierakstīts viss attiecīgajā lietotnē rādītais vai atskaņotais. Tāpēc piesardzīgi apejieties ar parolēm, maksājumu informāciju, ziņojumiem, fotoattēliem un audio un video saturu."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Ierakstīt ekrānu"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Nevarēja atjaunināt pirmsiestatījumu"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Pirmsiestatījums"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Atlasīts"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Apkārtnes skaņas"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Pa kreisi"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Pa labi"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Izvērst, lai rādītu atsevišķu kreiso un labo vadīklu"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Sakļaut, lai rādītu vienotu vadīklu"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Izslēgt apkārtnes skaņas"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Ieslēgt apkārtnes skaņas"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Rīki"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Subtitri reāllaikā"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Piezīme"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Rādīt zemas prioritātes paziņojumu ikonas"</string> <string name="other" msgid="429768510980739978">"Citi"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"noņemt elementu"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"pievienotu elementu pēdējā pozīcijā"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Pārvietot elementu"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Pievienot elementu vēlamajā pozīcijā"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Pārvietot uz pozīciju numur <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Pievienot elementu pozīcijā numur <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Nederīga pozīcija."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"izvēlēties lietotāju"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Nav piekļuves internetam"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Atvērt <xliff:g id="ID_1">%s</xliff:g> iestatījumus."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Rediģēt ātro iestatījumu secību."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Barošanas izvēlne"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_1">%1$d</xliff:g>. lpp. no <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Bloķēšanas ekrāns"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"izmantotu ierīci"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Atvēršanai izmantojiet pirksta nospiedumu"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Nepieciešama autentifikācija. Pieskarieties pirksta nospieduma sensoram, lai veiktu autentificēšanu."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Notiekošs tālruņa zvans"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilie dati"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Ir izveidots savienojums"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Īslaicīgi izveidots savienojums"</string> diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml index f71ca44fcc06..e4064e239b34 100644 --- a/packages/SystemUI/res/values-mk/strings.xml +++ b/packages/SystemUI/res/values-mk/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Тековно известување за сесија за снимање на екранот"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Да се снима екранот?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Снимање на една апликација"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Снимај го екранов"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Снимај го екранот %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Додека го снимате целиот екран, сѐ што е прикажано на екранот се снима. Затоа, бидете внимателни со лозинките, деталите за плаќање, пораките, фотографиите и аудиото и видеото."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Додека снимате апликација, може да се сними сѐ што се прикажува или пушта во таа апликација. Затоа, бидете внимателни со лозинките, деталите за плаќање, пораките, фотографиите и аудиото и видеото."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Снимај го екранот"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Не можеше да се ажурира зададената вредност"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Зададени вредности"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Избрано"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Опкружување"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Лево"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Десно"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Прошири на одвоените контроли одлево и оддесно"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Собери на унифицирана контрола"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Исклучи го звукот на опкружувањето"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Вклучи го звукот на опкружувањето"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Алатки"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Автоматски титлови"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Белешка"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Прикажувај икони за известувања со низок приоритет"</string> <string name="other" msgid="429768510980739978">"Друго"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"отстранување на плочката"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"додајте плочка на последната позиција"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Преместување на плочката"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Додајте плочка на саканата позиција"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Преместување на <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Додавање на позиција <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Позицијата е погрешна."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"изберете корисник"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Нема интернет"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Отворете ги поставките на <xliff:g id="ID_1">%s</xliff:g>."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Изменете го редот на „Брзи поставки“"</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Мени на копчето за вклучување"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Страница <xliff:g id="ID_1">%1$d</xliff:g> од <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Заклучен екран"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"внесете уред"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Користете отпечаток за да се отвори"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Потребна е проверка. Допрете го сензорот за отпечаток за да автентицирате."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Тековен телефонски повик"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобилен интернет"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Поврзано"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Привремено поврзано"</string> @@ -1451,7 +1440,7 @@ <string name="shortcut_helper_customize_mode_title" msgid="1467657117101096033">"Приспособете ги кратенките од тастатурата"</string> <string name="shortcut_customize_mode_remove_shortcut_dialog_title" msgid="7106420484940737208">"Да се отстрани кратенката?"</string> <string name="shortcut_customize_mode_reset_shortcut_dialog_title" msgid="8131184731313717780">"Да се ресетира на стандардните поставки?"</string> - <string name="shortcut_customize_mode_add_shortcut_description" msgid="6866025005347407696">"Притиснете го копчето за да доделите кратенка"</string> + <string name="shortcut_customize_mode_add_shortcut_description" msgid="6866025005347407696">"Притиснете копче за да доделите кратенка"</string> <string name="shortcut_customize_mode_remove_shortcut_description" msgid="6851287900585057128">"Ова ќе ја избрише вашата приспособена кратенка трајно."</string> <string name="shortcut_customize_mode_reset_shortcut_description" msgid="2081849715634358684">"Ова ќе ги избрише трајно сите ваши приспособени кратенки."</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Пребарувајте кратенки"</string> @@ -1468,11 +1457,11 @@ <string name="shortcut_helper_key_combinations_forward_slash" msgid="1238652537199346970">"коса црта"</string> <string name="shortcut_helper_content_description_drag_handle" msgid="5092426406009848110">"Рачка за влечење"</string> <string name="shortcut_helper_keyboard_settings_buttons_label" msgid="6720967595915985259">"Поставки за тастатурата"</string> - <string name="shortcut_helper_customize_dialog_set_shortcut_button_label" msgid="4754492225010429382">"Поставете кратенка"</string> + <string name="shortcut_helper_customize_dialog_set_shortcut_button_label" msgid="4754492225010429382">"Постави"</string> <string name="shortcut_helper_customize_dialog_remove_button_label" msgid="6546386970440176552">"Отстрани"</string> <string name="shortcut_helper_customize_dialog_reset_button_label" msgid="7645535254306312685">"Да, ресетирај"</string> <string name="shortcut_helper_customize_dialog_cancel_button_label" msgid="5595546460431741178">"Откажи"</string> - <string name="shortcut_helper_add_shortcut_dialog_placeholder" msgid="9154297849458741995">"Притиснете го копчето"</string> + <string name="shortcut_helper_add_shortcut_dialog_placeholder" msgid="9154297849458741995">"Притиснете копче"</string> <string name="shortcut_customizer_key_combination_in_use_error_message" msgid="7693234470526626327">"Комбинацијата на копчиња веќе се користи. Обидете се со друго копче."</string> <string name="shortcut_customizer_generic_error_message" msgid="3128454624049722741">"Кратенката не може да се постави."</string> <string name="shortcut_helper_plus_symbol" msgid="4534843157353732011">"+"</string> diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml index db3e91ae241d..601e6a13e628 100644 --- a/packages/SystemUI/res/values-ml/strings.xml +++ b/packages/SystemUI/res/values-ml/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"ഒരു സ്ക്രീൻ റെക്കോർഡിംഗ് സെഷനായി നിലവിലുള്ള അറിയിപ്പ്"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"നിങ്ങളുടെ സ്ക്രീൻ റെക്കോർഡ് ചെയ്യണോ?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"ഒരു ആപ്പ് റെക്കോർഡ് ചെയ്യുക"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"ഈ സ്ക്രീൻ റെക്കോർഡ് ചെയ്യുക"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"%s റെക്കോർഡ് ചെയ്യുക"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"നിങ്ങളുടെ സ്ക്രീൻ പൂർണ്ണമായി റെക്കോർഡ് ചെയ്യുമ്പോൾ, സ്ക്രീനിൽ ദൃശ്യമാകുന്ന എല്ലാം റെക്കോർഡ് ചെയ്യപ്പെടും. അതിനാൽ പാസ്വേഡുകൾ, പേയ്മെന്റ് വിശദാംശങ്ങൾ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ, ഓഡിയോ, വീഡിയോ എന്നിവ പോലുള്ള കാര്യങ്ങൾ നൽകുമ്പോൾ സൂക്ഷിക്കുക."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"നിങ്ങളുടെ ആപ്പ് റെക്കോർഡ് ചെയ്യുമ്പോൾ, ആ ആപ്പിൽ കാണിക്കുന്നതോ പ്ലേ ചെയ്യുന്നതോ ആയ എല്ലാ കാര്യങ്ങളും റെക്കോർഡ് ചെയ്യപ്പെടും. അതിനാൽ പാസ്വേഡുകൾ, പേയ്മെന്റ് വിശദാംശങ്ങൾ, സന്ദേശങ്ങൾ, ഫോട്ടോകൾ, ഓഡിയോ, വീഡിയോ എന്നിവ പോലുള്ള കാര്യങ്ങൾ നൽകുമ്പോൾ സൂക്ഷിക്കുക."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"സ്ക്രീൻ റെക്കോർഡ് ചെയ്യുക"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"പ്രീസെറ്റ് അപ്ഡേറ്റ് ചെയ്യാനായില്ല"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"പ്രീസെറ്റ്"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"തിരഞ്ഞെടുത്തു"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"സറൗണ്ടിംഗ്സ്"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"ഇടത്"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"വലത്"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"വേർതിരിച്ച ഇടത്, വലത് നിയന്ത്രണങ്ങളിലേക്ക് വികസിപ്പിക്കുക"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"ഏകീകൃത നിയന്ത്രണത്തിലേക്ക് ചുരുക്കുക"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"സറൗണ്ടിംഗ്സ് മ്യൂട്ട് ചെയ്യുക"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"സറൗണ്ടിംഗ്സ് അൺമ്യൂട്ട് ചെയ്യുക"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"ടൂളുകൾ"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"തത്സമയ ക്യാപ്ഷൻ"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"കുറിപ്പ്"</string> @@ -1298,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"ഉപകരണം നൽകുക"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"തുറക്കുന്നതിന് നിങ്ങളുടെ ഫിംഗർപ്രിന്റ് ഉപയോഗിക്കുക"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"പരിശോധിച്ചുറപ്പിക്കേണ്ടതുണ്ട്. പരിശോധിച്ചുറപ്പിക്കാൻ, വിരലടയാള സെൻസറിൽ സ്പർശിക്കുക."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"സജീവമായ ഫോൺ കോൾ"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"മൊബൈൽ ഡാറ്റ"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"കണക്റ്റ് ചെയ്തു"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"താൽക്കാലികമായി കണക്റ്റ് ചെയ്തിരിക്കുന്നു"</string> diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml index 75471baeca35..b865eedbf26e 100644 --- a/packages/SystemUI/res/values-mn/strings.xml +++ b/packages/SystemUI/res/values-mn/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Дэлгэц бичих горимын үргэлжилж буй мэдэгдэл"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Дэлгэцээ бичих үү?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Нэг аппыг бичих"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Энэ дэлгэцийг бичих"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"%s-г бичих"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Таныг бүтэн дэлгэцээ бичиж байхад дэлгэц дээр тань харуулж буй аливаа зүйлийг бичдэг. Тиймээс нууц үг, төлбөрийн дэлгэрэнгүй, мессеж, зураг, аудио, видео зэрэг зүйлд болгоомжтой хандаарай."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Таныг апп бичиж байхад тухайн аппад харуулж эсвэл тоглуулж буй аливаа зүйлийг бичдэг. Тиймээс нууц үг, төлбөрийн дэлгэрэнгүй, мессеж, зураг, аудио, видео зэрэг зүйлд болгоомжтой хандаарай."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Дэлгэцийг бичих"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Урьдчилсан тохируулгыг шинэчилж чадсангүй"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Урьдчилсан тохируулга"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Сонгосон"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Орчин тойрон"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Зүүн"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Баруун"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Зүүн, баруун талын тусдаа тохиргоо руу дэлгэх"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Нэгдсэн тохиргоо руу хураах"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Орчин тойрны дууг хаах"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Орчин тойрны дууг нээх"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Хэрэгсэл"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Шууд тайлбар"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Тэмдэглэл"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Бага ач холбогдолтой мэдэгдлийн дүрс тэмдгийг харуулах"</string> <string name="other" msgid="429768510980739978">"Бусад"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"хавтанг хасна уу"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"хавтанг сүүлийн байрлалд нэмэх"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Хавтанг зөөх"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Хавтанг хүссэн байрлалд нэмэх"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> руу зөөнө үү"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> байрлалд нэмнэ үү"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Байрлал буруу байна."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"хэрэглэгчийг сонгох"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Интернэт алга"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"<xliff:g id="ID_1">%s</xliff:g> тохиргоог нээнэ үү."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Шуурхай тохиргооны дарааллыг засна уу."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Асаах/унтраах цэс"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g>-н <xliff:g id="ID_1">%1$d</xliff:g>-р хуудас"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Түгжээтэй дэлгэц"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"төхөөрөмж оруулах"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Нээхийн тулд хурууны хээг ашиглана уу"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Баталгаажуулалт шаардлагатай. Баталгаажуулахын тулд хурууны хээ мэдрэгчид хүрнэ үү."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Үргэлжилж буй утасны дуудлага"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобайл дата"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Холбогдсон"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Түр зуур холбогдсон"</string> diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml index bd6cb131c972..e257ba159788 100644 --- a/packages/SystemUI/res/values-mr/strings.xml +++ b/packages/SystemUI/res/values-mr/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"स्क्रीन रेकॉर्ड सत्रासाठी सुरू असलेली सूचना"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"तुमची स्क्रीन रेकॉर्ड करायची आहे का?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"एक अॅप रेकॉर्ड करा"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"ही स्क्रीन रेकॉर्ड करा"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"%s रेकॉर्ड करा"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"तुम्ही तुमची पूर्ण स्क्रीन रेकॉर्ड करता, तेव्हा तुमच्या स्क्रीनवर दाखवलेली कोणतीही गोष्ट रेकॉर्ड केली जाते. त्यामुळे पासवर्ड, पेमेंट तपशील, मेसेज, फोटो आणि ऑडिओ व व्हिडिओ यांसारख्या गोष्टींबाबत सावधगिरी बाळगा."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"तुम्ही अॅप रेकॉर्ड करता, तेव्हा त्या अॅपमध्ये दाखवलेली किंवा प्ले केलेली कोणतीही गोष्ट रेकॉर्ड केली जाते. त्यामुळे पासवर्ड, पेमेंट तपशील, मेसेज, फोटो आणि ऑडिओ व व्हिडिओ यांसारख्या गोष्टींबाबत सावधगिरी बाळगा."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"स्क्रीन रेकॉर्ड करा"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"प्रीसेट अपडेट करता आले नाही"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"प्रीसेट"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"निवडला आहे"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"जवळपासचे आवाज"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"डावे"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"उजवे"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"डाव्या आणि उजव्या स्वतंत्र नियंत्रणांचा विस्तार करा"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"युनिफाइड नियंत्रणासाठी कोलॅप्स करा"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"जवळपासचे आवाज म्यूट करा"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"जवळपासचे आवाज अनम्यूट करा"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"टूल"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"लाइव्ह कॅप्शन"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"टीप"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"कमी प्राधान्य सूचना आयकन दर्शवा"</string> <string name="other" msgid="429768510980739978">"अन्य"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"टाइल काढून टाका"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"टाइल शेवटच्या स्थानावर जोडा"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"टाइल हलवा"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"हव्या असलेल्या स्थानावर टाइल जोडा"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> यावर हलवा"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> स्थानावर जोडा"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"स्थान चुकीचे आहे."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"वापरकर्ता निवडा"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"इंटरनेट नाही"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"<xliff:g id="ID_1">%s</xliff:g> सेटिंग्ज उघडा."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"क्विक सेटिंग्ज चा क्रम संपादित करा."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"पॉवर मेनू"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g> पैकी <xliff:g id="ID_1">%1$d</xliff:g> पेज"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"लॉक स्क्रीन"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"डिव्हाइस एंटर करा"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"उघडण्यासाठी फिंगरप्रिंट वापरा"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ऑथेंटिकेशन आवश्यक आहे. ऑथेंटिकेट करण्यासाठी फिंगरप्रिंट सेन्सरला स्पर्श करा."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"फोन कॉल सुरू आहे"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"मोबाइल डेटा"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"कनेक्ट केले आहे"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"तात्पुरते कनेक्ट केलेले"</string> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index 3af595760c85..bf65859aab7e 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Pemberitahuan breterusan untuk sesi rakaman skrin"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Rakam skrin anda?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Rakam satu apl"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Rakam skrin ini"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Rakam %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Apabila anda merakam seluruh skrin anda, apa-apa sahaja yang dipaparkan pada skrin anda akan dirakam. Oleh hal yang demikian, berhati-hati dengan perkara seperti kata laluan, butiran pembayaran, mesej, foto dan audio serta video."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Apabila anda merakam apl, apa-apa sahaja yang dipaparkan atau dimainkan dalam apl tersebut akan dirakam. Oleh hal yang demikian, berhati-hati dengan perkara seperti kata laluan, butiran pembayaran, mesej, foto dan audio serta video."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Rakam skrin"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Tidak dapat mengemaskinikan pratetapan"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Pratetapan"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Dipilih"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Persekitaran"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Kiri"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Kanan"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Kembangkan kepada kawalan berasingan sebelah kiri dan kanan"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Kuncupkan kepada kawalan yang disatukan"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Redamkan persekitaran"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Nyahredam persekitaran"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Alatan"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Sari Kata Langsung"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Nota"</string> @@ -1298,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"akses peranti"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Gunakan cap jari untuk membuka"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Pengesahan diperlukan. Sentuh penderia cap jari untuk pengesahan."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Panggilan telefon yang sedang berjalan"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Data mudah alih"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Disambungkan"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Disambungkan buat sementara waktu"</string> diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml index a8a2eaac0654..1c4055687d26 100644 --- a/packages/SystemUI/res/values-my/strings.xml +++ b/packages/SystemUI/res/values-my/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"ဖန်သားပြင် ရိုက်ကူးသည့် စက်ရှင်အတွက် ဆက်တိုက်လာနေသော အကြောင်းကြားချက်"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"ဖန်သားပြင်ကို ရိုက်ကူးမလား။"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"အက်ပ်တစ်ခုကို ရိုက်ကူးရန်"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"ဤစခရင်ကို ရိုက်ကူးရန်"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"%s ကို ရိုက်ကူးရန်"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"သင့်ဖန်သားပြင်တစ်ခုလုံး ရိုက်ကူးနေချိန်တွင် ဖန်သားပြင်တွင် ပြထားသည့် အရာအားလုံးကို ရိုက်ကူးသည်။ စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ မက်ဆေ့ဂျ်၊ ဓာတ်ပုံ၊ အသံနှင့် ဗီဒီယိုကဲ့သို့ အရာများကို ဂရုစိုက်ပါ။"</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"အက်ပ်ကို ရိုက်ကူးနေချိန်တွင် ယင်းအက်ပ်တွင် ပြထားသော (သို့) ဖွင့်ထားသော အရာအားလုံးကို ရိုက်ကူးသည်။ စကားဝှက်၊ ငွေပေးချေမှု အချက်အလက်၊ မက်ဆေ့ဂျ်၊ ဓာတ်ပုံ၊ အသံနှင့် ဗီဒီယိုကဲ့သို့ အရာများကို ဂရုစိုက်ပါ။"</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"ဖန်သားပြင်ကို ရိုက်ကူးရန်"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"အသင့်သုံးကို အပ်ဒိတ်လုပ်၍မရပါ"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"ကြိုတင်သတ်မှတ်ချက်"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"ရွေးထားသည်"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"ဝန်းကျင်အသံ"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"ဘယ်"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"ညာ"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"ဘယ်ညာခွဲထားသော ထိန်းချုပ်မှုများအဖြစ် ပိုပြပါ"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"ပေါင်းစည်းထားသော ထိန်းချုပ်မှုအဖြစ် လျှော့ပြပါ"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"ဝန်းကျင်အသံ ပိတ်ရန်"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"ဝန်းကျင်အသံ ပြန်ဖွင့်ရန်"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"တူးလ်များ"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"တိုက်ရိုက်စာတန်း"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"မှတ်စု"</string> @@ -869,7 +860,7 @@ <string name="keyboard_shortcut_join" msgid="3578314570034512676">"သို့မဟုတ်"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"ရှာဖွေစာလုံး ရှင်းထုတ်ရန်"</string> <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"လက်ကွက်ဖြတ်လမ်းများ"</string> - <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"ဖြတ်လမ်းများ ရှာရန်"</string> + <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"ရှာဖွေစာလုံး ဖြတ်လမ်း"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"ဖြတ်လမ်းလင့်ခ် မတွေ့ပါ"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"စနစ်"</string> <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"စာရိုက်ခြင်း"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"အရေးမကြီးသော အကြောင်းကြားချက် သင်္ကေတများ ပြရန်"</string> <string name="other" msgid="429768510980739978">"အခြား"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"အကွက်ငယ်ကို ဖယ်ရှားရန်"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"နောက်ဆုံးနေရာတွင် အကွက်ငယ် ထည့်ရန်"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"အကွက်ငယ်ကို ရွှေ့ရန်"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"ဆန္ဒရှိရာ နေရာတွင် အကွက်ငယ် ထည့်ရန်"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> သို့ ရွှေ့ရန်"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> အနေအထားသို့ ပေါင်းထည့်ရန်"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"နေရာ မမှန်ပါ။"</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"အသုံးပြုသူရွေးရန်"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"အင်တာနက် မရှိပါ"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"<xliff:g id="ID_1">%s</xliff:g> ဆက်တင်များကို ဖွင့်ပါ။"</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"‘အမြန်ဆက်တင်များ’ ၏ အစီအစဉ်ကို ပြင်ရန်။"</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"ပါဝါမီနူး"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"စာမျက်နှာ <xliff:g id="ID_2">%2$d</xliff:g> အနက်မှ စာမျက်နှာ <xliff:g id="ID_1">%1$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"လော့ခ်မျက်နှာပြင်"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"စက်ပစ္စည်းသို့ ဝင်ရန်"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ဖွင့်ရန် လက်ဗွေကို သုံးပါ"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"အထောက်အထားစိစစ်ခြင်း လိုအပ်သည်။ အထောက်အထားစိစစ်ရန် လက်ဗွေ အာရုံခံကိရိယာကို ထိပါ။"</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"လက်ရှိ ဖုန်းခေါ်ဆိုမှု"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"မိုဘိုင်းဒေတာ"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"ချိတ်ဆက်ထားသည်"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"ယာယီချိတ်ဆက်ထားသည်"</string> @@ -1454,7 +1443,7 @@ <string name="shortcut_customize_mode_add_shortcut_description" msgid="6866025005347407696">"ဖြတ်လမ်းလင့်ခ်သတ်မှတ်ရန် ကီးကို နှိပ်ပါ"</string> <string name="shortcut_customize_mode_remove_shortcut_description" msgid="6851287900585057128">"၎င်းသည် သင့်စိတ်ကြိုက် ဖြတ်လမ်းလင့်ခ်ကို အပြီးဖျက်ပါမည်။"</string> <string name="shortcut_customize_mode_reset_shortcut_description" msgid="2081849715634358684">"၎င်းသည် သင့်စိတ်ကြိုက်ဖြတ်လမ်းလင့်ခ်အားလုံးကို အပြီးဖျက်မည်။"</string> - <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"ဖြတ်လမ်းများ ရှာရန်"</string> + <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"ရှာဖွေစာလုံး ဖြတ်လမ်း"</string> <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"ရှာဖွေမှုရလဒ် မရှိပါ"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"လျှော့ပြရန် သင်္ကေတ"</string> <string name="shortcut_helper_content_description_meta_key" msgid="3989315044342124818">"လုပ်ဆောင်ချက် (သို့) Meta ကီးသင်္ကေတ"</string> @@ -1470,7 +1459,7 @@ <string name="shortcut_helper_keyboard_settings_buttons_label" msgid="6720967595915985259">"ကီးဘုတ်ဆက်တင်များ"</string> <string name="shortcut_helper_customize_dialog_set_shortcut_button_label" msgid="4754492225010429382">"ဖြတ်လမ်း သတ်မှတ်ရန်"</string> <string name="shortcut_helper_customize_dialog_remove_button_label" msgid="6546386970440176552">"ဖယ်ရှားရန်"</string> - <string name="shortcut_helper_customize_dialog_reset_button_label" msgid="7645535254306312685">"ပြန်လည်ပြင်ဆင်သတ်မှတ်မည်"</string> + <string name="shortcut_helper_customize_dialog_reset_button_label" msgid="7645535254306312685">"ပြင်ဆင်ရန်"</string> <string name="shortcut_helper_customize_dialog_cancel_button_label" msgid="5595546460431741178">"မလုပ်တော့"</string> <string name="shortcut_helper_add_shortcut_dialog_placeholder" msgid="9154297849458741995">"ကီးကို နှိပ်ပါ"</string> <string name="shortcut_customizer_key_combination_in_use_error_message" msgid="7693234470526626327">"ကီးပေါင်းစပ်ခြင်းကို သုံးနေပြီးဖြစ်သည်။ အခြားကီးကို စမ်းကြည့်ပါ။"</string> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index ae135cc5f09c..0b68bd921c6f 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Vedvarende varsel for et skjermopptak"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Vil du ta opp skjermen?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Ta opp én app"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Ta opp denne skjermen"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Ta opp %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Når du tar opp hele skjermen, blir alt som vises på skjermen, tatt opp. Derfor bør du være forsiktig med for eksempel passord, betalingsopplysninger, meldinger, bilder, lyd og video."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Når du tar opp en app, blir alt som vises eller spilles av i appen, tatt opp. Derfor bør du være forsiktig med for eksempel passord, betalingsopplysninger, meldinger, bilder, lyd og video."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Ta opp skjermen"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Kunne ikke oppdatere forhåndsinnstillingen"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Forhåndsinnstilling"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Valgt"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Omgivelser"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Venstre"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Høyre"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Utvid til separate kontroller for venstre og høyre"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Skjul til samlet kontroll"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Kutt lyden for omgivelsene"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Slå på lyden for omgivelsene"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Verktøy"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Direkteteksting"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Merknad"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Vis ikoner for varsler med lav prioritet"</string> <string name="other" msgid="429768510980739978">"Annet"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"fjerne infobrikken"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"legge til en brikke på den siste posisjonen"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Flytt infobrikken"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Legg til brikken på ønsket posisjon"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Flytt til <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Legg til posisjonen <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Posisjonen er ugyldig."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"velge en bruker"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Ingen internettilkobling"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Åpne <xliff:g id="ID_1">%s</xliff:g>-innstillingene."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Endre rekkefølgen på hurtiginnstillingene."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Av/på-meny"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Side <xliff:g id="ID_1">%1$d</xliff:g> av <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Låseskjerm"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"åpne enheten"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Bruk fingeravtrykk for å åpne"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autentisering kreves. Trykk på fingeravtrykkssensoren for å autentisere."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Pågående telefonsamtale"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobildata"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Tilkoblet"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Koblet til midlertidig"</string> @@ -1470,7 +1459,7 @@ <string name="shortcut_helper_keyboard_settings_buttons_label" msgid="6720967595915985259">"Tastaturinnstillinger"</string> <string name="shortcut_helper_customize_dialog_set_shortcut_button_label" msgid="4754492225010429382">"Angi hurtigtast"</string> <string name="shortcut_helper_customize_dialog_remove_button_label" msgid="6546386970440176552">"Fjern"</string> - <string name="shortcut_helper_customize_dialog_reset_button_label" msgid="7645535254306312685">"Ja, tilbakestill"</string> + <string name="shortcut_helper_customize_dialog_reset_button_label" msgid="7645535254306312685">"Tilbakestill"</string> <string name="shortcut_helper_customize_dialog_cancel_button_label" msgid="5595546460431741178">"Avbryt"</string> <string name="shortcut_helper_add_shortcut_dialog_placeholder" msgid="9154297849458741995">"Trykk på tasten"</string> <string name="shortcut_customizer_key_combination_in_use_error_message" msgid="7693234470526626327">"Tastekombinasjonen brukes allerede. Prøv en annen tast."</string> diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml index c701ebc6b4fd..818809b4acfc 100644 --- a/packages/SystemUI/res/values-ne/strings.xml +++ b/packages/SystemUI/res/values-ne/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"कुनै स्क्रिन रेकर्ड गर्ने सत्रका लागि चलिरहेको सूचना"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"तपाईंको स्क्रिन रेकर्ड गर्ने हो?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"एउटा एप रेकर्ड गर्नुहोस्"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"यो स्क्रिन रेकर्ड गर्नुहोस्"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"%s रेकर्ड गर्नुहोस्"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"तपाईंले आफ्नो पूरै स्क्रिन रेकर्ड गरिरहेका बेला तपाईंको स्क्रिनमा देखाइने सबै सामग्री रेकर्ड गरिन्छ। त्यसैले पासवर्ड, भुक्तानीसम्बन्धी विवरण, म्यासेज, फोटो र अडियो तथा भिडियो जस्ता कुरा हेर्दा वा प्ले गर्दा सावधानी अपनाउनुहोला।"</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"तपाईंले यो एप रेकर्ड गरिरहेका बेला यो एपमा देखाइने वा प्ले गरिने सबै सामग्री रेकर्ड गरिन्छ। त्यसैले पासवर्ड, भुक्तानीसम्बन्धी विवरण, म्यासेज, फोटो र अडियो तथा भिडियो जस्ता कुरा हेर्दा वा प्ले गर्दा सावधानी अपनाउनुहोला।"</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"स्क्रिन रेकर्ड गर्नुहोस्"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"प्रिसेट अपडेट गर्न सकिएन"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"पूर्वनिर्धारित"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"चयन गरिएको छ"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"वरपरका आवाज"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"बायाँ"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"दायाँ"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"दायाँ र बायाँतर्फको भोल्युम छुट्टाछुट्टै व्यवस्थापन गर्न भोल्युम प्यानल छुट्ट्याउनुहोस्"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"कोल्याप्स गरी एउटै कन्ट्रोल बनाउनुहोस्"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"वरपरका आवाज म्युट गर्नुहोस्"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"वरपरका आवाज अनम्युट गर्नुहोस्"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"टुल"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"लाइभ क्याप्सन"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"नोट"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"कम प्राथमिकताका सूचना आइकनहरू देखाउनुहोस्"</string> <string name="other" msgid="429768510980739978">"अन्य"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"टाइल हटाउनुहोस्"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"अन्तिम स्थानमा टाइल हाल्नुहोस्"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"टाइल सार्नुहोस्"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"आफूले चाहेको स्थानमा टाइल हाल्नुहोस्"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"टाइल सारेर <xliff:g id="POSITION">%1$d</xliff:g> मा लैजानुहोस्"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"टाइल यो अवस्था <xliff:g id="POSITION">%1$d</xliff:g> मा हाल्नुहोस्"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"पोजिसन अवैध छ।"</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"प्रयोगकर्ता छान्नुहोस्"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"इन्टरनेट छैन"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"<xliff:g id="ID_1">%s</xliff:g> सम्बन्धी सेटिङहरूलाई खोल्नुहोस्।"</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"द्रुत सेटिङमा भएका विकल्पहरूको क्रम बदल्नुहोस्।"</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"पावर मेनु"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g> मध्ये पृष्ठ <xliff:g id="ID_1">%1$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"लक स्क्रिन"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"डिभाइस हाल्नुहोस्"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"फिंगरप्रिन्ट प्रयोग गरी खोल्नुहोस्"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"पुष्टि गर्नु पर्ने हुन्छ। पुष्टि गर्न फिंगरप्रिन्ट सेन्सर छुनुहोस्।"</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"जारी फोन कल"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"मोबाइल डेटा"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"इन्टरनेटमा कनेक्ट गरिएको छ"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"यसमा केही समयका लागि कनेक्ट गरिएको हो"</string> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index 55b701e8dd03..546cd081af72 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Doorlopende melding voor een schermopname-sessie"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Je scherm opnemen?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Eén app opnemen"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Dit scherm opnemen"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"%s opnemen"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Als je je hele scherm opneemt, wordt alles opgenomen wat op je scherm wordt getoond. Wees daarom voorzichtig met bijvoorbeeld wachtwoorden, betalingsgegevens, berichten, foto\'s, en audio en video."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Als je een app opneemt, wordt alles opgenomen wat wordt getoond of afgespeeld in die app. Wees daarom voorzichtig met bijvoorbeeld wachtwoorden, betalingsgegevens, berichten, foto\'s, en audio en video."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Scherm opnemen"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Kan voorinstelling niet updaten"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Voorinstelling"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Geselecteerd"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Omgeving"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Links"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Rechts"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Uitvouwen naar gescheiden bediening voor links en rechts"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Samenvouwen tot geïntegreerde bediening"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Omgevingsgeluid uitzetten"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Omgevingsgeluid aanzetten"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Tools"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Live ondertiteling"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Notitie"</string> @@ -1298,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"apparaat opgeven"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Gebruik vingerafdruk om te openen"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Verificatie vereist. Raak de vingerafdruksensor aan om de verificatie uit te voeren."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Actief telefoongesprek"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobiele data"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Verbonden"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Tijdelijk verbonden"</string> diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml index 1ac2170b8ae3..d035f6a88de0 100644 --- a/packages/SystemUI/res/values-or/strings.xml +++ b/packages/SystemUI/res/values-or/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"ଏକ ସ୍କ୍ରିନ୍ ରେକର୍ଡ୍ ସେସନ୍ ପାଇଁ ଚାଲୁଥିବା ବିଜ୍ଞପ୍ତି"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"ଆପଣଙ୍କ ସ୍କ୍ରିନକୁ ରେକର୍ଡ କରିବେ?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"ଗୋଟିଏ ଆପ ରେକର୍ଡ କରନ୍ତୁ"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"ଏହି ସ୍କ୍ରିନକୁ ରେକର୍ଡ କରନ୍ତୁ"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"%sକୁ ରେକର୍ଡ କରନ୍ତୁ"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"ଆପଣ ଆପଣଙ୍କର ସମ୍ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନ ରେକର୍ଡ କରିବା ସମୟରେ, ଆପଣଙ୍କ ସ୍କ୍ରିନରେ ଦେଖାଯାଉଥିବା ସବୁକିଛି ରେକର୍ଡ ହୋଇଥାଏ। ତେଣୁ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ମେସେଜ, ଫଟୋ ଏବଂ ଅଡିଓ ଓ ଭିଡିଓ ପରି ବିଷୟଗୁଡ଼ିକ ପ୍ରତି ସତର୍କ ରୁହନ୍ତୁ।"</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"ଆପଣ ଏକ ଆପ ରେକର୍ଡ କରିବା ସମୟରେ, ସେହି ଆପରେ ଦେଖାଯାଉଥିବା କିମ୍ବା ପ୍ଲେ ହେଉଥିବା ସବୁକିଛି ରେକର୍ଡ ହୋଇଥାଏ। ତେଣୁ ପାସୱାର୍ଡ, ପେମେଣ୍ଟ ବିବରଣୀ, ମେସେଜ, ଫଟୋ ଏବଂ ଅଡିଓ ଓ ଭିଡିଓ ପରି ବିଷୟଗୁଡ଼ିକ ପ୍ରତି ସତର୍କ ରୁହନ୍ତୁ।"</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"ସ୍କ୍ରିନ ରେକର୍ଡ କରନ୍ତୁ"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"ପ୍ରିସେଟକୁ ଅପଡେଟ କରାଯାଇପାରିଲା ନାହିଁ"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"ପ୍ରିସେଟ"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"ଚୟନ କରାଯାଇଛି"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"ପରିପାର୍ଶ୍ୱ"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"ବାମ"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"ଡାହାଣ"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"ବାମ ଏବଂ ଡାହାଣ ଅଲଗା ନିୟନ୍ତ୍ରଣକୁ ବିସ୍ତାର କରନ୍ତୁ"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"ଏକତ୍ରିତ ନିୟନ୍ତ୍ରଣକୁ ସଙ୍କୁଚିତ କରନ୍ତୁ"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"ପରିପାର୍ଶ୍ୱକୁ ମ୍ୟୁଟ କରନ୍ତୁ"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"ପରିପାର୍ଶ୍ୱକୁ ଅନମ୍ୟୁଟ କରନ୍ତୁ"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"ଟୁଲ"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"ଲାଇଭ କେପ୍ସନ"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"ନୋଟ"</string> @@ -914,7 +905,7 @@ <string name="keyboard_shortcut_group_applications_assist" msgid="6772492350416591448">"Assistant"</string> <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"ବ୍ରାଉଜର୍"</string> <string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"କଣ୍ଟାକ୍ଟ"</string> - <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"ଇମେଲ୍"</string> + <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"ଇମେଲ"</string> <string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string> <string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"ମ୍ୟୁଜିକ୍"</string> <string name="keyboard_shortcut_group_applications_calendar" msgid="4229602992120154157">"Calendar"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"କମ୍-ଅଗ୍ରାଧିକାର ବିଜ୍ଞପ୍ତି ଆଇକନ୍ ଦେଖାନ୍ତୁ"</string> <string name="other" msgid="429768510980739978">"ଅନ୍ୟ"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"ଟାଇଲ୍ କାଢ଼ି ଦିଅନ୍ତୁ"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"ଶେଷ ପୋଜିସନରେ ଟାଇଲ ଯୋଗ କରିବା"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"ଟାଇଲ୍ ମୁଭ୍ କରନ୍ତୁ"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"ଇଚ୍ଛିତ ପୋଜିସନରେ ଟାଇଲ ଯୋଗ କରନ୍ତୁ"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g>କୁ ମୁଭ୍ କରନ୍ତୁ"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> ଅବସ୍ଥିତିରେ ଯୋଗ କରନ୍ତୁ"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"ଅବସ୍ଥିତି ଅବୈଧ ଅଟେ।"</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"ୟୁଜର ବାଛନ୍ତୁ"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"କୌଣସି ଇଣ୍ଟରନେଟ୍ କନେକ୍ସନ୍ ନାହିଁ"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"<xliff:g id="ID_1">%s</xliff:g> ସେଟିଙ୍ଗ ଖୋଲନ୍ତୁ।"</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"କୁଇକ ସେଟିଂସର କ୍ରମକୁ ଏଡିଟ କରନ୍ତୁ।"</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"ପାୱାର ମେନୁ"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"ପୃଷ୍ଠା <xliff:g id="ID_1">%1$d</xliff:g> ମୋଟ <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"ଲକ ସ୍କ୍ରିନ"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"ଡିଭାଇସ୍ ବିଷୟରେ ସୂଚନା ଲେଖନ୍ତୁ"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ଖୋଲିବାକୁ ଟିପଚିହ୍ନ ବ୍ୟବହାର କରନ୍ତୁ"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ପ୍ରମାଣୀକରଣ ଆବଶ୍ୟକ। ପ୍ରମାଣୀକରଣ କରିବାକୁ ଟିପଚିହ୍ନ ସେନ୍ସରକୁ ସ୍ପର୍ଶ କରନ୍ତୁ।"</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ଚାଲୁଥିବା ଫୋନ୍ କଲ୍"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"ମୋବାଇଲ ଡାଟା"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"ସଂଯୋଗ କରାଯାଇଛି"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"ଅସ୍ଥାୟୀ ରୂପେ କନେକ୍ଟ କରାଯାଇଛି"</string> diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index 6eda17ad14b9..7b718de7f074 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"ਕਿਸੇ ਸਕ੍ਰੀਨ ਰਿਕਾਰਡ ਸੈਸ਼ਨ ਲਈ ਚੱਲ ਰਹੀ ਸੂਚਨਾ"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"ਕੀ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ ਨੂੰ ਰਿਕਾਰਡ ਕਰਨਾ ਹੈ?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"ਇੱਕ ਐਪ ਨੂੰ ਰਿਕਾਰਡ ਕਰੋ"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"ਇਸ ਸਕ੍ਰੀਨ ਨੂੰ ਰਿਕਾਰਡ ਕਰੋ"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"%s ਨੂੰ ਰਿਕਾਰਡ ਕਰੋ"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"ਜਦੋਂ ਤੁਸੀਂ ਆਪਣੀ ਪੂਰੀ ਸਕ੍ਰੀਨ ਨੂੰ ਰਿਕਾਰਡ ਕਰ ਰਹੇ ਹੁੰਦੇ ਹੋ, ਤਾਂ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਖਾਈ ਜਾ ਰਹੀ ਹਰ ਚੀਜ਼ ਨੂੰ ਰਿਕਾਰਡ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ, ਫ਼ੋਟੋਆਂ ਅਤੇ ਨਾਲ ਹੀ ਆਡੀਓ ਅਤੇ ਵੀਡੀਓ ਵਰਗੀਆਂ ਚੀਜ਼ਾਂ ਵਾਸਤੇ ਸਾਵਧਾਨ ਰਹੋ।"</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"ਜਦੋਂ ਤੁਸੀਂ ਕਿਸੇ ਐਪ ਨੂੰ ਰਿਕਾਰਡ ਕਰ ਰਹੇ ਹੁੰਦੇ ਹੋ, ਤਾਂ ਉਸ ਐਪ ਵਿੱਚ ਦਿਖਾਈ ਜਾਂ ਚਲਾਈ ਜਾ ਰਹੀ ਹਰ ਚੀਜ਼ ਨੂੰ ਰਿਕਾਰਡ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ, ਫ਼ੋਟੋਆਂ ਅਤੇ ਆਡੀਓ ਅਤੇ ਵੀਡੀਓ ਵਰਗੀਆਂ ਚੀਜ਼ਾਂ ਵਾਸਤੇ ਸਾਵਧਾਨ ਰਹੋ।"</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡ ਕਰੋ"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"ਪ੍ਰੀਸੈੱਟ ਨੂੰ ਅੱਪਡੇਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"ਪ੍ਰੀਸੈੱਟ"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"ਚੁਣਿਆ ਗਿਆ"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"ਆਲੇ-ਦੁਆਲੇ"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"ਖੱਬੇ"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"ਸੱਜੇ"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"ਖੱਬੇ ਅਤੇ ਸੱਜੇ ਪਾਸੇ ਦੇ ਸ਼ੋਰ ਨੂੰ ਵੱਖ-ਵੱਖ ਕੰਟਰੋਲ ਕਰਨ ਲਈ ਵਿਸਤਾਰ ਕਰੋ"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"ਏਕੀਕ੍ਰਿਤ ਕੰਟਰੋਲ \'ਤੇ ਜਾਣ ਲਈ ਸਮੇਟੋ"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"ਆਲੇ-ਦੁਆਲੇ ਦੇ ਸ਼ੋਰ ਨੂੰ ਮਿਊਟ ਕਰੋ"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"ਆਲੇ-ਦੁਆਲੇ ਦੇ ਸ਼ੋਰ ਨੂੰ ਅਣਮਿਊਟ ਕਰੋ"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"ਟੂਲ"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"ਲਾਈਵ ਸੁਰਖੀਆਂ"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"ਨੋਟ-ਕਥਨ"</string> @@ -466,7 +457,7 @@ <string name="zen_modes_dialog_done" msgid="6654130880256438950">"ਹੋ ਗਿਆ"</string> <string name="zen_modes_dialog_settings" msgid="2310248023728936697">"ਸੈਟਿੰਗਾਂ"</string> <string name="zen_mode_on" msgid="9085304934016242591">"ਚਾਲੂ"</string> - <string name="zen_mode_on_with_details" msgid="7416143430557895497">"<xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g> • \'ਤੇ"</string> + <string name="zen_mode_on_with_details" msgid="7416143430557895497">"ਚਾਲੂ • <xliff:g id="TRIGGER_DESCRIPTION">%1$s</xliff:g>"</string> <string name="zen_mode_off" msgid="1736604456618147306">"ਬੰਦ"</string> <string name="zen_mode_set_up" msgid="8231201163894922821">"ਸੈੱਟ ਨਹੀਂ ਹੈ"</string> <string name="zen_mode_no_manual_invocation" msgid="1769975741344633672">"ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਪ੍ਰਬੰਧਨ ਕਰੋ"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"ਘੱਟ ਤਰਜੀਹ ਵਾਲੇ ਸੂਚਨਾ ਪ੍ਰਤੀਕਾਂ ਨੂੰ ਦਿਖਾਓ"</string> <string name="other" msgid="429768510980739978">"ਹੋਰ"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"ਟਾਇਲ ਹਟਾਓ"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"ਪਿਛਲੀ ਸਥਿਤੀ \'ਤੇ ਟਾਇਲ ਸ਼ਾਮਲ ਕਰੋ"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"ਟਾਇਲ ਨੂੰ ਲਿਜਾਓ"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"ਮਨਪਸੰਦ ਸਥਿਤੀ \'ਤੇ ਟਾਇਲ ਸ਼ਾਮਲ ਕਰੋ"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> \'ਤੇ ਲਿਜਾਓ"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> ਸਥਾਨ \'ਤੇ ਸ਼ਾਮਲ ਕਰੋ"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"ਮੌਜੂਦਾ ਥਾਂ ਅਵੈਧ ਹੈ।"</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"ਵਰਤੋਂਕਾਰ ਚੁਣੋ"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"ਇੰਟਰਨੈੱਟ ਨਹੀਂ।"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"<xliff:g id="ID_1">%s</xliff:g> ਸੈਟਿੰਗਾਂ ਖੋਲ੍ਹੋ।"</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਦੇ ਕ੍ਰਮ ਦਾ ਸੰਪਾਦਨ ਕਰੋ।"</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"ਪਾਵਰ ਮੀਨੂ"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g> ਦਾ <xliff:g id="ID_1">%1$d</xliff:g> ਪੰਨਾ"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">" ਲਾਕ ਸਕ੍ਰੀਨ"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"ਡੀਵਾਈਸ ਵਿੱਚ ਦਾਖਲ ਹੋਵੋ"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ਖੋਲ੍ਹਣ ਲਈ ਫਿੰਗਰਪ੍ਰਿੰਟ ਵਰਤੋ"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ਪ੍ਰਮਾਣੀਕਰਨ ਲੋੜੀਂਦਾ ਹੈ। ਪ੍ਰਮਾਣਿਤ ਕਰਨ ਲਈ ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ ਨੂੰ ਸਪਰਸ਼ ਕਰੋ।"</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ਜਾਰੀ ਫ਼ੋਨ ਕਾਲ"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"ਮੋਬਾਈਲ ਡਾਟਾ"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"ਕਨੈਕਟ ਹੈ"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"ਕੁਝ ਸਮੇਂ ਲਈ ਕਨੈਕਟ ਹੈ"</string> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index 82e3f67c2b9e..b6dc2f61656c 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Stałe powiadomienie o sesji rejestrowania zawartości ekranu"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Nagrywać ekran?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Nagrywaj jedną aplikację"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Nagrywaj ten ekran"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Nagrywaj ekran %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Kiedy nagrywasz cały ekran, nagrane zostanie wszystko, co jest na nim widoczne. Dlatego uważaj na hasła, dane do płatności, wiadomości, zdjęcia, nagrania audio czy filmy."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Kiedy nagrywasz aplikację, wszystko, co jest w niej wyświetlane lub odtwarzane, zostaje nagrane. Dlatego zachowaj ostrożność w zakresie haseł, danych do płatności, wiadomości, zdjęć, audio i filmów."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Nagrywaj ekran"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Nie udało się zaktualizować gotowego ustawienia"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Gotowe ustawienie"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Wybrano"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Otoczenie"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Po lewej"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Po prawej"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Rozwiń, aby oddzielić elementy sterujące po lewej i po prawej stronie"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Zwiń do ujednoliconego sterowania"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Wycisz otoczenie"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Wyłącz wyciszenie otoczenia"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Narzędzia"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Napisy na żywo"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Notatka"</string> @@ -886,8 +877,8 @@ <string name="group_system_go_back" msgid="2730322046244918816">"Przejdź wstecz"</string> <string name="group_system_access_home_screen" msgid="4130366993484706483">"Wyświetl ekran główny"</string> <string name="group_system_overview_open_apps" msgid="5659958952937994104">"Wyświetl ostatnie aplikacje"</string> - <string name="group_system_cycle_forward" msgid="5478663965957647805">"Przełącz się do przodu między ostatnimi aplikacjami"</string> - <string name="group_system_cycle_back" msgid="8194102916946802902">"Przełącz się wstecz między ostatnimi aplikacjami"</string> + <string name="group_system_cycle_forward" msgid="5478663965957647805">"Przełącz się między ostatnio używanymi aplikacjami (do przodu)"</string> + <string name="group_system_cycle_back" msgid="8194102916946802902">"Przełącz się między ostatnio używanymi aplikacjami (do tyłu)"</string> <string name="group_system_access_all_apps_search" msgid="1553588630154197469">"Otwórz listę aplikacji"</string> <string name="group_system_access_system_settings" msgid="8731721963449070017">"Otwórz ustawienia"</string> <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Otwórz asystenta"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Pokazuj ikony powiadomień o niskim priorytecie"</string> <string name="other" msgid="429768510980739978">"Inne"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"usunąć kartę"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"dodaj kafelek do ostatniej pozycji"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Przenieś kartę"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Dodaj kafelek do wybranej pozycji"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Przenieś do pozycji <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Dodaj w pozycji <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Nieprawidłowa pozycja."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"wybrać użytkownika"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Brak internetu"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Otwórz ustawienia: <xliff:g id="ID_1">%s</xliff:g>."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Edytuj kolejność Szybkich ustawień."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menu zasilania"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Strona <xliff:g id="ID_1">%1$d</xliff:g> z <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Ekran blokady"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"otwórz urządzenie"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"By otworzyć, użyj odcisku palca"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Wymagane uwierzytelnienie. Dotknij czytnika liniii papilarnych, by uwierzytelnić."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Aktywne połączenie"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilna transmisja danych"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Połączono"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Tymczasowe połączenie"</string> @@ -1473,7 +1462,7 @@ <string name="shortcut_helper_customize_dialog_reset_button_label" msgid="7645535254306312685">"Tak, zresetuj"</string> <string name="shortcut_helper_customize_dialog_cancel_button_label" msgid="5595546460431741178">"Anuluj"</string> <string name="shortcut_helper_add_shortcut_dialog_placeholder" msgid="9154297849458741995">"Naciśnij klawisz"</string> - <string name="shortcut_customizer_key_combination_in_use_error_message" msgid="7693234470526626327">"Kombinacja klawiszy jest już używana. Użyj innego klawisza."</string> + <string name="shortcut_customizer_key_combination_in_use_error_message" msgid="7693234470526626327">"Ta kombinacja klawiszy jest już używana. Użyj innego klawisza."</string> <string name="shortcut_customizer_generic_error_message" msgid="3128454624049722741">"Nie można ustawić skrótu."</string> <string name="shortcut_helper_plus_symbol" msgid="4534843157353732011">"+"</string> <string name="launch_keyboard_tutorial_notification_title" msgid="8849933155160522519">"Nawiguj za pomocą klawiatury"</string> diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml index 4ebc7ae6fbce..e7bcaa25e7fb 100644 --- a/packages/SystemUI/res/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificação contínua para uma sessão de gravação de tela"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Gravar a tela?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Gravar um app"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Gravar esta tela"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Gravar %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Quando você grava a tela toda, tudo o que aparece nela é registrado. Portanto, tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Quando você grava um app, todas as informações visíveis ou abertas nele ficam registradas. Portanto, tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Gravar a tela"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Não foi possível atualizar a predefinição"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Predefinição"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Selecionado"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Som ambiente"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Lado esquerdo"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Lado direito"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Abrir para controles separados da esquerda e da direita"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Fechar para controle unificado"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Silenciar som ambiente"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Ativar som ambiente"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Ferramentas"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Legenda instantânea"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Observação"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Mostrar ícones de notificações de baixa prioridade"</string> <string name="other" msgid="429768510980739978">"Outros"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"remover o bloco"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"adicionar o bloco à última posição"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Mover bloco"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Adicionar o bloco à posição desejada"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Mover para <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Adicionar à posição <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Posição inválida."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"escolher o usuário"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Sem Internet"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Abrir configurações de <xliff:g id="ID_1">%s</xliff:g>."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Editar a ordem das Configurações rápidas."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menu liga/desliga"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Página <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Tela de bloqueio"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"acessar o dispositivo"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Use a impressão digital para abrir"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticação obrigatória. Toque no sensor de impressão digital para autenticar."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Chamada em andamento"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Dados móveis"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Conectado"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Temporariamente conectado"</string> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index 2b49139074f4..a9de96156d5b 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificação persistente de uma sessão de gravação de ecrã"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Gravar o ecrã?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Gravar uma app"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Gravar este ecrã"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Gravar %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Quando está a gravar o ecrã inteiro, tudo o que é apresentado no ecrã é gravado. Por isso, tenha cuidado com, por exemplo, palavras-passe, detalhes de pagamento, mensagens, fotos, áudio e vídeo."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Quando está a gravar uma app, tudo o que é apresentado ou reproduzido nessa app é gravado. Por isso, tenha cuidado com, por exemplo, palavras-passe, detalhes de pagamento, mensagens, fotos, áudio e vídeo."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Gravar ecrã"</string> @@ -1291,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"entrar no dispositivo"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Utilize a impressão digital para abrir"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticação necessária. Toque no sensor de impressões digitais para autenticar."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Chamada telefónica em curso"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Dados móveis"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Ligado"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Ligado temporariamente"</string> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index 4ebc7ae6fbce..e7bcaa25e7fb 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificação contínua para uma sessão de gravação de tela"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Gravar a tela?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Gravar um app"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Gravar esta tela"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Gravar %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Quando você grava a tela toda, tudo o que aparece nela é registrado. Portanto, tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Quando você grava um app, todas as informações visíveis ou abertas nele ficam registradas. Portanto, tenha cuidado com senhas, detalhes de pagamento, mensagens, fotos, áudios e vídeos."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Gravar a tela"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Não foi possível atualizar a predefinição"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Predefinição"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Selecionado"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Som ambiente"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Lado esquerdo"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Lado direito"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Abrir para controles separados da esquerda e da direita"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Fechar para controle unificado"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Silenciar som ambiente"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Ativar som ambiente"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Ferramentas"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Legenda instantânea"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Observação"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Mostrar ícones de notificações de baixa prioridade"</string> <string name="other" msgid="429768510980739978">"Outros"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"remover o bloco"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"adicionar o bloco à última posição"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Mover bloco"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Adicionar o bloco à posição desejada"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Mover para <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Adicionar à posição <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Posição inválida."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"escolher o usuário"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Sem Internet"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Abrir configurações de <xliff:g id="ID_1">%s</xliff:g>."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Editar a ordem das Configurações rápidas."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menu liga/desliga"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Página <xliff:g id="ID_1">%1$d</xliff:g> de <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Tela de bloqueio"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"acessar o dispositivo"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Use a impressão digital para abrir"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autenticação obrigatória. Toque no sensor de impressão digital para autenticar."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Chamada em andamento"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Dados móveis"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Conectado"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Temporariamente conectado"</string> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index 6f49a80537c0..7fb1169af6f9 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Notificare în curs pentru o sesiune de înregistrare a ecranului"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Înregistrezi ecranul?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Înregistrează o aplicație"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Înregistrează acest ecran"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Înregistrează %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Când înregistrezi întregul ecran, se înregistrează tot ce apare pe ecran. Prin urmare, ai grijă cu parolele, detaliile de plată, mesajele, fotografiile și conținutul audio și video."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Când înregistrezi o aplicație, se înregistrează tot ce se afișează sau se redă în aplicație. Prin urmare, ai grijă cu parolele, detaliile de plată, mesajele, fotografiile și conținutul audio și video."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Înregistrează ecranul"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Nu s-a putut actualiza presetarea"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Presetare"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Selectat"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Împrejurimi"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Stânga"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Dreapta"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Extinde comenzile separate la stânga și la dreapta"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Restrânge la comanda unificată"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Dezactivează sunetul ambiental"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Activează sunetul ambiental"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Instrumente"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Subtitrări live"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Notă"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Afișează pictogramele de notificare cu prioritate redusă"</string> <string name="other" msgid="429768510980739978">"Altele"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"elimină cardul"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"adaugă cardul în ultima poziție"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Mută cardul"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Adaugă cardul în poziția dorită"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Mută pe poziția <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Adaugă pe poziția <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Poziție nevalidă."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"alege utilizatorul"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Fără conexiune la internet"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Deschide setările <xliff:g id="ID_1">%s</xliff:g>."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Editează ordinea Setărilor rapide."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Meniul de pornire"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Pagina <xliff:g id="ID_1">%1$d</xliff:g> din <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Ecran de blocare"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"Accesează dispozitivul"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Folosește amprenta ca să deschizi"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autentificare obligatorie. Atinge senzorul de amprentă pentru a te autentifica."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Apel telefonic în desfășurare"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Date mobile"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Conectat"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Conectat temporar"</string> @@ -1470,7 +1459,7 @@ <string name="shortcut_helper_keyboard_settings_buttons_label" msgid="6720967595915985259">"Setările tastaturii"</string> <string name="shortcut_helper_customize_dialog_set_shortcut_button_label" msgid="4754492225010429382">"Setează o comandă rapidă"</string> <string name="shortcut_helper_customize_dialog_remove_button_label" msgid="6546386970440176552">"Elimină"</string> - <string name="shortcut_helper_customize_dialog_reset_button_label" msgid="7645535254306312685">"Da, resetează"</string> + <string name="shortcut_helper_customize_dialog_reset_button_label" msgid="7645535254306312685">"Resetează"</string> <string name="shortcut_helper_customize_dialog_cancel_button_label" msgid="5595546460431741178">"Anulează"</string> <string name="shortcut_helper_add_shortcut_dialog_placeholder" msgid="9154297849458741995">"Apasă tasta"</string> <string name="shortcut_customizer_key_combination_in_use_error_message" msgid="7693234470526626327">"Combinația de taste este deja folosită. Încearcă altă tastă."</string> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index c534c7341992..448c2457efe1 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Текущее уведомление для записи видео с экрана"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Начать запись экрана?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Записывать одно приложение"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Записывать этот экран"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Записывать экран \"%s\""</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"На видео попадет все, что будет происходить на экране. Поэтому будьте осторожны с паролями, сведениями о способах оплаты, сообщениями, фотографиями, аудио- и видеозаписями."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"На видео попадет все, что происходит в выбранном приложении. Поэтому будьте осторожны с паролями, сведениями о способах оплаты, сообщениями, фотографиями, аудио- и видеозаписями."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Запись экрана"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Не удалось обновить набор настроек."</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Набор настроек"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Выбрано"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Окружающие звуки"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Левый"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Правый"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Разделить на левый и правый элемент управления"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Объединить в один элемент управления"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Заглушить окружающие звуки"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Не заглушать окружающие звуки"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Инструменты"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Автоматические субтитры"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Заметка"</string> @@ -864,11 +855,11 @@ <string name="keyboard_shortcut_group_system_recents" msgid="8628108256824616927">"Недавние"</string> <string name="keyboard_shortcut_group_system_back" msgid="1055709713218453863">"Назад"</string> <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"Уведомления"</string> - <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Быстрые клавиши"</string> + <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"Сочетания клавиш"</string> <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"Переключение раскладки"</string> <string name="keyboard_shortcut_join" msgid="3578314570034512676">"или"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Удалить поисковый запрос"</string> - <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Быстрые клавиши"</string> + <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Сочетания клавиш"</string> <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Поиск сочетаний клавиш"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Нет сочетаний клавиш."</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Система"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Показывать значки уведомлений с низким приоритетом"</string> <string name="other" msgid="429768510980739978">"Другое"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"удалить панель"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"добавить параметр в конец"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Переместить панель"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Выбрать, куда добавить параметр"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Переместить на позицию <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Добавить на позицию <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Недопустимое расположение."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"выбрать пользователя"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Нет подключения к Интернету."</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Открыть настройки <xliff:g id="ID_1">%s</xliff:g>."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Изменить порядок быстрых настроек."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Меню кнопки питания"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Страница <xliff:g id="ID_1">%1$d</xliff:g> из <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Заблокированный экран"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"указать устройство"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Используйте отпечаток пальца для входа."</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Требуется аутентификация. Приложите палец к сканеру отпечатков."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Текущий вызов"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобильный интернет"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Подключено"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Временное подключение"</string> @@ -1422,7 +1411,7 @@ <string name="connected_display_icon_desc" msgid="6373560639989971997">"Экран подключен"</string> <string name="privacy_dialog_title" msgid="7839968133469098311">"Микрофон и камера"</string> <string name="privacy_dialog_summary" msgid="2458769652125995409">"Недавнее использование приложениями"</string> - <string name="privacy_dialog_more_button" msgid="7610604080293562345">"Посмотреть недавний доступ"</string> + <string name="privacy_dialog_more_button" msgid="7610604080293562345">"История доступа"</string> <string name="privacy_dialog_done_button" msgid="4504330708531434263">"Готово"</string> <string name="privacy_dialog_expand_action" msgid="9129262348628331377">"Развернуть и показать параметры"</string> <string name="privacy_dialog_collapse_action" msgid="277419962019466347">"Свернуть"</string> @@ -1444,17 +1433,17 @@ <string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"Многозадачность"</string> <string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"Разделение экрана"</string> <string name="shortcut_helper_category_input" msgid="8674018654124839566">"Ввод"</string> - <string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Быстрые клавиши для приложений"</string> + <string name="shortcut_helper_category_app_shortcuts" msgid="8010249408308587117">"Приложения"</string> <string name="shortcut_helper_category_current_app_shortcuts" msgid="4017840565974573628">"Это приложение"</string> <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Специальные возможности"</string> - <string name="shortcut_helper_title" msgid="8567500639300970049">"Быстрые клавиши"</string> - <string name="shortcut_helper_customize_mode_title" msgid="1467657117101096033">"Как настроить быстрые клавиши"</string> + <string name="shortcut_helper_title" msgid="8567500639300970049">"Сочетания клавиш"</string> + <string name="shortcut_helper_customize_mode_title" msgid="1467657117101096033">"Настройки сочетаний клавиш"</string> <string name="shortcut_customize_mode_remove_shortcut_dialog_title" msgid="7106420484940737208">"Удалить сочетание клавиш?"</string> <string name="shortcut_customize_mode_reset_shortcut_dialog_title" msgid="8131184731313717780">"Сбросить настройки?"</string> <string name="shortcut_customize_mode_add_shortcut_description" msgid="6866025005347407696">"Нажмите клавишу, чтобы назначить сочетание клавиш."</string> <string name="shortcut_customize_mode_remove_shortcut_description" msgid="6851287900585057128">"Настроенное сочетание будет безвозвратно удалено."</string> - <string name="shortcut_customize_mode_reset_shortcut_description" msgid="2081849715634358684">"Все пользовательские ярлыки будут безвозвратно удалены."</string> - <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Найти быстрые клавиши"</string> + <string name="shortcut_customize_mode_reset_shortcut_description" msgid="2081849715634358684">"Все настроенные сочетания клавиш будут безвозвратно удалены."</string> + <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Найти"</string> <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Ничего не найдено"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Значок \"Свернуть\""</string> <string name="shortcut_helper_content_description_meta_key" msgid="3989315044342124818">"Значок клавиши Meta для выполнения действия"</string> diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml index 78331a0236fd..d5c90b566ad6 100644 --- a/packages/SystemUI/res/values-si/strings.xml +++ b/packages/SystemUI/res/values-si/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"තිර පටිගත කිරීමේ සැසියක් සඳහා කෙරෙන දැනුම් දීම"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"ඔබේ තිරය පටිගත කරන්න ද?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"එක් යෙදුමක් පටිගත කරන්න"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"මෙම තිරය පටිගත කරන්න"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"%s පටිගත කරන්න"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"ඔබ ඔබේ සම්පූර්ණ තිරය පටිගත කරන විට, ඔබේ තිරයේ පෙන්වන ඕනෑම දෙයක් වාර්තා වේ. ඒ නිසා මුරපද, ගෙවීම් විස්තර, පණිවුඩ, ඡායාරූප, සහ ශ්රව්ය සහ දෘශ්ය වැනි දේවල් පිළිබඳ ප්රවේශම් වන්න."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"ඔබ යෙදුමක් පටිගත කරන විට, එම යෙදුමේ පෙන්වන හෝ වාදනය කරන ඕනෑම දෙයක් වාර්තා වේ. ඒ නිසා මුරපද, ගෙවීම් විස්තර, පණිවුඩ, ඡායාරූප, සහ ශ්රව්ය සහ දෘශ්ය වැනි දේවල් පිළිබඳ ප්රවේශම් වන්න."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"තිරය පටිගත කරන්න"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"පෙර සැකසීම යාවත්කාලීන කළ නොහැකි විය"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"පෙරසැකසුම"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"තෝරන ලදි"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"වටපිටාව"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"වම"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"දකුණ"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"වමට සහ දකුණට වෙන් වූ පාලන වෙත පුළුල් කරන්න"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"ඒකාබද්ධ පාලනයට හකුළන්න"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"අවට පරිසරය නිහඬ කරන්න"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"අවට නිහඬ නොකරන්න"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"මෙවලම්"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"සජීවී සිරස්තල"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"සටහන"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"අඩු ප්රමුඛතා දැනුම්දීම් අයිකන පෙන්වන්න"</string> <string name="other" msgid="429768510980739978">"වෙනත්"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"ටයිල් ඉවත් කරන්න"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"ටයිල් එක අවසාන ස්ථානයට එක් කරන්න"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"ටයිල් ගෙන යන්න"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"අපේක්ෂිත ස්ථානයට ටයිල් එක එක් කරන්න"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> වෙත ගෙන යන්න"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> ස්ථානයට එක් කරන්න"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"ස්ථානය අවලංගුයි."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"පරිශීලක තෝරන්න"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"අන්තර්ජාලය නැත"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"<xliff:g id="ID_1">%s</xliff:g> සැකසීම් විවෘත කරන්න."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"ඉක්මන් සැකසීම්වල අනුපිළිවෙල සංස්කරණය කරන්න."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"බල මෙනුව"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g> න් <xliff:g id="ID_1">%1$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"අගුලු තිරය"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"උපාංගය ඇතුළු කරන්න"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"විවෘත කිරීමට ඇඟිලි සලකුණ භාවිත කරන්න"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"සත්යාපනය අවශ්යයි. සත්යාපනය කිරීමට ඇඟිලි සලකුණු සංවේදකය ස්පර්ශ කරන්න."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ක්රියාත්මක වන දුරකථන ඇමතුම"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"ජංගම දත්ත"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"සම්බන්ධයි"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"තාවකාලිකව සම්බන්ධ කළා"</string> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index cf8972e72002..af84fd19bb0c 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Zobrazuje sa upozornenie týkajúce sa relácie záznamu obrazovky"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Chcete nahrávať obrazovku?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Nahrávať jednu aplikáciu"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Nahrať túto obrazovku"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Nahrať obrazovku %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Pri nahrávaní celej obrazovky sa zaznamená všetko, čo sa na nej zobrazuje. Preto venujte pozornosť položkám, ako sú heslá, platobné údaje, správy, fotky a zvuk či video."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Pri nahrávaní aplikácie sa zaznamená všetko, čo sa v nej zobrazuje alebo prehráva. Preto venujte pozornosť položkám, ako sú heslá, platobné údaje, správy, fotky a zvuk či video."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Nahrávať obrazovku"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Predvoľbu sa nepodarilo aktualizovať"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Predvoľba"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Vybrané"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Okolie"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Vľavo"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Vpravo"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Rozbaliť na samostatné ovládanie ľavej a pravej strany"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Zbaliť na jednotné ovládanie"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Vypnúť zvuk okolia"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Zapnúť zvuk okolia"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Nástroje"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Živý prepis"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Poznámka"</string> @@ -886,8 +877,8 @@ <string name="group_system_go_back" msgid="2730322046244918816">"Prechod späť"</string> <string name="group_system_access_home_screen" msgid="4130366993484706483">"Prechod na plochu"</string> <string name="group_system_overview_open_apps" msgid="5659958952937994104">"Zobrazenie nedávnych aplikácií"</string> - <string name="group_system_cycle_forward" msgid="5478663965957647805">"Cyklické prechádzanie dopredu po nedávnych aplikáciách"</string> - <string name="group_system_cycle_back" msgid="8194102916946802902">"Cyklické prechádzanie dozadu po nedávnych aplikáciách"</string> + <string name="group_system_cycle_forward" msgid="5478663965957647805">"Cyklické prechádzanie dopredu nedávnymi aplikáciámi"</string> + <string name="group_system_cycle_back" msgid="8194102916946802902">"Cyklické prechádzanie dozadu nedávnymi aplikáciami"</string> <string name="group_system_access_all_apps_search" msgid="1553588630154197469">"Otvorenie zoznamu aplikácií"</string> <string name="group_system_access_system_settings" msgid="8731721963449070017">"Otvorenie nastavení"</string> <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Otvoriť asistenta"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Zobraziť ikony upozornení s nízkou prioritou"</string> <string name="other" msgid="429768510980739978">"Ďalšie"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"odstrániť kartu"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"pridáte kartu na poslednú pozíciu"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Presunúť kartu"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Pridať kartu na požadovanú pozíciu"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Presunúť na <xliff:g id="POSITION">%1$d</xliff:g>. pozíciu"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Pridať na <xliff:g id="POSITION">%1$d</xliff:g>. pozíciu"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Pozícia je neplatná."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"vybrať používateľa"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Žiadny internet"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Otvoriť nastavenia <xliff:g id="ID_1">%s</xliff:g>"</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Upraviť poradie rýchlych nastavení"</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Ponuka vypínača"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Strana <xliff:g id="ID_1">%1$d</xliff:g> z <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Uzamknutá obrazovka"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"vstúpte do zariadenia"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Otvorte odtlačkom prsta"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Vyžaduje sa overenie. Dotknite sa senzora odtlačkov prstov."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Prebiehajúci telefonický hovor"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobilné dáta"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Pripojené"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Dočasne pripojené"</string> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index d0063fdf98d6..1242774768b3 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Nenehno obveščanje o seji snemanja zaslona"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Želite posneti zaslon?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Snemanje ene aplikacije"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Snemanje tega zaslona"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Snemanje zaslona %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Pri snemanju celotnega zaslona se posname vse, kar je prikazano na zaslonu. Zato bodite previdni z gesli, podatki za plačilo, sporočili, fotografijami ter z zvokom in videom."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Pri snemanju aplikacije se posname vse, kar je prikazano ali predvajano v tej aplikaciji. Zato bodite previdni z gesli, podatki za plačilo, sporočili, fotografijami ter z zvokom in videom."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Snemanje zaslona"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Prednastavljenih vrednosti ni bilo mogoče posodobiti"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Prednastavljeno"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Izbrano"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Okolica"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Levo"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Desno"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Razširitev na ločene kontrolnike za levo in desno stran"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Strnitev v enotni kontrolnik"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Izklop okoliškega zvoka"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Vklop okoliškega zvoka"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Orodja"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Samodejni podnapisi"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Opomba"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Pokaži ikone obvestil z nizko stopnjo prednosti"</string> <string name="other" msgid="429768510980739978">"Drugo"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"odstranitev ploščice"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"dodajanje ploščice na zadnji položaj"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Premik ploščice"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Dodaj ploščico na želeno mesto"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Premik na položaj <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Dodajanje na položaj <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Položaj je neveljaven."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"izbiro uporabnika"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Brez internetne povezave"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Odpri nastavitve za <xliff:g id="ID_1">%s</xliff:g>."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Urejanje vrstnega reda hitrih nastavitev."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Meni za vklop/izklop"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_1">%1$d</xliff:g>. stran od <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Zaklenjen zaslon"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"vstop v napravo"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Odprite s prstnim odtisom"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Zahtevano je preverjanje pristnosti. Za preverjanje pristnosti se dotaknite tipala prstnih odtisov."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Poteka klic"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Prenos podatkov v mobilnem omrežju"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Povezano"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Začasno vzpostavljena povezava"</string> @@ -1468,9 +1457,9 @@ <string name="shortcut_helper_key_combinations_forward_slash" msgid="1238652537199346970">"poševnica naprej"</string> <string name="shortcut_helper_content_description_drag_handle" msgid="5092426406009848110">"Ročica za vlečenje"</string> <string name="shortcut_helper_keyboard_settings_buttons_label" msgid="6720967595915985259">"Nastavitve tipkovnice"</string> - <string name="shortcut_helper_customize_dialog_set_shortcut_button_label" msgid="4754492225010429382">"Nastavite bližnjico"</string> + <string name="shortcut_helper_customize_dialog_set_shortcut_button_label" msgid="4754492225010429382">"Nast. bliž."</string> <string name="shortcut_helper_customize_dialog_remove_button_label" msgid="6546386970440176552">"Odstrani"</string> - <string name="shortcut_helper_customize_dialog_reset_button_label" msgid="7645535254306312685">"Da, ponastavi"</string> + <string name="shortcut_helper_customize_dialog_reset_button_label" msgid="7645535254306312685">"Da"</string> <string name="shortcut_helper_customize_dialog_cancel_button_label" msgid="5595546460431741178">"Prekliči"</string> <string name="shortcut_helper_add_shortcut_dialog_placeholder" msgid="9154297849458741995">"Pritisnite tipko"</string> <string name="shortcut_customizer_key_combination_in_use_error_message" msgid="7693234470526626327">"Kombinacija tipk je že v uporabi. Poskusite z drugo tipko."</string> diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml index 803a5e558621..c3d13539e1f9 100644 --- a/packages/SystemUI/res/values-sq/strings.xml +++ b/packages/SystemUI/res/values-sq/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Njoftim i vazhdueshëm për një seancë regjistrimi të ekranit"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Të regjistrohet ekrani?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Regjistro një aplikacion"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Regjistro këtë ekran"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Regjistro %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Kur regjistron të gjithë ekranin, regjistrohet çdo gjë e shfaqur në ekranin tënd. Prandaj, ki kujdes me gjërat si fjalëkalimet, detajet e pagesave, mesazhet, fotografitë, si dhe audion dhe videon."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Kur regjistron një aplikacion, regjistrohet çdo gjë që shfaqet ose luhet në atë aplikacion. Prandaj, ki kujdes me gjërat si fjalëkalimet, detajet e pagesave, mesazhet, fotografitë, si dhe audion dhe videon."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Regjistro ekranin"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Paravendosja nuk mund të përditësohej"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Paravendosja"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Zgjedhur"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Ambienti rrethues"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Majtas"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Djathtas"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Zgjero te kontrollet e veçuara majtas dhe djathtas"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Palos te kontrolli i unifikuar"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Vendos në heshtje ambientin rrethues"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Anulo vendosjen në heshtje të ambientit rrethues"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Veglat"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Titrat në çast"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Shënim"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Shfaq ikonat e njoftimeve me përparësi të ulët"</string> <string name="other" msgid="429768510980739978">"Të tjera"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"hiq pllakëzën"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"shtuar pllakëzën në pozicionin e fundit"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Zhvendos pllakëzën"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Shto pllakëzën në pozicionin e dëshiruar"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Zhvendos te <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Shto te pozicioni <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Pozicion i pavlefshëm."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"zgjidh përdoruesin"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Nuk ka internet"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Hap cilësimet e <xliff:g id="ID_1">%s</xliff:g>."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Modifiko renditjen e \"Cilësimeve të shpejta\"."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menyja e energjisë"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Faqja <xliff:g id="ID_1">%1$d</xliff:g> nga <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Ekrani i kyçjes"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"për të hyrë në pajisje"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Përdor gjurmën e gishtit për ta hapur"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Kërkohet vërtetimi. Prek sensorin e gjurmës së gishtit për t\'u vërtetuar."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Telefonatë në vazhdim"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Të dhënat celulare"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Lidhur"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Lidhur përkohësisht"</string> @@ -1470,7 +1459,7 @@ <string name="shortcut_helper_keyboard_settings_buttons_label" msgid="6720967595915985259">"Cilësimet e tastierës"</string> <string name="shortcut_helper_customize_dialog_set_shortcut_button_label" msgid="4754492225010429382">"Cakto shkurtoren"</string> <string name="shortcut_helper_customize_dialog_remove_button_label" msgid="6546386970440176552">"Hiq"</string> - <string name="shortcut_helper_customize_dialog_reset_button_label" msgid="7645535254306312685">"Po, rivendosi"</string> + <string name="shortcut_helper_customize_dialog_reset_button_label" msgid="7645535254306312685">"Po"</string> <string name="shortcut_helper_customize_dialog_cancel_button_label" msgid="5595546460431741178">"Anulo"</string> <string name="shortcut_helper_add_shortcut_dialog_placeholder" msgid="9154297849458741995">"Shtyp tastin"</string> <string name="shortcut_customizer_key_combination_in_use_error_message" msgid="7693234470526626327">"Kombinimi i tasteve është tashmë në përdorim. Provo një tast tjetër."</string> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index 17870727a7e7..344b012c2c80 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Обавештење о сесији снимања екрана је активно"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Желите да снимите екран?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Сними једну апликацију"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Сними овај екран"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Сними %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Када снимате цео екран, снима се све што је на њему. Зато пазите на лозинке, информације о плаћању, поруке, слике, аудио и видео садржај."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Када снимате апликацију, снима се сав садржај који се приказује или пушта у њој. Зато пазите на лозинке, информације о плаћању, поруке, слике, аудио и видео садржај."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Сними екран"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Ажурирање задатих подешавања није успело"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Унапред одређена подешавања"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Изабрано"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Окружење"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Лево"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Десно"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Прошири на контроле раздвојене на леву и десну страну"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Скупи у јединствену контролу"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Искључи звук окружења"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Укључи звук окружења"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Алатке"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Титл уживо"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Белешка"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Прикажи иконе обавештења ниског приоритета"</string> <string name="other" msgid="429768510980739978">"Друго"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"уклонили плочицу"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"додали плочицу на последњу позицију"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Преместите плочицу"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Додајте плочицу на жељену позицију"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Преместите на <xliff:g id="POSITION">%1$d</xliff:g>. позицију"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Додајте на <xliff:g id="POSITION">%1$d</xliff:g>. позицију"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Позиција је неважећа."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"одабрали корисника"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Нема интернета"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Отвори подешавања за <xliff:g id="ID_1">%s</xliff:g>."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Измените редослед Брзих подешавања."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Мени дугмета за укључивање"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_1">%1$d</xliff:g>. страна од <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Закључан екран"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"унесите уређај"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Отворите помоћу отиска прста"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Потребна је потврда идентитета. Додирните сензор за отисак прста да бисте потврдили идентитет."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Актуелни телефонски позив"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобилни подаци"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Повезано"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Привремено повезано"</string> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index 6d9f721fad37..4d862d9842a8 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Avisering om att skärminspelning pågår"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Vill du spela in det som visas på skärmen?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Spela in en app"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Spela in den här skärmen"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Spela in %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"När du spelar in hela skärmen spelas allt som visas på skärmen in. Var försiktig med sådant som lösenord, betalningsuppgifter, meddelanden, foton, ljud och video."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"När du spelar in en app spelas allt som visas eller spelas upp i appen in. Var försiktig med sådant som lösenord, betalningsuppgifter, meddelanden, foton, ljud och video."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Spela in skärmen"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Det gick inte att uppdatera förinställningen"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Förinställning"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Markerad"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Omgivningsläge"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Vänster"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Höger"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Utöka till kontroller till vänster och höger"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Komprimera till enhetlig kontroll"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Stäng av omgivningsljudet"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Slå på omgivningsljudet"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Verktyg"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Live Caption"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Anteckning"</string> @@ -1298,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"ange enhet"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Öppna med fingeravtryck"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Autentisering krävs. Identifiera dig genom att trycka på fingeravtryckssensorn."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Pågående samtal"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobildata"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Ansluten"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Tillfälligt ansluten"</string> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index 6fb8f081e896..731765437ced 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Arifa inayoendelea ya kipindi cha kurekodi skrini"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Ungependa kurekodi skrini yako?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Rekodi programu moja"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Rekodi skrini hii"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Rekodi %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Unaporekodi skrini yako nzima, chochote kinachoonyeshwa kwenye skrini yako kitarekodiwa. Kwa hivyo kuwa mwangalifu na vitu kama vile manenosiri, maelezo ya malipo, ujumbe, picha, sauti na video."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Unaporekodi programu, chochote kinachoonyeshwa au kuchezwa kwenye programu hiyo kitarekodiwa. Kwa hivyo kuwa mwangalifu na vitu kama vile manenosiri, maelezo ya malipo, ujumbe, picha, sauti na video."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Rekodi skrini"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Imeshindwa kusasisha mipangilio iliyowekwa mapema"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Mipangilio iliyowekwa mapema"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Umechagua"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Mazingira"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Kushoto"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Kulia"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Panua iwe vidhibiti vilivyotenganishwa kushoto na kulia"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Kunja iwe kidhibiti cha pamoja"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Zima sauti ya mazingira"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Rejesha sauti ya mazingira"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Zana"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Manukuu Papo Hapo"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Dokezo"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Onyesha aikoni za arifa zisizo muhimu"</string> <string name="other" msgid="429768510980739978">"Nyingine"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"ondoa kigae"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"weka kigae kwenye nafasi ya mwisho"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Hamisha kigae"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Weka kigae kwenye nafasi unayopenda"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Hamishia kwenye <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Ongeza kwenye nafasi ya <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Nafasi si sahihi."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"chagua mtumiaji"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Hakuna intaneti"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Fungua mipangilio ya <xliff:g id="ID_1">%s</xliff:g>."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Badilisha mpangilio wa Mipangilio ya Haraka."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Menyu ya kuzima/kuwasha"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Ukurasa wa <xliff:g id="ID_1">%1$d</xliff:g> kati ya <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Skrini iliyofungwa"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"weka kifaa"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Tumia alama ya kidole kufungua"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Uthibitishaji unahitajika. Gusa kitambua alama ya kidole ili uthibitishe."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Simu inayoendelea"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Data ya mtandao wa simu"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Imeunganishwa"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Imeunganishwa kwa muda"</string> @@ -1468,9 +1457,9 @@ <string name="shortcut_helper_key_combinations_forward_slash" msgid="1238652537199346970">"mkwaju wa mbele"</string> <string name="shortcut_helper_content_description_drag_handle" msgid="5092426406009848110">"Aikoni ya buruta"</string> <string name="shortcut_helper_keyboard_settings_buttons_label" msgid="6720967595915985259">"Mipangilio ya Kibodi"</string> - <string name="shortcut_helper_customize_dialog_set_shortcut_button_label" msgid="4754492225010429382">"Weka njia ya mkato"</string> + <string name="shortcut_helper_customize_dialog_set_shortcut_button_label" msgid="4754492225010429382">"Weka mkato"</string> <string name="shortcut_helper_customize_dialog_remove_button_label" msgid="6546386970440176552">"Ondoa"</string> - <string name="shortcut_helper_customize_dialog_reset_button_label" msgid="7645535254306312685">"Ndiyo, rejesha"</string> + <string name="shortcut_helper_customize_dialog_reset_button_label" msgid="7645535254306312685">"Ndiyo"</string> <string name="shortcut_helper_customize_dialog_cancel_button_label" msgid="5595546460431741178">"Acha"</string> <string name="shortcut_helper_add_shortcut_dialog_placeholder" msgid="9154297849458741995">"Bonyeza kitufe"</string> <string name="shortcut_customizer_key_combination_in_use_error_message" msgid="7693234470526626327">"Tayari unatumia mchanganyiko wa vitufe. Jaribu kitufe kingine."</string> diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml index ead1f8330401..5a7defae136f 100644 --- a/packages/SystemUI/res/values-ta/strings.xml +++ b/packages/SystemUI/res/values-ta/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"திரை ரெக்கார்டிங் அமர்விற்கான தொடர் அறிவிப்பு"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"உங்கள் திரையை ரெக்கார்டு செய்யவா?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"ஓர் ஆப்ஸை ரெக்கார்டு செய்தல்"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"இந்தத் திரையை ரெக்கார்டு செய்"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"ரெக்கார்டு %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"முழுத் திரையை நீங்கள் ரெக்கார்டு செய்யும்போது அதில் காட்டப்படும் அனைத்தும் ரெக்கார்டு செய்யப்படும். எனவே கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், மெசேஜ்கள், படங்கள், ஆடியோ, வீடியோ போன்றவை குறித்துக் கவனத்துடன் இருங்கள்."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"ஓர் ஆப்ஸை ரெக்கார்டு செய்யும்போது அதில் காட்டப்படும் அல்லது பிளே செய்யப்படும் அனைத்தும் ரெக்கார்டு செய்யப்படும். எனவே கடவுச்சொற்கள், பேமெண்ட் விவரங்கள், மெசேஜ்கள், படங்கள், ஆடியோ, வீடியோ போன்றவை குறித்துக் கவனத்துடன் இருங்கள்."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"திரையை ரெக்கார்டு செய்"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"முன்னமைவைப் புதுப்பிக்க முடியவில்லை"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"முன்னமைவு"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"தேர்ந்தெடுக்கப்பட்டது"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"சுற்றுப்புறங்கள்"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"இடது"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"வலது"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"இடது மற்றும் வலதுபுறம் உள்ள கட்டுப்பாடுகளை விரிவாக்கும்"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"ஒருங்கிணைந்த கட்டுப்பாட்டுக்குச் சுருக்கும்"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"சுற்றுப்புறங்களின் ஒலியை அடக்கும்"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"சுற்றுப்புறங்களின் ஒலியை இயக்கும்"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"கருவிகள்"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"உடனடி வசனம்"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"குறிப்பு"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"குறைந்த முன்னுரிமை உள்ள அறிவிப்பு ஐகான்களைக் காட்டு"</string> <string name="other" msgid="429768510980739978">"மற்றவை"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"கட்டத்தை அகற்றும்"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"கடைசி இடத்தில் கட்டத்தைச் சேர்க்கலாம்"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"கட்டத்தை நகர்த்து"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"விரும்பிய இடத்தில் கட்டத்தைச் சேர்க்கலாம்"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g>க்கு நகர்த்தும்"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g>ல் சேர்க்கும்"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"நிலை தவறானது."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"பயனரைத் தேர்வுசெய்யவும்"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"இணைய இணைப்பு இல்லை"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"<xliff:g id="ID_1">%s</xliff:g> அமைப்புகளைத் திற."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"விரைவு அமைப்புகளின் வரிசையை மாற்றலாம்."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"பவர் மெனு"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"பக்கம் <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"லாக் ஸ்கிரீன்"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"சாதனத்தைத் திற"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"கைரேகையைப் பயன்படுத்தி திறந்திடுங்கள்"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"அங்கீகாரம் தேவை. கைரேகை சென்சாரைத் தொட்டு அங்கீகரியுங்கள்."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"செயலில் உள்ள மொபைல் அழைப்பு"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"மொபைல் டேட்டா"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"இணைக்கப்பட்டது"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"தற்காலிகமாக இணைக்கப்பட்டுள்ளது"</string> diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index 73a4250dd143..1be6ce61a399 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"స్క్రీన్ రికార్డ్ సెషన్ కోసం ఆన్గోయింగ్ నోటిఫికేషన్"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"మీ స్క్రీన్ను రికార్డ్ చేయాలా?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"ఒక యాప్ను రికార్డ్ చేయండి"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"ఈ స్క్రీన్ను రికార్డ్ చేయండి"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"%s రికార్డ్ చేయండి"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"మీ ఫుల్ స్క్రీన్ను మీరు రికార్డ్ చేసేటప్పుడు, మీ స్క్రీన్పై కనిపించేవన్నీ రికార్డ్ అవుతాయి. కాబట్టి పాస్వర్డ్లు, పేమెంట్ వివరాలు, మెసేజ్లు, ఫోటోలు, ఆడియో, ఇంకా వీడియో వంటి విషయాల్లో జాగ్రత్త వహించండి."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"మీరు యాప్ను రికార్డ్ చేసేటప్పుడు, సంబంధిత యాప్లో కనిపించేవన్నీ లేదా ప్లే అయ్యేవన్నీ రికార్డ్ అవుతాయి. కాబట్టి పాస్వర్డ్లు, పేమెంట్ వివరాలు, మెసేజ్లు, ఫోటోలు, ఆడియో, ఇంకా వీడియో వంటి విషయాల్లో జాగ్రత్త వహించండి."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"స్క్రీన్ను రికార్డ్ చేయండి"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"ప్రీసెట్ను అప్డేట్ చేయడం సాధ్యపడలేదు"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"ప్రీసెట్"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"ఎంచుకోబడింది"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"పరిసరాలు"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"ఎడమ వైపునకు"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"కుడి వైపునకు"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"ఎడమ, కుడి అని వేరు చేయబడిన కంట్రోల్స్కు విస్తరించండి"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"యూనిఫైడ్ కంట్రోల్కు కుదించండి"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"పరిసరాలను మ్యూట్ చేయండి"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"పరిసరాలను అన్మ్యూట్ చేయండి"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"టూల్స్"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"లైవ్ క్యాప్షన్"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"గమనిక"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"తక్కువ ప్రాధాన్యత నోటిఫికేషన్ చిహ్నాలను చూపించు"</string> <string name="other" msgid="429768510980739978">"ఇతరం"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"టైల్ను తీసివేయండి"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"చివరి పొజిషన్కు టైల్ను జోడించండి"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"టైల్ను తరలించండి"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"కావలసిన పొజిషన్కు టైల్ను జోడించండి"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g>కు తరలించండి"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> స్థానానికి జోడించండి"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"ప్రస్తుత పొజిషన్ చెల్లదు."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"యూజర్ను ఎంపిక చేయండి"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"ఇంటర్నెట్ లేదు"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"<xliff:g id="ID_1">%s</xliff:g> సెట్టింగ్లను తెరవండి."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"క్విక్ సెట్టింగ్ల క్రమాన్ని ఎడిట్ చేయండి."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"పవర్ మెనూ"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_2">%2$d</xliff:g>లో <xliff:g id="ID_1">%1$d</xliff:g>వ పేజీ"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"లాక్ స్క్రీన్"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"పరికరాన్ని ఎంటర్ చేయండి"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"తెరవడానికి వేలిముద్రను ఉపయోగించండి"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ప్రామాణీకరణ అవసరం. ప్రామాణీకరించడానికి వేలిముద్ర సెన్సార్ను తాకండి."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"ఫోన్ కాల్ జరుగుతోంది"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"మొబైల్ డేటా"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"కనెక్ట్ చేయబడింది"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"తాత్కాలికంగా కనెక్ట్ చేయబడింది"</string> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index c46a9d7c981c..3770addf98e3 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"การแจ้งเตือนต่อเนื่องสำหรับเซสชันการบันทึกหน้าจอ"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"บันทึกหน้าจอไหม"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"บันทึกแอปเดียว"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"บันทึกหน้าจอนี้"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"บันทึก %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"ขณะบันทึกทั้งหน้าจอ ระบบจะบันทึกทุกสิ่งที่แสดงอยู่บนหน้าจอ ดังนั้นโปรดระวังสิ่งต่างๆ อย่างเช่นรหัสผ่าน รายละเอียดการชำระเงิน ข้อความ รูปภาพ รวมถึงเสียงและวิดีโอ"</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"ขณะบันทึกแอป ระบบจะบันทึกทุกสิ่งที่แสดงหรือเล่นอยู่ในแอปดังกล่าว ดังนั้นโปรดระวังสิ่งต่างๆ อย่างเช่นรหัสผ่าน รายละเอียดการชำระเงิน ข้อความ รูปภาพ รวมถึงเสียงและวิดีโอ"</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"บันทึกหน้าจอ"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"ไม่สามารถอัปเดตค่าที่กำหนดล่วงหน้า"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"ค่าที่กำหนดล่วงหน้า"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"เลือกแล้ว"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"เสียงแวดล้อม"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"ซ้าย"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"ขวา"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"ขยายเป็นการควบคุมที่แยกด้านซ้ายและขวา"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"ยุบเป็นการควบคุมแบบรวม"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"ปิดเสียงแวดล้อม"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"เปิดเสียงแวดล้อม"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"เครื่องมือ"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"คำบรรยายสด"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"จดบันทึก"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"แสดงไอคอนการแจ้งเตือนลำดับความสำคัญต่ำ"</string> <string name="other" msgid="429768510980739978">"อื่นๆ"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"นำชิ้นส่วนออก"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"เพิ่มการ์ดไปยังตำแหน่งสุดท้าย"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"ย้ายชิ้นส่วน"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"เพิ่มการ์ดไปยังตำแหน่งที่ต้องการ"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"ย้ายไปที่ <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"เพิ่มไปยังตำแหน่ง <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"ตำแหน่งไม่ถูกต้อง"</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"เลือกผู้ใช้"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"ไม่มีอินเทอร์เน็ต"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"เปิดการตั้งค่า <xliff:g id="ID_1">%s</xliff:g>"</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"แก้ไขลำดับของการตั้งค่าด่วน"</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"เมนูเปิด/ปิด"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"หน้า <xliff:g id="ID_1">%1$d</xliff:g> จาก <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"หน้าจอล็อก"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"เข้าถึงอุปกรณ์"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"ใช้ลายนิ้วมือเพื่อเปิด"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"ต้องมีการตรวจสอบสิทธิ์ แตะเซ็นเซอร์ลายนิ้วมือเพื่อตรวจสอบสิทธิ์"</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"กำลังโทรอยู่"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"อินเทอร์เน็ตมือถือ"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"เชื่อมต่อแล้ว"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"เชื่อมต่อแล้วชั่วคราว"</string> @@ -1453,7 +1442,7 @@ <string name="shortcut_customize_mode_reset_shortcut_dialog_title" msgid="8131184731313717780">"รีเซ็ตกลับเป็นค่าเริ่มต้นไหม"</string> <string name="shortcut_customize_mode_add_shortcut_description" msgid="6866025005347407696">"กดแป้นเพื่อกำหนดแป้นพิมพ์ลัด"</string> <string name="shortcut_customize_mode_remove_shortcut_description" msgid="6851287900585057128">"การดำเนินการนี้จะลบแป้นพิมพ์ลัดที่กำหนดเองอย่างถาวร"</string> - <string name="shortcut_customize_mode_reset_shortcut_description" msgid="2081849715634358684">"การดำเนินการนี้จะลบทางลัดที่กำหนดเองทั้งหมดอย่างถาวร"</string> + <string name="shortcut_customize_mode_reset_shortcut_description" msgid="2081849715634358684">"การดำเนินการนี้จะลบแป้นพิมพ์ลัดที่กำหนดเองทั้งหมดอย่างถาวร"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"ค้นหาแป้นพิมพ์ลัด"</string> <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"ไม่พบผลการค้นหา"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"ไอคอนยุบ"</string> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index 6953458e2382..d28915eccb73 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Kasalukuyang notification para sa session ng pag-record ng screen"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"I-record ang iyong screen?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Mag-record ng isang app"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"I-record ang screen na ito"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"I-record ang %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Kapag nire-record mo ang iyong buong screen, nire-record ang anumang ipinapakita sa screen mo. Kaya mag-ingat sa mga bagay-bagay tulad ng mga password, detalye ng pagbabayad, mensahe, larawan, at audio at video."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Kapag nagre-record ka ng app, nire-record ang anumang ipinapakita o pine-play sa app na iyon. Kaya mag-ingat sa mga bagay-bagay tulad ng mga password, detalye ng pagbabayad, mensahe, larawan, at audio at video."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"I-record ang screen"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Hindi ma-update ang preset"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Preset"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Napili"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Paligid"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Kaliwa"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Kanan"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"I-expand sa kaliwa at kanang magkahiwalay na mga kontrol"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"I-collapse sa pinag-isang kontrol"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"I-mute ang paligid"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"I-unmute ang paligid"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Mga Tool"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Instant Caption"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Tala"</string> @@ -1298,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"ilagay ang device"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Gamitin ang fingerprint para buksan"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Kailangan ng pag-authenticate. Pindutin ang sensor para sa fingerprint para mag-authenticate."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Kasalukuyang may tawag sa telepono"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobile data"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Nakakonekta"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Pansamantalang nakakonekta"</string> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index 441cec1d18dd..29a5763385bd 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ekran kaydı oturumu için devam eden bildirim"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Ekranınız kaydedilsin mi?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Bir uygulamayı kaydet"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Bu ekranı kaydet"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"%s ekranını kaydet"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Ekranın tamamını kaydederken ekranınızda gösterilen her şey kaydedilir. Bu nedenle şifre, ödeme ayrıntıları, mesaj, fotoğraf, ses ve video gibi öğeler konusunda dikkatli olun."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Bir uygulamayı kaydettiğinizde o uygulamada gösterilen veya oynatılan her şey kaydedilir. Bu nedenle şifre, ödeme ayrıntıları, mesaj, fotoğraf, ses ve video gibi öğeler konusunda dikkatli olun."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Ekranı kaydet"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Hazır ayar güncellenemedi"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Hazır Ayar"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Seçili"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Çevredeki sesler"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Sol"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Sağ"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Sol ve sağ kontrolleri ayırarak genişlet"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Kontrolleri birleştirerek daralt"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Çevredeki sesleri kapat"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Çevredeki sesleri aç"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Araçlar"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Canlı Altyazı"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Not"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Düşük öncelikli bildirim simgelerini göster"</string> <string name="other" msgid="429768510980739978">"Diğer"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"Kutuyu kaldırmak için"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"kutuyu son konuma ekleyin"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Kutuyu taşı"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"kutuyu istediğiniz konuma ekleyin"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> konumuna taşı"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"<xliff:g id="POSITION">%1$d</xliff:g> konumuna ekle"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Konum geçersiz."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"kullanıcı seç"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"İnternet yok"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"<xliff:g id="ID_1">%s</xliff:g> ayarlarını aç."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Hızlı Ayarlar\'ın sırasını düzenleyin."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Güç menüsü"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Sayfa <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Kilit ekranı"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"cihaz girin"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Açmak için parmak izi kullanın"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Kimlik doğrulaması gerekiyor. Kimlik doğrulaması için parmak izi sensörüne dokunun."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Devam eden telefon görüşmesi"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobil veri"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Bağlı"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Geçici olarak bağlandı"</string> @@ -1468,9 +1457,9 @@ <string name="shortcut_helper_key_combinations_forward_slash" msgid="1238652537199346970">"eğik çizgi"</string> <string name="shortcut_helper_content_description_drag_handle" msgid="5092426406009848110">"Sürükleme tutamacı"</string> <string name="shortcut_helper_keyboard_settings_buttons_label" msgid="6720967595915985259">"Klavye Ayarları"</string> - <string name="shortcut_helper_customize_dialog_set_shortcut_button_label" msgid="4754492225010429382">"Kısayol ayarla"</string> + <string name="shortcut_helper_customize_dialog_set_shortcut_button_label" msgid="4754492225010429382">"Ayarla"</string> <string name="shortcut_helper_customize_dialog_remove_button_label" msgid="6546386970440176552">"Kaldır"</string> - <string name="shortcut_helper_customize_dialog_reset_button_label" msgid="7645535254306312685">"Evet, sıfırlansın"</string> + <string name="shortcut_helper_customize_dialog_reset_button_label" msgid="7645535254306312685">"Sıfırla"</string> <string name="shortcut_helper_customize_dialog_cancel_button_label" msgid="5595546460431741178">"İptal"</string> <string name="shortcut_helper_add_shortcut_dialog_placeholder" msgid="9154297849458741995">"Tuşa basın"</string> <string name="shortcut_customizer_key_combination_in_use_error_message" msgid="7693234470526626327">"Tuş kombinasyonu zaten kullanılıyor. Başka bir tuş deneyin."</string> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index af70c6fa39f0..ea839cc9f96a 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Сповіщення про сеанс запису екрана"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Записати відео з екрана?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Записувати один додаток"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Записати цей екран"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Записати екран \"%s\""</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Коли ви записуєте вміст усього екрана, на відео потрапляє все, що на ньому відображається. Тому будьте уважні з паролями, повідомленнями, фотографіями, аудіо, відео, платіжною інформацією тощо."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Коли ви записуєте додаток, на відео потрапляє все, що відображається або відтворюється в ньому. Тому будьте уважні з паролями, повідомленнями, фотографіями, аудіо, відео, платіжною інформацією тощо."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Записувати вміст екрана"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Не вдалось оновити набір налаштувань"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Набір налаштувань"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Вибрано"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Звуки оточення"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Ліворуч"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Праворуч"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Розгорнути в окремі елементи керування ліворуч і праворуч"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Згорнути в єдиний елемент керування"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Вимкнути звуки оточення"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Увімкнути звуки оточення"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Інструменти"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Живі субтитри"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Нотатка"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Показувати значки сповіщень із низьким пріоритетом"</string> <string name="other" msgid="429768510980739978">"Інше"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"вилучити опцію"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"додати панель на останню позицію"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Перемістити опцію"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"додати панель на потрібну позицію"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Перемістити на позицію <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Додати на позицію <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Позиція недійсна."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"вибрати користувача"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Немає Інтернету"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Відкрити налаштування <xliff:g id="ID_1">%s</xliff:g>."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Змінити порядок швидких налаштувань."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Меню кнопки живлення"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Сторінка <xliff:g id="ID_1">%1$d</xliff:g> з <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Заблокований екран"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"відкрити пристрій"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Щоб відкрити, використайте відбиток пальця"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Пройдіть автентифікацію. Для цього торкніться сканера відбитків пальців."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Активний телефонний виклик"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Мобільний трафік"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Підключено"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Тимчасово з’єднано"</string> @@ -1454,7 +1443,7 @@ <string name="shortcut_customize_mode_add_shortcut_description" msgid="6866025005347407696">"Натисніть клавішу, щоб призначити комбінацію клавіш"</string> <string name="shortcut_customize_mode_remove_shortcut_description" msgid="6851287900585057128">"Вашу власну комбінацію клавіш буде видалено назавжди."</string> <string name="shortcut_customize_mode_reset_shortcut_description" msgid="2081849715634358684">"Усі ваші власні комбінації клавіш буде видалено назавжди."</string> - <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Комбінації клавіш для пошуку"</string> + <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Пошук комбінацій клавіш"</string> <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Нічого не знайдено"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Значок згортання"</string> <string name="shortcut_helper_content_description_meta_key" msgid="3989315044342124818">"Значок клавіші дії або метаклавіші"</string> diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml index 28aa1bb36c8b..63fa93d74ea9 100644 --- a/packages/SystemUI/res/values-ur/strings.xml +++ b/packages/SystemUI/res/values-ur/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"اسکرین ریکارڈ سیشن کیلئے جاری اطلاع"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"آپ کی اسکرین ریکارڈ کریں؟"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"ایک ایپ ریکارڈ کریں"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"یہ اسکرین ریکارڈ کریں"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"%s ریکارڈ کریں"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"جب آپ اپنی پوری اسکرین کو ریکارڈ کر رہے ہوتے ہیں تو آپ کی اسکرین پر دکھائی گئی ہر چیز ریکارڈ کی جاتی ہے۔ لہذا، پاس ورڈز، ادائیگی کی تفصیلات، پیغامات، تصاویر، ساتھ ہی آڈیو اور ویڈیو جیسی چیزوں کے سلسلے میں محتاط رہیں۔"</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"جب آپ کسی ایپ کو ریکارڈ کر رہے ہوتے ہیں تو اس ایپ میں دکھائی گئی یا چلائی گئی ہر چیز ریکارڈ کی جاتی ہے۔ لہذا، پاس ورڈز، ادائیگی کی تفصیلات، پیغامات، تصاویر، ساتھ ہی آڈیو اور ویڈیو جیسی چیزوں کے سلسلے میں محتاط رہیں۔"</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"اسکرین ریکارڈ کریں"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"پہلے سے ترتیب شدہ کو اپ ڈیٹ نہیں کیا جا سکا"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"پہلے سے ترتیب شدہ"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"منتخب کردہ"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"اطراف"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"دائیں"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"بائیں"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"بائیں اور دائیں علیحدہ کردہ کنٹرولز کو پھیلائیں"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"یونیفائیڈ کنٹرول کیلئے سکیڑیں"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"اطراف کو خاموش کریں"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"اطراف کی آواز چالو کریں"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"ٹولز"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"لائیو کیپشن"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"نوٹ"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"کم ترجیحی اطلاع کے آئیکنز دکھائیں"</string> <string name="other" msgid="429768510980739978">"دیگر"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"ٹائل ہٹائیں"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"ٹائل کو آخری پوزیشن پر شامل کریں"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"ٹائل منتقل کریں"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"ٹائل کو مطلوبہ پوزیشن پر شامل کریں"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"<xliff:g id="POSITION">%1$d</xliff:g> میں منتقل کریں"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"پوزیشن <xliff:g id="POSITION">%1$d</xliff:g> میں شامل کریں"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"پوزیشن غلط ہے۔"</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"صارف منتخب کریں"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"انٹرنیٹ نہیں ہے"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"<xliff:g id="ID_1">%s</xliff:g> ترتیبات کھولیں۔"</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"فوری ترتیبات کی ترتیب میں ترمیم کریں۔"</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"پاور مینیو"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"صفحہ <xliff:g id="ID_1">%1$d</xliff:g> از <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"مقفل اسکرین"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"آلہ درج کریں"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"کھولنے کے لیے فنگر پرنٹ کا استعمال کریں"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"توثیق مطلوب ہے۔ توثیق کرنے کے لیے فنگر پرنٹ سینسر کو ٹچ کریں۔"</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"جاری فون کال"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"موبائل ڈیٹا"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"منسلک ہے"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"عارضی طور پر منسلک ہے"</string> @@ -1452,8 +1441,8 @@ <string name="shortcut_customize_mode_remove_shortcut_dialog_title" msgid="7106420484940737208">"شارٹ کٹ ہٹائیں؟"</string> <string name="shortcut_customize_mode_reset_shortcut_dialog_title" msgid="8131184731313717780">"ڈیفالٹ پر واپس ری سیٹ کریں؟"</string> <string name="shortcut_customize_mode_add_shortcut_description" msgid="6866025005347407696">"شارٹ کٹ تفویض کرنے کے لیے کلید کو دبائیں"</string> - <string name="shortcut_customize_mode_remove_shortcut_description" msgid="6851287900585057128">"یہ آپ کا حسب ضرورت شارٹ کٹ مستقل طور پر حذف کر دے گا۔"</string> - <string name="shortcut_customize_mode_reset_shortcut_description" msgid="2081849715634358684">"یہ آپ کے تمام حسب ضرورت شارٹ کٹس کو مستقل طور پر حذف کر دے گا۔"</string> + <string name="shortcut_customize_mode_remove_shortcut_description" msgid="6851287900585057128">"اس سے آپ کا حسب ضرورت شارٹ کٹ مستقل طور پر حذف ہو جائے گا۔"</string> + <string name="shortcut_customize_mode_reset_shortcut_description" msgid="2081849715634358684">"اس سے آپ کے تمام حسب ضرورت شارٹ کٹس مستقل طور پر حذف ہو جائیں گے۔"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"تلاش کے شارٹ کٹس"</string> <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"تلاش کا کوئی نتیجہ نہیں ہے"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"آئیکن سکیڑیں"</string> diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml index 394a6e462754..a20f42d88c7c 100644 --- a/packages/SystemUI/res/values-uz/strings.xml +++ b/packages/SystemUI/res/values-uz/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Ekrandan yozib olish seansi uchun joriy bildirishnoma"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Ekran yozib olinsinmi?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Bitta ilovani yozib olish"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Bu ekranni yozib olish"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Yozib olish: %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Butun ekranni yozib olishda ekranda koʻrsatilgan barcha axborotlar yozib olinadi. Shu sababli parollar, toʻlov tafsilotlari, xabarlar, suratlar, audio va video chiqmasligi uchun ehtiyot boʻling."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Ilovani yozib olishda ilovada koʻrsatilgan yoki ijro etilgan barcha axborotlar yozib olinadi. Shu sababli parollar, toʻlov tafsilotlari, xabarlar, suratlar, audio va video chiqmasligi uchun ehtiyot boʻling."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Ekranni yozib olish"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Andoza yangilanmadi"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Andoza"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Tanlangan"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Atrof-muhit"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Chap"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Oʻng"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Chap va oʻngga ajratilgan boshqaruv elementlariga yoyish"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Yagona boshqaruvga yigʻish"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Atrof-muhitni ovozsiz qilish"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Atrof-muhitni sukutdan chiqarish"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Vositalar"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Jonli izoh"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Qayd"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Muhim boʻlmagan bildirishnoma ikonkalarini koʻrsatish"</string> <string name="other" msgid="429768510980739978">"Boshqa"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"katakchani olib tashlash"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"kartochkani oxirgi oʻringa qoʻshish"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Katakchani boshqa joyga olish"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Kartochkani kerakli oʻringa qoʻshish"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Bu joyga olish: <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Bu joyga kiritish: <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Pozitsiya yaroqsiz."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"foydalanuvchini tanlash"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Internetga ulanmagansiz"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"<xliff:g id="ID_1">%s</xliff:g> sozlamalarini ochish."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Tezkor sozlamalar tartibini tahrirlash"</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Quvvat menyusi"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"<xliff:g id="ID_1">%1$d</xliff:g>-sahifa, jami: <xliff:g id="ID_2">%2$d</xliff:g> ta sahifa"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Ekran qulfi"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"qurilmani ochish"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Ochish uchun barmoq izidan foydalaning"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Haqiqiylikni tekshirish talab etiladi. Autentifikatsiya uchun barmoq izi skaneriga tegining."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Joriy telefon chaqiruvi"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Mobil internet"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Ulangan"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Vaqtincha ulangan"</string> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index 81ac5e70a7e2..2a8fa4c9cc7b 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Thông báo đang diễn ra về phiên ghi màn hình"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Ghi màn hình?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Ghi một ứng dụng"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Ghi màn hình này"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"Ghi %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Khi bạn ghi toàn màn hình, mọi nội dung trên màn hình của bạn đều được ghi. Vì vậy, hãy thận trọng để không làm lộ thông tin như mật khẩu, thông tin thanh toán, tin nhắn, ảnh, âm thanh và video."</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Khi bạn ghi một ứng dụng, mọi nội dung xuất hiện hoặc phát trong ứng dụng đó sẽ đều được ghi. Vì vậy, hãy thận trọng để không làm lộ thông tin như mật khẩu, thông tin thanh toán, tin nhắn, ảnh, âm thanh và video."</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Ghi màn hình"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Không cập nhật được giá trị đặt trước"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Chế độ đặt sẵn"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Đã chọn"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Âm lượng xung quanh"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Trái"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Phải"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Mở rộng thành các nút điều khiển tách biệt bên trái và bên phải"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Thu gọn thành nút điều khiển hợp nhất"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Tắt tiếng xung quanh"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Bật tiếng xung quanh"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Công cụ"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Phụ đề trực tiếp"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Ghi chú"</string> @@ -857,7 +848,7 @@ <string name="keyboard_key_move_end" msgid="99190401463834854">"Cuối"</string> <string name="keyboard_key_insert" msgid="4621692715704410493">"Insert"</string> <string name="keyboard_key_num_lock" msgid="7209960042043090548">"Num Lock"</string> - <string name="keyboard_key_numpad_template" msgid="7316338238459991821">"Bàn phím số <xliff:g id="NAME">%1$s</xliff:g>"</string> + <string name="keyboard_key_numpad_template" msgid="7316338238459991821">"Số <xliff:g id="NAME">%1$s</xliff:g> trên bàn phím số"</string> <string name="notif_inline_reply_remove_attachment_description" msgid="7954075334095405429">"Xóa tệp đính kèm"</string> <string name="keyboard_shortcut_group_system" msgid="1583416273777875970">"Hệ thống"</string> <string name="keyboard_shortcut_group_system_home" msgid="7465138628692109907">"Màn hình chính"</string> @@ -869,7 +860,7 @@ <string name="keyboard_shortcut_join" msgid="3578314570034512676">"hoặc"</string> <string name="keyboard_shortcut_clear_text" msgid="6631051796030377857">"Xoá cụm từ tìm kiếm"</string> <string name="keyboard_shortcut_search_list_title" msgid="4271769465397671138">"Phím tắt"</string> - <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Tìm lối tắt"</string> + <string name="keyboard_shortcut_search_list_hint" msgid="5982623262974326746">"Tìm phím tắt"</string> <string name="keyboard_shortcut_search_list_no_result" msgid="6819302191660875501">"Không tìm thấy lối tắt"</string> <string name="keyboard_shortcut_search_category_system" msgid="1151182120757052669">"Hệ thống"</string> <string name="keyboard_shortcut_search_category_input" msgid="5440558509904296233">"Đầu vào"</string> @@ -886,8 +877,8 @@ <string name="group_system_go_back" msgid="2730322046244918816">"Quay lại"</string> <string name="group_system_access_home_screen" msgid="4130366993484706483">"Chuyển đến màn hình chính"</string> <string name="group_system_overview_open_apps" msgid="5659958952937994104">"Xem các ứng dụng gần đây"</string> - <string name="group_system_cycle_forward" msgid="5478663965957647805">"Di chuyển tiến trong danh sách các ứng dụng gần đây"</string> - <string name="group_system_cycle_back" msgid="8194102916946802902">"Di chuyển lùi trong danh sách các ứng dụng gần đây"</string> + <string name="group_system_cycle_forward" msgid="5478663965957647805">"Di chuyển tiến qua các ứng dụng gần đây"</string> + <string name="group_system_cycle_back" msgid="8194102916946802902">"Di chuyển lùi qua các ứng dụng gần đây"</string> <string name="group_system_access_all_apps_search" msgid="1553588630154197469">"Mở danh sách ứng dụng"</string> <string name="group_system_access_system_settings" msgid="8731721963449070017">"Mở phần cài đặt"</string> <string name="group_system_access_google_assistant" msgid="7210074957915968110">"Mở Trợ lý"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Hiển thị biểu tượng thông báo có mức ưu tiên thấp"</string> <string name="other" msgid="429768510980739978">"Khác"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"xóa ô"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"thêm ô vào vị trí cuối cùng"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Di chuyển ô"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Thêm ô vào vị trí mong muốn"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Di chuyển tới <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Thêm vào vị trí <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Vị trí không hợp lệ."</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"chọn người dùng"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Không có Internet"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Mở cài đặt <xliff:g id="ID_1">%s</xliff:g>."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Chỉnh sửa thứ tự của trình đơn Cài đặt nhanh."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Trình đơn nguồn"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Trang <xliff:g id="ID_1">%1$d</xliff:g> / <xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Màn hình khóa"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"truy cập thiết bị"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Dùng vân tay để mở"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Bạn cần phải xác thực. Hãy chạm vào cảm biến vân tay để xác thực."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Đang gọi điện thoại"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Dữ liệu di động"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Đã kết nối"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Tạm thời có kết nối"</string> @@ -1449,12 +1438,12 @@ <string name="shortcut_helper_category_a11y" msgid="6314444792641773464">"Hỗ trợ tiếp cận"</string> <string name="shortcut_helper_title" msgid="8567500639300970049">"Phím tắt"</string> <string name="shortcut_helper_customize_mode_title" msgid="1467657117101096033">"Tuỳ chỉnh phím tắt"</string> - <string name="shortcut_customize_mode_remove_shortcut_dialog_title" msgid="7106420484940737208">"Xoá lối tắt?"</string> + <string name="shortcut_customize_mode_remove_shortcut_dialog_title" msgid="7106420484940737208">"Xoá phím tắt?"</string> <string name="shortcut_customize_mode_reset_shortcut_dialog_title" msgid="8131184731313717780">"Đặt lại về phím tắt mặc định?"</string> - <string name="shortcut_customize_mode_add_shortcut_description" msgid="6866025005347407696">"Nhấn phím để chỉ định lối tắt"</string> - <string name="shortcut_customize_mode_remove_shortcut_description" msgid="6851287900585057128">"Thao tác này sẽ xoá vĩnh viễn lối tắt tuỳ chỉnh của bạn."</string> + <string name="shortcut_customize_mode_add_shortcut_description" msgid="6866025005347407696">"Nhấn phím để chỉ định phím tắt"</string> + <string name="shortcut_customize_mode_remove_shortcut_description" msgid="6851287900585057128">"Thao tác này sẽ xoá vĩnh viễn phím tắt tuỳ chỉnh của bạn."</string> <string name="shortcut_customize_mode_reset_shortcut_description" msgid="2081849715634358684">"Thao tác này sẽ xoá vĩnh viễn mọi phím tắt tuỳ chỉnh của bạn."</string> - <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Tìm lối tắt"</string> + <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"Tìm phím tắt"</string> <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"Không có kết quả tìm kiếm nào"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"Biểu tượng Thu gọn"</string> <string name="shortcut_helper_content_description_meta_key" msgid="3989315044342124818">"Biểu tượng phím Meta (phím hành động)"</string> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index 1649b3a02428..8f0b2f11da93 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"持续显示屏幕录制会话通知"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"要录制屏幕吗?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"录制单个应用"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"录制此屏幕"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"录制“%s”屏幕"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"录制整个屏幕时,屏幕上显示的所有内容均会被录制。因此,请务必小心操作,谨防泄露密码、付款详情、消息、照片、音频、视频等敏感信息。"</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"录制单个应用时,该应用中显示或播放的所有内容均会被录制。因此,请务必小心操作,谨防泄露密码、付款信息、消息、照片、音频、视频等。"</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"录制屏幕"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"无法更新预设"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"预设"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"已选择"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"周围声音"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"左侧"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"右侧"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"展开为左侧和右侧的单独控件"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"收起为统一控件"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"将周围声音静音"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"取消周围声音静音"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"工具"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"实时字幕"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"记事"</string> @@ -490,7 +481,7 @@ <string name="keyguard_retry" msgid="886802522584053523">"向上滑动即可重试"</string> <string name="accesssibility_keyguard_retry" msgid="8880238862712870676">"向上滑动即可再次尝试人脸解锁"</string> <string name="require_unlock_for_nfc" msgid="1305686454823018831">"需要解锁才能使用 NFC"</string> - <string name="do_disclosure_generic" msgid="4896482821974707167">"此设备归贵单位所有"</string> + <string name="do_disclosure_generic" msgid="4896482821974707167">"此设备归贵组织所有"</string> <string name="do_disclosure_with_name" msgid="2091641464065004091">"此设备归<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>所有"</string> <string name="do_financed_disclosure_with_name" msgid="6723004643314467864">"这是<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>提供的设备"</string> <string name="phone_hint" msgid="6682125338461375925">"滑动图标即可拨打电话"</string> @@ -624,7 +615,7 @@ <string name="quick_settings_financed_disclosure_named_management" msgid="2307703784594859524">"此设备由<xliff:g id="ORGANIZATION_NAME">%s</xliff:g>提供"</string> <string name="quick_settings_disclosure_management_named_vpn" msgid="4137564460025113168">"此设备归贵组织所有,已通过“<xliff:g id="VPN_APP">%1$s</xliff:g>”连接到互联网"</string> <string name="quick_settings_disclosure_named_management_named_vpn" msgid="2169227918166358741">"此设备归<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>所有,已通过“<xliff:g id="VPN_APP">%2$s</xliff:g>”连接到互联网"</string> - <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"此设备归贵单位所有"</string> + <string name="quick_settings_disclosure_management" msgid="5515296598440684962">"此设备归贵组织所有"</string> <string name="quick_settings_disclosure_named_management" msgid="3476472755775165827">"此设备归<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>所有"</string> <string name="quick_settings_disclosure_management_vpns" msgid="929181757984262902">"此设备归贵组织所有,已通过 VPN 连接到互联网"</string> <string name="quick_settings_disclosure_named_management_vpns" msgid="3312645578322079185">"此设备归<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>所有,已通过 VPN 连接到互联网"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"显示低优先级的通知图标"</string> <string name="other" msgid="429768510980739978">"其他"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"移除功能块"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"将功能块添加到最后一个位置"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"移动功能块"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"将功能块添加到所需位置"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"移至 <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"添加到位置 <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"位置无效。"</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"选择用户"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"未连接到互联网"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"打开<xliff:g id="ID_1">%s</xliff:g>设置。"</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"修改快捷设置的顺序。"</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"电源菜单"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"第 <xliff:g id="ID_1">%1$d</xliff:g> 页,共 <xliff:g id="ID_2">%2$d</xliff:g> 页"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"锁定屏幕"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"进入设备"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"使用指纹即可打开"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"需要进行身份验证。请轻触指纹传感器以验证身份。"</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"正在进行通话"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"移动数据网络"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"已连接"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"已暂时连接"</string> @@ -1439,7 +1428,7 @@ <string name="privacy_dialog_active_app_usage_2" msgid="2770926061339921767">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”正在使用(<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string> <string name="privacy_dialog_recent_app_usage_2" msgid="2874689735085367167">"“<xliff:g id="APP_NAME">%1$s</xliff:g>”最近使用过(<xliff:g id="ATTRIBUTION_LABEL">%2$s</xliff:g> • <xliff:g id="PROXY_LABEL">%3$s</xliff:g>)"</string> <string name="shortcut_helper_category_system" msgid="462110876978937359">"系统"</string> - <string name="shortcut_helper_category_system_controls" msgid="3153344561395751020">"系统控件"</string> + <string name="shortcut_helper_category_system_controls" msgid="3153344561395751020">"系统控制"</string> <string name="shortcut_helper_category_system_apps" msgid="6001757545472556810">"系统应用"</string> <string name="shortcut_helper_category_multitasking" msgid="7413381961404090136">"多任务处理"</string> <string name="shortcutHelper_category_split_screen" msgid="1159669813444812244">"分屏"</string> @@ -1450,10 +1439,10 @@ <string name="shortcut_helper_title" msgid="8567500639300970049">"键盘快捷键"</string> <string name="shortcut_helper_customize_mode_title" msgid="1467657117101096033">"自定义键盘快捷键"</string> <string name="shortcut_customize_mode_remove_shortcut_dialog_title" msgid="7106420484940737208">"要移除快捷键吗?"</string> - <string name="shortcut_customize_mode_reset_shortcut_dialog_title" msgid="8131184731313717780">"要重置为默认快捷方式吗?"</string> + <string name="shortcut_customize_mode_reset_shortcut_dialog_title" msgid="8131184731313717780">"要重置为默认快捷键吗?"</string> <string name="shortcut_customize_mode_add_shortcut_description" msgid="6866025005347407696">"按下按键即可指定快捷键"</string> <string name="shortcut_customize_mode_remove_shortcut_description" msgid="6851287900585057128">"此操作会永久删除您的自定义快捷键。"</string> - <string name="shortcut_customize_mode_reset_shortcut_description" msgid="2081849715634358684">"此操作会永久删除您的所有自定义快捷方式。"</string> + <string name="shortcut_customize_mode_reset_shortcut_description" msgid="2081849715634358684">"此操作会永久删除您的所有自定义快捷键。"</string> <string name="shortcut_helper_search_placeholder" msgid="5488547526269871819">"搜索快捷键"</string> <string name="shortcut_helper_no_search_results" msgid="8554756497996692160">"无搜索结果"</string> <string name="shortcut_helper_content_description_collapse_icon" msgid="8028015738431664954">"收起图标"</string> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index 29e9712f6878..afae659eb972 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"持續顯示錄影畫面工作階段通知"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"要錄影螢幕畫面嗎?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"錄影一個應用程式"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"錄影此畫面"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"錄影 %s"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"當你錄影整個螢幕畫面時,系統會錄影螢幕畫面上顯示的任何內容。因此,請謹慎處理密碼、付款資料、訊息、相片、音訊和影片等。"</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"當你錄影應用程式時,系統會錄影該應用程式中顯示或播放的任何內容。因此,請謹慎處理密碼、付款資料、訊息、相片、音訊和影片等。"</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"錄影螢幕畫面"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"無法更新預設"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"預設"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"揀咗"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"環境聲音"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"左"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"右"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"打開就可以分開左右控制"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"收埋就可以統一控制"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"環境聲音靜音"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"取消環境聲音靜音"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"工具"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"即時字幕"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"筆記"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"顯示低優先順序通知圖示"</string> <string name="other" msgid="429768510980739978">"其他"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"移除圖塊"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"加圖塊去上一個位置"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"移動圖塊"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"加圖塊去目標位置"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"移去 <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"加去位置 <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"位置冇效。"</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"揀使用者"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"沒有互聯網連線"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"開啟<xliff:g id="ID_1">%s</xliff:g>設定頁面。"</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"編輯「快速設定」嘅次序"</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"電源選單"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"第 <xliff:g id="ID_1">%1$d</xliff:g> 頁 (共 <xliff:g id="ID_2">%2$d</xliff:g> 頁)"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"螢幕鎖定"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"進入裝置"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"使用指紋即可開啟"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"需要驗證。掂一下指紋感應器就可以驗證。"</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"通話中"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"流動數據"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"已連線"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"已暫時連線"</string> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index 1c809851cbce..f52e906add3e 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -111,10 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"持續顯示螢幕畫面錄製工作階段通知"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"要錄製畫面嗎?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"錄製單一應用程式"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"錄製這個畫面"</string> + <string name="screenrecord_permission_dialog_option_text_entire_screen_for_display" msgid="4169494703993148253">"錄製「%s」畫面"</string> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"錄製整個畫面時,系統會錄下畫面上的所有內容。因此,請謹慎處理密碼、付款資料、訊息、相片和影音內容等資訊。"</string> <string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"當你錄製應用程式畫面時,系統會錄下該應用程式顯示或播放的所有內容。因此,請謹慎處理密碼、付款資料、訊息、相片和影音內容等資訊。"</string> <string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"錄製畫面"</string> @@ -417,20 +415,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"無法更新預設設定"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"預設"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"已選取"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"環境"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"左"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"右"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"展開為左右獨立控制選項"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"收合為統合控制選項"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"將環境靜音"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"取消環境靜音"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"工具"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"即時字幕"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"筆記"</string> @@ -976,11 +967,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"顯示低優先順序通知圖示"</string> <string name="other" msgid="429768510980739978">"其他"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"移除圖塊"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"將設定方塊新增到最後一個位置"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"移動圖塊"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"將設定方塊新增到所需位置"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"移至 <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"新增到位置 <xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"位置無效。"</string> @@ -996,8 +985,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"選擇使用者"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"沒有網際網路連線"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"開啟「<xliff:g id="ID_1">%s</xliff:g>」設定。"</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"編輯「快速設定」的順序。"</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"電源鍵選單"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"第 <xliff:g id="ID_1">%1$d</xliff:g> 頁,共 <xliff:g id="ID_2">%2$d</xliff:g> 頁"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"螢幕鎖定"</string> @@ -1301,7 +1289,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"進入裝置"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"使用指紋即可開啟"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"需要驗證。輕觸指紋感應器即可進行驗證。"</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"通話中"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"行動數據"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"已連線"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"已暫時建立連線"</string> @@ -1473,7 +1462,7 @@ <string name="shortcut_helper_customize_dialog_reset_button_label" msgid="7645535254306312685">"是,請重設"</string> <string name="shortcut_helper_customize_dialog_cancel_button_label" msgid="5595546460431741178">"取消"</string> <string name="shortcut_helper_add_shortcut_dialog_placeholder" msgid="9154297849458741995">"按下按鍵"</string> - <string name="shortcut_customizer_key_combination_in_use_error_message" msgid="7693234470526626327">"這個按鍵組合已在使用中,請改用其他按鍵。"</string> + <string name="shortcut_customizer_key_combination_in_use_error_message" msgid="7693234470526626327">"按鍵組合重複,請改用其他按鍵。"</string> <string name="shortcut_customizer_generic_error_message" msgid="3128454624049722741">"無法設定捷徑。"</string> <string name="shortcut_helper_plus_symbol" msgid="4534843157353732011">"+"</string> <string name="launch_keyboard_tutorial_notification_title" msgid="8849933155160522519">"使用鍵盤操作"</string> diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index 6a8483d48a09..a63167ed8ac2 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -111,8 +111,8 @@ <string name="screenrecord_channel_description" msgid="4147077128486138351">"Isaziso esiqhubekayo seseshini yokurekhoda isikrini"</string> <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Rekhoda isikrini sakho?"</string> <string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Rekhoda i-app eyodwa"</string> - <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen (4882406311415082016) --> - <skip /> + <string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="4882406311415082016">"Rekhoda lesi sikrini"</string> + <!-- String.format failed for translation --> <!-- no translation found for screenrecord_permission_dialog_option_text_entire_screen_for_display (4169494703993148253) --> <skip /> <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Uma urekhoda sonke isikrini sakho, noma yini evela esikrinini iyarekhodwa. Ngakho-ke qaphela ngezinto ezifana namaphasiwedi, imininingwane yenkokhelo, imilayezo, izithombe, nomsindo nevidiyo."</string> @@ -417,20 +417,13 @@ <string name="hearing_devices_presets_error" msgid="350363093458408536">"Ayikwazanga ukubuyekeza ukusetha ngaphambilini"</string> <string name="hearing_devices_preset_label" msgid="7878267405046232358">"Ukusetha ngaphambilini"</string> <string name="hearing_devices_spinner_item_selected" msgid="3137083889662762383">"Okukhethiwe"</string> - <!-- no translation found for hearing_devices_ambient_label (629440938614895797) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_left (3586965448230412600) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_control_right (6192137602448918383) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_expand_controls (2131816068187709200) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_collapse_controls (2261097656446201581) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_mute (1836882837647429416) --> - <skip /> - <!-- no translation found for hearing_devices_ambient_unmute (2187938085943876814) --> - <skip /> + <string name="hearing_devices_ambient_label" msgid="629440938614895797">"Izindawo ezizungezile"</string> + <string name="hearing_devices_ambient_control_left" msgid="3586965448230412600">"Kwesokunxele"</string> + <string name="hearing_devices_ambient_control_right" msgid="6192137602448918383">"Kwesokudla"</string> + <string name="hearing_devices_ambient_expand_controls" msgid="2131816068187709200">"Nwebela ezilawulini ezihlukanisiwe zakwesokunxele nakwesokudla"</string> + <string name="hearing_devices_ambient_collapse_controls" msgid="2261097656446201581">"Goqa ezilawulini ezihlanganisiwe"</string> + <string name="hearing_devices_ambient_mute" msgid="1836882837647429416">"Thulisa izindawo ezizungezile"</string> + <string name="hearing_devices_ambient_unmute" msgid="2187938085943876814">"Susa ukuthula ezindaweni ezizungezile"</string> <string name="hearing_devices_tools_label" msgid="1929081464316074476">"Amathuluzi"</string> <string name="quick_settings_hearing_devices_live_caption_title" msgid="1054814050932225451">"Okushuthwe Bukhoma"</string> <string name="quick_settings_notes_label" msgid="1028004078001002623">"Inothi"</string> @@ -976,11 +969,9 @@ <string name="tuner_low_priority" msgid="8412666814123009820">"Bonisa izithonjana zesaziso zokubaluleka okuncane"</string> <string name="other" msgid="429768510980739978">"Okunye"</string> <string name="accessibility_qs_edit_remove_tile_action" msgid="775511891457193480">"susa ithayela"</string> - <!-- no translation found for accessibility_qs_edit_tile_add_action (8311378984458545661) --> - <skip /> + <string name="accessibility_qs_edit_tile_add_action" msgid="8311378984458545661">"faka ithayela endaweni yokugcina"</string> <string name="accessibility_qs_edit_tile_start_move" msgid="2009373939914517817">"Hambisa ithayela"</string> - <!-- no translation found for accessibility_qs_edit_tile_start_add (8141710006899065161) --> - <skip /> + <string name="accessibility_qs_edit_tile_start_add" msgid="8141710006899065161">"Faka ithayela endaweni oyifunayo"</string> <string name="accessibility_qs_edit_tile_move_to_position" msgid="5198161544045930556">"Hambisa ku-<xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibility_qs_edit_tile_add_to_position" msgid="9029163095148274690">"Engeza kusikhundla se-<xliff:g id="POSITION">%1$d</xliff:g>"</string> <string name="accessibilit_qs_edit_tile_add_move_invalid_position" msgid="2858467994472624487">"Indawo ayivumelekile."</string> @@ -996,8 +987,7 @@ <string name="accessibility_quick_settings_choose_user_action" msgid="4554388498186576087">"khetha umsebenzisi"</string> <string name="data_connection_no_internet" msgid="691058178914184544">"Ayikho i-inthanethi"</string> <string name="accessibility_quick_settings_open_settings" msgid="536838345505030893">"Vula izilungiselelo ze-<xliff:g id="ID_1">%s</xliff:g>."</string> - <!-- no translation found for accessibility_quick_settings_edit (6544873823850165) --> - <skip /> + <string name="accessibility_quick_settings_edit" msgid="6544873823850165">"Hlela i-oda Lamasethingi Asheshayo."</string> <string name="accessibility_quick_settings_power_menu" msgid="6820426108301758412">"Imenyu yamandla"</string> <string name="accessibility_quick_settings_page" msgid="7506322631645550961">"Ikhasi <xliff:g id="ID_1">%1$d</xliff:g> kwangu-<xliff:g id="ID_2">%2$d</xliff:g>"</string> <string name="tuner_lock_screen" msgid="2267383813241144544">"Khiya isikrini"</string> @@ -1301,7 +1291,8 @@ <string name="accessibility_enter_hint" msgid="2617864063504824834">"faka idivayisi"</string> <string name="keyguard_try_fingerprint" msgid="2825130772993061165">"Sebenzisa izigxivizo zeminwe ukuvula"</string> <string name="accessibility_fingerprint_bouncer" msgid="7189102492498735519">"Ukufakazela ubuqiniso budingekile. Thinta inzwa yezigxivizo zeminwe ukuze uqinisekise."</string> - <string name="ongoing_phone_call_content_description" msgid="5332334388483099947">"Ikholi yefoni eqhubekayo"</string> + <!-- no translation found for ongoing_call_content_description (6394763878322348560) --> + <skip /> <string name="mobile_data_settings_title" msgid="3955246641380064901">"Idatha yeselula"</string> <string name="mobile_data_connection_active" msgid="944490013299018227">"Ixhunyiwe"</string> <string name="mobile_data_temp_connection_active" msgid="4590222725908806824">"Ixhume okwesikhashana"</string> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 33e29c11254c..8bf4e373a6e0 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -1771,6 +1771,7 @@ <!-- Ongoing activity chip --> <dimen name="ongoing_activity_chip_max_text_width">74dp</dimen> + <dimen name="ongoing_activity_chip_margin_start">5dp</dimen> <!-- The activity chip side padding, used with the default phone icon. --> <dimen name="ongoing_activity_chip_side_padding">12dp</dimen> <!-- The activity chip side padding, used with an icon that has embedded padding (e.g. if the icon comes from the notification's smallIcon field). If the icon has padding, the chip itself can have less padding. --> @@ -2104,6 +2105,8 @@ <dimen name="volume_dialog_background_corner_radius">30dp</dimen> <dimen name="volume_dialog_background_vertical_margin">-10dp</dimen> + <!-- top margin covers half the ringer button + components spacing --> + <dimen name="volume_dialog_background_top_margin">-28dp</dimen> <dimen name="volume_dialog_components_spacing">8dp</dimen> <dimen name="volume_dialog_floating_sliders_spacing">8dp</dimen> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index 94698bcb88b8..691fb50a15b8 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -79,7 +79,7 @@ the chip. --> <item name="android:layout_height">match_parent</item> <item name="android:layout_gravity">center_vertical|start</item> - <item name="android:layout_marginStart">5dp</item> + <item name="android:layout_marginStart">@dimen/ongoing_activity_chip_margin_start</item> </style> <style name="StatusBar.Chip.Text"> diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java index 7033e641dc2c..c0c4ec335a34 100644 --- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java +++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java @@ -19,6 +19,7 @@ package com.android.systemui.clipboardoverlay; import static android.content.ClipDescription.CLASSIFICATION_COMPLETE; import static com.android.systemui.Flags.clipboardNoninteractiveOnLockscreen; +import static com.android.systemui.Flags.clipboardOverlayMultiuser; import static com.android.systemui.Flags.overrideSuppressOverlayCondition; import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ENTERED; import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_UPDATED; @@ -35,12 +36,18 @@ import android.os.UserHandle; import android.provider.Settings; import android.util.Log; +import androidx.annotation.NonNull; + import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.UiEventLogger; import com.android.systemui.CoreStartable; import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.settings.UserTracker; import com.android.systemui.user.utils.UserScopedService; +import java.util.concurrent.Executor; + import javax.inject.Inject; import javax.inject.Provider; @@ -61,42 +68,71 @@ public class ClipboardListener implements private final Context mContext; private final Provider<ClipboardOverlayController> mOverlayProvider; private final ClipboardToast mClipboardToast; - private final ClipboardManager mClipboardManager; - private final KeyguardManager mKeyguardManager; + private final UserScopedService<ClipboardManager> mClipboardManagerProvider; + private final UserScopedService<KeyguardManager> mKeyguardManagerProvider; private final UiEventLogger mUiEventLogger; private final ClipboardOverlaySuppressionController mClipboardOverlaySuppressionController; private ClipboardOverlay mClipboardOverlay; + private ClipboardManager mClipboardManagerForUser; + private KeyguardManager mKeyguardManagerForUser; + + private final UserTracker mUserTracker; + private final Executor mMainExecutor; + + private final UserTracker.Callback mCallback = new UserTracker.Callback() { + @Override + public void onUserChanged(int newUser, @NonNull Context userContext) { + UserTracker.Callback.super.onUserChanged(newUser, userContext); + mClipboardManagerForUser.removePrimaryClipChangedListener(ClipboardListener.this); + setUser(mUserTracker.getUserHandle()); + mClipboardManagerForUser.addPrimaryClipChangedListener(ClipboardListener.this); + } + }; @Inject public ClipboardListener(Context context, Provider<ClipboardOverlayController> clipboardOverlayControllerProvider, ClipboardToast clipboardToast, + UserTracker userTracker, UserScopedService<ClipboardManager> clipboardManager, - KeyguardManager keyguardManager, + UserScopedService<KeyguardManager> keyguardManager, UiEventLogger uiEventLogger, + @Main Executor mainExecutor, ClipboardOverlaySuppressionController clipboardOverlaySuppressionController) { mContext = context; mOverlayProvider = clipboardOverlayControllerProvider; mClipboardToast = clipboardToast; - mClipboardManager = clipboardManager.forUser(UserHandle.CURRENT); - mKeyguardManager = keyguardManager; + mClipboardManagerProvider = clipboardManager; + mKeyguardManagerProvider = keyguardManager; mUiEventLogger = uiEventLogger; mClipboardOverlaySuppressionController = clipboardOverlaySuppressionController; + + mMainExecutor = mainExecutor; + mUserTracker = userTracker; + setUser(mUserTracker.getUserHandle()); + } + + private void setUser(UserHandle user) { + mClipboardManagerForUser = mClipboardManagerProvider.forUser(user); + mKeyguardManagerForUser = mKeyguardManagerProvider.forUser(user); } @Override public void start() { - mClipboardManager.addPrimaryClipChangedListener(this); + if (clipboardOverlayMultiuser()) { + mUserTracker.addCallback(mCallback, mMainExecutor); + } + mClipboardManagerForUser.addPrimaryClipChangedListener(this); } @Override public void onPrimaryClipChanged() { - if (!mClipboardManager.hasPrimaryClip()) { + if (!mClipboardManagerForUser.hasPrimaryClip()) { return; } - String clipSource = mClipboardManager.getPrimaryClipSource(); - ClipData clipData = mClipboardManager.getPrimaryClip(); + String clipSource = mClipboardManagerForUser.getPrimaryClipSource(); + ClipData clipData = mClipboardManagerForUser.getPrimaryClip(); if (overrideSuppressOverlayCondition()) { if (mClipboardOverlaySuppressionController.shouldSuppressOverlay(clipData, clipSource, @@ -112,7 +148,7 @@ public class ClipboardListener implements } // user should not access intents before setup or while device is locked - if ((clipboardNoninteractiveOnLockscreen() && mKeyguardManager.isDeviceLocked()) + if ((clipboardNoninteractiveOnLockscreen() && mKeyguardManagerForUser.isDeviceLocked()) || !isUserSetupComplete() || clipData == null // shouldn't happen, but just in case || clipData.getItemCount() == 0) { diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/dagger/ClipboardOverlayModule.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/dagger/ClipboardOverlayModule.java index 307a07f1aec4..6c10eea07ffc 100644 --- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/dagger/ClipboardOverlayModule.java +++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/dagger/ClipboardOverlayModule.java @@ -18,6 +18,7 @@ package com.android.systemui.clipboardoverlay.dagger; import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT; +import static com.android.systemui.Flags.clipboardOverlayMultiuser; import static com.android.systemui.Flags.enableViewCaptureTracing; import static com.android.systemui.util.ConvenienceExtensionsKt.toKotlinLazy; @@ -34,6 +35,7 @@ import com.android.app.viewcapture.ViewCaptureAwareWindowManager; import com.android.systemui.clipboardoverlay.ClipboardOverlayView; import com.android.systemui.res.R; import com.android.systemui.settings.DisplayTracker; +import com.android.systemui.settings.UserTracker; import dagger.Lazy; import dagger.Module; @@ -54,18 +56,28 @@ public interface ClipboardOverlayModule { @Provides @OverlayWindowContext static Context provideWindowContext(DisplayManager displayManager, - DisplayTracker displayTracker, Context context) { + DisplayTracker displayTracker, Context context, UserTracker userTracker) { Display display = displayManager.getDisplay(displayTracker.getDefaultDisplayId()); - return context.createWindowContext(display, TYPE_SCREENSHOT, null); + if (clipboardOverlayMultiuser()) { + return userTracker.getUserContext().createWindowContext(display, TYPE_SCREENSHOT, null); + } else { + return context.createWindowContext(display, TYPE_SCREENSHOT, null); + } } /** * */ @Provides - static ClipboardOverlayView provideClipboardOverlayView(@OverlayWindowContext Context context) { - return (ClipboardOverlayView) LayoutInflater.from(context).inflate( - R.layout.clipboard_overlay, null); + static ClipboardOverlayView provideClipboardOverlayView( + @OverlayWindowContext Context overlayContext, Context context) { + if (clipboardOverlayMultiuser()) { + return (ClipboardOverlayView) LayoutInflater.from(context).inflate( + R.layout.clipboard_overlay, null); + } else { + return (ClipboardOverlayView) LayoutInflater.from(overlayContext).inflate( + R.layout.clipboard_overlay, null); + } } /** diff --git a/packages/SystemUI/src/com/android/systemui/common/shared/model/ContentDescription.kt b/packages/SystemUI/src/com/android/systemui/common/shared/model/ContentDescription.kt index 08e8293cbe9c..d628aca7f9e8 100644 --- a/packages/SystemUI/src/com/android/systemui/common/shared/model/ContentDescription.kt +++ b/packages/SystemUI/src/com/android/systemui/common/shared/model/ContentDescription.kt @@ -24,13 +24,9 @@ import android.content.Context * be a [reference][ContentDescription.Resource] to a resource. */ sealed class ContentDescription { - data class Loaded( - val description: String?, - ) : ContentDescription() + data class Loaded(val description: String?) : ContentDescription() - data class Resource( - @StringRes val res: Int, - ) : ContentDescription() + data class Resource(@StringRes val res: Int) : ContentDescription() companion object { /** @@ -39,6 +35,7 @@ sealed class ContentDescription { * Prefer [com.android.systemui.common.ui.binder.ContentDescriptionViewBinder.bind] over * this method. This should only be used for testing or concatenation purposes. */ + @JvmStatic fun ContentDescription?.loadContentDescription(context: Context): String? { return when (this) { null -> null diff --git a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java index 014c0db618e1..35c0149fb7ac 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/FrameworkServicesModule.java @@ -430,6 +430,12 @@ public class FrameworkServicesModule { @Provides @Singleton + static UserScopedService<KeyguardManager> provideKeyguardManagerUserScoped(Context context) { + return new UserScopedServiceImpl<>(context, KeyguardManager.class); + } + + @Provides + @Singleton static LatencyTracker provideLatencyTracker(Context context) { return LatencyTracker.getInstance(context); } diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ShortcutHelperCoreStartable.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ShortcutHelperCoreStartable.kt index cb6d6f32923d..19a19d551613 100644 --- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ShortcutHelperCoreStartable.kt +++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ShortcutHelperCoreStartable.kt @@ -26,34 +26,34 @@ import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.keyboard.shortcut.data.repository.ShortcutHelperStateRepository +import com.android.systemui.plugins.ActivityStarter import com.android.systemui.statusbar.CommandQueue +import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch -import javax.inject.Inject - @SysUISingleton class ShortcutHelperCoreStartable -@Inject constructor( +@Inject +constructor( private val commandQueue: CommandQueue, private val broadcastDispatcher: BroadcastDispatcher, private val stateRepository: ShortcutHelperStateRepository, + private val activityStarter: ActivityStarter, @Background private val backgroundScope: CoroutineScope, ) : CoreStartable { override fun start() { registerBroadcastReceiver( action = Intent.ACTION_SHOW_KEYBOARD_SHORTCUTS, - onReceive = { - backgroundScope.launch { stateRepository.show() } - } + onReceive = { showShortcutHelper() }, ) registerBroadcastReceiver( action = Intent.ACTION_DISMISS_KEYBOARD_SHORTCUTS, - onReceive = { stateRepository.hide() } + onReceive = { stateRepository.hide() }, ) registerBroadcastReceiver( action = Intent.ACTION_CLOSE_SYSTEM_DIALOGS, - onReceive = { stateRepository.hide() } + onReceive = { stateRepository.hide() }, ) commandQueue.addCallback( object : CommandQueue.Callbacks { @@ -62,7 +62,7 @@ class ShortcutHelperCoreStartable } override fun toggleKeyboardShortcutsMenu(deviceId: Int) { - backgroundScope.launch { stateRepository.toggle(deviceId) } + toggleShortcutHelper(deviceId) } } ) @@ -71,14 +71,33 @@ class ShortcutHelperCoreStartable private fun registerBroadcastReceiver(action: String, onReceive: () -> Unit) { broadcastDispatcher.registerReceiver( receiver = - object : BroadcastReceiver() { - override fun onReceive(context: Context, intent: Intent) { - onReceive() - } - }, + object : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + onReceive() + } + }, filter = IntentFilter(action), flags = Context.RECEIVER_EXPORTED or Context.RECEIVER_VISIBLE_TO_INSTANT_APPS, user = UserHandle.ALL, ) } -}
\ No newline at end of file + + private fun showShortcutHelper() { + dismissKeyguardThenPerformShortcutHelperAction { stateRepository.show() } + } + + private fun toggleShortcutHelper(deviceId: Int? = null) { + dismissKeyguardThenPerformShortcutHelperAction { stateRepository.toggle(deviceId) } + } + + private fun dismissKeyguardThenPerformShortcutHelperAction(action: suspend () -> Unit) { + activityStarter.dismissKeyguardThenExecute( + /* action= */ { + backgroundScope.launch { action() } + false + }, + /* cancel= */ {}, + /* afterKeyguardGone= */ true, + ) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModel.kt index 0f5f07393114..d61165c16625 100644 --- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModel.kt @@ -129,7 +129,7 @@ constructor( val iconDrawable = userContext.packageManager.getApplicationIcon(type.packageName) IconSource(painter = DrawablePainter(drawable = iconDrawable)) - } catch (e: NameNotFoundException) { + } catch (_: NameNotFoundException) { Log.w( "ShortcutHelperViewModel", "Package not found when retrieving icon for ${type.packageName}", @@ -234,6 +234,7 @@ constructor( fun onViewClosed() { stateInteractor.onViewClosed() + resetSearchQuery() } fun onViewOpened() { @@ -243,4 +244,8 @@ constructor( fun onSearchQueryChanged(query: String) { searchQuery.value = query } + + private fun resetSearchQuery(){ + searchQuery.value = "" + } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java index d95a126fe4bd..a7a432497be6 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java @@ -60,7 +60,6 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor; import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionBootInteractor; import com.android.systemui.keyguard.domain.interactor.StartKeyguardTransitionModule; import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransitionModule; -import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransitionModule; import com.android.systemui.keyguard.ui.view.AlternateBouncerWindowViewBinder; import com.android.systemui.keyguard.ui.viewmodel.KeyguardQuickAffordancesCombinedViewModelModule; import com.android.systemui.log.SessionTracker; @@ -110,6 +109,7 @@ import java.util.concurrent.Executor; DeviceEntryIconTransitionModule.class, FalsingModule.class, PrimaryBouncerTransitionModule.class, + PrimaryBouncerTransitionImplModule.class, KeyguardDataQuickAffordanceModule.class, KeyguardQuickAffordancesCombinedViewModelModule.class, KeyguardRepositoryModule.class, diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/PrimaryBouncerTransitionModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/PrimaryBouncerTransitionModule.kt new file mode 100644 index 000000000000..cc070b66917b --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/PrimaryBouncerTransitionModule.kt @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2025 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.keyguard.dagger + +import android.content.res.Resources +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.keyguard.ui.transitions.BlurConfig +import com.android.systemui.keyguard.ui.transitions.PrimaryBouncerTransition +import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToPrimaryBouncerTransitionViewModel +import com.android.systemui.keyguard.ui.viewmodel.AodToPrimaryBouncerTransitionViewModel +import com.android.systemui.keyguard.ui.viewmodel.DozingToPrimaryBouncerTransitionViewModel +import com.android.systemui.keyguard.ui.viewmodel.GlanceableHubToPrimaryBouncerTransitionViewModel +import com.android.systemui.keyguard.ui.viewmodel.LockscreenToPrimaryBouncerTransitionViewModel +import com.android.systemui.keyguard.ui.viewmodel.OccludedToPrimaryBouncerTransitionViewModel +import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToAodTransitionViewModel +import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToDozingTransitionViewModel +import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGlanceableHubTransitionViewModel +import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel +import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToLockscreenTransitionViewModel +import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToOccludedTransitionViewModel +import com.android.systemui.res.R +import com.android.systemui.window.flag.WindowBlurFlag +import dagger.Binds +import dagger.Module +import dagger.Provides +import dagger.multibindings.IntoSet +import dagger.multibindings.Multibinds +import kotlinx.coroutines.ExperimentalCoroutinesApi + +/** + * Base module that defines the [PrimaryBouncerTransition] multibinding. All variants of SystemUI + * can install this module to get the default empty version of the multibinding + */ +@Module +interface PrimaryBouncerTransitionModule { + @Multibinds fun primaryBouncerTransitions(): Set<PrimaryBouncerTransition> + + companion object { + @Provides + @SysUISingleton + fun provideBlurConfig(@Main resources: Resources): BlurConfig { + val minBlurRadius = resources.getDimensionPixelSize(R.dimen.min_window_blur_radius) + val maxBlurRadius = + if (WindowBlurFlag.isEnabled) { + resources.getDimensionPixelSize(R.dimen.max_shade_window_blur_radius) + } else { + resources.getDimensionPixelSize(R.dimen.max_window_blur_radius) + } + return BlurConfig(minBlurRadius.toFloat(), maxBlurRadius.toFloat()) + } + } +} + +/** + * Module that installs all the implementations of [PrimaryBouncerTransition] from different + * keyguard states to and away from the primary bouncer. + */ +@ExperimentalCoroutinesApi +@Module +interface PrimaryBouncerTransitionImplModule { + @Binds + @IntoSet + fun fromAod(impl: AodToPrimaryBouncerTransitionViewModel): PrimaryBouncerTransition + + @Binds + @IntoSet + fun fromAlternateBouncer( + impl: AlternateBouncerToPrimaryBouncerTransitionViewModel + ): PrimaryBouncerTransition + + @Binds + @IntoSet + fun fromDozing(impl: DozingToPrimaryBouncerTransitionViewModel): PrimaryBouncerTransition + + @Binds + @IntoSet + fun fromLockscreen( + impl: LockscreenToPrimaryBouncerTransitionViewModel + ): PrimaryBouncerTransition + + @Binds + @IntoSet + fun fromGlanceableHub( + impl: GlanceableHubToPrimaryBouncerTransitionViewModel + ): PrimaryBouncerTransition + + @Binds + @IntoSet + fun fromOccluded(impl: OccludedToPrimaryBouncerTransitionViewModel): PrimaryBouncerTransition + + @Binds + @IntoSet + fun toAod(impl: PrimaryBouncerToAodTransitionViewModel): PrimaryBouncerTransition + + @Binds + @IntoSet + fun toLockscreen(impl: PrimaryBouncerToLockscreenTransitionViewModel): PrimaryBouncerTransition + + @Binds + @IntoSet + fun toDozing(impl: PrimaryBouncerToDozingTransitionViewModel): PrimaryBouncerTransition + + @Binds + @IntoSet + fun toGlanceableHub( + impl: PrimaryBouncerToGlanceableHubTransitionViewModel + ): PrimaryBouncerTransition + + @Binds + @IntoSet + fun toGone(impl: PrimaryBouncerToGoneTransitionViewModel): PrimaryBouncerTransition + + @Binds + @IntoSet + fun toOccluded(impl: PrimaryBouncerToOccludedTransitionViewModel): PrimaryBouncerTransition +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/BlurConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/BlurConfig.kt new file mode 100644 index 000000000000..542fb9b46bef --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/BlurConfig.kt @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2025 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.keyguard.ui.transitions + +import javax.inject.Inject + +/** Config that provides the max and min blur radius for the window blurs. */ +data class BlurConfig(val minBlurRadiusPx: Float, val maxBlurRadiusPx: Float) { + // No-op config that will be used by dagger of other SysUI variants which don't blur the + // background surface. + @Inject constructor() : this(0.0f, 0.0f) +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/PrimaryBouncerTransition.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/PrimaryBouncerTransition.kt index 4a0817b2bdf8..e77e9dd9e9ed 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/PrimaryBouncerTransition.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/PrimaryBouncerTransition.kt @@ -16,37 +16,15 @@ package com.android.systemui.keyguard.ui.transitions -import android.content.res.Resources -import android.util.MathUtils -import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.dagger.qualifiers.Main -import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToPrimaryBouncerTransitionViewModel -import com.android.systemui.keyguard.ui.viewmodel.AodToPrimaryBouncerTransitionViewModel -import com.android.systemui.keyguard.ui.viewmodel.DozingToPrimaryBouncerTransitionViewModel -import com.android.systemui.keyguard.ui.viewmodel.GlanceableHubToPrimaryBouncerTransitionViewModel -import com.android.systemui.keyguard.ui.viewmodel.LockscreenToPrimaryBouncerTransitionViewModel -import com.android.systemui.keyguard.ui.viewmodel.OccludedToPrimaryBouncerTransitionViewModel -import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToAodTransitionViewModel -import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToDozingTransitionViewModel -import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGlanceableHubTransitionViewModel -import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel -import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToLockscreenTransitionViewModel -import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToOccludedTransitionViewModel -import com.android.systemui.res.R -import com.android.systemui.window.flag.WindowBlurFlag -import dagger.Binds -import dagger.Module -import dagger.Provides -import dagger.multibindings.IntoSet -import javax.inject.Inject -import kotlinx.coroutines.ExperimentalCoroutinesApi +import android.util.MathUtils.lerp import kotlinx.coroutines.flow.Flow /** * Each PrimaryBouncerTransition is responsible for updating various UI states based on the nature * of the transition. * - * MUST list implementing classes in dagger module [PrimaryBouncerTransitionModule]. + * MUST list implementing classes in dagger module + * [com.android.systemui.keyguard.dagger.PrimaryBouncerTransitionImplModule]. */ interface PrimaryBouncerTransition { /** Radius of blur applied to the window's root view. */ @@ -56,93 +34,5 @@ interface PrimaryBouncerTransition { starBlurRadius: Float, endBlurRadius: Float, transitionProgress: Float, - ): Float { - return MathUtils.lerp(starBlurRadius, endBlurRadius, transitionProgress) - } -} - -/** - * Module that installs all the transitions from different keyguard states to and away from the - * primary bouncer. - */ -@ExperimentalCoroutinesApi -@Module -interface PrimaryBouncerTransitionModule { - @Binds - @IntoSet - fun fromAod(impl: AodToPrimaryBouncerTransitionViewModel): PrimaryBouncerTransition - - @Binds - @IntoSet - fun fromAlternateBouncer( - impl: AlternateBouncerToPrimaryBouncerTransitionViewModel - ): PrimaryBouncerTransition - - @Binds - @IntoSet - fun fromDozing(impl: DozingToPrimaryBouncerTransitionViewModel): PrimaryBouncerTransition - - @Binds - @IntoSet - fun fromLockscreen( - impl: LockscreenToPrimaryBouncerTransitionViewModel - ): PrimaryBouncerTransition - - @Binds - @IntoSet - fun fromGlanceableHub( - impl: GlanceableHubToPrimaryBouncerTransitionViewModel - ): PrimaryBouncerTransition - - @Binds - @IntoSet - fun fromOccluded(impl: OccludedToPrimaryBouncerTransitionViewModel): PrimaryBouncerTransition - - @Binds - @IntoSet - fun toAod(impl: PrimaryBouncerToAodTransitionViewModel): PrimaryBouncerTransition - - @Binds - @IntoSet - fun toLockscreen(impl: PrimaryBouncerToLockscreenTransitionViewModel): PrimaryBouncerTransition - - @Binds - @IntoSet - fun toDozing(impl: PrimaryBouncerToDozingTransitionViewModel): PrimaryBouncerTransition - - @Binds - @IntoSet - fun toGlanceableHub( - impl: PrimaryBouncerToGlanceableHubTransitionViewModel - ): PrimaryBouncerTransition - - @Binds - @IntoSet - fun toGone(impl: PrimaryBouncerToGoneTransitionViewModel): PrimaryBouncerTransition - - @Binds - @IntoSet - fun toOccluded(impl: PrimaryBouncerToOccludedTransitionViewModel): PrimaryBouncerTransition - - companion object { - @Provides - @SysUISingleton - fun provideBlurConfig(@Main resources: Resources): BlurConfig { - val minBlurRadius = resources.getDimensionPixelSize(R.dimen.min_window_blur_radius) - val maxBlurRadius = - if (WindowBlurFlag.isEnabled) { - resources.getDimensionPixelSize(R.dimen.max_shade_window_blur_radius) - } else { - resources.getDimensionPixelSize(R.dimen.max_window_blur_radius) - } - return BlurConfig(minBlurRadius.toFloat(), maxBlurRadius.toFloat()) - } - } -} - -/** Config that provides the max and min blur radius for the window blurs. */ -data class BlurConfig(val minBlurRadiusPx: Float, val maxBlurRadiusPx: Float) { - // No-op config that will be used by dagger of other SysUI variants which don't blur the - // background surface. - @Inject constructor() : this(0.0f, 0.0f) + ): Float = lerp(starBlurRadius, endBlurRadius, transitionProgress) } diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/BaseMediaProjectionPermissionDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/BaseMediaProjectionPermissionDialogDelegate.kt index e17255a7c2f0..b4dca5dbcb39 100644 --- a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/BaseMediaProjectionPermissionDialogDelegate.kt +++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/BaseMediaProjectionPermissionDialogDelegate.kt @@ -16,24 +16,16 @@ package com.android.systemui.mediaprojection.permission import android.app.AlertDialog -import android.content.Context import android.os.Bundle import android.view.Gravity -import android.view.LayoutInflater import android.view.View -import android.view.ViewGroup -import android.view.ViewStub import android.view.WindowManager -import android.view.accessibility.AccessibilityNodeInfo -import android.widget.AdapterView -import android.widget.ArrayAdapter import android.widget.ImageView import android.widget.Spinner import android.widget.TextView import androidx.annotation.CallSuper import androidx.annotation.ColorRes import androidx.annotation.DrawableRes -import androidx.annotation.LayoutRes import androidx.annotation.StringRes import com.android.systemui.mediaprojection.MediaProjectionMetricsLogger import com.android.systemui.res.R @@ -48,7 +40,7 @@ abstract class BaseMediaProjectionPermissionDialogDelegate<T : AlertDialog>( @DrawableRes private val dialogIconDrawable: Int? = null, @ColorRes private val dialogIconTint: Int? = null, @ScreenShareMode val defaultSelectedMode: Int = screenShareOptions.first().mode, -) : DialogDelegate<T>, AdapterView.OnItemSelectedListener { +) : DialogDelegate<T> { private lateinit var dialogTitle: TextView private lateinit var cancelButton: TextView private lateinit var screenShareModeSpinner: Spinner @@ -84,12 +76,10 @@ abstract class BaseMediaProjectionPermissionDialogDelegate<T : AlertDialog>( dialogTitle = dialog.requireViewById(R.id.screen_share_dialog_title) cancelButton = dialog.requireViewById(android.R.id.button2) updateIcon() - createOptionsView(getOptionsViewLayoutId()) if (!::viewBinder.isInitialized) { viewBinder = createViewBinder() } viewBinder.bind() - initScreenShareSpinner() } private fun updateIcon() { @@ -102,34 +92,6 @@ abstract class BaseMediaProjectionPermissionDialogDelegate<T : AlertDialog>( } } - private fun initScreenShareSpinner() { - val adapter = OptionsAdapter(dialog.context.applicationContext, screenShareOptions) - screenShareModeSpinner = dialog.requireViewById(R.id.screen_share_mode_options) - screenShareModeSpinner.adapter = adapter - screenShareModeSpinner.onItemSelectedListener = this - - // disable redundant Touch & Hold accessibility action for Switch Access - screenShareModeSpinner.accessibilityDelegate = - object : View.AccessibilityDelegate() { - override fun onInitializeAccessibilityNodeInfo( - host: View, - info: AccessibilityNodeInfo, - ) { - info.removeAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK) - super.onInitializeAccessibilityNodeInfo(host, info) - } - } - screenShareModeSpinner.isLongClickable = false - val defaultModePosition = screenShareOptions.indexOfFirst { it.mode == defaultSelectedMode } - screenShareModeSpinner.setSelection(defaultModePosition, /* animate= */ false) - } - - override fun onItemSelected(adapterView: AdapterView<*>?, view: View, pos: Int, id: Long) { - viewBinder.onItemSelected(pos) - } - - override fun onNothingSelected(parent: AdapterView<*>?) {} - fun getSelectedScreenShareOption(): ScreenShareOption { return viewBinder.selectedScreenShareOption } @@ -147,44 +109,4 @@ abstract class BaseMediaProjectionPermissionDialogDelegate<T : AlertDialog>( protected fun setCancelButtonOnClickListener(listener: View.OnClickListener?) { cancelButton.setOnClickListener(listener) } - - // Create additional options that is shown under the share mode spinner - // Eg. the audio and tap toggles in SysUI Recorder - @LayoutRes protected open fun getOptionsViewLayoutId(): Int? = null - - private fun createOptionsView(@LayoutRes layoutId: Int?) { - if (layoutId == null) return - val stub = dialog.requireViewById<View>(R.id.options_stub) as ViewStub - stub.layoutResource = layoutId - stub.inflate() - } -} - -private class OptionsAdapter(context: Context, private val options: List<ScreenShareOption>) : - ArrayAdapter<String>( - context, - R.layout.screen_share_dialog_spinner_text, - options.map { context.getString(it.spinnerText, it.displayName) }, - ) { - - override fun isEnabled(position: Int): Boolean { - return options[position].spinnerDisabledText == null - } - - override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View { - val inflater = LayoutInflater.from(parent.context) - val view = inflater.inflate(R.layout.screen_share_dialog_spinner_item_text, parent, false) - val titleTextView = view.requireViewById<TextView>(android.R.id.text1) - val errorTextView = view.requireViewById<TextView>(android.R.id.text2) - titleTextView.text = getItem(position) - errorTextView.text = options[position].spinnerDisabledText - if (isEnabled(position)) { - errorTextView.visibility = View.GONE - titleTextView.isEnabled = true - } else { - errorTextView.visibility = View.VISIBLE - titleTextView.isEnabled = false - } - return view - } } diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/BaseMediaProjectionPermissionViewBinder.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/BaseMediaProjectionPermissionViewBinder.kt index 728255d168f2..d23db7c51482 100644 --- a/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/BaseMediaProjectionPermissionViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/BaseMediaProjectionPermissionViewBinder.kt @@ -17,8 +17,17 @@ package com.android.systemui.mediaprojection.permission import android.app.AlertDialog +import android.content.Context +import android.view.LayoutInflater import android.view.View +import android.view.ViewGroup +import android.view.ViewStub +import android.view.accessibility.AccessibilityNodeInfo +import android.widget.AdapterView +import android.widget.ArrayAdapter +import android.widget.Spinner import android.widget.TextView +import androidx.annotation.LayoutRes import com.android.systemui.mediaprojection.MediaProjectionMetricsLogger import com.android.systemui.res.R @@ -29,9 +38,10 @@ open class BaseMediaProjectionPermissionViewBinder( private val mediaProjectionMetricsLogger: MediaProjectionMetricsLogger, @ScreenShareMode val defaultSelectedMode: Int = screenShareOptions.first().mode, private val dialog: AlertDialog, -) { +) : AdapterView.OnItemSelectedListener { private lateinit var warning: TextView private lateinit var startButton: TextView + private lateinit var screenShareModeSpinner: Spinner var selectedScreenShareOption: ScreenShareOption = screenShareOptions.first { it.mode == defaultSelectedMode } private var shouldLogCancel: Boolean = true @@ -48,11 +58,13 @@ open class BaseMediaProjectionPermissionViewBinder( warning = dialog.requireViewById(R.id.text_warning) startButton = dialog.requireViewById(android.R.id.button1) initScreenShareOptions() + createOptionsView(getOptionsViewLayoutId()) } private fun initScreenShareOptions() { selectedScreenShareOption = screenShareOptions.first { it.mode == defaultSelectedMode } setOptionSpecificFields() + initScreenShareSpinner() } /** Sets fields on the dialog that change based on which option is selected. */ @@ -61,11 +73,35 @@ open class BaseMediaProjectionPermissionViewBinder( startButton.text = startButtonText } - open fun onItemSelected(pos: Int) { + private fun initScreenShareSpinner() { + val adapter = OptionsAdapter(dialog.context.applicationContext, screenShareOptions) + screenShareModeSpinner = dialog.requireViewById(R.id.screen_share_mode_options) + screenShareModeSpinner.adapter = adapter + screenShareModeSpinner.onItemSelectedListener = this + + // disable redundant Touch & Hold accessibility action for Switch Access + screenShareModeSpinner.accessibilityDelegate = + object : View.AccessibilityDelegate() { + override fun onInitializeAccessibilityNodeInfo( + host: View, + info: AccessibilityNodeInfo, + ) { + info.removeAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK) + super.onInitializeAccessibilityNodeInfo(host, info) + } + } + screenShareModeSpinner.isLongClickable = false + val defaultModePosition = screenShareOptions.indexOfFirst { it.mode == defaultSelectedMode } + screenShareModeSpinner.setSelection(defaultModePosition, /* animate= */ false) + } + + override fun onItemSelected(adapterView: AdapterView<*>?, view: View, pos: Int, id: Long) { selectedScreenShareOption = screenShareOptions[pos] setOptionSpecificFields() } + override fun onNothingSelected(parent: AdapterView<*>?) {} + private val warningText: String get() = dialog.context.getString(selectedScreenShareOption.warningText, appName) @@ -78,4 +114,44 @@ open class BaseMediaProjectionPermissionViewBinder( listener?.onClick(view) } } + + // Create additional options that is shown under the share mode spinner + // Eg. the audio and tap toggles in SysUI Recorder + @LayoutRes protected open fun getOptionsViewLayoutId(): Int? = null + + private fun createOptionsView(@LayoutRes layoutId: Int?) { + if (layoutId == null) return + val stub = dialog.requireViewById<View>(R.id.options_stub) as ViewStub + stub.layoutResource = layoutId + stub.inflate() + } +} + +private class OptionsAdapter(context: Context, private val options: List<ScreenShareOption>) : + ArrayAdapter<String>( + context, + R.layout.screen_share_dialog_spinner_text, + options.map { context.getString(it.spinnerText, it.displayName) }, + ) { + + override fun isEnabled(position: Int): Boolean { + return options[position].spinnerDisabledText == null + } + + override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View { + val inflater = LayoutInflater.from(parent.context) + val view = inflater.inflate(R.layout.screen_share_dialog_spinner_item_text, parent, false) + val titleTextView = view.requireViewById<TextView>(android.R.id.text1) + val errorTextView = view.requireViewById<TextView>(android.R.id.text2) + titleTextView.text = getItem(position) + errorTextView.text = options[position].spinnerDisabledText + if (isEnabled(position)) { + errorTextView.visibility = View.GONE + titleTextView.isEnabled = true + } else { + errorTextView.visibility = View.VISIBLE + titleTextView.isEnabled = false + } + return view + } } diff --git a/packages/SystemUI/src/com/android/systemui/power/domain/interactor/PowerInteractor.kt b/packages/SystemUI/src/com/android/systemui/power/domain/interactor/PowerInteractor.kt index 8a3ee1248f57..f15a7b30dce7 100644 --- a/packages/SystemUI/src/com/android/systemui/power/domain/interactor/PowerInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/power/domain/interactor/PowerInteractor.kt @@ -224,6 +224,10 @@ constructor( } } + fun onWalletLaunchGestureDetected() { + repository.updateWakefulness(powerButtonLaunchGestureTriggered = true) + } + companion object { private const val FSI_WAKE_WHY = "full_screen_intent" diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegate.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegate.kt index 1da4c1d9469d..e5ff2529e335 100644 --- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegate.kt +++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialogDelegate.kt @@ -15,34 +15,15 @@ */ package com.android.systemui.screenrecord -import android.annotation.SuppressLint -import android.app.Activity -import android.app.PendingIntent import android.content.Context -import android.content.Intent import android.hardware.display.DisplayManager import android.os.Bundle -import android.os.Handler -import android.os.Looper -import android.os.ResultReceiver import android.os.UserHandle -import android.view.Display -import android.view.MotionEvent.ACTION_MOVE -import android.view.View -import android.view.accessibility.AccessibilityNodeInfo -import android.widget.AdapterView -import android.widget.ArrayAdapter -import android.widget.Spinner -import android.widget.Switch -import androidx.annotation.LayoutRes import androidx.annotation.StyleRes import com.android.systemui.dagger.qualifiers.Application -import com.android.systemui.mediaprojection.MediaProjectionCaptureTarget import com.android.systemui.mediaprojection.MediaProjectionMetricsLogger -import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorActivity import com.android.systemui.mediaprojection.permission.BaseMediaProjectionPermissionDialogDelegate import com.android.systemui.mediaprojection.permission.BaseMediaProjectionPermissionViewBinder -import com.android.systemui.mediaprojection.permission.ENTIRE_SCREEN import com.android.systemui.mediaprojection.permission.SINGLE_APP import com.android.systemui.mediaprojection.permission.ScreenShareMode import com.android.systemui.plugins.ActivityStarter @@ -115,17 +96,18 @@ class ScreenRecordPermissionDialogDelegate( ): ScreenRecordPermissionDialogDelegate } - private lateinit var tapsSwitch: Switch - private lateinit var audioSwitch: Switch - private lateinit var options: Spinner - override fun createViewBinder(): BaseMediaProjectionPermissionViewBinder { return ScreenRecordPermissionViewBinder( + hostUserHandle, hostUid, mediaProjectionMetricsLogger, defaultSelectedMode, displayManager, dialog, + controller, + activityStarter, + userContextProvider, + onStartRecordingClicked, ) } @@ -137,143 +119,6 @@ class ScreenRecordPermissionDialogDelegate( super<BaseMediaProjectionPermissionDialogDelegate>.onCreate(dialog, savedInstanceState) setDialogTitle(R.string.screenrecord_permission_dialog_title) dialog.setTitle(R.string.screenrecord_title) - setStartButtonOnClickListener { v: View? -> - onStartRecordingClicked?.run() - val selectedScreenShareOption = getSelectedScreenShareOption() - if (selectedScreenShareOption.mode == ENTIRE_SCREEN) { - requestScreenCapture(/* captureTarget= */ null, selectedScreenShareOption.displayId) - } - if (selectedScreenShareOption.mode == SINGLE_APP) { - val intent = Intent(dialog.context, MediaProjectionAppSelectorActivity::class.java) - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - - // We can't start activity for result here so we use result receiver to get - // the selected target to capture - intent.putExtra( - MediaProjectionAppSelectorActivity.EXTRA_CAPTURE_REGION_RESULT_RECEIVER, - CaptureTargetResultReceiver(), - ) - - intent.putExtra( - MediaProjectionAppSelectorActivity.EXTRA_HOST_APP_USER_HANDLE, - hostUserHandle, - ) - intent.putExtra(MediaProjectionAppSelectorActivity.EXTRA_HOST_APP_UID, hostUid) - intent.putExtra( - MediaProjectionAppSelectorActivity.EXTRA_SCREEN_SHARE_TYPE, - MediaProjectionAppSelectorActivity.ScreenShareType.ScreenRecord.name, - ) - activityStarter.startActivity(intent, /* dismissShade= */ true) - } - dialog.dismiss() - } setCancelButtonOnClickListener { dialog.dismiss() } - initRecordOptionsView() - } - - @LayoutRes override fun getOptionsViewLayoutId(): Int = R.layout.screen_record_options - - @SuppressLint("ClickableViewAccessibility") - private fun initRecordOptionsView() { - // TODO(b/378514312): Move this function to ScreenRecordPermissionViewBinder - audioSwitch = dialog.requireViewById(R.id.screenrecord_audio_switch) - tapsSwitch = dialog.requireViewById(R.id.screenrecord_taps_switch) - - // Add these listeners so that the switch only responds to movement - // within its target region, to meet accessibility requirements - audioSwitch.setOnTouchListener { _, event -> event.action == ACTION_MOVE } - tapsSwitch.setOnTouchListener { _, event -> event.action == ACTION_MOVE } - - options = dialog.requireViewById(R.id.screen_recording_options) - val a: ArrayAdapter<*> = - ScreenRecordingAdapter( - dialog.context, - android.R.layout.simple_spinner_dropdown_item, - MODES, - ) - a.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) - options.adapter = a - options.setOnItemClickListenerInt { _: AdapterView<*>?, _: View?, _: Int, _: Long -> - audioSwitch.isChecked = true - } - - // disable redundant Touch & Hold accessibility action for Switch Access - options.accessibilityDelegate = - object : View.AccessibilityDelegate() { - override fun onInitializeAccessibilityNodeInfo( - host: View, - info: AccessibilityNodeInfo, - ) { - info.removeAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK) - super.onInitializeAccessibilityNodeInfo(host, info) - } - } - options.isLongClickable = false - } - - /** - * Starts screen capture after some countdown - * - * @param captureTarget target to capture (could be e.g. a task) or null to record the whole - * screen - */ - private fun requestScreenCapture( - captureTarget: MediaProjectionCaptureTarget?, - displayId: Int = Display.DEFAULT_DISPLAY, - ) { - val userContext = userContextProvider.userContext - val showTaps = getSelectedScreenShareOption().mode != SINGLE_APP && tapsSwitch.isChecked - val audioMode = - if (audioSwitch.isChecked) options.selectedItem as ScreenRecordingAudioSource - else ScreenRecordingAudioSource.NONE - val startIntent = - PendingIntent.getForegroundService( - userContext, - RecordingService.REQUEST_CODE, - RecordingService.getStartIntent( - userContext, - Activity.RESULT_OK, - audioMode.ordinal, - showTaps, - displayId, - captureTarget, - ), - PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE, - ) - val stopIntent = - PendingIntent.getService( - userContext, - RecordingService.REQUEST_CODE, - RecordingService.getStopIntent(userContext), - PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE, - ) - controller.startCountdown(DELAY_MS, INTERVAL_MS, startIntent, stopIntent) - } - - private inner class CaptureTargetResultReceiver : - ResultReceiver(Handler(Looper.getMainLooper())) { - override fun onReceiveResult(resultCode: Int, resultData: Bundle) { - if (resultCode == Activity.RESULT_OK) { - val captureTarget = - resultData.getParcelable( - MediaProjectionAppSelectorActivity.KEY_CAPTURE_TARGET, - MediaProjectionCaptureTarget::class.java, - ) - - // Start recording of the selected target - requestScreenCapture(captureTarget) - } - } - } - - companion object { - private val MODES = - listOf( - ScreenRecordingAudioSource.INTERNAL, - ScreenRecordingAudioSource.MIC, - ScreenRecordingAudioSource.MIC_AND_INTERNAL, - ) - private const val DELAY_MS: Long = 3000 - private const val INTERVAL_MS: Long = 1000 } } diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionViewBinder.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionViewBinder.kt index 88f373ea75a0..9f7e1ade964a 100644 --- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionViewBinder.kt @@ -17,27 +17,51 @@ package com.android.systemui.screenrecord import android.annotation.SuppressLint +import android.app.Activity import android.app.AlertDialog +import android.app.PendingIntent +import android.content.Intent import android.hardware.display.DisplayManager import android.os.Build +import android.os.Bundle +import android.os.Handler +import android.os.Looper +import android.os.ResultReceiver +import android.os.UserHandle import android.view.Display +import android.view.MotionEvent.ACTION_MOVE import android.view.View import android.view.View.GONE import android.view.View.VISIBLE +import android.view.accessibility.AccessibilityNodeInfo +import android.widget.AdapterView +import android.widget.ArrayAdapter +import android.widget.Spinner +import android.widget.Switch +import androidx.annotation.LayoutRes +import com.android.systemui.mediaprojection.MediaProjectionCaptureTarget import com.android.systemui.mediaprojection.MediaProjectionMetricsLogger +import com.android.systemui.mediaprojection.appselector.MediaProjectionAppSelectorActivity import com.android.systemui.mediaprojection.permission.BaseMediaProjectionPermissionViewBinder import com.android.systemui.mediaprojection.permission.ENTIRE_SCREEN import com.android.systemui.mediaprojection.permission.SINGLE_APP import com.android.systemui.mediaprojection.permission.ScreenShareMode import com.android.systemui.mediaprojection.permission.ScreenShareOption +import com.android.systemui.plugins.ActivityStarter import com.android.systemui.res.R +import com.android.systemui.settings.UserContextProvider class ScreenRecordPermissionViewBinder( - hostUid: Int, + private val hostUserHandle: UserHandle, + private val hostUid: Int, mediaProjectionMetricsLogger: MediaProjectionMetricsLogger, @ScreenShareMode defaultSelectedMode: Int, displayManager: DisplayManager, private val dialog: AlertDialog, + private val controller: RecordingController, + private val activityStarter: ActivityStarter, + private val userContextProvider: UserContextProvider, + private val onStartRecordingClicked: Runnable?, ) : BaseMediaProjectionPermissionViewBinder( createOptionList(displayManager), @@ -47,21 +71,90 @@ class ScreenRecordPermissionViewBinder( defaultSelectedMode, dialog, ) { + private lateinit var tapsSwitch: Switch + private lateinit var audioSwitch: Switch private lateinit var tapsView: View + private lateinit var options: Spinner override fun bind() { super.bind() initRecordOptionsView() + setStartButtonOnClickListener { _: View? -> + onStartRecordingClicked?.run() + if (selectedScreenShareOption.mode == ENTIRE_SCREEN) { + requestScreenCapture( + captureTarget = null, + displayId = selectedScreenShareOption.displayId, + ) + } + if (selectedScreenShareOption.mode == SINGLE_APP) { + val intent = Intent(dialog.context, MediaProjectionAppSelectorActivity::class.java) + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + + // We can't start activity for result here so we use result receiver to get + // the selected target to capture + intent.putExtra( + MediaProjectionAppSelectorActivity.EXTRA_CAPTURE_REGION_RESULT_RECEIVER, + CaptureTargetResultReceiver(), + ) + + intent.putExtra( + MediaProjectionAppSelectorActivity.EXTRA_HOST_APP_USER_HANDLE, + hostUserHandle, + ) + intent.putExtra(MediaProjectionAppSelectorActivity.EXTRA_HOST_APP_UID, hostUid) + intent.putExtra( + MediaProjectionAppSelectorActivity.EXTRA_SCREEN_SHARE_TYPE, + MediaProjectionAppSelectorActivity.ScreenShareType.ScreenRecord.name, + ) + activityStarter.startActivity(intent, /* dismissShade= */ true) + } + dialog.dismiss() + } } @SuppressLint("ClickableViewAccessibility") private fun initRecordOptionsView() { + audioSwitch = dialog.requireViewById(R.id.screenrecord_audio_switch) + tapsSwitch = dialog.requireViewById(R.id.screenrecord_taps_switch) + tapsView = dialog.requireViewById(R.id.show_taps) updateTapsViewVisibility() + + // Add these listeners so that the switch only responds to movement + // within its target region, to meet accessibility requirements + audioSwitch.setOnTouchListener { _, event -> event.action == ACTION_MOVE } + tapsSwitch.setOnTouchListener { _, event -> event.action == ACTION_MOVE } + + options = dialog.requireViewById(R.id.screen_recording_options) + val a: ArrayAdapter<*> = + ScreenRecordingAdapter( + dialog.context, + android.R.layout.simple_spinner_dropdown_item, + MODES, + ) + a.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) + options.adapter = a + options.setOnItemClickListenerInt { _: AdapterView<*>?, _: View?, _: Int, _: Long -> + audioSwitch.isChecked = true + } + + // disable redundant Touch & Hold accessibility action for Switch Access + options.accessibilityDelegate = + object : View.AccessibilityDelegate() { + override fun onInitializeAccessibilityNodeInfo( + host: View, + info: AccessibilityNodeInfo, + ) { + info.removeAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK) + super.onInitializeAccessibilityNodeInfo(host, info) + } + } + options.isLongClickable = false } - override fun onItemSelected(pos: Int) { - super.onItemSelected(pos) + override fun onItemSelected(adapterView: AdapterView<*>?, view: View, pos: Int, id: Long) { + super.onItemSelected(adapterView, view, pos, id) updateTapsViewVisibility() } @@ -69,7 +162,73 @@ class ScreenRecordPermissionViewBinder( tapsView.visibility = if (selectedScreenShareOption.mode == SINGLE_APP) GONE else VISIBLE } + @LayoutRes override fun getOptionsViewLayoutId(): Int = R.layout.screen_record_options + + /** + * Starts screen capture after some countdown + * + * @param captureTarget target to capture (could be e.g. a task) or null to record the whole + * screen + */ + private fun requestScreenCapture( + captureTarget: MediaProjectionCaptureTarget?, + displayId: Int = Display.DEFAULT_DISPLAY, + ) { + val userContext = userContextProvider.userContext + val showTaps = selectedScreenShareOption.mode != SINGLE_APP && tapsSwitch.isChecked + val audioMode = + if (audioSwitch.isChecked) options.selectedItem as ScreenRecordingAudioSource + else ScreenRecordingAudioSource.NONE + val startIntent = + PendingIntent.getForegroundService( + userContext, + RecordingService.REQUEST_CODE, + RecordingService.getStartIntent( + userContext, + Activity.RESULT_OK, + audioMode.ordinal, + showTaps, + displayId, + captureTarget, + ), + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE, + ) + val stopIntent = + PendingIntent.getService( + userContext, + RecordingService.REQUEST_CODE, + RecordingService.getStopIntent(userContext), + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE, + ) + controller.startCountdown(DELAY_MS, INTERVAL_MS, startIntent, stopIntent) + } + + private inner class CaptureTargetResultReceiver : + ResultReceiver(Handler(Looper.getMainLooper())) { + override fun onReceiveResult(resultCode: Int, resultData: Bundle) { + if (resultCode == Activity.RESULT_OK) { + val captureTarget = + resultData.getParcelable( + MediaProjectionAppSelectorActivity.KEY_CAPTURE_TARGET, + MediaProjectionCaptureTarget::class.java, + ) + + // Start recording of the selected target + requestScreenCapture(captureTarget) + } + } + } + companion object { + private val MODES = + listOf( + ScreenRecordingAudioSource.INTERNAL, + ScreenRecordingAudioSource.MIC, + ScreenRecordingAudioSource.MIC_AND_INTERNAL, + ) + + private const val DELAY_MS: Long = 3000 + private const val INTERVAL_MS: Long = 1000 private val RECORDABLE_DISPLAY_TYPES = intArrayOf( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java index 862f33bb4ec3..c6a4d15705f0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java @@ -183,6 +183,7 @@ public class CommandQueue extends IStatusBar.Stub implements private static final int MSG_ENTER_DESKTOP = 80 << MSG_SHIFT; private static final int MSG_SET_SPLITSCREEN_FOCUS = 81 << MSG_SHIFT; private static final int MSG_TOGGLE_QUICK_SETTINGS_PANEL = 82 << MSG_SHIFT; + private static final int MSG_WALLET_ACTION_LAUNCH_GESTURE = 83 << MSG_SHIFT; public static final int FLAG_EXCLUDE_NONE = 0; public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0; public static final int FLAG_EXCLUDE_RECENTS_PANEL = 1 << 1; @@ -343,6 +344,11 @@ public class CommandQueue extends IStatusBar.Stub implements default void onCameraLaunchGestureDetected(int source) { } /** + * Notifies SysUI that the wallet launch gesture was detected. + */ + default void onWalletLaunchGestureDetected() {} + + /** * Notifies SysUI that the emergency action gesture was detected. */ default void onEmergencyActionLaunchGestureDetected() { } @@ -953,6 +959,18 @@ public class CommandQueue extends IStatusBar.Stub implements } @Override + public void onWalletLaunchGestureDetected() { + synchronized (mLock) { + if (mPowerInteractor != null) { + mPowerInteractor.get().onWalletLaunchGestureDetected(); + } + + mHandler.removeMessages(MSG_WALLET_ACTION_LAUNCH_GESTURE); + mHandler.obtainMessage(MSG_WALLET_ACTION_LAUNCH_GESTURE).sendToTarget(); + } + } + + @Override public void onEmergencyActionLaunchGestureDetected() { synchronized (mLock) { mHandler.removeMessages(MSG_EMERGENCY_ACTION_LAUNCH_GESTURE); @@ -1642,6 +1660,11 @@ public class CommandQueue extends IStatusBar.Stub implements mCallbacks.get(i).onCameraLaunchGestureDetected(msg.arg1); } break; + case MSG_WALLET_ACTION_LAUNCH_GESTURE: + for (int i = 0; i < mCallbacks.size(); i++) { + mCallbacks.get(i).onWalletLaunchGestureDetected(); + } + break; case MSG_EMERGENCY_ACTION_LAUNCH_GESTURE: for (int i = 0; i < mCallbacks.size(); i++) { mCallbacks.get(i).onEmergencyActionLaunchGestureDetected(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/StatusBarChipsModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/StatusBarChipsModule.kt index 6db610bbc3a6..e86a9915fcc2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/StatusBarChipsModule.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/StatusBarChipsModule.kt @@ -20,10 +20,8 @@ import com.android.systemui.CoreStartable import com.android.systemui.dagger.SysUISingleton import com.android.systemui.log.LogBuffer import com.android.systemui.log.LogBufferFactory -import com.android.systemui.statusbar.chips.notification.demo.ui.viewmodel.DemoNotifChipViewModel import com.android.systemui.statusbar.chips.notification.domain.interactor.StatusBarNotificationChipsInteractor import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips -import dagger.Binds import dagger.Lazy import dagger.Module import dagger.Provides @@ -32,11 +30,6 @@ import dagger.multibindings.IntoMap @Module abstract class StatusBarChipsModule { - @Binds - @IntoMap - @ClassKey(DemoNotifChipViewModel::class) - abstract fun binds(impl: DemoNotifChipViewModel): CoreStartable - companion object { @Provides @SysUISingleton diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/demo/ui/viewmodel/DemoNotifChipViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/demo/ui/viewmodel/DemoNotifChipViewModel.kt deleted file mode 100644 index 5fa19ddef1be..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/demo/ui/viewmodel/DemoNotifChipViewModel.kt +++ /dev/null @@ -1,175 +0,0 @@ -/* - * 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.chips.notification.demo.ui.viewmodel - -import android.content.pm.PackageManager -import android.content.pm.PackageManager.NameNotFoundException -import android.graphics.drawable.Drawable -import com.android.systemui.CoreStartable -import com.android.systemui.common.shared.model.Icon -import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips -import com.android.systemui.statusbar.chips.ui.model.ColorsModel -import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel -import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipViewModel -import com.android.systemui.statusbar.commandline.CommandRegistry -import com.android.systemui.statusbar.commandline.ParseableCommand -import com.android.systemui.statusbar.commandline.Type -import com.android.systemui.util.time.SystemClock -import java.io.PrintWriter -import javax.inject.Inject -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow - -/** - * A view model that will emit demo promoted ongoing notification chips from [chip] based on adb - * commands sent by the user. - * - * Example adb commands: - * - * To show a chip with the SysUI icon and custom text and color: - * ``` - * adb shell cmd statusbar demo-notif -p com.android.systemui -t 10min -c "\\#434343" - * ``` - * - * To hide the chip: - * ``` - * adb shell cmd statusbar demo-notif --hide - * ``` - * - * See [DemoNotifCommand] for more information on the adb command spec. - */ -@SysUISingleton -class DemoNotifChipViewModel -@Inject -constructor( - private val commandRegistry: CommandRegistry, - private val packageManager: PackageManager, - private val systemClock: SystemClock, -) : OngoingActivityChipViewModel, CoreStartable { - override fun start() { - commandRegistry.registerCommand(DEMO_COMMAND_NAME) { DemoNotifCommand() } - } - - private val _chip = - MutableStateFlow<OngoingActivityChipModel>(OngoingActivityChipModel.Hidden()) - override val chip: StateFlow<OngoingActivityChipModel> = _chip.asStateFlow() - - private inner class DemoNotifCommand : ParseableCommand(DEMO_COMMAND_NAME) { - private val packageName: String? by - param( - longName = "packageName", - shortName = "p", - description = "The package name for app \"posting\" the demo notification", - valueParser = Type.String, - ) - - private val text: String? by - param( - longName = "text", - shortName = "t", - description = "Text to display in the chip", - valueParser = Type.String, - ) - - private val backgroundColor: Int? by - param( - longName = "color", - shortName = "c", - description = - "The color to show as the chip background color. " + - "You can either just write a basic color like 'red' or 'green', " + - "or you can include a #RRGGBB string in this format: \"\\\\#434343\".", - valueParser = Type.Color, - ) - - private val hide by - flag(longName = "hide", description = "Hides any existing demo notification chip") - - override fun execute(pw: PrintWriter) { - if (!StatusBarNotifChips.isEnabled) { - pw.println( - "Error: com.android.systemui.status_bar_notification_chips must be enabled " + - "before using this demo feature" - ) - return - } - - if (hide) { - _chip.value = OngoingActivityChipModel.Hidden() - return - } - - val currentPackageName = packageName - if (currentPackageName == null) { - pw.println("--packageName (or -p) must be included") - return - } - - val appIcon = getAppIcon(currentPackageName) - if (appIcon == null) { - pw.println("Package $currentPackageName could not be found") - return - } - - val colors = - if (backgroundColor != null) { - ColorsModel.Custom(backgroundColorInt = backgroundColor!!) - } else { - ColorsModel.Themed - } - - val currentText = text - if (currentText != null) { - _chip.value = - OngoingActivityChipModel.Shown.Text( - icon = appIcon, - colors = colors, - text = currentText, - ) - } else { - _chip.value = - OngoingActivityChipModel.Shown.Timer( - icon = appIcon, - colors = colors, - startTimeMs = systemClock.elapsedRealtime(), - onClickListener = null, - ) - } - } - - private fun getAppIcon(packageName: String): OngoingActivityChipModel.ChipIcon? { - lateinit var iconDrawable: Drawable - try { - // Note: For the real implementation, we should check if applicationInfo exists - // before fetching the icon, so that we either don't show the chip or show a good - // backup icon in case the app info can't be found for some reason. - iconDrawable = packageManager.getApplicationIcon(packageName) - } catch (e: NameNotFoundException) { - return null - } - return OngoingActivityChipModel.ChipIcon.FullColorAppIcon( - Icon.Loaded(drawable = iconDrawable, contentDescription = null) - ) - } - } - - companion object { - private const val DEMO_COMMAND_NAME = "demo-notif" - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/domain/interactor/SingleNotificationChipInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/domain/interactor/SingleNotificationChipInteractor.kt index dff6f567f6c6..836cf49d4d63 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/domain/interactor/SingleNotificationChipInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/domain/interactor/SingleNotificationChipInteractor.kt @@ -42,12 +42,15 @@ import kotlinx.coroutines.flow.map * * [StatusBarNotificationChipsInteractor] will collect all the individual instances of this * interactor and send all the necessary information to the UI layer. + * + * @property creationTime the time when the notification first appeared as promoted. */ @OptIn(ExperimentalCoroutinesApi::class) class SingleNotificationChipInteractor @AssistedInject constructor( @Assisted startingModel: ActiveNotificationModel, + @Assisted val creationTime: Long, private val activityManagerRepository: ActivityManagerRepository, @StatusBarChipsLog private val logBuffer: LogBuffer, ) { @@ -142,6 +145,9 @@ constructor( @AssistedFactory fun interface Factory { - fun create(startingModel: ActiveNotificationModel): SingleNotificationChipInteractor + fun create( + startingModel: ActiveNotificationModel, + creationTime: Long, + ): SingleNotificationChipInteractor } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/domain/interactor/StatusBarNotificationChipsInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/domain/interactor/StatusBarNotificationChipsInteractor.kt index e8cb35b06999..2121f94caced 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/domain/interactor/StatusBarNotificationChipsInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/domain/interactor/StatusBarNotificationChipsInteractor.kt @@ -29,6 +29,7 @@ import com.android.systemui.statusbar.chips.notification.domain.model.Notificati import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor import com.android.systemui.util.kotlin.pairwise +import com.android.systemui.util.time.SystemClock import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -48,6 +49,7 @@ class StatusBarNotificationChipsInteractor @Inject constructor( @Background private val backgroundScope: CoroutineScope, + private val systemClock: SystemClock, private val activeNotificationsInteractor: ActiveNotificationsInteractor, private val singleNotificationChipInteractorFactory: SingleNotificationChipInteractor.Factory, @StatusBarChipsLog private val logBuffer: LogBuffer, @@ -95,21 +97,26 @@ constructor( activeNotificationsInteractor.promotedOngoingNotifications .pairwise(initialValue = emptyList()) .collect { (oldNotifs, currentNotifs) -> - val removedNotifs = oldNotifs.minus(currentNotifs.toSet()) - removedNotifs.forEach { removedNotif -> - val wasRemoved = promotedNotificationInteractorMap.remove(removedNotif.key) + val removedNotifKeys = + oldNotifs.map { it.key }.minus(currentNotifs.map { it.key }.toSet()) + removedNotifKeys.forEach { removedNotifKey -> + val wasRemoved = promotedNotificationInteractorMap.remove(removedNotifKey) if (wasRemoved == null) { logger.w({ "Attempted to remove $str1 from interactor map but it wasn't present" }) { - str1 = removedNotif.key + str1 = removedNotifKey } } } + currentNotifs.forEach { notif -> val interactor = promotedNotificationInteractorMap.computeIfAbsent(notif.key) { - singleNotificationChipInteractorFactory.create(notif) + singleNotificationChipInteractorFactory.create( + notif, + creationTime = systemClock.currentTimeMillis(), + ) } interactor.setNotification(notif) } @@ -130,7 +137,15 @@ constructor( val notificationChips: Flow<List<NotificationChipModel>> = if (StatusBarNotifChips.isEnabled) { // For all our current interactors... - promotedNotificationInteractors.flatMapLatest { interactors -> + promotedNotificationInteractors.flatMapLatest { intrs -> + // Stable-sort the promoted notifications by when they first appeared so that: + // 1) The chips don't switch places if the older chip gets a notification update. + // 2) The chips don't switch places when the second chip is tapped. (Whichever + // notification is showing heads-up is considered to be the top notification, which + // means tapping the second chip would move it to be the first chip if we didn't + // sort by appearance time here.) + // 3) Older chips get hidden if there's not enough room for all chips. + val interactors = intrs.sortedByDescending { it.creationTime } if (interactors.isNotEmpty()) { // Combine each interactor's [notificationChip] flow... val allNotificationChips: List<Flow<NotificationChipModel?>> = diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt index bcd8cfaa5c5a..2f6431b05c8b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/notification/ui/viewmodel/NotifChipsViewModel.kt @@ -33,6 +33,7 @@ import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.launch /** A view model for status bar chips for promoted ongoing notifications. */ @@ -50,11 +51,12 @@ constructor( */ val chips: Flow<List<OngoingActivityChipModel.Shown>> = combine( - notifChipsInteractor.notificationChips, - headsUpNotificationInteractor.statusBarHeadsUpState, - ) { notifications, headsUpState -> - notifications.map { it.toActivityChipModel(headsUpState) } - } + notifChipsInteractor.notificationChips, + headsUpNotificationInteractor.statusBarHeadsUpState, + ) { notifications, headsUpState -> + notifications.map { it.toActivityChipModel(headsUpState) } + } + .distinctUntilChanged() /** Converts the notification to the [OngoingActivityChipModel] object. */ private fun NotificationChipModel.toActivityChipModel( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt index c40df98f39ba..059e69a9275b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt @@ -104,12 +104,6 @@ object OngoingActivityChipBinder { defaultIconView.visibility = View.VISIBLE defaultIconView.tintView(iconTint) } - is OngoingActivityChipModel.ChipIcon.FullColorAppIcon -> { - StatusBarNotifChips.assertInNewMode() - IconViewBinder.bind(icon.impl, defaultIconView) - defaultIconView.visibility = View.VISIBLE - defaultIconView.untintView() - } is OngoingActivityChipModel.ChipIcon.StatusBarView -> { StatusBarConnectedDisplays.assertInLegacyMode() setStatusBarIconView(defaultIconView, icon.impl, iconTint, backgroundView) @@ -176,10 +170,6 @@ object OngoingActivityChipBinder { this.imageTintList = ColorStateList.valueOf(color) } - private fun ImageView.untintView() { - this.imageTintList = null - } - private fun generateCustomIconLayoutParams(iconView: ImageView): FrameLayout.LayoutParams { val customIconSize = iconView.context.resources.getDimensionPixelSize( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/ColorsModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/ColorsModel.kt index efedf41e4684..cac25d04f1a5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/ColorsModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/ColorsModel.kt @@ -39,26 +39,12 @@ sealed interface ColorsModel { Utils.getColorAttrDefaultColor(context, com.android.internal.R.attr.colorPrimary) } - /** - * The chip should have the given background color and primary text color. - * - * If [primaryTextColorInt] is null, the text color will match the current UI mode (light/dark). - */ - data class Custom(val backgroundColorInt: Int, val primaryTextColorInt: Int? = null) : - ColorsModel { + /** The chip should have the given background color and primary text color. */ + data class Custom(val backgroundColorInt: Int, val primaryTextColorInt: Int) : ColorsModel { override fun background(context: Context): ColorStateList = ColorStateList.valueOf(backgroundColorInt) - // TODO(b/361346412): When UI mode changes, the chip should automatically re-render with - // the right text color. Right now, it has the right text color when the chip is first - // created but the color doesn't update if UI mode changes. - override fun text(context: Context): Int { - return primaryTextColorInt - ?: Utils.getColorAttrDefaultColor( - context, - com.android.internal.R.color.materialColorOnSurface, - ) - } + override fun text(context: Context): Int = primaryTextColorInt } /** The chip should have a red background with white text. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/OngoingActivityChipModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/OngoingActivityChipModel.kt index 18217d786cd4..c81e8e211507 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/OngoingActivityChipModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/model/OngoingActivityChipModel.kt @@ -153,8 +153,5 @@ sealed class OngoingActivityChipModel { * UI created internally. */ data class SingleColorIcon(val impl: Icon) : ChipIcon - - /** This icon is an app icon in full color (so it should not get tinted in any way). */ - data class FullColorAppIcon(val impl: Icon) : ChipIcon } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModel.kt index 45efc57685f7..baa9d8b8b794 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModel.kt @@ -24,20 +24,19 @@ import com.android.systemui.statusbar.chips.StatusBarChipLogTags.pad import com.android.systemui.statusbar.chips.StatusBarChipsLog import com.android.systemui.statusbar.chips.call.ui.viewmodel.CallChipViewModel import com.android.systemui.statusbar.chips.casttootherdevice.ui.viewmodel.CastToOtherDeviceChipViewModel -import com.android.systemui.statusbar.chips.notification.demo.ui.viewmodel.DemoNotifChipViewModel import com.android.systemui.statusbar.chips.notification.shared.StatusBarNotifChips import com.android.systemui.statusbar.chips.notification.ui.viewmodel.NotifChipsViewModel import com.android.systemui.statusbar.chips.screenrecord.ui.viewmodel.ScreenRecordChipViewModel import com.android.systemui.statusbar.chips.sharetoapp.ui.viewmodel.ShareToAppChipViewModel import com.android.systemui.statusbar.chips.ui.model.MultipleOngoingActivityChipsModel import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel -import com.android.systemui.util.kotlin.combine import com.android.systemui.util.kotlin.pairwise import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn @@ -57,7 +56,6 @@ constructor( castToOtherDeviceChipViewModel: CastToOtherDeviceChipViewModel, callChipViewModel: CallChipViewModel, notifChipsViewModel: NotifChipsViewModel, - demoNotifChipViewModel: DemoNotifChipViewModel, @StatusBarChipsLog private val logger: LogBuffer, ) { private enum class ChipType { @@ -66,8 +64,6 @@ constructor( CastToOtherDevice, Call, Notification, - /** A demo of a notification chip, used just for testing. */ - DemoNotification, } /** Model that helps us internally track the various chip states from each of the types. */ @@ -89,7 +85,6 @@ constructor( val castToOtherDevice: OngoingActivityChipModel.Hidden, val call: OngoingActivityChipModel.Hidden, val notifs: OngoingActivityChipModel.Hidden, - val demoNotif: OngoingActivityChipModel.Hidden, ) : InternalChipModel } @@ -99,7 +94,6 @@ constructor( val castToOtherDevice: OngoingActivityChipModel = OngoingActivityChipModel.Hidden(), val call: OngoingActivityChipModel = OngoingActivityChipModel.Hidden(), val notifs: List<OngoingActivityChipModel.Shown> = emptyList(), - val demoNotif: OngoingActivityChipModel = OngoingActivityChipModel.Hidden(), ) /** Bundles all the incoming chips into one object to easily pass to various flows. */ @@ -110,8 +104,7 @@ constructor( castToOtherDeviceChipViewModel.chip, callChipViewModel.chip, notifChipsViewModel.chips, - demoNotifChipViewModel.chip, - ) { screenRecord, shareToApp, castToOtherDevice, call, notifs, demoNotif -> + ) { screenRecord, shareToApp, castToOtherDevice, call, notifs -> logger.log( TAG, LogLevel.INFO, @@ -129,9 +122,8 @@ constructor( str1 = call.logName // TODO(b/364653005): Log other information for notification chips. str2 = notifs.map { it.logName }.toString() - str3 = demoNotif.logName }, - { "... > Call=$str1 > Notifs=$str2 > DemoNotif=$str3" }, + { "... > Call=$str1 > Notifs=$str2" }, ) ChipBundle( screenRecord = screenRecord, @@ -139,7 +131,6 @@ constructor( castToOtherDevice = castToOtherDevice, call = call, notifs = notifs, - demoNotif = demoNotif, ) } // Some of the chips could have timers in them and we don't want the start time @@ -282,14 +273,6 @@ constructor( remainingChips = bundle.copy(notifs = bundle.notifs.subList(1, bundle.notifs.size)), ) - bundle.demoNotif is OngoingActivityChipModel.Shown -> { - StatusBarNotifChips.assertInNewMode() - MostImportantChipResult( - mostImportantChip = - InternalChipModel.Shown(ChipType.DemoNotification, bundle.demoNotif), - remainingChips = bundle.copy(demoNotif = OngoingActivityChipModel.Hidden()), - ) - } else -> { // We should only get here if all chip types are hidden check(bundle.screenRecord is OngoingActivityChipModel.Hidden) @@ -297,7 +280,6 @@ constructor( check(bundle.castToOtherDevice is OngoingActivityChipModel.Hidden) check(bundle.call is OngoingActivityChipModel.Hidden) check(bundle.notifs.isEmpty()) - check(bundle.demoNotif is OngoingActivityChipModel.Hidden) MostImportantChipResult( mostImportantChip = InternalChipModel.Hidden( @@ -306,7 +288,6 @@ constructor( castToOtherDevice = bundle.castToOtherDevice, call = bundle.call, notifs = OngoingActivityChipModel.Hidden(), - demoNotif = bundle.demoNotif, ), // All the chips are already hidden, so no need to filter anything out of the // bundle. @@ -335,7 +316,6 @@ constructor( ChipType.CastToOtherDevice -> new.castToOtherDevice ChipType.Call -> new.call ChipType.Notification -> new.notifs - ChipType.DemoNotification -> new.demoNotif } } else if (new is InternalChipModel.Shown) { // If we have a chip to show, always show it. @@ -357,7 +337,6 @@ constructor( castToOtherDevice = OngoingActivityChipModel.Hidden(), call = OngoingActivityChipModel.Hidden(), notifs = OngoingActivityChipModel.Hidden(), - demoNotif = OngoingActivityChipModel.Hidden(), ) private val DEFAULT_MULTIPLE_INTERNAL_HIDDEN_MODEL = diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/CallbackHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/CallbackHandler.java index 5391992baf16..03d6494e9de7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/CallbackHandler.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/CallbackHandler.java @@ -171,28 +171,6 @@ public class CallbackHandler extends Handler implements EmergencyListener, Signa } @Override - public void setCallIndicator(IconState statusIcon, int subId) { - String currentCallback = new StringBuilder() - .append("setCallIndicator: ") - .append("statusIcon=").append(statusIcon).append(",") - .append("subId=").append(subId) - .toString(); - if (!currentCallback.equals(mLastCallback)) { - mLastCallback = currentCallback; - String log = new StringBuilder() - .append(SSDF.format(System.currentTimeMillis())).append(",") - .append(currentCallback).append(",") - .toString(); - recordLastCallback(log); - } - post(() -> { - for (SignalCallback signalCluster : mSignalCallbacks) { - signalCluster.setCallIndicator(statusIcon, subId); - } - }); - } - - @Override public void setSubs(List<SubscriptionInfo> subs) { String currentCallback = new StringBuilder() .append("setSubs: ") diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/EthernetSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/EthernetSignalController.java index acd97795c128..70f713519ecd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/EthernetSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/EthernetSignalController.java @@ -20,10 +20,12 @@ import android.net.NetworkCapabilities; import com.android.settingslib.AccessibilityContentDescriptions; import com.android.settingslib.SignalIcon.IconGroup; +import com.android.systemui.statusbar.pipeline.ethernet.domain.EthernetInteractor; import java.util.BitSet; -/** */ +/** @deprecated use {@link EthernetInteractor} instead. */ +@Deprecated public class EthernetSignalController extends SignalController<ConnectivityState, IconGroup> { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java index d6df987ba5a1..a6ac372023e4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java @@ -44,6 +44,7 @@ import com.android.settingslib.mobile.MobileStatusTracker.SubscriptionDefaults; import com.android.settingslib.mobile.TelephonyIcons; import com.android.settingslib.net.SignalStrengthUtil; import com.android.systemui.res.R; +import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor; import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy; import com.android.systemui.util.CarrierConfigTracker; @@ -55,7 +56,10 @@ import java.util.Map; /** * Monitors the mobile signal changes and update the SysUI icons. + * + * @deprecated Use {@link MobileIconsInteractor} instead. */ +@Deprecated public class MobileSignalController extends SignalController<MobileState, MobileIconGroup> { private static final SimpleDateFormat SSDF = new SimpleDateFormat("MM-dd HH:mm:ss.SSS"); private static final int STATUS_HISTORY_SIZE = 64; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/SignalCallback.kt b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/SignalCallback.kt index 6be407af581d..cf8240dc1626 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/SignalCallback.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/SignalCallback.kt @@ -22,7 +22,13 @@ import android.telephony.SubscriptionInfo * SignalCallback contains all of the connectivity updates from [NetworkController]. Implement this * interface to be able to draw iconography for Wi-Fi, mobile data, ethernet, call strength * indicators, etc. + * + * @deprecated */ +@Deprecated( + "Use Recommended Architecture classes instead: MobileIconsInteractor, WifiInteractor, " + + "AirplaneModeInteractor, and EthernetInteractor" +) interface SignalCallback { /** * Called when the Wi-Fi iconography has been updated. Implement this method to draw Wi-Fi icons @@ -35,8 +41,8 @@ interface SignalCallback { * Called when the mobile iconography has been updated. Implement this method to draw mobile * indicators * - * @param mobileDataIndicators a box type containing enough information to properly draw - * mobile data icons + * @param mobileDataIndicators a box type containing enough information to properly draw mobile + * data icons * * NOTE: phones can have multiple subscriptions, so this [mobileDataIndicators] object should be * indexed based on its [subId][MobileDataIndicators.subId] @@ -44,8 +50,8 @@ interface SignalCallback { fun setMobileDataIndicators(mobileDataIndicators: MobileDataIndicators) {} /** - * Called when the list of mobile data subscriptions has changed. Use this method as a chance - * to remove views that are no longer needed, or to make room for new icons to come in + * Called when the list of mobile data subscriptions has changed. Use this method as a chance to + * remove views that are no longer needed, or to make room for new icons to come in * * @param subs a [SubscriptionInfo] for each subscription that we know about */ @@ -53,8 +59,7 @@ interface SignalCallback { /** * Called when: - * 1. The number of [MobileSignalController]s goes to 0 while mobile data is enabled - * OR + * 1. The number of [MobileSignalController]s goes to 0 while mobile data is enabled OR * 2. The presence of any SIM changes * * @param show whether or not to show a "no sim" view @@ -86,6 +91,7 @@ interface SignalCallback { /** * Callback for listeners to be able to update the connectivity status + * * @param noDefaultNetwork whether there is any default network. * @param noValidatedNetwork whether there is any validated network. * @param noNetworksAvailable whether there is any WiFi networks available. @@ -93,15 +99,8 @@ interface SignalCallback { fun setConnectivityStatus( noDefaultNetwork: Boolean, noValidatedNetwork: Boolean, - noNetworksAvailable: Boolean - ) { } - - /** - * Callback for listeners to be able to update the call indicator - * @param statusIcon the icon for the call indicator - * @param subId subscription ID for which to update the UI - */ - fun setCallIndicator(statusIcon: IconState, subId: Int) {} + noNetworksAvailable: Boolean, + ) {} } /** Box type for [SignalCallback.setWifiIndicators] */ @@ -113,19 +112,28 @@ data class WifiIndicators( @JvmField val activityOut: Boolean, @JvmField val description: String?, @JvmField val isTransient: Boolean, - @JvmField val statusLabel: String? + @JvmField val statusLabel: String?, ) { override fun toString(): String { return StringBuilder("WifiIndicators[") - .append("enabled=").append(enabled) - .append(",statusIcon=").append(statusIcon?.toString() ?: "") - .append(",qsIcon=").append(qsIcon?.toString() ?: "") - .append(",activityIn=").append(activityIn) - .append(",activityOut=").append(activityOut) - .append(",qsDescription=").append(description) - .append(",isTransient=").append(isTransient) - .append(",statusLabel=").append(statusLabel) - .append(']').toString() + .append("enabled=") + .append(enabled) + .append(",statusIcon=") + .append(statusIcon?.toString() ?: "") + .append(",qsIcon=") + .append(qsIcon?.toString() ?: "") + .append(",activityIn=") + .append(activityIn) + .append(",activityOut=") + .append(activityOut) + .append(",qsDescription=") + .append(description) + .append(",isTransient=") + .append(isTransient) + .append(",statusLabel=") + .append(statusLabel) + .append(']') + .toString() } } @@ -142,23 +150,37 @@ data class MobileDataIndicators( @JvmField val qsDescription: CharSequence?, @JvmField val subId: Int, @JvmField val roaming: Boolean, - @JvmField val showTriangle: Boolean + @JvmField val showTriangle: Boolean, ) { override fun toString(): String { - return java.lang.StringBuilder("MobileDataIndicators[") - .append("statusIcon=").append(statusIcon?.toString() ?: "") - .append(",qsIcon=").append(qsIcon?.toString() ?: "") - .append(",statusType=").append(statusType) - .append(",qsType=").append(qsType) - .append(",activityIn=").append(activityIn) - .append(",activityOut=").append(activityOut) - .append(",typeContentDescription=").append(typeContentDescription) - .append(",typeContentDescriptionHtml=").append(typeContentDescriptionHtml) - .append(",description=").append(qsDescription) - .append(",subId=").append(subId) - .append(",roaming=").append(roaming) - .append(",showTriangle=").append(showTriangle) - .append(']').toString() + return java.lang + .StringBuilder("MobileDataIndicators[") + .append("statusIcon=") + .append(statusIcon?.toString() ?: "") + .append(",qsIcon=") + .append(qsIcon?.toString() ?: "") + .append(",statusType=") + .append(statusType) + .append(",qsType=") + .append(qsType) + .append(",activityIn=") + .append(activityIn) + .append(",activityOut=") + .append(activityOut) + .append(",typeContentDescription=") + .append(typeContentDescription) + .append(",typeContentDescriptionHtml=") + .append(typeContentDescriptionHtml) + .append(",description=") + .append(qsDescription) + .append(",subId=") + .append(subId) + .append(",roaming=") + .append(roaming) + .append(",showTriangle=") + .append(showTriangle) + .append(']') + .toString() } } @@ -166,13 +188,20 @@ data class MobileDataIndicators( data class IconState( @JvmField val visible: Boolean, @JvmField val icon: Int, - @JvmField val contentDescription: String + @JvmField val contentDescription: String, ) { override fun toString(): String { val builder = java.lang.StringBuilder() - return builder.append("[visible=").append(visible).append(',') - .append("icon=").append(icon).append(',') - .append("contentDescription=").append(contentDescription).append(']') - .toString() + return builder + .append("[visible=") + .append(visible) + .append(',') + .append("icon=") + .append(icon) + .append(',') + .append("contentDescription=") + .append(contentDescription) + .append(']') + .toString() } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/SignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/SignalController.java index 2d2ee4a1317e..8cb312110e76 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/SignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/SignalController.java @@ -34,7 +34,11 @@ import java.util.List; * * @param <T> State of the SysUI controller. * @param <I> Icon groups of the SysUI controller for a given State. + * + * @deprecated "Use Recommended Architecture classes instead: MobileIconsInteractor, WifiInteractor, + * AirplaneModeInteractor, and EthernetInteractor */ +@Deprecated public abstract class SignalController<T extends ConnectivityState, I extends IconGroup> { // Save the previous SignalController.States of all SignalControllers for dumps. static final boolean RECORD_HISTORY = true; @@ -167,10 +171,6 @@ public abstract class SignalController<T extends ConnectivityState, I extends Ic } } - protected final void notifyCallStateChange(IconState statusIcon, int subId) { - mCallbackHandler.setCallIndicator(statusIcon, subId); - } - /** * Returns the resource if resId is not 0, and an empty string otherwise. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiSignalController.java index 0e572bef3b00..9854e27e9d58 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiSignalController.java @@ -36,11 +36,13 @@ import com.android.settingslib.mobile.TelephonyIcons; import com.android.settingslib.wifi.WifiStatusTracker; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.res.R; +import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor; import java.io.PrintWriter; import java.util.BitSet; -/** */ +/** @deprecated use {@link WifiInteractor} instead. */ +@Deprecated public class WifiSignalController extends SignalController<WifiState, IconGroup> { private final boolean mHasMobileDataFeature; private final WifiStatusTracker mWifiTracker; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarOrchestrator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarOrchestrator.kt index f91c5dd1b3ed..9d55f6c1b12a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarOrchestrator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarOrchestrator.kt @@ -39,8 +39,8 @@ import com.android.systemui.statusbar.phone.CentralSurfaces import com.android.systemui.statusbar.phone.PhoneStatusBarTransitions import com.android.systemui.statusbar.phone.PhoneStatusBarViewController import com.android.systemui.statusbar.window.StatusBarWindowController -import com.android.systemui.statusbar.window.data.model.StatusBarWindowState import com.android.systemui.statusbar.window.data.repository.StatusBarWindowStatePerDisplayRepository +import com.android.systemui.statusbar.window.shared.model.StatusBarWindowState import com.android.wm.shell.bubbles.Bubbles import dagger.Lazy import dagger.assisted.Assisted diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt index eb6ec9f59a3e..c7535ec14d5d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt @@ -141,9 +141,6 @@ constructor( wasAdded = false, wasUpdated = false, // Force-set this notification to show heads-up. - // TODO(b/364653005): This means that if you tap on the second notification chip, - // then it moves to become the first chip because whatever notification is showing - // heads-up is considered to be the top notification. shouldHeadsUpEver = true, shouldHeadsUpAgain = true, isPinnedByUser = true, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java index ae311512db01..720a755f633c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java @@ -63,7 +63,7 @@ public interface CentralSurfaces extends Dumpable, LifecycleOwner, CoreStartable boolean SPEW = false; boolean DEBUG_GESTURES = false; boolean DEBUG_MEDIA_FAKE_ARTWORK = false; - boolean DEBUG_CAMERA_LIFT = false; + boolean DEBUG_POWER_BUTTON_GESTURE = false; boolean DEBUG_WINDOW_STATE = false; boolean DEBUG_WAKEUP_DELAY = Compile.IS_DEBUG; boolean SHOW_LOCKSCREEN_MEDIA_ARTWORK = true; @@ -312,6 +312,15 @@ public interface CentralSurfaces extends Dumpable, LifecycleOwner, CoreStartable void setLaunchCameraOnFinishedGoingToSleep(boolean launch); void setLaunchCameraOnFinishedWaking(boolean launch); + /** + * Notifies SysUI to launch wallet when device finishes sleeping. + */ + void setLaunchWalletOnFinishedGoingToSleep(boolean launch); + + /** + * Notifies SysUI to launch wallet when device finishes waking. + */ + void setLaunchWalletOnFinishedWaking(boolean launch); void setLaunchEmergencyActionOnFinishedGoingToSleep(boolean launch); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java index adfcb710da92..1c19dbe31a19 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java @@ -16,6 +16,9 @@ package com.android.systemui.statusbar.phone; +import static android.service.quickaccesswallet.Flags.launchWalletOptionOnPowerDoubleTap; +import static android.service.quickaccesswallet.Flags.launchWalletViaSysuiCallbacks; + import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE; import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_WAKING; @@ -70,6 +73,7 @@ import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.notification.headsup.HeadsUpManager; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler; +import com.android.systemui.wallet.controller.QuickAccessWalletController; import dagger.Lazy; @@ -119,6 +123,11 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba private int mDisabled2; private final EmergencyGestureIntentFactory mEmergencyGestureIntentFactory; + private QuickAccessWalletController mWalletController; + + enum PowerButtonLaunchGestureTarget { + LAUNCH_CAMERA_ON_GESTURE, LAUNCH_WALLET_ON_GESTURE + } @Inject CentralSurfacesCommandQueueCallbacks( @@ -152,7 +161,8 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba QSHost qsHost, ActivityStarter activityStarter, KeyguardInteractor keyguardInteractor, - EmergencyGestureIntentFactory emergencyGestureIntentFactory) { + EmergencyGestureIntentFactory emergencyGestureIntentFactory, + QuickAccessWalletController walletController) { mCentralSurfaces = centralSurfaces; mQsController = quickSettingsController; mContext = context; @@ -186,6 +196,7 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba mVibratorOptional, resources); mActivityStarter = activityStarter; mEmergencyGestureIntentFactory = emergencyGestureIntentFactory; + mWalletController = walletController; } @Override @@ -346,9 +357,15 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba @Override public void onCameraLaunchGestureDetected(int source) { + if (launchWalletOptionOnPowerDoubleTap() && launchWalletViaSysuiCallbacks()) { + onPowerButtonLaunchGestureTriggered( + PowerButtonLaunchGestureTarget.LAUNCH_CAMERA_ON_GESTURE, source); + return; + } + mCentralSurfaces.setLastCameraLaunchSource(source); if (mCentralSurfaces.isGoingToSleep()) { - if (CentralSurfaces.DEBUG_CAMERA_LIFT) { + if (CentralSurfaces.DEBUG_POWER_BUTTON_GESTURE) { Slog.d(CentralSurfaces.TAG, "Finish going to sleep before launching camera"); } mCentralSurfaces.setLaunchCameraOnFinishedGoingToSleep(true); @@ -356,7 +373,7 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba } if (!mCameraLauncherLazy.get().canCameraGestureBeLaunched( mPanelExpansionInteractor.getBarState())) { - if (CentralSurfaces.DEBUG_CAMERA_LIFT) { + if (CentralSurfaces.DEBUG_POWER_BUTTON_GESTURE) { Slog.d(CentralSurfaces.TAG, "Can't launch camera right now"); } return; @@ -389,7 +406,7 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba CentralSurfaces.LAUNCH_TRANSITION_TIMEOUT_MS + 1000L); } if (isWakingUpOrAwake()) { - if (CentralSurfaces.DEBUG_CAMERA_LIFT) { + if (CentralSurfaces.DEBUG_POWER_BUTTON_GESTURE) { Slog.d(CentralSurfaces.TAG, "Launching camera"); } if (mStatusBarKeyguardViewManager.isBouncerShowing()) { @@ -404,7 +421,7 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba // we will dismiss us too early since we are waiting on an activity to be drawn and // incorrectly get notified because of the screen on event (which resumes and pauses // some activities) - if (CentralSurfaces.DEBUG_CAMERA_LIFT) { + if (CentralSurfaces.DEBUG_POWER_BUTTON_GESTURE) { Slog.d(CentralSurfaces.TAG, "Deferring until screen turns on"); } mCentralSurfaces.setLaunchCameraOnFinishedWaking(true); @@ -413,6 +430,13 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba } @Override + public void onWalletLaunchGestureDetected() { + onPowerButtonLaunchGestureTriggered( + PowerButtonLaunchGestureTarget.LAUNCH_WALLET_ON_GESTURE, + /* cameraLaunchSource=*/ -1); + } + + @Override public void onEmergencyActionLaunchGestureDetected() { Intent emergencyIntent = mEmergencyGestureIntentFactory.invoke( EmergencyGesture.ACTION_LAUNCH_EMERGENCY); @@ -577,4 +601,152 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba HapticFeedbackConstants.GESTURE_START ); } + + private void onPowerButtonLaunchGestureTriggered(PowerButtonLaunchGestureTarget target, + int cameraLaunchSource) { + if (!launchWalletOptionOnPowerDoubleTap() || !launchWalletViaSysuiCallbacks()) { + return; + } + + if (target == PowerButtonLaunchGestureTarget.LAUNCH_CAMERA_ON_GESTURE) { + mCentralSurfaces.setLastCameraLaunchSource(cameraLaunchSource); + } + + if (mCentralSurfaces.isGoingToSleep()) { + setLaunchAppOnFinishedGoingToSleep(target); + return; + } + + if (!canAppBeLaunched(PowerButtonLaunchGestureTarget.LAUNCH_CAMERA_ON_GESTURE)) { + if (CentralSurfaces.DEBUG_POWER_BUTTON_GESTURE) { + Slog.d(CentralSurfaces.TAG, "Can't launch app via power button gesture right " + + "now"); + } + return; + } + + if (target == PowerButtonLaunchGestureTarget.LAUNCH_CAMERA_ON_GESTURE) { + mKeyguardInteractor.onCameraLaunchDetected(cameraLaunchSource); + } + + wakeUpFromAppLaunch(target); + vibrateForCameraGesture(); + + if (target == PowerButtonLaunchGestureTarget.LAUNCH_CAMERA_ON_GESTURE && + cameraLaunchSource == StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP) { + Slog.v(CentralSurfaces.TAG, "Camera launch"); + mKeyguardUpdateMonitor.onCameraLaunched(); + } + + if (!mKeyguardStateController.isShowing()) { + switch (target) { + case LAUNCH_CAMERA_ON_GESTURE: + startInsecureCameraIntent(cameraLaunchSource); + break; + case LAUNCH_WALLET_ON_GESTURE: + mWalletController.startGestureUiIntent(mActivityStarter, + /* animationController=*/ null); + break; + } + } else { + if (!mCentralSurfaces.isDeviceInteractive()) { + // Avoid flickering of the scrim when we instant launch and the bouncer + // comes on. + mCentralSurfaces.acquireGestureWakeLock( + CentralSurfaces.LAUNCH_TRANSITION_TIMEOUT_MS + 1000L); + } + if (isWakingUpOrAwake()) { + if (CentralSurfaces.DEBUG_POWER_BUTTON_GESTURE) { + Slog.d(CentralSurfaces.TAG, "Launching app via double power button " + + "gesture"); + } + if (mStatusBarKeyguardViewManager.isBouncerShowing()) { + mStatusBarKeyguardViewManager.reset(true /* hide */); + } + mCentralSurfaces.startLaunchTransitionTimeout(); + switch (target) { + case LAUNCH_CAMERA_ON_GESTURE: + mCameraLauncherLazy.get().launchCamera(cameraLaunchSource, + mPanelExpansionInteractor.isFullyCollapsed()); + break; + case LAUNCH_WALLET_ON_GESTURE: + mWalletController.startGestureUiIntent(mActivityStarter, + /* animationController=*/ null); + break; + } + mCentralSurfaces.updateScrimController(); + } else { + // We need to defer the app launch until the screen comes on, since otherwise + // we will dismiss us too early since we are waiting on an activity to be drawn and + // incorrectly get notified because of the screen on event (which resumes and pauses + // some activities) + if (CentralSurfaces.DEBUG_POWER_BUTTON_GESTURE) { + Slog.d(CentralSurfaces.TAG, "Deferring until screen turns on"); + } + setLaunchAppOnFinishedWaking(target); + } + } + } + + private void setLaunchAppOnFinishedGoingToSleep(PowerButtonLaunchGestureTarget target) { + if (CentralSurfaces.DEBUG_POWER_BUTTON_GESTURE) { + Slog.d(CentralSurfaces.TAG, + "Finish going to sleep before LAUNCHING"); + } + switch (target) { + case LAUNCH_CAMERA_ON_GESTURE: + Slog.d(CentralSurfaces.TAG, "setLaunchCameraOnFinishedGoingToSleep"); + mCentralSurfaces.setLaunchCameraOnFinishedGoingToSleep(true); + break; + case LAUNCH_WALLET_ON_GESTURE: + Slog.d(CentralSurfaces.TAG, "setLaunchWalletOnFinishedGoingToSleep"); + mCentralSurfaces.setLaunchWalletOnFinishedGoingToSleep(true); + break; + + } + } + + private boolean canAppBeLaunched(PowerButtonLaunchGestureTarget target) { + if (target == PowerButtonLaunchGestureTarget.LAUNCH_CAMERA_ON_GESTURE && + !mCameraLauncherLazy.get().canCameraGestureBeLaunched( + mPanelExpansionInteractor.getBarState())) { + if (CentralSurfaces.DEBUG_POWER_BUTTON_GESTURE) { + Slog.d(CentralSurfaces.TAG, "Can't launch camera right now"); + } + return false; + } + return true; + } + + private void startInsecureCameraIntent(int source) { + final Intent cameraIntent = CameraIntents.getInsecureCameraIntent(mContext, + mUserTracker.getUserId()); + cameraIntent.putExtra(CameraIntents.EXTRA_LAUNCH_SOURCE, source); + mActivityStarter.startActivityDismissingKeyguard(cameraIntent, + /* onlyProvisioned=*/ false, /* dismissShade=*/ true, + /* disallowEnterPictureInPictureWhileLaunching=*/ true, + /* callback=*/ null, /*flags=*/ 0,/* animationController=*/ null, + mUserTracker.getUserHandle()); + } + + private void setLaunchAppOnFinishedWaking(PowerButtonLaunchGestureTarget target) { + switch (target) { + case LAUNCH_CAMERA_ON_GESTURE: + mCentralSurfaces.setLaunchCameraOnFinishedWaking(true); + break; + case LAUNCH_WALLET_ON_GESTURE: + mCentralSurfaces.setLaunchWalletOnFinishedWaking(true); + break; + } + } + + private void wakeUpFromAppLaunch(PowerButtonLaunchGestureTarget appLaunch) { + if (!mCentralSurfaces.isDeviceInteractive()) { + int reason = appLaunch == PowerButtonLaunchGestureTarget.LAUNCH_CAMERA_ON_GESTURE ? + PowerManager.WAKE_REASON_CAMERA_LAUNCH : PowerManager.WAKE_REASON_GESTURE; + String details = appLaunch == PowerButtonLaunchGestureTarget.LAUNCH_CAMERA_ON_GESTURE ? + "com.android.systemui:CAMERA_GESTURE" : "com.android.systemui:WALLET_GESTURE"; + mPowerManager.wakeUp(SystemClock.uptimeMillis(), reason, details); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesEmptyImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesEmptyImpl.kt index d4f2a93c025b..7241c80b52cc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesEmptyImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesEmptyImpl.kt @@ -142,6 +142,10 @@ abstract class CentralSurfacesEmptyImpl : CentralSurfaces { override fun setLaunchCameraOnFinishedWaking(launch: Boolean) {} + override fun setLaunchWalletOnFinishedGoingToSleep(launch: Boolean) {} + + override fun setLaunchWalletOnFinishedWaking(launch: Boolean) {} + override fun setLaunchEmergencyActionOnFinishedGoingToSleep(launch: Boolean) {} override fun setLaunchEmergencyActionOnFinishedWaking(launch: Boolean) {} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java index 2bc417e4aada..aba30d2ea5a5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java @@ -27,6 +27,9 @@ import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS; import static androidx.lifecycle.Lifecycle.State.RESUMED; +import static android.service.quickaccesswallet.Flags.launchWalletOptionOnPowerDoubleTap; +import static android.service.quickaccesswallet.Flags.launchWalletViaSysuiCallbacks; + import static com.android.systemui.Dependency.TIME_TICK_HANDLER_NAME; import static com.android.systemui.Flags.keyboardShortcutHelperRewrite; import static com.android.systemui.Flags.lightRevealMigration; @@ -35,7 +38,6 @@ import static com.android.systemui.Flags.statusBarSignalPolicyRefactor; import static com.android.systemui.charging.WirelessChargingAnimation.UNKNOWN_BATTERY_LEVEL; import static com.android.systemui.flags.Flags.SHORTCUT_LIST_SEARCH_LAYOUT; import static com.android.systemui.statusbar.StatusBarState.SHADE; - import android.annotation.Nullable; import android.app.ActivityOptions; import android.app.IWallpaperManager; @@ -230,6 +232,7 @@ import com.android.systemui.util.concurrency.DelayableExecutor; import com.android.systemui.util.concurrency.MessageRouter; import com.android.systemui.util.kotlin.JavaAdapter; import com.android.systemui.volume.VolumeComponent; +import com.android.systemui.wallet.controller.QuickAccessWalletController; import com.android.wm.shell.bubbles.Bubbles; import com.android.wm.shell.startingsurface.SplashscreenContentDrawer; import com.android.wm.shell.startingsurface.StartingSurface; @@ -329,6 +332,20 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { } @Override + public void setLaunchWalletOnFinishedGoingToSleep(boolean launch) { + if (launchWalletOptionOnPowerDoubleTap() && launchWalletViaSysuiCallbacks()) { + mLaunchWalletOnFinishedGoingToSleep = launch; + } + } + + @Override + public void setLaunchWalletOnFinishedWaking(boolean launch) { + if (launchWalletOptionOnPowerDoubleTap() && launchWalletViaSysuiCallbacks()) { + mLaunchWalletWhenFinishedWaking = launch; + } + } + + @Override public void setLaunchEmergencyActionOnFinishedGoingToSleep(boolean launch) { mLaunchEmergencyActionOnFinishedGoingToSleep = launch; } @@ -512,6 +529,8 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { private Runnable mLaunchTransitionCancelRunnable; private boolean mLaunchCameraWhenFinishedWaking; private boolean mLaunchCameraOnFinishedGoingToSleep; + private boolean mLaunchWalletWhenFinishedWaking; + private boolean mLaunchWalletOnFinishedGoingToSleep; private boolean mLaunchEmergencyActionWhenFinishedWaking; private boolean mLaunchEmergencyActionOnFinishedGoingToSleep; private int mLastCameraLaunchSource; @@ -577,6 +596,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { private final EmergencyGestureIntentFactory mEmergencyGestureIntentFactory; private final ViewCaptureAwareWindowManager mViewCaptureAwareWindowManager; + private final QuickAccessWalletController mWalletController; /** * Public constructor for CentralSurfaces. @@ -691,7 +711,8 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { BrightnessMirrorShowingInteractor brightnessMirrorShowingInteractor, GlanceableHubContainerController glanceableHubContainerController, EmergencyGestureIntentFactory emergencyGestureIntentFactory, - ViewCaptureAwareWindowManager viewCaptureAwareWindowManager + ViewCaptureAwareWindowManager viewCaptureAwareWindowManager, + QuickAccessWalletController walletController ) { mContext = context; mNotificationsController = notificationsController; @@ -790,6 +811,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { mGlanceableHubContainerController = null; } mEmergencyGestureIntentFactory = emergencyGestureIntentFactory; + mWalletController = walletController; mLockscreenShadeTransitionController = lockscreenShadeTransitionController; mStartingSurfaceOptional = startingSurfaceOptional; @@ -2509,6 +2531,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { mCameraLauncherLazy.get().setLaunchingAffordance(false); releaseGestureWakeLock(); mLaunchCameraWhenFinishedWaking = false; + mLaunchWalletWhenFinishedWaking = false; mDeviceInteractive = false; updateNotificationPanelTouchState(); @@ -2522,6 +2545,15 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { mLastCameraLaunchSource)); } + if (mLaunchWalletOnFinishedGoingToSleep && launchWalletOptionOnPowerDoubleTap() + && launchWalletViaSysuiCallbacks()) { + mLaunchWalletOnFinishedGoingToSleep = false; + + // This gets executed before we will show Keyguard, so post it in order that the + // state is correct. + mMainExecutor.execute(() -> mCommandQueueCallbacks.onWalletLaunchGestureDetected()); + } + if (mLaunchEmergencyActionOnFinishedGoingToSleep) { mLaunchEmergencyActionOnFinishedGoingToSleep = false; @@ -2627,6 +2659,12 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { mShadeSurface.isFullyCollapsed()); mLaunchCameraWhenFinishedWaking = false; } + if (mLaunchWalletWhenFinishedWaking && launchWalletOptionOnPowerDoubleTap() + && launchWalletViaSysuiCallbacks()) { + mLaunchWalletWhenFinishedWaking = false; + mWalletController.startGestureUiIntent(mActivityStarter, + /*animationController=*/ null); + } if (mLaunchEmergencyActionWhenFinishedWaking) { mLaunchEmergencyActionWhenFinishedWaking = false; Intent emergencyIntent = mEmergencyGestureIntentFactory.invoke( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java index 2433b78fc183..6028f1727f52 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java @@ -528,6 +528,7 @@ public class KeyguardStatusBarViewController extends ViewController<KeyguardStat return; } mDozing = dozing; + updateViewState(); } /** Animate the keyguard status bar in. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt index 2467e0890100..ccd1b6c4e266 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.phone import android.app.StatusBarManager.WINDOW_STATUS_BAR import android.graphics.Point import android.util.Log +import android.view.Display.DEFAULT_DISPLAY import android.view.InputDevice import android.view.MotionEvent import android.view.View @@ -39,7 +40,6 @@ import com.android.systemui.shade.ShadeExpandsOnStatusBarLongPress import com.android.systemui.shade.ShadeLogger import com.android.systemui.shade.ShadeViewController import com.android.systemui.shade.StatusBarLongPressGestureDetector -import com.android.systemui.shade.data.repository.ShadeDisplaysRepository import com.android.systemui.shade.display.StatusBarTouchShadeDisplayPolicy import com.android.systemui.shade.domain.interactor.PanelExpansionInteractor import com.android.systemui.shade.shared.flag.ShadeWindowGoesAround @@ -85,7 +85,6 @@ private constructor( private val darkIconDispatcher: DarkIconDispatcher, private val statusBarContentInsetsProvider: StatusBarContentInsetsProvider, private val lazyStatusBarShadeDisplayPolicy: Lazy<StatusBarTouchShadeDisplayPolicy>, - private val shadeDisplaysRepository: ShadeDisplaysRepository, ) : ViewController<PhoneStatusBarView>(view) { private lateinit var battery: BatteryMeterView @@ -301,12 +300,12 @@ private constructor( } // With the StatusBarConnectedDisplays changes, status bar touches should result in - // shade interaction only if ShadeWindowGoesAround.isEnabled or if touch is on the - // display which currently hosts the shade. + // shade interaction only if ShadeWindowGoesAround.isEnabled or if touch is on default + // display. return if ( !StatusBarConnectedDisplays.isEnabled || ShadeWindowGoesAround.isEnabled || - context.displayId == shadeDisplaysRepository.displayId.value + context.displayId == DEFAULT_DISPLAY ) { shadeViewController.handleExternalTouch(event) } else { @@ -367,7 +366,6 @@ private constructor( @DisplaySpecific private val darkIconDispatcher: DarkIconDispatcher, private val statusBarContentInsetsProviderStore: StatusBarContentInsetsProviderStore, private val lazyStatusBarShadeDisplayPolicy: Lazy<StatusBarTouchShadeDisplayPolicy>, - private val shadeDisplaysRepository: ShadeDisplaysRepository, ) { fun create(view: PhoneStatusBarView): PhoneStatusBarViewController { val statusBarMoveFromCenterAnimationController = @@ -396,7 +394,6 @@ private constructor( darkIconDispatcher, statusBarContentInsetsProviderStore.defaultDisplay, lazyStatusBarShadeDisplayPolicy, - shadeDisplaysRepository, ) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.kt index d699b3821a36..f2fd794975c9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconHolder.kt @@ -16,11 +16,7 @@ package com.android.systemui.statusbar.phone import android.annotation.IntDef -import android.content.Context -import android.graphics.drawable.Icon -import android.os.UserHandle import com.android.internal.statusbar.StatusBarIcon -import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.CallIndicatorIconState import com.android.systemui.statusbar.pipeline.icons.shared.model.ModernStatusBarViewCreator /** Wraps [com.android.internal.statusbar.StatusBarIcon] so we can still have a uniform list */ @@ -136,30 +132,6 @@ open class StatusBarIconHolder private constructor() { holder.tag = subId return holder } - - /** Creates a new StatusBarIconHolder from a CallIndicatorIconState. */ - @JvmStatic - fun fromCallIndicatorState( - context: Context, - state: CallIndicatorIconState, - ): StatusBarIconHolder { - val holder = StatusBarIconHolder() - val resId = if (state.isNoCalling) state.noCallingResId else state.callStrengthResId - val contentDescription = - if (state.isNoCalling) state.noCallingDescription else state.callStrengthDescription - holder.icon = - StatusBarIcon( - UserHandle.SYSTEM, - context.packageName, - Icon.createWithResource(context, resId), - 0, - 0, - contentDescription, - StatusBarIcon.Type.SystemIcon, - ) - holder.tag = state.subId - return holder - } } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java index d5fafe222c40..30dc9b90d0c5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java @@ -17,8 +17,9 @@ package com.android.systemui.statusbar.phone; import static com.android.systemui.Flags.statusBarSignalPolicyRefactor; +import static com.android.systemui.common.shared.model.ContentDescription.loadContentDescription; -import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.Context; import android.os.Handler; import android.util.ArraySet; @@ -26,6 +27,7 @@ import android.util.Log; import com.android.settingslib.mobile.TelephonyIcons; import com.android.systemui.CoreStartable; +import com.android.systemui.common.shared.model.Icon; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.res.R; import com.android.systemui.statusbar.connectivity.IconState; @@ -33,16 +35,13 @@ import com.android.systemui.statusbar.connectivity.NetworkController; import com.android.systemui.statusbar.connectivity.SignalCallback; import com.android.systemui.statusbar.phone.ui.StatusBarIconController; import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor; +import com.android.systemui.statusbar.pipeline.ethernet.domain.EthernetInteractor; +import com.android.systemui.statusbar.pipeline.ethernet.shared.StatusBarSignalPolicyRefactorEthernet; import com.android.systemui.statusbar.policy.SecurityController; import com.android.systemui.tuner.TunerService; import com.android.systemui.tuner.TunerService.Tunable; -import com.android.systemui.util.CarrierConfigTracker; import com.android.systemui.util.kotlin.JavaAdapter; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - import javax.inject.Inject; /** Controls the signal policies for icons shown in the statusbar. */ @@ -59,56 +58,48 @@ public class StatusBarSignalPolicy private final String mSlotMobile; private final String mSlotEthernet; private final String mSlotVpn; - private final String mSlotNoCalling; - private final String mSlotCallStrength; private final Context mContext; private final StatusBarIconController mIconController; private final NetworkController mNetworkController; private final SecurityController mSecurityController; private final Handler mHandler = Handler.getMain(); - private final CarrierConfigTracker mCarrierConfigTracker; private final TunerService mTunerService; private final JavaAdapter mJavaAdapter; private final AirplaneModeInteractor mAirplaneModeInteractor; + private final EthernetInteractor mEthernetInteractor; private boolean mHideAirplane; private boolean mHideMobile; private boolean mHideEthernet; - private final boolean mActivityEnabled; - private final ArrayList<CallIndicatorIconState> mCallIndicatorStates = new ArrayList<>(); private boolean mInitialized; @Inject public StatusBarSignalPolicy( Context context, StatusBarIconController iconController, - CarrierConfigTracker carrierConfigTracker, NetworkController networkController, SecurityController securityController, TunerService tunerService, JavaAdapter javaAdapter, - AirplaneModeInteractor airplaneModeInteractor + AirplaneModeInteractor airplaneModeInteractor, + EthernetInteractor ethernetInteractor ) { mContext = context; mIconController = iconController; - mCarrierConfigTracker = carrierConfigTracker; mJavaAdapter = javaAdapter; mNetworkController = networkController; mSecurityController = securityController; mTunerService = tunerService; mAirplaneModeInteractor = airplaneModeInteractor; + mEthernetInteractor = ethernetInteractor; mSlotAirplane = mContext.getString(com.android.internal.R.string.status_bar_airplane); mSlotMobile = mContext.getString(com.android.internal.R.string.status_bar_mobile); mSlotEthernet = mContext.getString(com.android.internal.R.string.status_bar_ethernet); mSlotVpn = mContext.getString(com.android.internal.R.string.status_bar_vpn); - mSlotNoCalling = mContext.getString(com.android.internal.R.string.status_bar_no_calling); - mSlotCallStrength = - mContext.getString(com.android.internal.R.string.status_bar_call_strength); - mActivityEnabled = mContext.getResources().getBoolean(R.bool.config_showActivity); } @Override @@ -123,6 +114,9 @@ public class StatusBarSignalPolicy mJavaAdapter.alwaysCollectFlow( mAirplaneModeInteractor.isAirplaneMode(), this::updateAirplaneModeIcon); + if (StatusBarSignalPolicyRefactorEthernet.isEnabled()) { + mJavaAdapter.alwaysCollectFlow(mEthernetInteractor.getIcon(), this::updateEthernetIcon); + } } /** Call to initialize and register this class with the system. */ @@ -140,6 +134,9 @@ public class StatusBarSignalPolicy mAirplaneModeInteractor.isAirplaneMode(), this::updateAirplaneModeIcon); } + if (StatusBarSignalPolicyRefactorEthernet.isEnabled()) { + mJavaAdapter.alwaysCollectFlow(mEthernetInteractor.getIcon(), this::updateEthernetIcon); + } } public void destroy() { @@ -201,45 +198,11 @@ public class StatusBarSignalPolicy } @Override - public void setCallIndicator(@NonNull IconState statusIcon, int subId) { - if (DEBUG) { - Log.d(TAG, "setCallIndicator: " - + "statusIcon = " + statusIcon + "," - + "subId = " + subId); - } - CallIndicatorIconState state = getNoCallingState(subId); - if (state == null) { + public void setEthernetIndicators(IconState state) { + if (StatusBarSignalPolicyRefactorEthernet.isEnabled()) { return; } - if (statusIcon.icon == R.drawable.ic_shade_no_calling_sms) { - state.isNoCalling = statusIcon.visible; - state.noCallingDescription = statusIcon.contentDescription; - } else { - state.callStrengthResId = statusIcon.icon; - state.callStrengthDescription = statusIcon.contentDescription; - } - if (mCarrierConfigTracker.getCallStrengthConfig(subId)) { - mIconController.setCallStrengthIcons(mSlotCallStrength, - CallIndicatorIconState.copyStates(mCallIndicatorStates)); - } else { - mIconController.removeIcon(mSlotCallStrength, subId); - } - mIconController.setNoCallingIcons(mSlotNoCalling, - CallIndicatorIconState.copyStates(mCallIndicatorStates)); - } - private CallIndicatorIconState getNoCallingState(int subId) { - for (CallIndicatorIconState state : mCallIndicatorStates) { - if (state.subId == subId) { - return state; - } - } - Log.e(TAG, "Unexpected subscription " + subId); - return null; - } - - @Override - public void setEthernetIndicators(IconState state) { int resId = state.icon; String description = state.contentDescription; @@ -251,6 +214,22 @@ public class StatusBarSignalPolicy } } + private void updateEthernetIcon(@Nullable Icon.Resource ethernetIcon) { + if (StatusBarSignalPolicyRefactorEthernet.isUnexpectedlyInLegacyMode()) { + return; + } + + if (ethernetIcon != null) { + mIconController.setIcon( + mSlotEthernet, + ethernetIcon.getRes(), + loadContentDescription(ethernetIcon.getContentDescription(), mContext)); + mIconController.setIconVisibility(mSlotEthernet, true); + } else { + mIconController.setIconVisibility(mSlotEthernet, false); + } + } + @Override public void setIsAirplaneMode(IconState icon) { if (statusBarSignalPolicyRefactor()) { @@ -287,64 +266,4 @@ public class StatusBarSignalPolicy mContext.getString(R.string.accessibility_airplane_mode)); } } - - /** - * Stores the statusbar state for no Calling & SMS. - */ - public static class CallIndicatorIconState { - public boolean isNoCalling; - public int noCallingResId; - public int callStrengthResId; - public int subId; - public String noCallingDescription; - public String callStrengthDescription; - - private CallIndicatorIconState(int subId) { - this.subId = subId; - this.noCallingResId = R.drawable.ic_shade_no_calling_sms; - this.callStrengthResId = TelephonyIcons.MOBILE_CALL_STRENGTH_ICONS[0]; - } - - @Override - public boolean equals(Object o) { - // Skipping reference equality bc this should be more of a value type - if (o == null || getClass() != o.getClass()) { - return false; - } - CallIndicatorIconState that = (CallIndicatorIconState) o; - return isNoCalling == that.isNoCalling - && noCallingResId == that.noCallingResId - && callStrengthResId == that.callStrengthResId - && subId == that.subId - && noCallingDescription == that.noCallingDescription - && callStrengthDescription == that.callStrengthDescription; - - } - - @Override - public int hashCode() { - return Objects.hash(isNoCalling, noCallingResId, - callStrengthResId, subId, noCallingDescription, callStrengthDescription); - } - - private void copyTo(CallIndicatorIconState other) { - other.isNoCalling = isNoCalling; - other.noCallingResId = noCallingResId; - other.callStrengthResId = callStrengthResId; - other.subId = subId; - other.noCallingDescription = noCallingDescription; - other.callStrengthDescription = callStrengthDescription; - } - - private static List<CallIndicatorIconState> copyStates( - List<CallIndicatorIconState> inStates) { - ArrayList<CallIndicatorIconState> outStates = new ArrayList<>(); - for (CallIndicatorIconState state : inStates) { - CallIndicatorIconState copy = new CallIndicatorIconState(state.subId); - state.copyTo(copy); - outStates.add(copy); - } - return outStates; - } - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconController.java index 0459b9749e0a..6c3438b659de 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconController.java @@ -26,7 +26,6 @@ import androidx.annotation.DrawableRes; import com.android.internal.statusbar.StatusBarIcon; import com.android.systemui.res.R; -import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.CallIndicatorIconState; import java.util.List; @@ -85,15 +84,6 @@ public interface StatusBarIconController { * {@link com.android.systemui.statusbar.pipeline.mobile.ui.binder.MobileIconBinder}. */ void setNewMobileIconSubIds(List<Integer> subIds); - /** - * Display the no calling & SMS icons. - */ - void setCallStrengthIcons(String slot, List<CallIndicatorIconState> states); - - /** - * Display the no calling & SMS icons. - */ - void setNoCallingIcons(String slot, List<CallIndicatorIconState> states); /** Sets whether the icon in the given slot should be visible or not. */ void setIconVisibility(String slot, boolean b); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerImpl.java index e66e8138102e..42a72d2f186f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ui/StatusBarIconControllerImpl.java @@ -47,7 +47,6 @@ import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.StatusIconDisplayable; import com.android.systemui.statusbar.phone.StatusBarIconHolder; import com.android.systemui.statusbar.phone.StatusBarIconHolder.BindableIconHolder; -import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.CallIndicatorIconState; import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags; import com.android.systemui.statusbar.pipeline.icons.shared.BindableIconsRegistry; import com.android.systemui.statusbar.pipeline.icons.shared.model.BindableIcon; @@ -332,56 +331,6 @@ public class StatusBarIconControllerImpl implements Tunable, } } - /** - * Accept a list of CallIndicatorIconStates, and show the call strength icons. - * @param slot statusbar slot for the call strength icons - * @param states All of the no Calling & SMS icon states - */ - @Override - public void setCallStrengthIcons(String slot, List<CallIndicatorIconState> states) { - Slot callStrengthSlot = mStatusBarIconList.getSlot(slot); - Collections.reverse(states); - for (CallIndicatorIconState state : states) { - if (!state.isNoCalling) { - StatusBarIconHolder holder = callStrengthSlot.getHolderForTag(state.subId); - if (holder == null) { - holder = StatusBarIconHolder.fromCallIndicatorState(mContext, state); - } else { - holder.setIcon(new StatusBarIcon(UserHandle.SYSTEM, mContext.getPackageName(), - Icon.createWithResource(mContext, state.callStrengthResId), 0, 0, - state.callStrengthDescription, StatusBarIcon.Type.SystemIcon)); - } - setIcon(slot, holder); - } - setIconVisibility(slot, !state.isNoCalling, state.subId); - } - } - - /** - * Accept a list of CallIndicatorIconStates, and show the no calling icons. - * @param slot statusbar slot for the no calling icons - * @param states All of the no Calling & SMS icon states - */ - @Override - public void setNoCallingIcons(String slot, List<CallIndicatorIconState> states) { - Slot noCallingSlot = mStatusBarIconList.getSlot(slot); - Collections.reverse(states); - for (CallIndicatorIconState state : states) { - if (state.isNoCalling) { - StatusBarIconHolder holder = noCallingSlot.getHolderForTag(state.subId); - if (holder == null) { - holder = StatusBarIconHolder.fromCallIndicatorState(mContext, state); - } else { - holder.setIcon(new StatusBarIcon(UserHandle.SYSTEM, mContext.getPackageName(), - Icon.createWithResource(mContext, state.noCallingResId), 0, 0, - state.noCallingDescription, StatusBarIcon.Type.SystemIcon)); - } - setIcon(slot, holder); - } - setIconVisibility(slot, state.isNoCalling, state.subId); - } - } - private final CommandQueue.Callbacks mCommandQueueCallbacks = new CommandQueue.Callbacks() { @Override public void setIcon(String slot, StatusBarIcon icon) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/ethernet/shared/StatusBarSignalPolicyRefactorEthernet.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/ethernet/shared/StatusBarSignalPolicyRefactorEthernet.kt new file mode 100644 index 000000000000..48747df23e0c --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/ethernet/shared/StatusBarSignalPolicyRefactorEthernet.kt @@ -0,0 +1,61 @@ +/* + * 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.pipeline.ethernet.shared + +import com.android.systemui.Flags +import com.android.systemui.flags.FlagToken +import com.android.systemui.flags.RefactorFlagUtils + +/** Helper for reading or using the status bar signal policy refactor ethernet flag state. */ +@Suppress("NOTHING_TO_INLINE") +object StatusBarSignalPolicyRefactorEthernet { + /** The aconfig flag name */ + const val FLAG_NAME = Flags.FLAG_STATUS_BAR_SIGNAL_POLICY_REFACTOR_ETHERNET + + /** A token used for dependency declaration */ + val token: FlagToken + get() = FlagToken(FLAG_NAME, isEnabled) + + /** Is the refactor enabled */ + @JvmStatic + inline val isEnabled + get() = Flags.statusBarSignalPolicyRefactorEthernet() + + /** + * Called to ensure code is only run when the flag is enabled. This protects users from the + * unintended behaviors caused by accidentally running new logic, while also crashing on an eng + * build to ensure that the refactor author catches issues in testing. + */ + @JvmStatic + inline fun isUnexpectedlyInLegacyMode() = + RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, FLAG_NAME) + + /** + * Called to ensure code is only run when the flag is enabled. This will throw an exception if + * the flag is not enabled to ensure that the refactor author catches issues in testing. + * Caution!! Using this check incorrectly will cause crashes in nextfood builds! + */ + @JvmStatic + inline fun assertInNewMode() = RefactorFlagUtils.assertInNewMode(isEnabled, FLAG_NAME) + + /** + * Called to ensure code is only run when the flag is disabled. This will throw an exception if + * the flag is enabled to ensure that the refactor author catches issues in testing. + */ + @JvmStatic + inline fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, FLAG_NAME) +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt index 99b4aa4b0cf6..d69dc1e06cd6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryImpl.kt @@ -143,7 +143,7 @@ class MobileConnectionRepositoryImpl( object : TelephonyCallback(), TelephonyCallback.CarrierNetworkListener, - TelephonyCallback.CarrierRoamingNtnModeListener, + TelephonyCallback.CarrierRoamingNtnListener, TelephonyCallback.DataActivityListener, TelephonyCallback.DataConnectionStateListener, TelephonyCallback.DataEnabledListener, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt index 7aab47a5d64a..3a6716ab4c7e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImpl.kt @@ -21,7 +21,7 @@ import android.os.OutcomeReceiver import android.telephony.TelephonyCallback import android.telephony.TelephonyManager import android.telephony.satellite.NtnSignalStrengthCallback -import android.telephony.satellite.SatelliteCommunicationAllowedStateCallback +import android.telephony.satellite.SatelliteCommunicationAccessStateCallback import android.telephony.satellite.SatelliteManager import android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS import android.telephony.satellite.SatelliteModemStateCallback @@ -263,9 +263,9 @@ constructor( private fun isSatelliteAvailableFlow(sm: SupportedSatelliteManager): Flow<Boolean> = conflatedCallbackFlow { - val callback = SatelliteCommunicationAllowedStateCallback { allowed -> + val callback = SatelliteCommunicationAccessStateCallback { allowed -> logBuffer.i({ bool1 = allowed }) { - "onSatelliteCommunicationAllowedStateChanged: $bool1" + "onSatelliteCommunicationAccessAllowedStateChanged: $bool1" } trySend(allowed) @@ -273,20 +273,20 @@ constructor( var registered = false try { - logBuffer.i { "registerForCommunicationAllowedStateChanged" } - sm.registerForCommunicationAllowedStateChanged( + logBuffer.i { "registerForCommunicationAccessStateChanged" } + sm.registerForCommunicationAccessStateChanged( bgDispatcher.asExecutor(), callback, ) registered = true } catch (e: Exception) { - logBuffer.e("Error calling registerForCommunicationAllowedStateChanged", e) + logBuffer.e("Error calling registerForCommunicationAccessStateChanged", e) } awaitClose { if (registered) { - logBuffer.i { "unRegisterForCommunicationAllowedStateChanged" } - sm.unregisterForCommunicationAllowedStateChanged(callback) + logBuffer.i { "unRegisterForCommunicationAccessStateChanged" } + sm.unregisterForCommunicationAccessStateChanged(callback) } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/window/data/repository/StatusBarWindowStatePerDisplayRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/window/data/repository/StatusBarWindowStatePerDisplayRepository.kt index bef8c84be5c9..460650ad76f3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/window/data/repository/StatusBarWindowStatePerDisplayRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/window/data/repository/StatusBarWindowStatePerDisplayRepository.kt @@ -24,7 +24,7 @@ import android.app.StatusBarManager.WINDOW_STATUS_BAR import android.app.StatusBarManager.WindowVisibleState import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.statusbar.CommandQueue -import com.android.systemui.statusbar.window.data.model.StatusBarWindowState +import com.android.systemui.statusbar.window.shared.model.StatusBarWindowState import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow import dagger.assisted.Assisted import dagger.assisted.AssistedFactory diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/window/shared/model/StatusBarWindowState.kt b/packages/SystemUI/src/com/android/systemui/statusbar/window/shared/model/StatusBarWindowState.kt index a99046ee05e9..5c7e66f4e018 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/window/shared/model/StatusBarWindowState.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/window/shared/model/StatusBarWindowState.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.statusbar.window.data.model +package com.android.systemui.statusbar.window.shared.model /** * Represents the state of the status bar *window* as a whole (as opposed to individual views within diff --git a/packages/SystemUI/src/com/android/systemui/util/CarrierConfigTracker.java b/packages/SystemUI/src/com/android/systemui/util/CarrierConfigTracker.java index f755feb7aa44..10a4f560e47c 100644 --- a/packages/SystemUI/src/com/android/systemui/util/CarrierConfigTracker.java +++ b/packages/SystemUI/src/com/android/systemui/util/CarrierConfigTracker.java @@ -60,10 +60,6 @@ public class CarrierConfigTracker private final Set<CarrierConfigChangedListener> mListeners = new ArraySet<>(); private final Set<DefaultDataSubscriptionChangedListener> mDataListeners = new ArraySet<>(); - private boolean mDefaultCallStrengthConfigLoaded; - private boolean mDefaultCallStrengthConfig; - private boolean mDefaultNoCallingConfigLoaded; - private boolean mDefaultNoCallingConfig; private boolean mDefaultCarrierProvisionsWifiMergedNetworksLoaded; private boolean mDefaultCarrierProvisionsWifiMergedNetworks; private boolean mDefaultShowOperatorNameConfigLoaded; @@ -146,42 +142,6 @@ public class CarrierConfigTracker } /** - * Returns the KEY_DISPLAY_CALL_STRENGTH_INDICATOR_BOOL value for the given subId. - */ - public boolean getCallStrengthConfig(int subId) { - synchronized (mCallStrengthConfigs) { - if (mCallStrengthConfigs.indexOfKey(subId) >= 0) { - return mCallStrengthConfigs.get(subId); - } - } - if (!mDefaultCallStrengthConfigLoaded) { - mDefaultCallStrengthConfig = - CarrierConfigManager.getDefaultConfig().getBoolean( - CarrierConfigManager.KEY_DISPLAY_CALL_STRENGTH_INDICATOR_BOOL); - mDefaultCallStrengthConfigLoaded = true; - } - return mDefaultCallStrengthConfig; - } - - /** - * Returns the KEY_USE_IP_FOR_CALLING_INDICATOR_BOOL value for the given subId. - */ - public boolean getNoCallingConfig(int subId) { - synchronized (mNoCallingConfigs) { - if (mNoCallingConfigs.indexOfKey(subId) >= 0) { - return mNoCallingConfigs.get(subId); - } - } - if (!mDefaultNoCallingConfigLoaded) { - mDefaultNoCallingConfig = - CarrierConfigManager.getDefaultConfig().getBoolean( - CarrierConfigManager.KEY_USE_IP_FOR_CALLING_INDICATOR_BOOL); - mDefaultNoCallingConfigLoaded = true; - } - return mDefaultNoCallingConfig; - } - - /** * Returns the KEY_CARRIER_PROVISIONS_WIFI_MERGED_NETWORKS_BOOL value for the given subId. */ public boolean getCarrierProvisionsWifiMergedNetworksBool(int subId) { diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/binder/VolumeDialogRingerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/binder/VolumeDialogRingerViewBinder.kt index 58b8f6254d9d..e8d19dd5e0e4 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/binder/VolumeDialogRingerViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/binder/VolumeDialogRingerViewBinder.kt @@ -83,6 +83,18 @@ constructor(private val viewModel: VolumeDialogRingerDrawerViewModel) { view.context.resources.getDimensionPixelSize( R.dimen.volume_dialog_background_corner_radius ) + val bottomDefaultRadius = volumeDialogBgFullRadius.toFloat() + val bottomCornerRadii = + floatArrayOf( + 0F, + 0F, + 0F, + 0F, + bottomDefaultRadius, + bottomDefaultRadius, + bottomDefaultRadius, + bottomDefaultRadius, + ) var backgroundAnimationProgress: Float by Delegates.observable(0F) { _, _, progress -> ringerBackgroundView.applyCorners( @@ -115,6 +127,8 @@ constructor(private val viewModel: VolumeDialogRingerDrawerViewModel) { drawerContainer.visibility = View.VISIBLE when (uiModel.drawerState) { is RingerDrawerState.Initial -> { + (volumeDialogBackgroundView.background as GradientDrawable) + .cornerRadii = bottomCornerRadii drawerContainer.animateAndBindDrawerButtons( viewModel, uiModel, @@ -123,6 +137,7 @@ constructor(private val viewModel: VolumeDialogRingerDrawerViewModel) { ) ringerDrawerTransitionListener.setProgressChangeEnabled(true) drawerContainer.closeDrawer( + ringerBackgroundView, uiModel.currentButtonIndex, ringerState.orientation, ) @@ -165,6 +180,7 @@ constructor(private val viewModel: VolumeDialogRingerDrawerViewModel) { ) } drawerContainer.closeDrawer( + ringerBackgroundView, uiModel.currentButtonIndex, ringerState.orientation, ) @@ -187,7 +203,11 @@ constructor(private val viewModel: VolumeDialogRingerDrawerViewModel) { } else { ringerDrawerTransitionListener.setProgressChangeEnabled(true) } - updateOpenState(drawerContainer, ringerState.orientation) + updateOpenState( + drawerContainer, + ringerState.orientation, + ringerBackgroundView, + ) drawerContainer.transitionToState( R.id.volume_dialog_ringer_drawer_open ) @@ -204,9 +224,6 @@ constructor(private val viewModel: VolumeDialogRingerDrawerViewModel) { volumeDialogBackgroundView.setBackgroundResource( R.drawable.volume_dialog_background ) - ringerBackgroundView.setBackgroundResource( - R.drawable.volume_dialog_ringer_background - ) } } } @@ -351,9 +368,13 @@ constructor(private val viewModel: VolumeDialogRingerDrawerViewModel) { } } - private fun MotionLayout.closeDrawer(selectedIndex: Int, orientation: Int) { + private fun MotionLayout.closeDrawer( + ringerBackground: View, + selectedIndex: Int, + orientation: Int, + ) { setTransition(R.id.close_to_open_transition) - updateCloseState(this, selectedIndex, orientation) + updateCloseState(this, selectedIndex, orientation, ringerBackground) transitionToState(R.id.volume_dialog_ringer_drawer_close) } diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/util/RingerDrawerConstraintsUtils.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/util/RingerDrawerConstraintsUtils.kt index c1e003727750..fb9884cf4341 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/util/RingerDrawerConstraintsUtils.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/ui/util/RingerDrawerConstraintsUtils.kt @@ -25,14 +25,21 @@ import androidx.constraintlayout.widget.ConstraintSet import com.android.systemui.res.R import com.android.systemui.util.children -fun updateOpenState(ringerDrawer: MotionLayout, orientation: Int) { +fun updateOpenState(ringerDrawer: MotionLayout, orientation: Int, ringerBackground: View) { val openSet = ringerDrawer.cloneConstraintSet(R.id.volume_dialog_ringer_drawer_open) + openSet.setVisibility(ringerBackground.id, View.VISIBLE) openSet.adjustOpenConstraintsForDrawer(ringerDrawer, orientation) ringerDrawer.updateState(R.id.volume_dialog_ringer_drawer_open, openSet) } -fun updateCloseState(ringerDrawer: MotionLayout, selectedIndex: Int, orientation: Int) { +fun updateCloseState( + ringerDrawer: MotionLayout, + selectedIndex: Int, + orientation: Int, + ringerBackground: View, +) { val closeSet = ringerDrawer.cloneConstraintSet(R.id.volume_dialog_ringer_drawer_close) + closeSet.setVisibility(ringerBackground.id, View.VISIBLE) closeSet.adjustClosedConstraintsForDrawer(ringerDrawer, selectedIndex, orientation) ringerDrawer.updateState(R.id.volume_dialog_ringer_drawer_close, closeSet) } diff --git a/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java b/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java index 389b6fb4b0ef..411e06ed1339 100644 --- a/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java +++ b/packages/SystemUI/src/com/android/systemui/wallet/controller/QuickAccessWalletController.java @@ -229,6 +229,35 @@ public class QuickAccessWalletController { } /** + * Starts the QuickAccessWallet Gesture UI (the app is launched by a hardware gesture). + * + * + * The Wallet target activity is defined as the {@link android.app.PendingIntent} returned by + * {@link QuickAccessWalletClient#getGestureTargetActivityPendingIntent} if that is not null. + * If that is null, then the method {@link QuickAccessWalletController#startQuickAccessUiIntent} + * as defined below is called, which starts the QuickAccessWallet UI. + * + * @param activityStarter an {@link ActivityStarter} to launch the Intent or PendingIntent. + * @param animationController an {@link ActivityTransitionAnimator.Controller} to provide a + * smooth animation for the activity launch. + */ + public void startGestureUiIntent(ActivityStarter activityStarter, + ActivityTransitionAnimator.Controller animationController){ + mQuickAccessWalletClient.getGestureTargetActivityPendingIntent( + mExecutor, + gesturePendingIntent -> { + if (gesturePendingIntent != null) { + activityStarter.startPendingIntentMaybeDismissingKeyguard( + gesturePendingIntent, null, null); + return; + } + + startQuickAccessUiIntent(activityStarter, animationController, true); + } + ); + } + + /** * Starts the QuickAccessWallet UI: either the app's designated UI, or the built-in Wallet UI. * * If the service has configured itself so that diff --git a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java index d8d53e006ab6..0c7989df7293 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java @@ -32,6 +32,7 @@ import android.app.KeyguardManager; import android.content.ClipData; import android.content.ClipDescription; import android.content.ClipboardManager; +import android.content.pm.UserInfo; import android.os.Build; import android.os.PersistableBundle; import android.os.UserHandle; @@ -45,6 +46,8 @@ import androidx.test.runner.AndroidJUnit4; import com.android.internal.logging.UiEventLogger; import com.android.systemui.Flags; import com.android.systemui.SysuiTestCase; +import com.android.systemui.settings.FakeUserTracker; +import com.android.systemui.user.utils.FakeUserScopedService; import org.junit.Before; import org.junit.Test; @@ -56,6 +59,7 @@ import org.mockito.MockitoAnnotations; import org.mockito.Spy; import java.util.ArrayList; +import java.util.List; import javax.inject.Provider; @@ -68,6 +72,10 @@ public class ClipboardListenerTest extends SysuiTestCase { @Mock private KeyguardManager mKeyguardManager; @Mock + private ClipboardManager mClipboardManagerSecondaryUser; + @Mock + private KeyguardManager mKeyguardManagerSecondaryUser; + @Mock private ClipboardOverlayController mOverlayController; @Mock private ClipboardToast mClipboardToast; @@ -76,9 +84,6 @@ public class ClipboardListenerTest extends SysuiTestCase { @Mock private ClipboardOverlaySuppressionController mClipboardOverlaySuppressionController; - private ClipData mSampleClipData; - private String mSampleSource = "Example source"; - @Captor private ArgumentCaptor<Runnable> mRunnableCaptor; @Captor @@ -89,6 +94,20 @@ public class ClipboardListenerTest extends SysuiTestCase { @Spy private Provider<ClipboardOverlayController> mOverlayControllerProvider; + private final FakeUserScopedService<ClipboardManager> mUserScopedClipboardManager = + new FakeUserScopedService<>(mClipboardManager); + private final FakeUserScopedService<KeyguardManager> mUserScopedKeyguardManager = + new FakeUserScopedService<>(mKeyguardManager); + private final FakeUserTracker mUserTracker = new FakeUserTracker(); + + private final List<UserInfo> mUserInfos = List.of( + new UserInfo(0, "system", 0), new UserInfo(50, "secondary", 0)); + private final ClipData mSampleClipData = new ClipData("Test", new String[]{"text/plain"}, + new ClipData.Item("Test Item")); + private final ClipData mSecondaryClipData = new ClipData( + "Test secondary", new String[]{"text/plain"}, new ClipData.Item("Secondary Item")); + private final String mSampleSource = "Example source"; + private ClipboardListener mClipboardListener; @@ -97,30 +116,38 @@ public class ClipboardListenerTest extends SysuiTestCase { mOverlayControllerProvider = () -> mOverlayController; MockitoAnnotations.initMocks(this); - when(mClipboardManager.hasPrimaryClip()).thenReturn(true); + Settings.Secure.putInt( mContext.getContentResolver(), SETTINGS_SECURE_USER_SETUP_COMPLETE, 1); - mSampleClipData = new ClipData("Test", new String[]{"text/plain"}, - new ClipData.Item("Test Item")); - when(mClipboardManager.getPrimaryClip()).thenReturn(mSampleClipData); - when(mClipboardManager.getPrimaryClipSource()).thenReturn(mSampleSource); + mUserTracker.set(mUserInfos, 0); + UserHandle user0 = mUserInfos.get(0).getUserHandle(); + UserHandle user1 = mUserInfos.get(1).getUserHandle(); + mUserScopedKeyguardManager.addImplementation(user0, mKeyguardManager); + mUserScopedKeyguardManager.addImplementation(user1, mKeyguardManagerSecondaryUser); + setupClipboardManager(mClipboardManager, user0, mSampleClipData); + setupClipboardManager(mClipboardManagerSecondaryUser, user1, mSecondaryClipData); mClipboardListener = new ClipboardListener( getContext(), mOverlayControllerProvider, mClipboardToast, - user -> { - if (UserHandle.CURRENT.equals(user)) { - return mClipboardManager; - } - return null; - }, - mKeyguardManager, + mUserTracker, + mUserScopedClipboardManager, + mUserScopedKeyguardManager, mUiEventLogger, + getContext().getMainExecutor(), mClipboardOverlaySuppressionController); } + private void setupClipboardManager( + ClipboardManager clipboardManager, UserHandle user, ClipData clipData) { + when(clipboardManager.hasPrimaryClip()).thenReturn(true); + when(clipboardManager.getPrimaryClip()).thenReturn(clipData); + when(clipboardManager.getPrimaryClipSource()).thenReturn(mSampleSource); + mUserScopedClipboardManager.addImplementation(user, clipboardManager); + } + @Test public void test_initialization() { @@ -160,6 +187,76 @@ public class ClipboardListenerTest extends SysuiTestCase { } @Test + @DisableFlags(Flags.FLAG_CLIPBOARD_OVERLAY_MULTIUSER) + public void test_noSwitchUserWithFlagOff() { + mClipboardListener.start(); + + mClipboardListener.onPrimaryClipChanged(); + mUserTracker.set(mUserInfos, 1); + mUserTracker.onUserChanged(mUserInfos.get(1).id); + mClipboardListener.onPrimaryClipChanged(); + + verify(mKeyguardManager, times(2)).isDeviceLocked(); + verify(mClipboardManager, times(2)).hasPrimaryClip(); + verify(mOverlayController, times(2)).setClipData(mSampleClipData, mSampleSource); + verifyNoMoreInteractions(mClipboardManagerSecondaryUser); + verifyNoMoreInteractions(mKeyguardManagerSecondaryUser); + } + + @Test + @EnableFlags(Flags.FLAG_CLIPBOARD_OVERLAY_MULTIUSER) + public void test_switchUserSwitchesClipboard() { + mClipboardListener.start(); + + mClipboardListener.onPrimaryClipChanged(); + verify(mClipboardManager).hasPrimaryClip(); + verify(mOverlayController).setClipData(mSampleClipData, mSampleSource); + + mUserTracker.set(mUserInfos, 1); + mUserTracker.onUserChanged(mUserInfos.get(1).id); + mClipboardListener.onPrimaryClipChanged(); + + verify(mClipboardManagerSecondaryUser).hasPrimaryClip(); + verify(mOverlayController).setClipData(mSecondaryClipData, mSampleSource); + } + + @Test + @DisableFlags(Flags.FLAG_CLIPBOARD_OVERLAY_MULTIUSER) + @EnableFlags(Flags.FLAG_CLIPBOARD_NONINTERACTIVE_ON_LOCKSCREEN) + public void test_deviceLockedForSecondaryUser_withoutMultiuser_showsOverlay() { + when(mKeyguardManager.isDeviceLocked()).thenReturn(false); + when(mKeyguardManagerSecondaryUser.isDeviceLocked()).thenReturn(true); + + mClipboardListener.start(); + mUserTracker.set(mUserInfos, 1); + mUserTracker.onUserChanged(mUserInfos.get(1).id); + mClipboardListener.onPrimaryClipChanged(); + + verify(mUiEventLogger, times(1)).log( + ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ENTERED, 0, mSampleSource); + verify(mOverlayController).setClipData(mSampleClipData, mSampleSource); + verifyNoMoreInteractions(mClipboardToast); + } + + @Test + @EnableFlags({Flags.FLAG_CLIPBOARD_OVERLAY_MULTIUSER, + Flags.FLAG_CLIPBOARD_NONINTERACTIVE_ON_LOCKSCREEN}) + public void test_deviceLockedForSecondaryUser_showsToast() { + when(mKeyguardManager.isDeviceLocked()).thenReturn(false); + when(mKeyguardManagerSecondaryUser.isDeviceLocked()).thenReturn(true); + + mClipboardListener.start(); + mUserTracker.set(mUserInfos, 1); + mUserTracker.onUserChanged(mUserInfos.get(1).id); + mClipboardListener.onPrimaryClipChanged(); + + verify(mUiEventLogger, times(1)).log( + ClipboardOverlayEvent.CLIPBOARD_TOAST_SHOWN, 0, mSampleSource); + verify(mClipboardToast, times(1)).showCopiedToast(); + verifyNoMoreInteractions(mOverlayControllerProvider); + } + + @Test @DisableFlags(Flags.FLAG_OVERRIDE_SUPPRESS_OVERLAY_CONDITION) public void test_shouldSuppressOverlay() { // Regardless of the package or emulator, nothing should be suppressed without the flag diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java index 1fcf02d417e1..7d3aa47e124d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java @@ -215,6 +215,7 @@ import com.android.systemui.util.settings.FakeSettings; import com.android.systemui.util.settings.SystemSettings; import com.android.systemui.util.time.FakeSystemClock; import com.android.systemui.volume.VolumeComponent; +import com.android.systemui.wallet.controller.QuickAccessWalletController; import com.android.wm.shell.bubbles.Bubbles; import com.android.wm.shell.startingsurface.StartingSurface; @@ -373,6 +374,7 @@ public class CentralSurfacesImplTest extends SysuiTestCase { @Mock private NotificationSettingsInteractor mNotificationSettingsInteractor; @Mock private ViewCaptureAwareWindowManager mViewCaptureAwareWindowManager; @Mock private StatusBarLongPressGestureDetector mStatusBarLongPressGestureDetector; + @Mock private QuickAccessWalletController mQuickAccessWalletController; private ShadeController mShadeController; private final FakeSystemClock mFakeSystemClock = new FakeSystemClock(); private final FakeGlobalSettings mFakeGlobalSettings = new FakeGlobalSettings(); @@ -640,7 +642,8 @@ public class CentralSurfacesImplTest extends SysuiTestCase { mBrightnessMirrorShowingInteractor, mGlanceableHubContainerController, mEmergencyGestureIntentFactory, - mViewCaptureAwareWindowManager + mViewCaptureAwareWindowManager, + mQuickAccessWalletController ); mScreenLifecycle.addObserver(mCentralSurfaces.mScreenObserver); mCentralSurfaces.initShadeVisibilityListener(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt index 0ba0aeb87225..243be3dc142d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt @@ -21,8 +21,12 @@ import android.app.StatusBarManager.WINDOW_STATE_HIDING import android.app.StatusBarManager.WINDOW_STATE_SHOWING import android.app.StatusBarManager.WINDOW_STATUS_BAR import android.graphics.Insets +import android.hardware.display.DisplayManagerGlobal import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags +import android.view.Display +import android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS +import android.view.DisplayInfo import android.view.InputDevice import android.view.LayoutInflater import android.view.MotionEvent @@ -35,6 +39,7 @@ import androidx.test.filters.SmallTest import androidx.test.platform.app.InstrumentationRegistry import com.android.systemui.Flags as AconfigFlags import com.android.systemui.SysuiTestCase +import com.android.systemui.SysuiTestableContext import com.android.systemui.battery.BatteryMeterView import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags @@ -45,7 +50,6 @@ import com.android.systemui.shade.ShadeControllerImpl import com.android.systemui.shade.ShadeLogger import com.android.systemui.shade.ShadeViewController import com.android.systemui.shade.StatusBarLongPressGestureDetector -import com.android.systemui.shade.data.repository.fakeShadeDisplaysRepository import com.android.systemui.shade.display.StatusBarTouchShadeDisplayPolicy import com.android.systemui.shade.domain.interactor.PanelExpansionInteractor import com.android.systemui.statusbar.CommandQueue @@ -78,7 +82,6 @@ import org.mockito.Mockito.spy import org.mockito.Mockito.verify import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations -import org.mockito.kotlin.verifyNoMoreInteractions @SmallTest @RunWith(AndroidJUnit4::class) @@ -88,7 +91,6 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() { private val statusBarContentInsetsProvider = statusBarContentInsetsProviderStore.defaultDisplay private val fakeDarkIconDispatcher = kosmos.fakeDarkIconDispatcher - private val fakeShadeDisplaysRepository = kosmos.fakeShadeDisplaysRepository @Mock private lateinit var shadeViewController: ShadeViewController @Mock private lateinit var panelExpansionInteractor: PanelExpansionInteractor @Mock private lateinit var featureFlags: FeatureFlags @@ -111,6 +113,8 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() { private lateinit var view: PhoneStatusBarView private lateinit var controller: PhoneStatusBarViewController + private lateinit var viewForSecondaryDisplay: PhoneStatusBarView + private val clockView: Clock get() = view.requireViewById(R.id.clock) @@ -138,6 +142,26 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() { as PhoneStatusBarView controller = createAndInitController(view) } + + val contextForSecondaryDisplay = + SysuiTestableContext( + mContext.createDisplayContext( + Display( + DisplayManagerGlobal.getInstance(), + SECONDARY_DISPLAY_ID, + DisplayInfo(), + DEFAULT_DISPLAY_ADJUSTMENTS, + ) + ) + ) + + InstrumentationRegistry.getInstrumentation().runOnMainSync { + val parent = FrameLayout(contextForSecondaryDisplay) // add parent to keep layout params + viewForSecondaryDisplay = + LayoutInflater.from(contextForSecondaryDisplay) + .inflate(R.layout.status_bar, parent, false) as PhoneStatusBarView + createAndInitController(viewForSecondaryDisplay) + } } @Test @@ -264,10 +288,9 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() { @Test @DisableFlags(AconfigFlags.FLAG_STATUS_BAR_CONNECTED_DISPLAYS) - fun handleTouchEventFromStatusBar_statusBarConnectedDisplaysDisabled_viewReceivesEvent() { + fun handleTouchEventFromStatusBar_touchOnPrimaryDisplay_statusBarConnectedDisplaysDisabled_shadeReceivesEvent() { `when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true) `when`(shadeViewController.isViewEnabled).thenReturn(true) - fakeShadeDisplaysRepository.setDisplayId(SECONDARY_DISPLAY_ID) val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 2f, 0) view.onTouchEvent(event) @@ -280,10 +303,9 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() { AconfigFlags.FLAG_STATUS_BAR_CONNECTED_DISPLAYS, AconfigFlags.FLAG_SHADE_WINDOW_GOES_AROUND, ) - fun handleTouchEventFromStatusBar_statusBarConnectedDisplaysEnabled_shadeWindowGoesAroundEnabled_viewReceivesEvent() { + fun handleTouchEventFromStatusBar_touchOnPrimaryDisplay_statusBarConnectedDisplaysEnabled_shadeWindowGoesAroundEnabled_shadeReceivesEvent() { `when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true) `when`(shadeViewController.isViewEnabled).thenReturn(true) - fakeShadeDisplaysRepository.setDisplayId(SECONDARY_DISPLAY_ID) val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 2f, 0) view.onTouchEvent(event) @@ -294,10 +316,9 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() { @Test @EnableFlags(AconfigFlags.FLAG_STATUS_BAR_CONNECTED_DISPLAYS) @DisableFlags(AconfigFlags.FLAG_SHADE_WINDOW_GOES_AROUND) - fun handleTouchEventFromStatusBar_touchOnShadeDisplay_statusBarConnectedDisplaysEnabled_shadeWindowGoesAroundDisabled_viewReceivesEvent() { + fun handleTouchEventFromStatusBar_touchOnPrimaryDisplay_statusBarConnectedDisplaysEnabled_shadeWindowGoesAroundDisabled_shadeReceivesEvent() { `when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true) `when`(shadeViewController.isViewEnabled).thenReturn(true) - fakeShadeDisplaysRepository.setDisplayId(DISPLAY_ID) val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 2f, 0) view.onTouchEvent(event) @@ -306,18 +327,43 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() { } @Test + @DisableFlags(AconfigFlags.FLAG_STATUS_BAR_CONNECTED_DISPLAYS) + fun handleTouchEventFromStatusBar_touchOnSecondaryDisplay_statusBarConnectedDisplaysDisabled_shadeReceivesEvent() { + `when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true) + `when`(shadeViewController.isViewEnabled).thenReturn(true) + val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 2f, 0) + + viewForSecondaryDisplay.onTouchEvent(event) + + verify(shadeViewController).handleExternalTouch(event) + } + + @Test + @EnableFlags( + AconfigFlags.FLAG_STATUS_BAR_CONNECTED_DISPLAYS, + AconfigFlags.FLAG_SHADE_WINDOW_GOES_AROUND, + ) + fun handleTouchEventFromStatusBar_touchOnSecondaryDisplay_statusBarConnectedDisplaysEnabled_shadeWindowGoesAroundEnabled_shadeReceivesEvent() { + `when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true) + `when`(shadeViewController.isViewEnabled).thenReturn(true) + val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 2f, 0) + + viewForSecondaryDisplay.onTouchEvent(event) + + verify(shadeViewController).handleExternalTouch(event) + } + + @Test @EnableFlags(AconfigFlags.FLAG_STATUS_BAR_CONNECTED_DISPLAYS) @DisableFlags(AconfigFlags.FLAG_SHADE_WINDOW_GOES_AROUND) - fun handleTouchEventFromStatusBar_touchNotOnShadeDisplay_statusBarConnectedDisplaysEnabled_shadeWindowGoesAroundDisabled_viewDoesNotReceiveEvent() { + fun handleTouchEventFromStatusBar_touchOnSecondaryDisplay_statusBarConnectedDisplaysEnabled_shadeWindowGoesAroundDisabled_shadeDoesNotReceiveEvent() { `when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true) `when`(shadeViewController.isViewEnabled).thenReturn(true) - fakeShadeDisplaysRepository.setDisplayId(SECONDARY_DISPLAY_ID) val event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 2f, 0) - view.onTouchEvent(event) + viewForSecondaryDisplay.onTouchEvent(event) - verify(shadeViewController).isViewEnabled - verifyNoMoreInteractions(shadeViewController) + verify(shadeViewController, never()).handleExternalTouch(event) } @Test @@ -493,7 +539,6 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() { fakeDarkIconDispatcher, statusBarContentInsetsProviderStore, Lazy { statusBarTouchShadeDisplayPolicy }, - fakeShadeDisplaysRepository, ) .create(view) .also { it.init() } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt index 728f4183ccce..3a25ecb27404 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionRepositoryTest.kt @@ -37,7 +37,7 @@ import android.telephony.ServiceState.STATE_OUT_OF_SERVICE import android.telephony.SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX import android.telephony.SubscriptionManager.PROFILE_CLASS_UNSET import android.telephony.TelephonyCallback -import android.telephony.TelephonyCallback.CarrierRoamingNtnModeListener +import android.telephony.TelephonyCallback.CarrierRoamingNtnListener import android.telephony.TelephonyCallback.DataActivityListener import android.telephony.TelephonyCallback.DisplayInfoListener import android.telephony.TelephonyCallback.ServiceStateListener @@ -1311,7 +1311,7 @@ class MobileConnectionRepositoryTest : SysuiTestCase() { // Starts out false assertThat(latest).isFalse() - val callback = getTelephonyCallbackForType<CarrierRoamingNtnModeListener>() + val callback = getTelephonyCallbackForType<CarrierRoamingNtnListener>() callback.onCarrierRoamingNtnModeChanged(true) assertThat(latest).isTrue() diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt index 89f2d3db7f40..599729d953d4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt @@ -22,7 +22,7 @@ import android.telephony.TelephonyCallback import android.telephony.TelephonyManager import android.telephony.satellite.NtnSignalStrength import android.telephony.satellite.NtnSignalStrengthCallback -import android.telephony.satellite.SatelliteCommunicationAllowedStateCallback +import android.telephony.satellite.SatelliteCommunicationAccessStateCallback import android.telephony.satellite.SatelliteManager import android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED import android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_RETRYING @@ -193,19 +193,19 @@ class DeviceBasedSatelliteRepositoryImplTest : SysuiTestCase() { runCurrent() val callback = - withArgCaptor<SatelliteCommunicationAllowedStateCallback> { + withArgCaptor<SatelliteCommunicationAccessStateCallback> { verify(satelliteManager) - .registerForCommunicationAllowedStateChanged(any(), capture()) + .registerForCommunicationAccessStateChanged(any(), capture()) } // WHEN satellite manager says it's not available - callback.onSatelliteCommunicationAllowedStateChanged(false) + callback.onAccessAllowedStateChanged(false) // THEN it's not! assertThat(latest).isFalse() // WHEN satellite manager says it's changed to available - callback.onSatelliteCommunicationAllowedStateChanged(true) + callback.onAccessAllowedStateChanged(true) // THEN it is! assertThat(latest).isTrue() @@ -219,7 +219,7 @@ class DeviceBasedSatelliteRepositoryImplTest : SysuiTestCase() { // GIVEN SatelliteManager gon' throw exceptions when we ask to register the callback doThrow(RuntimeException("Test exception")) .`when`(satelliteManager) - .registerForCommunicationAllowedStateChanged(any(), any()) + .registerForCommunicationAccessStateChanged(any(), any()) // WHEN the latest value is requested (and thus causes an exception to be thrown) val latest by collectLastValue(underTest.isSatelliteAllowedForCurrentLocation) @@ -236,9 +236,9 @@ class DeviceBasedSatelliteRepositoryImplTest : SysuiTestCase() { runCurrent() val callback = - withArgCaptor<SatelliteCommunicationAllowedStateCallback> { + withArgCaptor<SatelliteCommunicationAccessStateCallback> { verify(satelliteManager) - .registerForCommunicationAllowedStateChanged(any(), capture()) + .registerForCommunicationAccessStateChanged(any(), capture()) } val telephonyCallback = @@ -249,7 +249,7 @@ class DeviceBasedSatelliteRepositoryImplTest : SysuiTestCase() { ) // GIVEN satellite is currently provisioned - callback.onSatelliteCommunicationAllowedStateChanged(true) + callback.onAccessAllowedStateChanged(true) assertThat(latest).isTrue() @@ -261,7 +261,7 @@ class DeviceBasedSatelliteRepositoryImplTest : SysuiTestCase() { // THEN listener is re-registered verify(satelliteManager, times(2)) - .registerForCommunicationAllowedStateChanged(any(), any()) + .registerForCommunicationAccessStateChanged(any(), any()) } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/wallet/controller/QuickAccessWalletControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/wallet/controller/QuickAccessWalletControllerTest.java index 40094e507f9a..733e2edaec84 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wallet/controller/QuickAccessWalletControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wallet/controller/QuickAccessWalletControllerTest.java @@ -16,21 +16,26 @@ package com.android.systemui.wallet.controller; +import static android.service.quickaccesswallet.Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.PendingIntent; import android.app.role.RoleManager; import android.content.Intent; +import android.platform.test.annotations.EnableFlags; import android.service.quickaccesswallet.GetWalletCardsRequest; import android.service.quickaccesswallet.QuickAccessWalletClient; import android.testing.TestableLooper; @@ -54,6 +59,7 @@ import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.mockito.Spy; import java.util.List; @@ -101,15 +107,22 @@ public class QuickAccessWalletControllerTest extends SysuiTestCase { callback.onWalletPendingIntentRetrieved(null); return null; }).when(mQuickAccessWalletClient).getWalletPendingIntent(any(), any()); + doAnswer(invocation -> { + QuickAccessWalletClient.GesturePendingIntentCallback callback = + (QuickAccessWalletClient.GesturePendingIntentCallback) invocation + .getArguments()[1]; + callback.onGesturePendingIntentRetrieved(null); + return null; + }).when(mQuickAccessWalletClient).getGestureTargetActivityPendingIntent(any(), any()); - mController = new QuickAccessWalletController( + mController = spy(new QuickAccessWalletController( mContext, MoreExecutors.directExecutor(), MoreExecutors.directExecutor(), mSecureSettings, mQuickAccessWalletClient, mClock, - mRoleManager); + mRoleManager)); } @Test @@ -287,4 +300,41 @@ public class QuickAccessWalletControllerTest extends SysuiTestCase { intent.getComponent().getClassName(), "com.google.android.apps.testapp.TestActivity"); } + + @Test + @EnableFlags(FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) + public void getGestureUiIntent_targetActivityViaPendingIntent_intentComponentIsCorrect() { + doAnswer(invocation -> { + QuickAccessWalletClient.GesturePendingIntentCallback callback = + (QuickAccessWalletClient.GesturePendingIntentCallback) invocation + .getArguments()[1]; + Intent intent = new Intent(Intent.ACTION_VIEW).setClassName( + "com.google.android.apps.testapp", + "com.google.android.apps.testapp.GestureTestActivity"); + callback.onGesturePendingIntentRetrieved( + PendingIntent.getActivity(mContext, 0, intent, + PendingIntent.FLAG_IMMUTABLE)); + return null; + }).when(mQuickAccessWalletClient).getGestureTargetActivityPendingIntent(any(), any()); + mController.startGestureUiIntent(mActivityStarter, mAnimationController); + verify(mActivityStarter).startPendingIntentMaybeDismissingKeyguard( + mPendingIntentCaptor.capture(), + nullable(Runnable.class), + nullable(ActivityTransitionAnimator.Controller.class)); + PendingIntent pendingIntent = mPendingIntentCaptor.getValue(); + Intent intent = pendingIntent.getIntent(); + assertEquals(intent.getAction(), Intent.ACTION_VIEW); + assertEquals( + intent.getComponent().getClassName(), + "com.google.android.apps.testapp.GestureTestActivity"); + } + + @Test + @EnableFlags(FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) + public void getGestureUiIntent_noPendingIntent_startsQuickAccessUiIntent() { + mController.startGestureUiIntent(mActivityStarter, mAnimationController); + + verify(mController).startQuickAccessUiIntent(eq(mActivityStarter), eq(mAnimationController), + anyBoolean()); + } } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt index b8d26ef53fc7..47991b3b9689 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt @@ -53,6 +53,7 @@ import com.android.systemui.kosmos.backgroundScope import com.android.systemui.kosmos.testDispatcher import com.android.systemui.kosmos.testScope import com.android.systemui.model.sysUiState +import com.android.systemui.plugins.activityStarter import com.android.systemui.settings.displayTracker import com.android.systemui.settings.userTracker import com.android.systemui.statusbar.phone.systemUIDialogFactory @@ -67,12 +68,7 @@ var Kosmos.shortcutHelperMultiTaskingShortcutsSource: KeyboardShortcutGroupsSour Kosmos.Fixture { MultitaskingShortcutsSource(mainResources, applicationContext) } val Kosmos.shortcutHelperStateRepository by - Kosmos.Fixture { - ShortcutHelperStateRepository( - fakeInputManager.inputManager, - testDispatcher, - ) - } + Kosmos.Fixture { ShortcutHelperStateRepository(fakeInputManager.inputManager, testDispatcher) } var Kosmos.shortcutHelperInputShortcutsSource: KeyboardShortcutGroupsSource by Kosmos.Fixture { @@ -151,14 +147,15 @@ val Kosmos.customShortcutCategoriesRepository by } val Kosmos.shortcutHelperCoreStartable by - Kosmos.Fixture { - ShortcutHelperCoreStartable( - fakeCommandQueue, - broadcastDispatcher, - shortcutHelperStateRepository, - testScope, - ) - } + Kosmos.Fixture { + ShortcutHelperCoreStartable( + fakeCommandQueue, + broadcastDispatcher, + shortcutHelperStateRepository, + activityStarter, + testScope, + ) + } val Kosmos.shortcutHelperTestHelper by Kosmos.Fixture { @@ -168,6 +165,7 @@ val Kosmos.shortcutHelperTestHelper by broadcastDispatcher, fakeCommandQueue, fakeInputManager, + activityStarter, windowManager, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/data/repository/ShortcutHelperTestHelper.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/data/repository/ShortcutHelperTestHelper.kt index 04eacaafcf91..e5f2449a8ebe 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/data/repository/ShortcutHelperTestHelper.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/data/repository/ShortcutHelperTestHelper.kt @@ -25,8 +25,10 @@ import android.view.WindowManager.KeyboardShortcutsReceiver import com.android.systemui.broadcast.FakeBroadcastDispatcher import com.android.systemui.keyboard.shortcut.ShortcutHelperCoreStartable import com.android.systemui.keyguard.data.repository.FakeCommandQueue +import com.android.systemui.plugins.ActivityStarter import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.whenever +import org.mockito.kotlin.eq class ShortcutHelperTestHelper( coreStartable: ShortcutHelperCoreStartable, @@ -34,13 +36,9 @@ class ShortcutHelperTestHelper( private val fakeBroadcastDispatcher: FakeBroadcastDispatcher, private val fakeCommandQueue: FakeCommandQueue, private val fakeInputManager: FakeInputManager, - windowManager: WindowManager + private val activityStarter: ActivityStarter, + windowManager: WindowManager, ) { - - companion object { - const val DEFAULT_DEVICE_ID = 123 - } - private var imeShortcuts: List<KeyboardShortcutGroup> = emptyList() private var currentAppsShortcuts: List<KeyboardShortcutGroup> = emptyList() @@ -48,12 +46,13 @@ class ShortcutHelperTestHelper( whenever(windowManager.requestImeKeyboardShortcuts(any(), any())).thenAnswer { val keyboardShortcutReceiver = it.getArgument<KeyboardShortcutsReceiver>(0) keyboardShortcutReceiver.onKeyboardShortcutsReceived(imeShortcuts) - return@thenAnswer Unit } whenever(windowManager.requestAppKeyboardShortcuts(any(), any())).thenAnswer { val keyboardShortcutReceiver = it.getArgument<KeyboardShortcutsReceiver>(0) keyboardShortcutReceiver.onKeyboardShortcutsReceived(currentAppsShortcuts) - return@thenAnswer Unit + } + whenever(activityStarter.dismissKeyguardThenExecute(any(), any(), eq(true))).then { + (it.arguments[0] as ActivityStarter.OnDismissAction).onDismiss() } coreStartable.start() } @@ -77,21 +76,21 @@ class ShortcutHelperTestHelper( fun hideThroughCloseSystemDialogs() { fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly( context, - Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS) + Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS), ) } fun hideFromActivity() { fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly( context, - Intent(Intent.ACTION_DISMISS_KEYBOARD_SHORTCUTS) + Intent(Intent.ACTION_DISMISS_KEYBOARD_SHORTCUTS), ) } fun showFromActivity() { fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly( context, - Intent(Intent.ACTION_SHOW_KEYBOARD_SHORTCUTS) + Intent(Intent.ACTION_SHOW_KEYBOARD_SHORTCUTS), ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/notification/domain/interactor/SingleNotificationChipInteractorFactoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/notification/domain/interactor/SingleNotificationChipInteractorFactoryKosmos.kt index 1c095e11dffa..b36b463826d6 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/notification/domain/interactor/SingleNotificationChipInteractorFactoryKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/notification/domain/interactor/SingleNotificationChipInteractorFactoryKosmos.kt @@ -23,9 +23,10 @@ import com.android.systemui.statusbar.chips.statusBarChipsLogger val Kosmos.singleNotificationChipInteractorFactory: SingleNotificationChipInteractor.Factory by Kosmos.Fixture { - SingleNotificationChipInteractor.Factory { startingModel -> + SingleNotificationChipInteractor.Factory { startingModel, creationTime -> SingleNotificationChipInteractor( startingModel, + creationTime, activityManagerRepository.fake, logBuffer = statusBarChipsLogger, ) diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/notification/domain/interactor/StatusBarNotificationChipsInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/notification/domain/interactor/StatusBarNotificationChipsInteractorKosmos.kt index 03e9f3d52ca3..234efcb204b5 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/notification/domain/interactor/StatusBarNotificationChipsInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/notification/domain/interactor/StatusBarNotificationChipsInteractorKosmos.kt @@ -20,11 +20,13 @@ import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.testScope import com.android.systemui.statusbar.chips.statusBarChipsLogger import com.android.systemui.statusbar.notification.domain.interactor.activeNotificationsInteractor +import com.android.systemui.util.time.fakeSystemClock val Kosmos.statusBarNotificationChipsInteractor: StatusBarNotificationChipsInteractor by Kosmos.Fixture { StatusBarNotificationChipsInteractor( testScope.backgroundScope, + fakeSystemClock, activeNotificationsInteractor, singleNotificationChipInteractorFactory, logBuffer = statusBarChipsLogger, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelKosmos.kt index 0300bf4636ea..ee34aa642e51 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelKosmos.kt @@ -20,7 +20,6 @@ import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.testScope import com.android.systemui.statusbar.chips.call.ui.viewmodel.callChipViewModel import com.android.systemui.statusbar.chips.casttootherdevice.ui.viewmodel.castToOtherDeviceChipViewModel -import com.android.systemui.statusbar.chips.notification.demo.ui.viewmodel.demoNotifChipViewModel import com.android.systemui.statusbar.chips.notification.ui.viewmodel.notifChipsViewModel import com.android.systemui.statusbar.chips.screenrecord.ui.viewmodel.screenRecordChipViewModel import com.android.systemui.statusbar.chips.sharetoapp.ui.viewmodel.shareToAppChipViewModel @@ -35,7 +34,6 @@ val Kosmos.ongoingActivityChipsViewModel: OngoingActivityChipsViewModel by castToOtherDeviceChipViewModel = castToOtherDeviceChipViewModel, callChipViewModel = callChipViewModel, notifChipsViewModel = notifChipsViewModel, - demoNotifChipViewModel = demoNotifChipViewModel, logger = statusBarChipsLogger, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/notification/demo/ui/viewmodel/DemoNotifChipViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/ethernet/domain/EthernetInteractorKosmos.kt index 2316a2fdcd2b..3be68180abba 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/chips/notification/demo/ui/viewmodel/DemoNotifChipViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/ethernet/domain/EthernetInteractorKosmos.kt @@ -14,18 +14,10 @@ * limitations under the License. */ -package com.android.systemui.statusbar.chips.notification.demo.ui.viewmodel +package com.android.systemui.statusbar.pipeline.ethernet.domain -import android.content.packageManager import com.android.systemui.kosmos.Kosmos -import com.android.systemui.statusbar.commandline.commandRegistry -import com.android.systemui.util.time.fakeSystemClock +import com.android.systemui.kosmos.Kosmos.Fixture +import com.android.systemui.statusbar.pipeline.shared.data.repository.connectivityRepository -val Kosmos.demoNotifChipViewModel: DemoNotifChipViewModel by - Kosmos.Fixture { - DemoNotifChipViewModel( - commandRegistry = commandRegistry, - packageManager = packageManager, - systemClock = fakeSystemClock, - ) - } +val Kosmos.ethernetInteractor by Fixture { EthernetInteractor(connectivityRepository) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/window/data/repository/FakeStatusBarWindowStatePerDisplayRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/window/data/repository/FakeStatusBarWindowStatePerDisplayRepository.kt index 6532a7ecc85a..b240132dd902 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/window/data/repository/FakeStatusBarWindowStatePerDisplayRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/window/data/repository/FakeStatusBarWindowStatePerDisplayRepository.kt @@ -17,7 +17,7 @@ package com.android.systemui.statusbar.window.data.repository import android.view.Display -import com.android.systemui.statusbar.window.data.model.StatusBarWindowState +import com.android.systemui.statusbar.window.shared.model.StatusBarWindowState import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java index 0089199cfb88..8f48b1f4523d 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java @@ -20,7 +20,6 @@ import android.testing.LeakCheck; import androidx.annotation.Nullable; import com.android.internal.statusbar.StatusBarIcon; -import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.CallIndicatorIconState; import com.android.systemui.statusbar.phone.ui.IconManager; import com.android.systemui.statusbar.phone.ui.StatusBarIconController; @@ -77,14 +76,6 @@ public class FakeStatusBarIconController extends BaseLeakChecker<IconManager> } @Override - public void setCallStrengthIcons(String slot, List<CallIndicatorIconState> states) { - } - - @Override - public void setNoCallingIcons(String slot, List<CallIndicatorIconState> states) { - } - - @Override public void setIconVisibility(String slotTty, boolean b) { } diff --git a/packages/SystemUI/utils/kairos/Android.bp b/packages/SystemUI/utils/kairos/Android.bp index 1442591eab99..e10de9978252 100644 --- a/packages/SystemUI/utils/kairos/Android.bp +++ b/packages/SystemUI/utils/kairos/Android.bp @@ -22,7 +22,7 @@ package { java_library { name: "kairos", host_supported: true, - kotlincflags: ["-opt-in=com.android.systemui.kairos.ExperimentalFrpApi"], + kotlincflags: ["-opt-in=com.android.systemui.kairos.ExperimentalKairosApi"], srcs: ["src/**/*.kt"], static_libs: [ "kotlin-stdlib", @@ -32,6 +32,7 @@ java_library { java_test { name: "kairos-test", + kotlincflags: ["-opt-in=com.android.systemui.kairos.ExperimentalKairosApi"], optimize: { enabled: false, }, diff --git a/packages/SystemUI/utils/kairos/README.md b/packages/SystemUI/utils/kairos/README.md index 85f622ca05f3..5174c45a8d82 100644 --- a/packages/SystemUI/utils/kairos/README.md +++ b/packages/SystemUI/utils/kairos/README.md @@ -22,22 +22,21 @@ you can view the semantics for `Kairos` [here](docs/semantics.md). ## Usage -First, stand up a new `FrpNetwork`. All reactive events and state is kept +First, stand up a new `KairosNetwork`. All reactive events and state is kept consistent within a single network. ``` kotlin val coroutineScope: CoroutineScope = ... -val frpNetwork = coroutineScope.newFrpNetwork() +val network = coroutineScope.launchKairosNetwork() ``` -You can use the `FrpNetwork` to stand-up a network of reactive events and state. -Events are modeled with `TFlow` (short for "transactional flow"), and state -`TState` (short for "transactional state"). +You can use the `KairosNetwork` to stand-up a network of reactive events and +state. Events are modeled with `Events`, and states with `State`. ``` kotlin -suspend fun activate(network: FrpNetwork) { +suspend fun activate(network: KairosNetwork) { network.activateSpec { - val input = network.mutableTFlow<Unit>() + val input = network.mutableEvents<Unit>() // Launch a long-running side-effect that emits to the network // every second. launchEffect { @@ -47,7 +46,7 @@ suspend fun activate(network: FrpNetwork) { } } // Accumulate state - val count: TState<Int> = input.fold { _, i -> i + 1 } + val count: State<Int> = input.foldState { _, i -> i + 1 } // Observe events to perform side-effects in reaction to them input.observe { println("Got event ${count.sample()} at time: ${System.currentTimeMillis()}") @@ -56,7 +55,7 @@ suspend fun activate(network: FrpNetwork) { } ``` -`FrpNetwork.activateSpec` will suspend indefinitely; cancelling the invocation +`KairosNetwork.activateSpec` will suspend indefinitely; cancelling the invocation will tear-down all effects and obervers running within the lambda. ## Resources diff --git a/packages/SystemUI/utils/kairos/docs/flow-to-kairos-cheatsheet.md b/packages/SystemUI/utils/kairos/docs/flow-to-kairos-cheatsheet.md index 9f7fd022f019..afe64377676d 100644 --- a/packages/SystemUI/utils/kairos/docs/flow-to-kairos-cheatsheet.md +++ b/packages/SystemUI/utils/kairos/docs/flow-to-kairos-cheatsheet.md @@ -2,117 +2,116 @@ ## Key differences -* Kairos evaluates all events (`TFlow` emissions + observers) in a transaction. +* Kairos evaluates all events (`Events` emissions + observers) in a transaction. -* Kairos splits `Flow` APIs into two distinct types: `TFlow` and `TState` +* Kairos splits `Flow` APIs into two distinct types: `Events` and `State` - * `TFlow` is roughly equivalent to `SharedFlow` w/ a replay cache that + * `Events` is roughly equivalent to `SharedFlow` w/ a replay cache that exists for the duration of the current Kairos transaction and shared with `SharingStarted.WhileSubscribed()` - * `TState` is roughly equivalent to `StateFlow` shared with + * `State` is roughly equivalent to `StateFlow` shared with `SharingStarted.Eagerly`, but the current value can only be queried within a Kairos transaction, and the value is only updated at the end of the transaction * Kairos further divides `Flow` APIs based on how they internally use state: - * **FrpTransactionScope:** APIs that internally query some state need to be + * **TransactionScope:** APIs that internally query some state need to be performed within an Kairos transaction * this scope is available from the other scopes, and from most lambdas passed to other Kairos APIs - * **FrpStateScope:** APIs that internally accumulate state in reaction to - events need to be performed within an FRP State scope (akin to a - `CoroutineScope`) + * **StateScope:** APIs that internally accumulate state in reaction to events + need to be performed within a State scope (akin to a `CoroutineScope`) - * this scope is a side-effect-free subset of FrpBuildScope, and so can be - used wherever you have an FrpBuildScope + * this scope is a side-effect-free subset of BuildScope, and so can be + used wherever you have an BuildScope - * **FrpBuildScope:** APIs that perform external side-effects (`Flow.collect`) - need to be performed within an FRP Build scope (akin to a `CoroutineScope`) + * **BuildScope:** APIs that perform external side-effects (`Flow.collect`) + need to be performed within a Build scope (akin to a `CoroutineScope`) - * this scope is available from `FrpNetwork.activateSpec { … }` + * this scope is available from `Network.activateSpec { … }` * All other APIs can be used anywhere ## emptyFlow() -Use `emptyTFlow` +Use `emptyEvents` ``` kotlin -// this TFlow emits nothing -val noEvents: TFlow<Int> = emptyTFlow +// this Events emits nothing +val noEvents: Events<Int> = emptyEvents ``` ## map { … } -Use `TFlow.map` / `TState.map` +Use `Events.map` / `State.map` ``` kotlin -val anInt: TState<Int> = … -val squared: TState<Int> = anInt.map { it * it } -val messages: TFlow<String> = … -val messageLengths: TFlow<Int> = messages.map { it.size } +val anInt: State<Int> = … +val squared: State<Int> = anInt.map { it * it } +val messages: Events<String> = … +val messageLengths: Events<Int> = messages.map { it.size } ``` ## filter { … } / mapNotNull { … } -### I have a TFlow +### I have an Events -Use `TFlow.filter` / `TFlow.mapNotNull` +Use `Events.filter` / `Events.mapNotNull` ``` kotlin -val messages: TFlow<String> = … -val nonEmpty: TFlow<String> = messages.filter { it.isNotEmpty() } +val messages: Events<String> = … +val nonEmpty: Events<String> = messages.filter { it.isNotEmpty() } ``` -### I have a TState +### I have a State -Convert the `TState` to `TFlow` using `TState.stateChanges`, then use -`TFlow.filter` / `TFlow.mapNotNull` +Convert the `State` to `Events` using `State.stateChanges`, then use +`Events.filter` / `Events.mapNotNull` -If you need to convert back to `TState`, use `TFlow.hold(initialValue)` on the -result. +If you need to convert back to `State`, use `Events.holdState(initialValue)` on +the result. ``` kotlin -tState.stateChanges.filter { … }.hold(initialValue) +state.stateChanges.filter { … }.holdState(initialValue) ``` -Note that `TFlow.hold` is only available within an `FrpStateScope` in order to -track the lifetime of the state accumulation. +Note that `Events.holdState` is only available within an `StateScope` in order +to track the lifetime of the state accumulation. ## combine(...) { … } -### I have TStates +### I have States -Use `combine(TStates)` +Use `combine(States)` ``` kotlin -val someInt: TState<Int> = … -val someString: TState<String> = … -val model: TState<MyModel> = combine(someInt, someString) { i, s -> MyModel(i, s) } +val someInt: State<Int> = … +val someString: State<String> = … +val model: State<MyModel> = combine(someInt, someString) { i, s -> MyModel(i, s) } ``` -### I have TFlows +### I have Events -Convert the TFlows to TStates using `TFlow.hold(initialValue)`, then use -`combine(TStates)` +Convert the Events to States using `Events.holdState(initialValue)`, then use +`combine(States)` If you want the behavior of Flow.combine where nothing is emitted until each -TFlow has emitted at least once, you can use filter: +Events has emitted at least once, you can use filter: ``` kotlin // null used as an example, can use a different sentinel if needed -combine(tFlowA.hold(null), tFlowB.hold(null)) { a, b -> +combine(eventsA.holdState(null), eventsB.holdState(null)) { a, b -> a?.let { b?.let { … } } } .filterNotNull() ``` -Note that `TFlow.hold` is only available within an `FrpStateScope` in order to -track the lifetime of the state accumulation. +Note that `Events.holdState` is only available within an `StateScope` in order +to track the lifetime of the state accumulation. #### Explanation @@ -126,7 +125,7 @@ has emitted at least once. This often bites developers. As a workaround, developers generally append `.onStart { emit(initialValue) }` to the `Flows` that don't immediately emit. -Kairos avoids this gotcha by forcing usage of `TState` for `combine`, thus +Kairos avoids this gotcha by forcing usage of `State` for `combine`, thus ensuring that there is always a current value to be combined for each input. ## collect { … } @@ -134,197 +133,197 @@ ensuring that there is always a current value to be combined for each input. Use `observe { … }` ``` kotlin -val job: Job = tFlow.observe { println("observed: $it") } +val job: Job = events.observe { println("observed: $it") } ``` -Note that `observe` is only available within an `FrpBuildScope` in order to -track the lifetime of the observer. `FrpBuildScope` can only come from a -top-level `FrpNetwork.transaction { … }`, or a sub-scope created by using a -`-Latest` operator. +Note that `observe` is only available within a `BuildScope` in order to track +the lifetime of the observer. `BuildScope` can only come from a top-level +`Network.transaction { … }`, or a sub-scope created by using a `-Latest` +operator. ## sample(flow) { … } -### I want to sample a TState +### I want to sample a State -Use `TState.sample()` to get the current value of a `TState`. This can be -invoked anywhere you have access to an `FrpTransactionScope`. +Use `State.sample()` to get the current value of a `State`. This can be +invoked anywhere you have access to an `TransactionScope`. ``` kotlin -// the lambda passed to map receives an FrpTransactionScope, so it can invoke +// the lambda passed to map receives an TransactionScope, so it can invoke // sample -tFlow.map { tState.sample() } +events.map { state.sample() } ``` #### Explanation -To keep all state-reads consistent, the current value of a TState can only be -queried within a Kairos transaction, modeled with `FrpTransactionScope`. Note -that both `FrpStateScope` and `FrpBuildScope` extend `FrpTransactionScope`. +To keep all state-reads consistent, the current value of a State can only be +queried within a Kairos transaction, modeled with `TransactionScope`. Note that +both `StateScope` and `BuildScope` extend `TransactionScope`. -### I want to sample a TFlow +### I want to sample an Events -Convert to a `TState` by using `TFlow.hold(initialValue)`, then use `sample`. +Convert to a `State` by using `Events.holdState(initialValue)`, then use `sample`. -Note that `hold` is only available within an `FrpStateScope` in order to track +Note that `holdState` is only available within an `StateScope` in order to track the lifetime of the state accumulation. ## stateIn(scope, sharingStarted, initialValue) -Use `TFlow.hold(initialValue)`. There is no need to supply a sharingStarted -argument; all states are accumulated eagerly. +Use `Events.holdState(initialValue)`. There is no need to supply a +sharingStarted argument; all states are accumulated eagerly. ``` kotlin -val ints: TFlow<Int> = … -val lastSeenInt: TState<Int> = ints.hold(initialValue = 0) +val ints: Events<Int> = … +val lastSeenInt: State<Int> = ints.holdState(initialValue = 0) ``` -Note that `hold` is only available within an `FrpStateScope` in order to track +Note that `holdState` is only available within an `StateScope` in order to track the lifetime of the state accumulation (akin to the scope parameter of -`Flow.stateIn`). `FrpStateScope` can only come from a top-level -`FrpNetwork.transaction { … }`, or a sub-scope created by using a `-Latest` -operator. Also note that `FrpBuildScope` extends `FrpStateScope`. +`Flow.stateIn`). `StateScope` can only come from a top-level +`Network.transaction { … }`, or a sub-scope created by using a `-Latest` +operator. Also note that `BuildScope` extends `StateScope`. ## distinctUntilChanged() -Use `distinctUntilChanged` like normal. This is only available for `TFlow`; -`TStates` are already `distinctUntilChanged`. +Use `distinctUntilChanged` like normal. This is only available for `Events`; +`States` are already `distinctUntilChanged`. ## merge(...) -### I have TFlows +### I have Eventss -Use `merge(TFlows) { … }`. The lambda argument is used to disambiguate multiple +Use `merge(Events) { … }`. The lambda argument is used to disambiguate multiple simultaneous emissions within the same transaction. #### Explanation -Under Kairos's rules, a `TFlow` may only emit up to once per transaction. This -means that if we are merging two or more `TFlows` that are emitting at the same -time (within the same transaction), the resulting merged `TFlow` must emit a +Under Kairos's rules, an `Events` may only emit up to once per transaction. This +means that if we are merging two or more `Events` that are emitting at the same +time (within the same transaction), the resulting merged `Events` must emit a single value. The lambda argument allows the developer to decide what to do in this case. -### I have TStates +### I have States -If `combine` doesn't satisfy your needs, you can use `TState.stateChanges` to -convert to a `TFlow`, and then `merge`. +If `combine` doesn't satisfy your needs, you can use `State.changes` to +convert to a `Events`, and then `merge`. ## conflatedCallbackFlow { … } -Use `tFlow { … }`. +Use `events { … }`. As a shortcut, if you already have a `conflatedCallbackFlow { … }`, you can -convert it to a TFlow via `Flow.toTFlow()`. +convert it to an Events via `Flow.toEvents()`. -Note that `tFlow` is only available within an `FrpBuildScope` in order to track -the lifetime of the input registration. +Note that `events` is only available within a `BuildScope` in order to track the +lifetime of the input registration. ## first() -### I have a TState +### I have a State -Use `TState.sample`. +Use `State.sample`. -### I have a TFlow +### I have an Events -Use `TFlow.nextOnly`, which works exactly like `Flow.first` but instead of -suspending it returns a `TFlow` that emits once. +Use `Events.nextOnly`, which works exactly like `Flow.first` but instead of +suspending it returns a `Events` that emits once. The naming is intentionally different because `first` implies that it is the first-ever value emitted from the `Flow` (which makes sense for cold `Flows`), whereas `nextOnly` indicates that only the next value relative to the current transaction (the one `nextOnly` is being invoked in) will be emitted. -Note that `nextOnly` is only available within an `FrpStateScope` in order to -track the lifetime of the state accumulation. +Note that `nextOnly` is only available within an `StateScope` in order to track +the lifetime of the state accumulation. ## flatMapLatest { … } If you want to use -Latest to cancel old side-effects, similar to what the Flow -Latest operators offer for coroutines, see `mapLatest`. -### I have a TState… +### I have a State… -#### …and want to switch TStates +#### …and want to switch States -Use `TState.flatMap` +Use `State.flatMap` ``` kotlin -val flattened = tState.flatMap { a -> getTState(a) } +val flattened = state.flatMap { a -> gestate(a) } ``` -#### …and want to switch TFlows +#### …and want to switch Events -Use `TState<TFlow<T>>.switch()` +Use `State<Events<T>>.switchEvents()` ``` kotlin -val tFlow = tState.map { a -> getTFlow(a) }.switch() +val events = state.map { a -> getEvents(a) }.switchEvents() ``` -### I have a TFlow… +### I have an Events… -#### …and want to switch TFlows +#### …and want to switch Events -Use `hold` to convert to a `TState<TFlow<T>>`, then use `switch` to switch to -the latest `TFlow`. +Use `holdState` to convert to a `State<Events<T>>`, then use `switchEvents` to +switch to the latest `Events`. ``` kotlin -val tFlow = tFlowOfFlows.hold(emptyTFlow).switch() +val events = eventsOfFlows.holdState(emptyEvents).switchEvents() ``` -#### …and want to switch TStates +#### …and want to switch States -Use `hold` to convert to a `TState<TState<T>>`, then use `flatMap` to switch to -the latest `TState`. +Use `holdState` to convert to a `State<State<T>>`, then use `flatMap` to switch +to the latest `State`. ``` kotlin -val tState = tFlowOfStates.hold(tStateOf(initialValue)).flatMap { it } +val state = eventsOfStates.holdState(stateOf(initialValue)).flatMap { it } ``` ## mapLatest { … } / collectLatest { … } -`FrpStateScope` and `FrpBuildScope` both provide `-Latest` operators that +`StateScope` and `BuildScope` both provide `-Latest` operators that automatically cancel old work when new values are emitted. ``` kotlin -val currentModel: TState<SomeModel> = … -val mapped: TState<...> = currentModel.mapLatestBuild { model -> +val currentModel: State<SomeModel> = … +val mapped: State<...> = currentModel.mapLatestBuild { model -> effect { "new model in the house: $model" } model.someState.observe { "someState: $it" } - val someData: TState<SomeInfo> = + val someData: State<SomeInfo> = getBroadcasts(model.uri) .map { extractInfo(it) } - .hold(initialInfo) + .holdState(initialInfo) … } ``` ## flowOf(...) -### I want a TState +### I want a State -Use `tStateOf(initialValue)`. +Use `stateOf(initialValue)`. -### I want a TFlow +### I want an Events Use `now.map { initialValue }` -Note that `now` is only available within an `FrpTransactionScope`. +Note that `now` is only available within an `TransactionScope`. #### Explanation -`TFlows` are not cold, and so there isn't a notion of "emit this value once +`Events` are not cold, and so there isn't a notion of "emit this value once there is a collector" like there is for `Flow`. The closest analog would be -`TState`, since the initial value is retained indefinitely until there is an +`State`, since the initial value is retained indefinitely until there is an observer. However, it is often useful to immediately emit a value within the -current transaction, usually when using a `flatMap` or `switch`. In these cases, -using `now` explicitly models that the emission will occur within the current -transaction. +current transaction, usually when using a `flatMap` or `switchEvents`. In these +cases, using `now` explicitly models that the emission will occur within the +current transaction. ``` kotlin -fun <T> FrpTransactionScope.tFlowOf(value: T): TFlow<T> = now.map { value } +fun <T> TransactionScope.eventsOf(value: T): Events<T> = now.map { value } ``` ## MutableStateFlow / MutableSharedFlow -Use `MutableTState(frpNetwork, initialValue)` and `MutableTFlow(frpNetwork)`. +Use `MutableState(frpNetwork, initialValue)` and `MutableEvents(frpNetwork)`. diff --git a/packages/SystemUI/utils/kairos/docs/semantics.md b/packages/SystemUI/utils/kairos/docs/semantics.md index d43bb4447061..c8e468050037 100644 --- a/packages/SystemUI/utils/kairos/docs/semantics.md +++ b/packages/SystemUI/utils/kairos/docs/semantics.md @@ -33,39 +33,39 @@ sealed class Time : Comparable<Time> { typealias Transactional<T> = (Time) -> T -typealias TFlow<T> = SortedMap<Time, T> +typealias Events<T> = SortedMap<Time, T> private fun <T> SortedMap<Time, T>.pairwise(): List<Pair<Pair<Time, T>, Pair<Time<T>>>> = // NOTE: pretend evaluation is lazy, so that error() doesn't immediately throw (toList() + Pair(Time.Infinity, error("no value"))).zipWithNext() -class TState<T> internal constructor( +class State<T> internal constructor( internal val current: Transactional<T>, - val stateChanges: TFlow<T>, + val stateChanges: Events<T>, ) -val emptyTFlow: TFlow<Nothing> = emptyMap() +val emptyEvents: Events<Nothing> = emptyMap() -fun <A, B> TFlow<A>.map(f: FrpTransactionScope.(A) -> B): TFlow<B> = - mapValues { (t, a) -> FrpTransactionScope(t).f(a) } +fun <A, B> Events<A>.map(f: TransactionScope.(A) -> B): Events<B> = + mapValues { (t, a) -> TransactionScope(t).f(a) } -fun <A> TFlow<A>.filter(f: FrpTransactionScope.(A) -> Boolean): TFlow<A> = - filter { (t, a) -> FrpTransactionScope(t).f(a) } +fun <A> Events<A>.filter(f: TransactionScope.(A) -> Boolean): Events<A> = + filter { (t, a) -> TransactionScope(t).f(a) } fun <A> merge( - first: TFlow<A>, - second: TFlow<A>, + first: Events<A>, + second: Events<A>, onCoincidence: Time.(A, A) -> A, -): TFlow<A> = +): Events<A> = first.toMutableMap().also { result -> second.forEach { (t, a) -> result.merge(t, a) { f, s -> - FrpTranscationScope(t).onCoincidence(f, a) + TransactionScope(t).onCoincidence(f, a) } } }.toSortedMap() -fun <A> TState<TFlow<A>>.switch(): TFlow<A> { +fun <A> State<Events<A>>.switchEvents(): Events<A> { val truncated = listOf(Pair(Time.BigBang, current.invoke(Time.BigBang))) + stateChanges.dropWhile { (time, _) -> time < time0 } val events = @@ -77,7 +77,7 @@ fun <A> TState<TFlow<A>>.switch(): TFlow<A> { return events.toSortedMap() } -fun <A> TState<TFlow<A>>.switchPromptly(): TFlow<A> { +fun <A> State<Events<A>>.switchEventsPromptly(): Events<A> { val truncated = listOf(Pair(Time.BigBang, current.invoke(Time.BigBang))) + stateChanges.dropWhile { (time, _) -> time < time0 } val events = @@ -89,24 +89,24 @@ fun <A> TState<TFlow<A>>.switchPromptly(): TFlow<A> { return events.toSortedMap() } -typealias GroupedTFlow<K, V> = TFlow<Map<K, V>> +typealias GroupedEvents<K, V> = Events<Map<K, V>> -fun <K, V> TFlow<Map<K, V>>.groupByKey(): GroupedTFlow<K, V> = this +fun <K, V> Events<Map<K, V>>.groupByKey(): GroupedEvents<K, V> = this -fun <K, V> GroupedTFlow<K, V>.eventsForKey(key: K): TFlow<V> = +fun <K, V> GroupedEvents<K, V>.eventsForKey(key: K): Events<V> = map { m -> m[k] }.filter { it != null }.map { it!! } -fun <A, B> TState<A>.map(f: (A) -> B): TState<B> = - TState( +fun <A, B> State<A>.map(f: (A) -> B): State<B> = + State( current = { t -> f(current.invoke(t)) }, stateChanges = stateChanges.map { f(it) }, ) -fun <A, B, C> TState<A>.combineWith( - other: TState<B>, +fun <A, B, C> State<A>.combineWith( + other: State<B>, f: (A, B) -> C, -): TState<C> = - TState( +): State<C> = + State( current = { t -> f(current.invoke(t), other.current.invoke(t)) }, stateChanges = run { val aChanges = @@ -129,7 +129,7 @@ fun <A, B, C> TState<A>.combineWith( }, ) -fun <A> TState<TState<A>>.flatten(): TState<A> { +fun <A> State<State<A>>.flatten(): State<A> { val changes = stateChanges .pairwise() @@ -144,55 +144,55 @@ fun <A> TState<TState<A>>.flatten(): TState<A> { inWindow } } - return TState( + return State( current = { t -> current.invoke(t).current.invoke(t) }, stateChanges = changes.toSortedMap(), ) } -open class FrpTranscationScope internal constructor( +open class TransactionScope internal constructor( internal val currentTime: Time, ) { - val now: TFlow<Unit> = + val now: Events<Unit> = sortedMapOf(currentTime to Unit) fun <A> Transactional<A>.sample(): A = invoke(currentTime) - fun <A> TState<A>.sample(): A = + fun <A> State<A>.sample(): A = current.sample() } -class FrpStateScope internal constructor( +class StateScope internal constructor( time: Time, internal val stopTime: Time, -): FrpTransactionScope(time) { +): TransactionScope(time) { - fun <A, B> TFlow<A>.fold( + fun <A, B> Events<A>.foldState( initialValue: B, - f: FrpTransactionScope.(B, A) -> B, - ): TState<B> { + f: TransactionScope.(B, A) -> B, + ): State<B> { val truncated = dropWhile { (t, _) -> t < currentTime } .takeWhile { (t, _) -> t <= stopTime } - val folded = + val foldStateed = truncated .scan(Pair(currentTime, initialValue)) { (_, b) (t, a) -> - Pair(t, FrpTransactionScope(t).f(a, b)) + Pair(t, TransactionScope(t).f(a, b)) } val lookup = { t1 -> - folded.lastOrNull { (t0, _) -> t0 < t1 }?.value ?: initialValue + foldStateed.lastOrNull { (t0, _) -> t0 < t1 }?.value ?: initialValue } - return TState(lookup, folded.toSortedMap()) + return State(lookup, foldStateed.toSortedMap()) } - fun <A> TFlow<A>.hold(initialValue: A): TState<A> = - fold(initialValue) { _, a -> a } + fun <A> Events<A>.holdState(initialValue: A): State<A> = + foldState(initialValue) { _, a -> a } - fun <K, V> TFlow<Map<K, Maybe<V>>>.foldMapIncrementally( + fun <K, V> Events<Map<K, Maybe<V>>>.foldStateMapIncrementally( initialValues: Map<K, V> - ): TState<Map<K, V>> = - fold(initialValues) { patch, map -> + ): State<Map<K, V>> = + foldState(initialValues) { patch, map -> val eithers = patch.map { (k, v) -> if (v is Just) Left(k to v.value) else Right(k) } @@ -203,18 +203,18 @@ class FrpStateScope internal constructor( updated } - fun <K : Any, V> TFlow<Map<K, Maybe<TFlow<V>>>>.mergeIncrementally( - initialTFlows: Map<K, TFlow<V>>, - ): TFlow<Map<K, V>> = - foldMapIncrementally(initialTFlows).map { it.merge() }.switch() + fun <K : Any, V> Events<Map<K, Maybe<Events<V>>>>.mergeIncrementally( + initialEventss: Map<K, Events<V>>, + ): Events<Map<K, V>> = + foldStateMapIncrementally(initialEventss).map { it.merge() }.switchEvents() - fun <K, A, B> TFlow<Map<K, Maybe<A>>.mapLatestStatefulForKey( - transform: suspend FrpStateScope.(A) -> B, - ): TFlow<Map<K, Maybe<B>>> = + fun <K, A, B> Events<Map<K, Maybe<A>>.mapLatestStatefulForKey( + transform: suspend StateScope.(A) -> B, + ): Events<Map<K, Maybe<B>>> = pairwise().map { ((t0, patch), (t1, _)) -> patch.map { (k, ma) -> ma.map { a -> - FrpStateScope(t0, t1).transform(a) + StateScope(t0, t1).transform(a) } } } diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/BuildScope.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/BuildScope.kt new file mode 100644 index 000000000000..b6918703b404 --- /dev/null +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/BuildScope.kt @@ -0,0 +1,870 @@ +/* + * 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.kairos + +import com.android.systemui.kairos.util.Maybe +import com.android.systemui.kairos.util.just +import com.android.systemui.kairos.util.map +import kotlin.coroutines.CoroutineContext +import kotlin.coroutines.EmptyCoroutineContext +import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Deferred +import kotlinx.coroutines.DisposableHandle +import kotlinx.coroutines.Job +import kotlinx.coroutines.awaitCancellation +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.FlowCollector +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.dropWhile +import kotlinx.coroutines.flow.scan +import kotlinx.coroutines.launch + +/** A function that modifies the KairosNetwork. */ +typealias BuildSpec<A> = BuildScope.() -> A + +/** + * Constructs a [BuildSpec]. The passed [block] will be invoked with a [BuildScope] that can be used + * to perform network-building operations, including adding new inputs and outputs to the network, + * as well as all operations available in [TransactionScope]. + */ +@ExperimentalKairosApi +@Suppress("NOTHING_TO_INLINE") +inline fun <A> buildSpec(noinline block: BuildScope.() -> A): BuildSpec<A> = block + +/** Applies the [BuildSpec] within this [BuildScope]. */ +@ExperimentalKairosApi +inline operator fun <A> BuildScope.invoke(block: BuildScope.() -> A) = run(block) + +/** Operations that add inputs and outputs to a Kairos network. */ +@ExperimentalKairosApi +interface BuildScope : StateScope { + + /** + * A [KairosNetwork] handle that is bound to this [BuildScope]. + * + * It supports all of the standard functionality by which external code can interact with this + * Kairos network, but all [activated][KairosNetwork.activateSpec] [BuildSpec]s are bound as + * children to this [BuildScope], such that when this [BuildScope] is destroyed, all children + * are also destroyed. + */ + val kairosNetwork: KairosNetwork + + /** + * Defers invoking [block] until after the current [BuildScope] code-path completes, returning a + * [DeferredValue] that can be used to reference the result. + * + * Useful for recursive definitions. + * + * @see deferredBuildScopeAction + * @see DeferredValue + */ + fun <R> deferredBuildScope(block: BuildScope.() -> R): DeferredValue<R> + + /** + * Defers invoking [block] until after the current [BuildScope] code-path completes. + * + * Useful for recursive definitions. + * + * @see deferredBuildScope + */ + fun deferredBuildScopeAction(block: BuildScope.() -> Unit) + + /** + * Returns an [Events] containing the results of applying [transform] to each value of the + * original [Events]. + * + * [transform] can perform modifications to the Kairos network via its [BuildScope] receiver. + * Unlike [mapLatestBuild], these modifications are not undone with each subsequent emission of + * the original [Events]. + * + * **NOTE:** This API does not [observe] the original [Events], meaning that unless the returned + * (or a downstream) [Events] is observed separately, [transform] will not be invoked, and no + * internal side-effects will occur. + */ + fun <A, B> Events<A>.mapBuild(transform: BuildScope.(A) -> B): Events<B> + + /** + * Invokes [block] whenever this [Events] emits a value, allowing side-effects to be safely + * performed in reaction to the emission. + * + * Specifically, [block] is deferred to the end of the transaction, and is only actually + * executed if this [BuildScope] is still active by that time. It can be deactivated due to a + * -Latest combinator, for example. + * + * Shorthand for: + * ```kotlin + * events.observe { effect { ... } } + * ``` + */ + fun <A> Events<A>.observe( + coroutineContext: CoroutineContext = EmptyCoroutineContext, + block: EffectScope.(A) -> Unit = {}, + ): DisposableHandle + + /** + * Returns an [Events] containing the results of applying each [BuildSpec] emitted from the + * original [Events], and a [DeferredValue] containing the result of applying [initialSpecs] + * immediately. + * + * When each [BuildSpec] is applied, changes from the previously-active [BuildSpec] with the + * same key are undone (any registered [observers][observe] are unregistered, and any pending + * [side-effects][effect] are cancelled). + * + * If the [Maybe] contained within the value for an associated key is [none], then the + * previously-active [BuildSpec] will be undone with no replacement. + */ + fun <K, A, B> Events<Map<K, Maybe<BuildSpec<A>>>>.applyLatestSpecForKey( + initialSpecs: DeferredValue<Map<K, BuildSpec<B>>>, + numKeys: Int? = null, + ): Pair<Events<Map<K, Maybe<A>>>, DeferredValue<Map<K, B>>> + + /** + * Creates an instance of an [Events] with elements that are from [builder]. + * + * [builder] is run in its own coroutine, allowing for ongoing work that can emit to the + * provided [MutableState]. + * + * By default, [builder] is only running while the returned [Events] is being + * [observed][observe]. If you want it to run at all times, simply add a no-op observer: + * ```kotlin + * events { ... }.apply { observe() } + * ``` + */ + fun <T> events( + name: String? = null, + builder: suspend EventProducerScope<T>.() -> Unit, + ): Events<T> + + /** + * Creates an instance of an [Events] with elements that are emitted from [builder]. + * + * [builder] is run in its own coroutine, allowing for ongoing work that can emit to the + * provided [MutableState]. + * + * By default, [builder] is only running while the returned [Events] is being + * [observed][observe]. If you want it to run at all times, simply add a no-op observer: + * ```kotlin + * events { ... }.apply { observe() } + * ``` + * + * In the event of backpressure, emissions are *coalesced* into batches. When a value is + * [emitted][CoalescingEventProducerScope.emit] from [builder], it is merged into the batch via + * [coalesce]. Once the batch is consumed by the kairos network in the next transaction, the + * batch is reset back to [getInitialValue]. + */ + fun <In, Out> coalescingEvents( + getInitialValue: () -> Out, + coalesce: (old: Out, new: In) -> Out, + builder: suspend CoalescingEventProducerScope<In>.() -> Unit, + ): Events<Out> + + /** + * Creates a new [BuildScope] that is a child of this one. + * + * This new scope can be manually cancelled via the returned [Job], or will be cancelled + * automatically when its parent is cancelled. Cancellation will unregister all + * [observers][observe] and cancel all scheduled [effects][effect]. + * + * The return value from [block] can be accessed via the returned [DeferredValue]. + */ + fun <A> asyncScope(block: BuildSpec<A>): Pair<DeferredValue<A>, Job> + + // TODO: once we have context params, these can all become extensions: + + /** + * Returns an [Events] containing the results of applying the given [transform] function to each + * value of the original [Events]. + * + * Unlike [Events.map], [transform] can perform arbitrary asynchronous code. This code is run + * outside of the current Kairos transaction; when [transform] returns, the returned value is + * emitted from the result [Events] in a new transaction. + * + * Shorthand for: + * ```kotlin + * events.mapLatestBuild { a -> asyncEvent { transform(a) } }.flatten() + * ``` + */ + fun <A, B> Events<A>.mapAsyncLatest(transform: suspend (A) -> B): Events<B> = + mapLatestBuild { a -> asyncEvent { transform(a) } }.flatten() + + /** + * Invokes [block] whenever this [Events] emits a value. [block] receives an [BuildScope] that + * can be used to make further modifications to the Kairos network, and/or perform side-effects + * via [effect]. + * + * @see observe + */ + fun <A> Events<A>.observeBuild(block: BuildScope.(A) -> Unit = {}): DisposableHandle = + mapBuild(block).observe() + + /** + * Returns a [StateFlow] whose [value][StateFlow.value] tracks the current + * [value of this State][State.sample], and will emit at the same rate as [State.changes]. + * + * Note that the [value][StateFlow.value] is not available until the *end* of the current + * transaction. If you need the current value before this time, then use [State.sample]. + */ + fun <A> State<A>.toStateFlow(): StateFlow<A> { + val uninitialized = Any() + var initialValue: Any? = uninitialized + val innerStateFlow = MutableStateFlow<Any?>(uninitialized) + deferredBuildScope { + initialValue = sample() + changes.observe { + innerStateFlow.value = it + initialValue = null + } + } + + @Suppress("UNCHECKED_CAST") + fun getValue(innerValue: Any?): A = + when { + innerValue !== uninitialized -> innerValue as A + initialValue !== uninitialized -> initialValue as A + else -> + error( + "Attempted to access StateFlow.value before Kairos transaction has completed." + ) + } + + return object : StateFlow<A> { + override val replayCache: List<A> + get() = innerStateFlow.replayCache.map(::getValue) + + override val value: A + get() = getValue(innerStateFlow.value) + + override suspend fun collect(collector: FlowCollector<A>): Nothing { + innerStateFlow.collect { collector.emit(getValue(it)) } + } + } + } + + /** + * Returns a [SharedFlow] configured with a replay cache of size [replay] that emits the current + * [value][State.sample] of this [State] followed by all [changes]. + */ + fun <A> State<A>.toSharedFlow(replay: Int = 0): SharedFlow<A> { + val result = MutableSharedFlow<A>(replay, extraBufferCapacity = 1) + deferredBuildScope { + result.tryEmit(sample()) + changes.observe { a -> result.tryEmit(a) } + } + return result + } + + /** + * Returns a [SharedFlow] configured with a replay cache of size [replay] that emits values + * whenever this [Events] emits. + */ + fun <A> Events<A>.toSharedFlow(replay: Int = 0): SharedFlow<A> { + val result = MutableSharedFlow<A>(replay, extraBufferCapacity = 1) + observe { a -> result.tryEmit(a) } + return result + } + + /** + * Returns a [State] that holds onto the value returned by applying the most recently emitted + * [BuildSpec] from the original [Events], or the value returned by applying [initialSpec] if + * nothing has been emitted since it was constructed. + * + * When each [BuildSpec] is applied, changes from the previously-active [BuildSpec] are undone + * (any registered [observers][observe] are unregistered, and any pending [side-effects][effect] + * are cancelled). + */ + fun <A> Events<BuildSpec<A>>.holdLatestSpec(initialSpec: BuildSpec<A>): State<A> { + val (changes: Events<A>, initApplied: DeferredValue<A>) = applyLatestSpec(initialSpec) + return changes.holdStateDeferred(initApplied) + } + + /** + * Returns a [State] containing the value returned by applying the [BuildSpec] held by the + * original [State]. + * + * When each [BuildSpec] is applied, changes from the previously-active [BuildSpec] are undone + * (any registered [observers][observe] are unregistered, and any pending [side-effects][effect] + * are cancelled). + */ + fun <A> State<BuildSpec<A>>.applyLatestSpec(): State<A> { + val (appliedChanges: Events<A>, init: DeferredValue<A>) = + changes.applyLatestSpec(buildSpec { sample().applySpec() }) + return appliedChanges.holdStateDeferred(init) + } + + /** + * Returns an [Events] containing the results of applying each [BuildSpec] emitted from the + * original [Events]. + * + * When each [BuildSpec] is applied, changes from the previously-active [BuildSpec] are undone + * (any registered [observers][observe] are unregistered, and any pending [side-effects][effect] + * are cancelled). + */ + fun <A> Events<BuildSpec<A>>.applyLatestSpec(): Events<A> = applyLatestSpec(buildSpec {}).first + + /** + * Returns an [Events] that switches to a new [Events] produced by [transform] every time the + * original [Events] emits a value. + * + * [transform] can perform modifications to the Kairos network via its [BuildScope] receiver. + * When the original [Events] emits a new value, those changes are undone (any registered + * [observers][observe] are unregistered, and any pending [effects][effect] are cancelled). + */ + fun <A, B> Events<A>.flatMapLatestBuild(transform: BuildScope.(A) -> Events<B>): Events<B> = + mapCheap { buildSpec { transform(it) } }.applyLatestSpec().flatten() + + /** + * Returns a [State] by applying [transform] to the value held by the original [State]. + * + * [transform] can perform modifications to the Kairos network via its [BuildScope] receiver. + * When the value held by the original [State] changes, those changes are undone (any registered + * [observers][observe] are unregistered, and any pending [effects][effect] are cancelled). + */ + fun <A, B> State<A>.flatMapLatestBuild(transform: BuildScope.(A) -> State<B>): State<B> = + mapLatestBuild { transform(it) }.flatten() + + /** + * Returns a [State] that transforms the value held inside this [State] by applying it to the + * [transform]. + * + * [transform] can perform modifications to the Kairos network via its [BuildScope] receiver. + * When the value held by the original [State] changes, those changes are undone (any registered + * [observers][observe] are unregistered, and any pending [effects][effect] are cancelled). + */ + fun <A, B> State<A>.mapLatestBuild(transform: BuildScope.(A) -> B): State<B> = + mapCheapUnsafe { buildSpec { transform(it) } }.applyLatestSpec() + + /** + * Returns an [Events] containing the results of applying each [BuildSpec] emitted from the + * original [Events], and a [DeferredValue] containing the result of applying [initialSpec] + * immediately. + * + * When each [BuildSpec] is applied, changes from the previously-active [BuildSpec] are undone + * (any registered [observers][observe] are unregistered, and any pending [side-effects][effect] + * are cancelled). + */ + fun <A : Any?, B> Events<BuildSpec<B>>.applyLatestSpec( + initialSpec: BuildSpec<A> + ): Pair<Events<B>, DeferredValue<A>> { + val (events, result) = + mapCheap { spec -> mapOf(Unit to just(spec)) } + .applyLatestSpecForKey(initialSpecs = mapOf(Unit to initialSpec), numKeys = 1) + val outEvents: Events<B> = + events.mapMaybe { + checkNotNull(it[Unit]) { "applyLatest: expected result, but none present in: $it" } + } + val outInit: DeferredValue<A> = deferredBuildScope { + val initResult: Map<Unit, A> = result.get() + check(Unit in initResult) { + "applyLatest: expected initial result, but none present in: $initResult" + } + @Suppress("UNCHECKED_CAST") + initResult.getOrDefault(Unit) { null } as A + } + return Pair(outEvents, outInit) + } + + /** + * Returns an [Events] containing the results of applying [transform] to each value of the + * original [Events]. + * + * [transform] can perform modifications to the Kairos network via its [BuildScope] receiver. + * With each invocation of [transform], changes from the previous invocation are undone (any + * registered [observers][observe] are unregistered, and any pending [side-effects][effect] are + * cancelled). + */ + fun <A, B> Events<A>.mapLatestBuild(transform: BuildScope.(A) -> B): Events<B> = + mapCheap { buildSpec { transform(it) } }.applyLatestSpec() + + /** + * Returns an [Events] containing the results of applying [transform] to each value of the + * original [Events], and a [DeferredValue] containing the result of applying [transform] to + * [initialValue] immediately. + * + * [transform] can perform modifications to the Kairos network via its [BuildScope] receiver. + * With each invocation of [transform], changes from the previous invocation are undone (any + * registered [observers][observe] are unregistered, and any pending [side-effects][effect] are + * cancelled). + */ + fun <A, B> Events<A>.mapLatestBuild( + initialValue: A, + transform: BuildScope.(A) -> B, + ): Pair<Events<B>, DeferredValue<B>> = + mapLatestBuildDeferred(deferredOf(initialValue), transform) + + /** + * Returns an [Events] containing the results of applying [transform] to each value of the + * original [Events], and a [DeferredValue] containing the result of applying [transform] to + * [initialValue] immediately. + * + * [transform] can perform modifications to the Kairos network via its [BuildScope] receiver. + * With each invocation of [transform], changes from the previous invocation are undone (any + * registered [observers][observe] are unregistered, and any pending [side-effects][effect] are + * cancelled). + */ + fun <A, B> Events<A>.mapLatestBuildDeferred( + initialValue: DeferredValue<A>, + transform: BuildScope.(A) -> B, + ): Pair<Events<B>, DeferredValue<B>> = + mapCheap { buildSpec { transform(it) } } + .applyLatestSpec(initialSpec = buildSpec { transform(initialValue.get()) }) + + /** + * Returns an [Events] containing the results of applying each [BuildSpec] emitted from the + * original [Events], and a [DeferredValue] containing the result of applying [initialSpecs] + * immediately. + * + * When each [BuildSpec] is applied, changes from the previously-active [BuildSpec] with the + * same key are undone (any registered [observers][observe] are unregistered, and any pending + * [side-effects][effect] are cancelled). + * + * If the [Maybe] contained within the value for an associated key is [none], then the + * previously-active [BuildSpec] will be undone with no replacement. + */ + fun <K, A, B> Events<Map<K, Maybe<BuildSpec<A>>>>.applyLatestSpecForKey( + initialSpecs: Map<K, BuildSpec<B>>, + numKeys: Int? = null, + ): Pair<Events<Map<K, Maybe<A>>>, DeferredValue<Map<K, B>>> = + applyLatestSpecForKey(deferredOf(initialSpecs), numKeys) + + fun <K, V> Incremental<K, BuildSpec<V>>.applyLatestSpecForKey( + numKeys: Int? = null + ): Incremental<K, V> { + val (events, initial) = updates.applyLatestSpecForKey(sampleDeferred(), numKeys) + return events.foldStateMapIncrementally(initial) + } + + /** + * Returns an [Events] containing the results of applying each [BuildSpec] emitted from the + * original [Events]. + * + * When each [BuildSpec] is applied, changes from the previously-active [BuildSpec] with the + * same key are undone (any registered [observers][observe] are unregistered, and any pending + * [side-effects][effect] are cancelled). + * + * If the [Maybe] contained within the value for an associated key is [none], then the + * previously-active [BuildSpec] will be undone with no replacement. + */ + fun <K, V> Events<Map<K, Maybe<BuildSpec<V>>>>.applyLatestSpecForKey( + numKeys: Int? = null + ): Events<Map<K, Maybe<V>>> = + applyLatestSpecForKey<K, V, Nothing>(deferredOf(emptyMap()), numKeys).first + + /** + * Returns a [State] containing the latest results of applying each [BuildSpec] emitted from the + * original [Events]. + * + * When each [BuildSpec] is applied, changes from the previously-active [BuildSpec] with the + * same key are undone (any registered [observers][observe] are unregistered, and any pending + * [side-effects][effect] are cancelled). + * + * If the [Maybe] contained within the value for an associated key is [none], then the + * previously-active [BuildSpec] will be undone with no replacement. + */ + fun <K, V> Events<Map<K, Maybe<BuildSpec<V>>>>.holdLatestSpecForKey( + initialSpecs: DeferredValue<Map<K, BuildSpec<V>>>, + numKeys: Int? = null, + ): Incremental<K, V> { + val (changes, initialValues) = applyLatestSpecForKey(initialSpecs, numKeys) + return changes.foldStateMapIncrementally(initialValues) + } + + /** + * Returns a [State] containing the latest results of applying each [BuildSpec] emitted from the + * original [Events]. + * + * When each [BuildSpec] is applied, changes from the previously-active [BuildSpec] with the + * same key are undone (any registered [observers][observe] are unregistered, and any pending + * [side-effects][effect] are cancelled). + * + * If the [Maybe] contained within the value for an associated key is [none], then the + * previously-active [BuildSpec] will be undone with no replacement. + */ + fun <K, V> Events<Map<K, Maybe<BuildSpec<V>>>>.holdLatestSpecForKey( + initialSpecs: Map<K, BuildSpec<V>> = emptyMap(), + numKeys: Int? = null, + ): Incremental<K, V> = holdLatestSpecForKey(deferredOf(initialSpecs), numKeys) + + /** + * Returns an [Events] containing the results of applying [transform] to each value of the + * original [Events], and a [DeferredValue] containing the result of applying [transform] to + * [initialValues] immediately. + * + * [transform] can perform modifications to the Kairos network via its [BuildScope] receiver. + * With each invocation of [transform], changes from the previous invocation are undone (any + * registered [observers][observe] are unregistered, and any pending [side-effects][effect] are + * cancelled). + * + * If the [Maybe] contained within the value for an associated key is [none], then the + * previously-active [BuildScope] will be undone with no replacement. + */ + fun <K, A, B> Events<Map<K, Maybe<A>>>.mapLatestBuildForKey( + initialValues: DeferredValue<Map<K, A>>, + numKeys: Int? = null, + transform: BuildScope.(K, A) -> B, + ): Pair<Events<Map<K, Maybe<B>>>, DeferredValue<Map<K, B>>> = + map { patch -> patch.mapValues { (k, v) -> v.map { buildSpec { transform(k, it) } } } } + .applyLatestSpecForKey( + deferredBuildScope { + initialValues.get().mapValues { (k, v) -> buildSpec { transform(k, v) } } + }, + numKeys = numKeys, + ) + + /** + * Returns an [Events] containing the results of applying [transform] to each value of the + * original [Events], and a [DeferredValue] containing the result of applying [transform] to + * [initialValues] immediately. + * + * [transform] can perform modifications to the Kairos network via its [BuildScope] receiver. + * With each invocation of [transform], changes from the previous invocation are undone (any + * registered [observers][observe] are unregistered, and any pending [side-effects][effect] are + * cancelled). + * + * If the [Maybe] contained within the value for an associated key is [none], then the + * previously-active [BuildScope] will be undone with no replacement. + */ + fun <K, A, B> Events<Map<K, Maybe<A>>>.mapLatestBuildForKey( + initialValues: Map<K, A>, + numKeys: Int? = null, + transform: BuildScope.(K, A) -> B, + ): Pair<Events<Map<K, Maybe<B>>>, DeferredValue<Map<K, B>>> = + mapLatestBuildForKey(deferredOf(initialValues), numKeys, transform) + + /** + * Returns an [Events] containing the results of applying [transform] to each value of the + * original [Events]. + * + * [transform] can perform modifications to the Kairos network via its [BuildScope] receiver. + * With each invocation of [transform], changes from the previous invocation are undone (any + * registered [observers][observe] are unregistered, and any pending [side-effects][effect] are + * cancelled). + * + * If the [Maybe] contained within the value for an associated key is [none], then the + * previously-active [BuildScope] will be undone with no replacement. + */ + fun <K, A, B> Events<Map<K, Maybe<A>>>.mapLatestBuildForKey( + numKeys: Int? = null, + transform: BuildScope.(K, A) -> B, + ): Events<Map<K, Maybe<B>>> = mapLatestBuildForKey(emptyMap(), numKeys, transform).first + + /** Returns a [Deferred] containing the next value to be emitted from this [Events]. */ + fun <R> Events<R>.nextDeferred(): Deferred<R> { + lateinit var next: CompletableDeferred<R> + val job = launchScope { nextOnly().observe { next.complete(it) } } + next = CompletableDeferred<R>(parent = job) + return next + } + + /** Returns a [State] that reflects the [StateFlow.value] of this [StateFlow]. */ + fun <A> StateFlow<A>.toState(): State<A> { + val initial = value + return events { dropWhile { it == initial }.collect { emit(it) } }.holdState(initial) + } + + /** Returns an [Events] that emits whenever this [Flow] emits. */ + fun <A> Flow<A>.toEvents(name: String? = null): Events<A> = + events(name) { collect { emit(it) } } + + /** + * Shorthand for: + * ```kotlin + * flow.toEvents().holdState(initialValue) + * ``` + */ + fun <A> Flow<A>.toState(initialValue: A): State<A> = toEvents().holdState(initialValue) + + /** + * Shorthand for: + * ```kotlin + * flow.scan(initialValue, operation).toEvents().holdState(initialValue) + * ``` + */ + fun <A, B> Flow<A>.scanToState(initialValue: B, operation: (B, A) -> B): State<B> = + scan(initialValue, operation).toEvents().holdState(initialValue) + + /** + * Shorthand for: + * ```kotlin + * flow.scan(initialValue) { a, f -> f(a) }.toEvents().holdState(initialValue) + * ``` + */ + fun <A> Flow<(A) -> A>.scanToState(initialValue: A): State<A> = + scanToState(initialValue) { a, f -> f(a) } + + /** + * Invokes [block] whenever this [Events] emits a value. [block] receives an [BuildScope] that + * can be used to make further modifications to the Kairos network, and/or perform side-effects + * via [effect]. + * + * With each invocation of [block], changes from the previous invocation are undone (any + * registered [observers][observe] are unregistered, and any pending [side-effects][effect] are + * cancelled). + */ + fun <A> Events<A>.observeLatestBuild(block: BuildScope.(A) -> Unit = {}): DisposableHandle = + mapLatestBuild { block(it) }.observe() + + /** + * Invokes [block] whenever this [Events] emits a value, allowing side-effects to be safely + * performed in reaction to the emission. + * + * With each invocation of [block], running effects from the previous invocation are cancelled. + */ + fun <A> Events<A>.observeLatest(block: EffectScope.(A) -> Unit = {}): DisposableHandle { + var innerJob: Job? = null + return observeBuild { + innerJob?.cancel() + innerJob = effect { block(it) } + } + } + + /** + * Invokes [block] with the value held by this [State], allowing side-effects to be safely + * performed in reaction to the state changing. + * + * With each invocation of [block], running effects from the previous invocation are cancelled. + */ + fun <A> State<A>.observeLatest(block: EffectScope.(A) -> Unit = {}): Job = launchScope { + var innerJob = effect { block(sample()) } + changes.observeBuild { + innerJob.cancel() + innerJob = effect { block(it) } + } + } + + /** + * Applies [block] to the value held by this [State]. [block] receives an [BuildScope] that can + * be used to make further modifications to the Kairos network, and/or perform side-effects via + * [effect]. + * + * [block] can perform modifications to the Kairos network via its [BuildScope] receiver. With + * each invocation of [block], changes from the previous invocation are undone (any registered + * [observers][observe] are unregistered, and any pending [side-effects][effect] are cancelled). + */ + fun <A> State<A>.observeLatestBuild(block: BuildScope.(A) -> Unit = {}): Job = launchScope { + var innerJob: Job = launchScope { block(sample()) } + changes.observeBuild { + innerJob.cancel() + innerJob = launchScope { block(it) } + } + } + + /** Applies the [BuildSpec] within this [BuildScope]. */ + fun <A> BuildSpec<A>.applySpec(): A = this() + + /** + * Applies the [BuildSpec] within this [BuildScope], returning the result as an [DeferredValue]. + */ + fun <A> BuildSpec<A>.applySpecDeferred(): DeferredValue<A> = deferredBuildScope { applySpec() } + + /** + * Invokes [block] on the value held in this [State]. [block] receives an [BuildScope] that can + * be used to make further modifications to the Kairos network, and/or perform side-effects via + * [effect]. + */ + fun <A> State<A>.observeBuild(block: BuildScope.(A) -> Unit = {}): Job = launchScope { + block(sample()) + changes.observeBuild(block) + } + + /** + * Invokes [block] with the current value of this [State], re-invoking whenever it changes, + * allowing side-effects to be safely performed in reaction value changing. + * + * Specifically, [block] is deferred to the end of the transaction, and is only actually + * executed if this [BuildScope] is still active by that time. It can be deactivated due to a + * -Latest combinator, for example. + * + * If the [State] is changing within the *current* transaction (i.e. [changes] is presently + * emitting) then [block] will be invoked for the first time with the new value; otherwise, it + * will be invoked with the [current][sample] value. + */ + fun <A> State<A>.observe(block: EffectScope.(A) -> Unit = {}): DisposableHandle = + now.map { sample() }.mergeWith(changes) { _, new -> new }.observe { block(it) } +} + +/** + * Returns an [Events] that emits the result of [block] once it completes. [block] is evaluated + * outside of the current Kairos transaction; when it completes, the returned [Events] emits in a + * new transaction. + * + * Shorthand for: + * ``` + * events { emitter: MutableEvents<A> -> + * val a = block() + * emitter.emit(a) + * } + * ``` + */ +@ExperimentalKairosApi +fun <A> BuildScope.asyncEvent(block: suspend () -> A): Events<A> = + events { + // TODO: if block completes synchronously, it would be nice to emit within this + // transaction + emit(block()) + } + .apply { observe() } + +/** + * Performs a side-effect in a safe manner w/r/t the current Kairos transaction. + * + * Specifically, [block] is deferred to the end of the current transaction, and is only actually + * executed if this [BuildScope] is still active by that time. It can be deactivated due to a + * -Latest combinator, for example. + * + * Shorthand for: + * ```kotlin + * launchScope { now.observe { block() } } + * ``` + */ +@ExperimentalKairosApi +fun BuildScope.effect( + context: CoroutineContext = EmptyCoroutineContext, + block: EffectScope.() -> Unit, +): Job = launchScope { now.observe(context) { block() } } + +/** + * Launches [block] in a new coroutine, returning a [Job] bound to the coroutine. + * + * This coroutine is not actually started until the *end* of the current Kairos transaction. This is + * done because the current [BuildScope] might be deactivated within this transaction, perhaps due + * to a -Latest combinator. If this happens, then the coroutine will never actually be started. + * + * Shorthand for: + * ```kotlin + * effect { effectCoroutineScope.launch { block() } } + * ``` + */ +@ExperimentalKairosApi +fun BuildScope.launchEffect(block: suspend CoroutineScope.() -> Unit): Job = asyncEffect(block) + +/** + * Launches [block] in a new coroutine, returning the result as a [Deferred]. + * + * This coroutine is not actually started until the *end* of the current Kairos transaction. This is + * done because the current [BuildScope] might be deactivated within this transaction, perhaps due + * to a -Latest combinator. If this happens, then the coroutine will never actually be started. + * + * Shorthand for: + * ```kotlin + * CompletableDeferred<R>.apply { + * effect { effectCoroutineScope.launch { complete(coroutineScope { block() }) } } + * } + * .await() + * ``` + */ +@ExperimentalKairosApi +fun <R> BuildScope.asyncEffect(block: suspend CoroutineScope.() -> R): Deferred<R> { + val result = CompletableDeferred<R>() + val job = effect { effectCoroutineScope.launch { result.complete(coroutineScope(block)) } } + val handle = job.invokeOnCompletion { result.cancel() } + result.invokeOnCompletion { + handle.dispose() + job.cancel() + } + return result +} + +/** Like [BuildScope.asyncScope], but ignores the result of [block]. */ +@ExperimentalKairosApi +fun BuildScope.launchScope(block: BuildSpec<*>): Job = asyncScope(block).second + +/** + * Creates an instance of an [Events] with elements that are emitted from [builder]. + * + * [builder] is run in its own coroutine, allowing for ongoing work that can emit to the provided + * [MutableState]. + * + * By default, [builder] is only running while the returned [Events] is being + * [observed][BuildScope.observe]. If you want it to run at all times, simply add a no-op observer: + * ```kotlin + * events { ... }.apply { observe() } + * ``` + * + * In the event of backpressure, emissions are *coalesced* into batches. When a value is + * [emitted][CoalescingEventProducerScope.emit] from [builder], it is merged into the batch via + * [coalesce]. Once the batch is consumed by the Kairos network in the next transaction, the batch + * is reset back to [initialValue]. + */ +@ExperimentalKairosApi +fun <In, Out> BuildScope.coalescingEvents( + initialValue: Out, + coalesce: (old: Out, new: In) -> Out, + builder: suspend CoalescingEventProducerScope<In>.() -> Unit, +): Events<Out> = coalescingEvents(getInitialValue = { initialValue }, coalesce, builder) + +/** + * Creates an instance of an [Events] with elements that are emitted from [builder]. + * + * [builder] is run in its own coroutine, allowing for ongoing work that can emit to the provided + * [MutableState]. + * + * By default, [builder] is only running while the returned [Events] is being + * [observed][BuildScope.observe]. If you want it to run at all times, simply add a no-op observer: + * ```kotlin + * events { ... }.apply { observe() } + * ``` + * + * In the event of backpressure, emissions are *conflated*; any older emissions are dropped and only + * the most recent emission will be used when the Kairos network is ready. + */ +@ExperimentalKairosApi +fun <T> BuildScope.conflatedEvents( + builder: suspend CoalescingEventProducerScope<T>.() -> Unit +): Events<T> = + coalescingEvents<T, Any?>(initialValue = Any(), coalesce = { _, new -> new }, builder = builder) + .mapCheap { + @Suppress("UNCHECKED_CAST") + it as T + } + +/** Scope for emitting to a [BuildScope.coalescingEvents]. */ +interface CoalescingEventProducerScope<in T> { + /** + * Inserts [value] into the current batch, enqueueing it for emission from this [Events] if not + * already pending. + * + * Backpressure occurs when [emit] is called while the Kairos network is currently in a + * transaction; if called multiple times, then emissions will be coalesced into a single batch + * that is then processed when the network is ready. + */ + fun emit(value: T) +} + +/** Scope for emitting to a [BuildScope.events]. */ +interface EventProducerScope<in T> { + /** + * Emits a [value] to this [Events], suspending the caller until the Kairos transaction + * containing the emission has completed. + */ + suspend fun emit(value: T) +} + +/** + * Suspends forever. Upon cancellation, runs [block]. Useful for unregistering callbacks inside of + * [BuildScope.events] and [BuildScope.coalescingEvents]. + */ +suspend fun awaitClose(block: () -> Unit): Nothing = + try { + awaitCancellation() + } finally { + block() + } diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/Combinators.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/Combinators.kt index ae9b8c85910f..c20864648f00 100644 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/Combinators.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/Combinators.kt @@ -25,42 +25,42 @@ import kotlinx.coroutines.flow.channelFlow import kotlinx.coroutines.flow.conflate /** - * Returns a [TFlow] that emits the value sampled from the [Transactional] produced by each emission - * of the original [TFlow], within the same transaction of the original emission. + * Returns an [Events] that emits the value sampled from the [Transactional] produced by each + * emission of the original [Events], within the same transaction of the original emission. */ -@ExperimentalFrpApi -fun <A> TFlow<Transactional<A>>.sampleTransactionals(): TFlow<A> = map { it.sample() } +@ExperimentalKairosApi +fun <A> Events<Transactional<A>>.sampleTransactionals(): Events<A> = map { it.sample() } -/** @see FrpTransactionScope.sample */ -@ExperimentalFrpApi -fun <A, B, C> TFlow<A>.sample( - state: TState<B>, - transform: suspend FrpTransactionScope.(A, B) -> C, -): TFlow<C> = map { transform(it, state.sample()) } +/** @see TransactionScope.sample */ +@ExperimentalKairosApi +fun <A, B, C> Events<A>.sample( + state: State<B>, + transform: TransactionScope.(A, B) -> C, +): Events<C> = map { transform(it, state.sample()) } -/** @see FrpTransactionScope.sample */ -@ExperimentalFrpApi -fun <A, B, C> TFlow<A>.sample( - transactional: Transactional<B>, - transform: suspend FrpTransactionScope.(A, B) -> C, -): TFlow<C> = map { transform(it, transactional.sample()) } +/** @see TransactionScope.sample */ +@ExperimentalKairosApi +fun <A, B, C> Events<A>.sample( + sampleable: Transactional<B>, + transform: TransactionScope.(A, B) -> C, +): Events<C> = map { transform(it, sampleable.sample()) } /** - * Like [sample], but if [state] is changing at the time it is sampled ([stateChanges] is emitting), - * then the new value is passed to [transform]. + * Like [sample], but if [state] is changing at the time it is sampled ([changes] is emitting), then + * the new value is passed to [transform]. * * Note that [sample] is both more performant, and safer to use with recursive definitions. You will * generally want to use it rather than this. * * @see sample */ -@ExperimentalFrpApi -fun <A, B, C> TFlow<A>.samplePromptly( - state: TState<B>, - transform: suspend FrpTransactionScope.(A, B) -> C, -): TFlow<C> = - sample(state) { a, b -> These.thiz<Pair<A, B>, B>(a to b) } - .mergeWith(state.stateChanges.map { These.that(it) }) { thiz, that -> +@ExperimentalKairosApi +fun <A, B, C> Events<A>.samplePromptly( + state: State<B>, + transform: TransactionScope.(A, B) -> C, +): Events<C> = + sample(state) { a, b -> These.thiz(a to b) } + .mergeWith(state.changes.map { These.that(it) }) { thiz, that -> These.both((thiz as These.This).thiz, (that as These.That).that) } .mapMaybe { these -> @@ -75,199 +75,204 @@ fun <A, B, C> TFlow<A>.samplePromptly( } /** - * Returns a cold [Flow] that, when collected, emits from this [TFlow]. [network] is needed to - * transactionally connect to / disconnect from the [TFlow] when collection starts/stops. + * Returns a cold [Flow] that, when collected, emits from this [Events]. [network] is needed to + * transactionally connect to / disconnect from the [Events] when collection starts/stops. */ -@ExperimentalFrpApi -fun <A> TFlow<A>.toColdConflatedFlow(network: FrpNetwork): Flow<A> = +@ExperimentalKairosApi +fun <A> Events<A>.toColdConflatedFlow(network: KairosNetwork): Flow<A> = channelFlow { network.activateSpec { observe { trySend(it) } } }.conflate() /** - * Returns a cold [Flow] that, when collected, emits from this [TState]. [network] is needed to - * transactionally connect to / disconnect from the [TState] when collection starts/stops. + * Returns a cold [Flow] that, when collected, emits from this [State]. [network] is needed to + * transactionally connect to / disconnect from the [State] when collection starts/stops. */ -@ExperimentalFrpApi -fun <A> TState<A>.toColdConflatedFlow(network: FrpNetwork): Flow<A> = +@ExperimentalKairosApi +fun <A> State<A>.toColdConflatedFlow(network: KairosNetwork): Flow<A> = channelFlow { network.activateSpec { observe { trySend(it) } } }.conflate() /** - * Returns a cold [Flow] that, when collected, applies this [FrpSpec] in a new transaction in this - * [network], and then emits from the returned [TFlow]. + * Returns a cold [Flow] that, when collected, applies this [BuildSpec] in a new transaction in this + * [network], and then emits from the returned [Events]. * - * When collection is cancelled, so is the [FrpSpec]. This means all ongoing work is cleaned up. + * When collection is cancelled, so is the [BuildSpec]. This means all ongoing work is cleaned up. */ -@ExperimentalFrpApi -@JvmName("flowSpecToColdConflatedFlow") -fun <A> FrpSpec<TFlow<A>>.toColdConflatedFlow(network: FrpNetwork): Flow<A> = +@ExperimentalKairosApi +@JvmName("eventsSpecToColdConflatedFlow") +fun <A> BuildSpec<Events<A>>.toColdConflatedFlow(network: KairosNetwork): Flow<A> = channelFlow { network.activateSpec { applySpec().observe { trySend(it) } } }.conflate() /** - * Returns a cold [Flow] that, when collected, applies this [FrpSpec] in a new transaction in this - * [network], and then emits from the returned [TState]. + * Returns a cold [Flow] that, when collected, applies this [BuildSpec] in a new transaction in this + * [network], and then emits from the returned [State]. * - * When collection is cancelled, so is the [FrpSpec]. This means all ongoing work is cleaned up. + * When collection is cancelled, so is the [BuildSpec]. This means all ongoing work is cleaned up. */ -@ExperimentalFrpApi +@ExperimentalKairosApi @JvmName("stateSpecToColdConflatedFlow") -fun <A> FrpSpec<TState<A>>.toColdConflatedFlow(network: FrpNetwork): Flow<A> = +fun <A> BuildSpec<State<A>>.toColdConflatedFlow(network: KairosNetwork): Flow<A> = channelFlow { network.activateSpec { applySpec().observe { trySend(it) } } }.conflate() /** * Returns a cold [Flow] that, when collected, applies this [Transactional] in a new transaction in - * this [network], and then emits from the returned [TFlow]. + * this [network], and then emits from the returned [Events]. */ -@ExperimentalFrpApi +@ExperimentalKairosApi @JvmName("transactionalFlowToColdConflatedFlow") -fun <A> Transactional<TFlow<A>>.toColdConflatedFlow(network: FrpNetwork): Flow<A> = +fun <A> Transactional<Events<A>>.toColdConflatedFlow(network: KairosNetwork): Flow<A> = channelFlow { network.activateSpec { sample().observe { trySend(it) } } }.conflate() /** * Returns a cold [Flow] that, when collected, applies this [Transactional] in a new transaction in - * this [network], and then emits from the returned [TState]. + * this [network], and then emits from the returned [State]. */ -@ExperimentalFrpApi +@ExperimentalKairosApi @JvmName("transactionalStateToColdConflatedFlow") -fun <A> Transactional<TState<A>>.toColdConflatedFlow(network: FrpNetwork): Flow<A> = +fun <A> Transactional<State<A>>.toColdConflatedFlow(network: KairosNetwork): Flow<A> = channelFlow { network.activateSpec { sample().observe { trySend(it) } } }.conflate() /** - * Returns a cold [Flow] that, when collected, applies this [FrpStateful] in a new transaction in - * this [network], and then emits from the returned [TFlow]. + * Returns a cold [Flow] that, when collected, applies this [Stateful] in a new transaction in this + * [network], and then emits from the returned [Events]. * - * When collection is cancelled, so is the [FrpStateful]. This means all ongoing work is cleaned up. + * When collection is cancelled, so is the [Stateful]. This means all ongoing work is cleaned up. */ -@ExperimentalFrpApi +@ExperimentalKairosApi @JvmName("statefulFlowToColdConflatedFlow") -fun <A> FrpStateful<TFlow<A>>.toColdConflatedFlow(network: FrpNetwork): Flow<A> = +fun <A> Stateful<Events<A>>.toColdConflatedFlow(network: KairosNetwork): Flow<A> = channelFlow { network.activateSpec { applyStateful().observe { trySend(it) } } }.conflate() /** * Returns a cold [Flow] that, when collected, applies this [Transactional] in a new transaction in - * this [network], and then emits from the returned [TState]. + * this [network], and then emits from the returned [State]. * - * When collection is cancelled, so is the [FrpStateful]. This means all ongoing work is cleaned up. + * When collection is cancelled, so is the [Stateful]. This means all ongoing work is cleaned up. */ -@ExperimentalFrpApi +@ExperimentalKairosApi @JvmName("statefulStateToColdConflatedFlow") -fun <A> FrpStateful<TState<A>>.toColdConflatedFlow(network: FrpNetwork): Flow<A> = +fun <A> Stateful<State<A>>.toColdConflatedFlow(network: KairosNetwork): Flow<A> = channelFlow { network.activateSpec { applyStateful().observe { trySend(it) } } }.conflate() -/** Return a [TFlow] that emits from the original [TFlow] only when [state] is `true`. */ -@ExperimentalFrpApi -fun <A> TFlow<A>.filter(state: TState<Boolean>): TFlow<A> = filter { state.sample() } +/** Return an [Events] that emits from the original [Events] only when [state] is `true`. */ +@ExperimentalKairosApi +fun <A> Events<A>.filter(state: State<Boolean>): Events<A> = filter { state.sample() } private fun Iterable<Boolean>.allTrue() = all { it } private fun Iterable<Boolean>.anyTrue() = any { it } -/** Returns a [TState] that is `true` only when all of [states] are `true`. */ -@ExperimentalFrpApi -fun allOf(vararg states: TState<Boolean>): TState<Boolean> = combine(*states) { it.allTrue() } +/** Returns a [State] that is `true` only when all of [states] are `true`. */ +@ExperimentalKairosApi +fun allOf(vararg states: State<Boolean>): State<Boolean> = combine(*states) { it.allTrue() } -/** Returns a [TState] that is `true` when any of [states] are `true`. */ -@ExperimentalFrpApi -fun anyOf(vararg states: TState<Boolean>): TState<Boolean> = combine(*states) { it.anyTrue() } +/** Returns a [State] that is `true` when any of [states] are `true`. */ +@ExperimentalKairosApi +fun anyOf(vararg states: State<Boolean>): State<Boolean> = combine(*states) { it.anyTrue() } -/** Returns a [TState] containing the inverse of the Boolean held by the original [TState]. */ -@ExperimentalFrpApi fun not(state: TState<Boolean>): TState<Boolean> = state.mapCheapUnsafe { !it } +/** Returns a [State] containing the inverse of the Boolean held by the original [State]. */ +@ExperimentalKairosApi fun not(state: State<Boolean>): State<Boolean> = state.mapCheapUnsafe { !it } /** - * Represents a modal FRP sub-network. + * Represents a modal Kairos sub-network. * - * When [enabled][enableMode], all network modifications are applied immediately to the FRP network. - * When the returned [TFlow] emits a [FrpBuildMode], that mode is enabled and replaces this mode, - * undoing all modifications in the process (any registered [observers][FrpBuildScope.observe] are - * unregistered, and any pending [side-effects][FrpBuildScope.effect] are cancelled). + * When [enabled][enableMode], all network modifications are applied immediately to the Kairos + * network. When the returned [Events] emits a [BuildMode], that mode is enabled and replaces this + * mode, undoing all modifications in the process (any registered [observers][BuildScope.observe] + * are unregistered, and any pending [side-effects][BuildScope.effect] are cancelled). * - * Use [compiledFrpSpec] to compile and stand-up a mode graph. + * Use [compiledBuildSpec] to compile and stand-up a mode graph. * - * @see FrpStatefulMode + * @see StatefulMode */ -@ExperimentalFrpApi -fun interface FrpBuildMode<out A> { +@ExperimentalKairosApi +fun interface BuildMode<out A> { /** - * Invoked when this mode is enabled. Returns a value and a [TFlow] that signals a switch to a + * Invoked when this mode is enabled. Returns a value and an [Events] that signals a switch to a * new mode. */ - suspend fun FrpBuildScope.enableMode(): Pair<A, TFlow<FrpBuildMode<A>>> + fun BuildScope.enableMode(): Pair<A, Events<BuildMode<A>>> } /** - * Returns an [FrpSpec] that, when [applied][FrpBuildScope.applySpec], stands up a modal-transition - * graph starting with this [FrpBuildMode], automatically switching to new modes as they are - * produced. + * Returns an [BuildSpec] that, when [applied][BuildScope.applySpec], stands up a modal-transition + * graph starting with this [BuildMode], automatically switching to new modes as they are produced. * - * @see FrpBuildMode + * @see BuildMode */ -@ExperimentalFrpApi -val <A> FrpBuildMode<A>.compiledFrpSpec: FrpSpec<TState<A>> - get() = frpSpec { - var modeChangeEvents by TFlowLoop<FrpBuildMode<A>>() - val activeMode: TState<Pair<A, TFlow<FrpBuildMode<A>>>> = +@ExperimentalKairosApi +val <A> BuildMode<A>.compiledBuildSpec: BuildSpec<State<A>> + get() = buildSpec { + var modeChangeEvents by EventsLoop<BuildMode<A>>() + val activeMode: State<Pair<A, Events<BuildMode<A>>>> = modeChangeEvents - .map { it.run { frpSpec { enableMode() } } } - .holdLatestSpec(frpSpec { enableMode() }) + .map { it.run { buildSpec { enableMode() } } } + .holdLatestSpec(buildSpec { enableMode() }) modeChangeEvents = - activeMode.map { statefully { it.second.nextOnly() } }.applyLatestStateful().switch() + activeMode + .map { statefully { it.second.nextOnly() } } + .applyLatestStateful() + .switchEvents() activeMode.map { it.first } } /** - * Represents a modal FRP sub-network. + * Represents a modal Kairos sub-network. * * When [enabled][enableMode], all state accumulation is immediately started. When the returned - * [TFlow] emits a [FrpBuildMode], that mode is enabled and replaces this mode, stopping all state + * [Events] emits a [BuildMode], that mode is enabled and replaces this mode, stopping all state * accumulation in the process. * * Use [compiledStateful] to compile and stand-up a mode graph. * - * @see FrpBuildMode + * @see BuildMode */ -@ExperimentalFrpApi -fun interface FrpStatefulMode<out A> { +@ExperimentalKairosApi +fun interface StatefulMode<out A> { /** - * Invoked when this mode is enabled. Returns a value and a [TFlow] that signals a switch to a + * Invoked when this mode is enabled. Returns a value and an [Events] that signals a switch to a * new mode. */ - suspend fun FrpStateScope.enableMode(): Pair<A, TFlow<FrpStatefulMode<A>>> + fun StateScope.enableMode(): Pair<A, Events<StatefulMode<A>>> } /** - * Returns an [FrpStateful] that, when [applied][FrpStateScope.applyStateful], stands up a - * modal-transition graph starting with this [FrpStatefulMode], automatically switching to new modes - * as they are produced. + * Returns an [Stateful] that, when [applied][StateScope.applyStateful], stands up a + * modal-transition graph starting with this [StatefulMode], automatically switching to new modes as + * they are produced. * - * @see FrpBuildMode + * @see BuildMode */ -@ExperimentalFrpApi -val <A> FrpStatefulMode<A>.compiledStateful: FrpStateful<TState<A>> +@ExperimentalKairosApi +val <A> StatefulMode<A>.compiledStateful: Stateful<State<A>> get() = statefully { - var modeChangeEvents by TFlowLoop<FrpStatefulMode<A>>() - val activeMode: TState<Pair<A, TFlow<FrpStatefulMode<A>>>> = + var modeChangeEvents by EventsLoop<StatefulMode<A>>() + val activeMode: State<Pair<A, Events<StatefulMode<A>>>> = modeChangeEvents .map { it.run { statefully { enableMode() } } } .holdLatestStateful(statefully { enableMode() }) modeChangeEvents = - activeMode.map { statefully { it.second.nextOnly() } }.applyLatestStateful().switch() + activeMode + .map { statefully { it.second.nextOnly() } } + .applyLatestStateful() + .switchEvents() activeMode.map { it.first } } /** - * Runs [spec] in this [FrpBuildScope], and then re-runs it whenever [rebuildSignal] emits. Returns - * a [TState] that holds the result of the currently-active [FrpSpec]. + * Runs [spec] in this [BuildScope], and then re-runs it whenever [rebuildSignal] emits. Returns a + * [State] that holds the result of the currently-active [BuildSpec]. */ -@ExperimentalFrpApi -fun <A> FrpBuildScope.rebuildOn(rebuildSignal: TFlow<*>, spec: FrpSpec<A>): TState<A> = +@ExperimentalKairosApi +fun <A> BuildScope.rebuildOn(rebuildSignal: Events<*>, spec: BuildSpec<A>): State<A> = rebuildSignal.map { spec }.holdLatestSpec(spec) /** - * Like [stateChanges] but also includes the old value of this [TState]. + * Like [changes] but also includes the old value of this [State]. * * Shorthand for: * ``` kotlin * stateChanges.map { WithPrev(previousValue = sample(), newValue = it) } * ``` */ -@ExperimentalFrpApi -val <A> TState<A>.transitions: TFlow<WithPrev<A, A>> - get() = stateChanges.map { WithPrev(previousValue = sample(), newValue = it) } +@ExperimentalKairosApi +val <A> State<A>.transitions: Events<WithPrev<A, A>> + get() = changes.map { WithPrev(previousValue = sample(), newValue = it) } diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/EffectScope.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/EffectScope.kt new file mode 100644 index 000000000000..7e257f2831af --- /dev/null +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/EffectScope.kt @@ -0,0 +1,48 @@ +/* + * 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.kairos + +import kotlinx.coroutines.CoroutineScope + +/** + * Scope for external side-effects triggered by the Kairos network. This still occurs within the + * context of a transaction, so general suspending calls are disallowed to prevent blocking the + * transaction. You can use [effectCoroutineScope] to [launch][kotlinx.coroutines.launch] new + * coroutines to perform long-running asynchronous work. This scope is alive for the duration of the + * containing [BuildScope] that this side-effect scope is running in. + */ +@ExperimentalKairosApi +interface EffectScope : TransactionScope { + /** + * A [CoroutineScope] whose lifecycle lives for as long as this [EffectScope] is alive. This is + * generally until the [Job][kotlinx.coroutines.Job] returned by [BuildScope.effect] is + * cancelled. + */ + @ExperimentalKairosApi val effectCoroutineScope: CoroutineScope + + /** + * A [KairosNetwork] instance that can be used to transactionally query / modify the Kairos + * network. + * + * The lambda passed to [KairosNetwork.transact] on this instance will receive an [BuildScope] + * that is lifetime-bound to this [EffectScope]. Once this [EffectScope] is no longer alive, any + * modifications to the Kairos network performed via this [KairosNetwork] instance will be + * undone (any registered [observers][BuildScope.observe] are unregistered, and any pending + * [side-effects][BuildScope.effect] are cancelled). + */ + @ExperimentalKairosApi val kairosNetwork: KairosNetwork +} diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/Events.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/Events.kt new file mode 100644 index 000000000000..e7d0096f2189 --- /dev/null +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/Events.kt @@ -0,0 +1,575 @@ +/* + * 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.kairos + +import com.android.systemui.kairos.internal.CompletableLazy +import com.android.systemui.kairos.internal.DemuxImpl +import com.android.systemui.kairos.internal.EventsImpl +import com.android.systemui.kairos.internal.Init +import com.android.systemui.kairos.internal.InitScope +import com.android.systemui.kairos.internal.InputNode +import com.android.systemui.kairos.internal.Network +import com.android.systemui.kairos.internal.NoScope +import com.android.systemui.kairos.internal.activated +import com.android.systemui.kairos.internal.cached +import com.android.systemui.kairos.internal.constInit +import com.android.systemui.kairos.internal.demuxMap +import com.android.systemui.kairos.internal.filterImpl +import com.android.systemui.kairos.internal.filterJustImpl +import com.android.systemui.kairos.internal.init +import com.android.systemui.kairos.internal.mapImpl +import com.android.systemui.kairos.internal.mergeNodes +import com.android.systemui.kairos.internal.mergeNodesLeft +import com.android.systemui.kairos.internal.neverImpl +import com.android.systemui.kairos.internal.switchDeferredImplSingle +import com.android.systemui.kairos.internal.switchPromptImplSingle +import com.android.systemui.kairos.internal.util.hashString +import com.android.systemui.kairos.util.Either +import com.android.systemui.kairos.util.Either.Left +import com.android.systemui.kairos.util.Either.Right +import com.android.systemui.kairos.util.Maybe +import com.android.systemui.kairos.util.just +import com.android.systemui.kairos.util.toMaybe +import java.util.concurrent.atomic.AtomicReference +import kotlin.reflect.KProperty +import kotlinx.coroutines.CoroutineStart +import kotlinx.coroutines.Job +import kotlinx.coroutines.async +import kotlinx.coroutines.coroutineScope + +/** A series of values of type [A] available at discrete points in time. */ +@ExperimentalKairosApi +sealed class Events<out A> { + companion object { + /** An [Events] with no values. */ + val empty: Events<Nothing> = EmptyEvents + } +} + +/** An [Events] with no values. */ +@ExperimentalKairosApi val emptyEvents: Events<Nothing> = Events.empty + +/** + * A forward-reference to an [Events]. Useful for recursive definitions. + * + * This reference can be used like a standard [Events], but will throw an error if its [loopback] is + * unset before the end of the first transaction which accesses it. + */ +@ExperimentalKairosApi +class EventsLoop<A> : Events<A>() { + private val deferred = CompletableLazy<Events<A>>() + + internal val init: Init<EventsImpl<A>> = + init(name = null) { deferred.value.init.connect(evalScope = this) } + + /** The [Events] this reference is referring to. */ + var loopback: Events<A>? = null + set(value) { + value?.let { + check(!deferred.isInitialized()) { "EventsLoop.loopback has already been set." } + deferred.setValue(value) + field = value + } + } + + operator fun getValue(thisRef: Any?, property: KProperty<*>): Events<A> = this + + operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Events<A>) { + loopback = value + } + + override fun toString(): String = "${this::class.simpleName}@$hashString" +} + +/** + * Returns an [Events] that acts as a deferred-reference to the [Events] produced by this [Lazy]. + * + * When the returned [Events] is accessed by the Kairos network, the [Lazy]'s [value][Lazy.value] + * will be queried and used. + * + * Useful for recursive definitions. + */ +@ExperimentalKairosApi fun <A> Lazy<Events<A>>.defer(): Events<A> = deferInline { value } + +/** + * Returns an [Events] that acts as a deferred-reference to the [Events] produced by this + * [DeferredValue]. + * + * When the returned [Events] is accessed by the Kairos network, the [DeferredValue] will be queried + * and used. + * + * Useful for recursive definitions. + */ +@ExperimentalKairosApi +fun <A> DeferredValue<Events<A>>.defer(): Events<A> = deferInline { unwrapped.value } + +/** + * Returns an [Events] that acts as a deferred-reference to the [Events] produced by [block]. + * + * When the returned [Events] is accessed by the Kairos network, [block] will be invoked and the + * returned [Events] will be used. + * + * Useful for recursive definitions. + */ +@ExperimentalKairosApi +fun <A> deferredEvents(block: KairosScope.() -> Events<A>): Events<A> = deferInline { + NoScope.block() +} + +/** Returns an [Events] that emits the new value of this [State] when it changes. */ +@ExperimentalKairosApi +val <A> State<A>.changes: Events<A> + get() = EventsInit(init(name = null) { init.connect(evalScope = this).changes }) + +/** + * Returns an [Events] that contains only the [just] results of applying [transform] to each value + * of the original [Events]. + * + * @see mapNotNull + */ +@ExperimentalKairosApi +fun <A, B> Events<A>.mapMaybe(transform: TransactionScope.(A) -> Maybe<B>): Events<B> = + map(transform).filterJust() + +/** + * Returns an [Events] that contains only the non-null results of applying [transform] to each value + * of the original [Events]. + * + * @see mapMaybe + */ +@ExperimentalKairosApi +fun <A, B> Events<A>.mapNotNull(transform: TransactionScope.(A) -> B?): Events<B> = mapMaybe { + transform(it).toMaybe() +} + +/** Returns an [Events] containing only values of the original [Events] that are not null. */ +@ExperimentalKairosApi +fun <A> Events<A?>.filterNotNull(): Events<A> = mapCheap { it.toMaybe() }.filterJust() + +/** Shorthand for `mapNotNull { it as? A }`. */ +@ExperimentalKairosApi +inline fun <reified A> Events<*>.filterIsInstance(): Events<A> = + mapCheap { it as? A }.filterNotNull() + +/** Shorthand for `mapMaybe { it }`. */ +@ExperimentalKairosApi +fun <A> Events<Maybe<A>>.filterJust(): Events<A> = + EventsInit(constInit(name = null, filterJustImpl { init.connect(evalScope = this) })) + +/** + * Returns an [Events] containing the results of applying [transform] to each value of the original + * [Events]. + */ +@ExperimentalKairosApi +fun <A, B> Events<A>.map(transform: TransactionScope.(A) -> B): Events<B> { + val mapped: EventsImpl<B> = mapImpl({ init.connect(evalScope = this) }) { a, _ -> transform(a) } + return EventsInit(constInit(name = null, mapped.cached())) +} + +/** + * Like [map], but the emission is not cached during the transaction. Use only if [transform] is + * fast and pure. + * + * @see map + */ +@ExperimentalKairosApi +fun <A, B> Events<A>.mapCheap(transform: TransactionScope.(A) -> B): Events<B> = + EventsInit( + constInit(name = null, mapImpl({ init.connect(evalScope = this) }) { a, _ -> transform(a) }) + ) + +/** + * Returns an [Events] that invokes [action] before each value of the original [Events] is emitted. + * Useful for logging and debugging. + * + * ``` + * pulse.onEach { foo(it) } == pulse.map { foo(it); it } + * ``` + * + * Note that the side effects performed in [onEach] are only performed while the resulting [Events] + * is connected to an output of the Kairos network. If your goal is to reliably perform side effects + * in response to an [Events], use the output combinators available in [BuildScope], such as + * [BuildScope.toSharedFlow] or [BuildScope.observe]. + */ +@ExperimentalKairosApi +fun <A> Events<A>.onEach(action: TransactionScope.(A) -> Unit): Events<A> = map { + action(it) + it +} + +/** + * Returns an [Events] containing only values of the original [Events] that satisfy the given + * [predicate]. + */ +@ExperimentalKairosApi +fun <A> Events<A>.filter(predicate: TransactionScope.(A) -> Boolean): Events<A> { + val pulse = filterImpl({ init.connect(evalScope = this) }) { predicate(it) } + return EventsInit(constInit(name = null, pulse)) +} + +/** + * Splits an [Events] of pairs into a pair of [Events], where each returned [Events] emits half of + * the original. + * + * Shorthand for: + * ```kotlin + * val lefts = map { it.first } + * val rights = map { it.second } + * return Pair(lefts, rights) + * ``` + */ +@ExperimentalKairosApi +fun <A, B> Events<Pair<A, B>>.unzip(): Pair<Events<A>, Events<B>> { + val lefts = map { it.first } + val rights = map { it.second } + return lefts to rights +} + +/** + * Merges the given [Events] into a single [Events] that emits events from both. + * + * Because [Events] can only emit one value per transaction, the provided [transformCoincidence] + * function is used to combine coincident emissions to produce the result value to be emitted by the + * merged [Events]. + */ +@ExperimentalKairosApi +fun <A> Events<A>.mergeWith( + other: Events<A>, + name: String? = null, + transformCoincidence: TransactionScope.(A, A) -> A = { a, _ -> a }, +): Events<A> { + val node = + mergeNodes( + name = name, + getPulse = { init.connect(evalScope = this) }, + getOther = { other.init.connect(evalScope = this) }, + ) { a, b -> + transformCoincidence(a, b) + } + return EventsInit(constInit(name = null, node)) +} + +/** + * Merges the given [Events] into a single [Events] that emits events from all. All coincident + * emissions are collected into the emitted [List], preserving the input ordering. + * + * @see mergeWith + * @see mergeLeft + */ +@ExperimentalKairosApi +fun <A> merge(vararg events: Events<A>): Events<List<A>> = events.asIterable().merge() + +/** + * Merges the given [Events] into a single [Events] that emits events from all. In the case of + * coincident emissions, the emission from the left-most [Events] is emitted. + * + * @see merge + */ +@ExperimentalKairosApi +fun <A> mergeLeft(vararg events: Events<A>): Events<A> = events.asIterable().mergeLeft() + +/** + * Merges the given [Events] into a single [Events] that emits events from all. + * + * Because [Events] can only emit one value per transaction, the provided [transformCoincidence] + * function is used to combine coincident emissions to produce the result value to be emitted by the + * merged [Events]. + */ +// TODO: can be optimized to avoid creating the intermediate list +fun <A> merge(vararg events: Events<A>, transformCoincidence: (A, A) -> A): Events<A> = + merge(*events).map { l -> l.reduce(transformCoincidence) } + +/** + * Merges the given [Events] into a single [Events] that emits events from all. All coincident + * emissions are collected into the emitted [List], preserving the input ordering. + * + * @see mergeWith + * @see mergeLeft + */ +@ExperimentalKairosApi +fun <A> Iterable<Events<A>>.merge(): Events<List<A>> = + EventsInit(constInit(name = null, mergeNodes { map { it.init.connect(evalScope = this) } })) + +/** + * Merges the given [Events] into a single [Events] that emits events from all. In the case of + * coincident emissions, the emission from the left-most [Events] is emitted. + * + * @see merge + */ +@ExperimentalKairosApi +fun <A> Iterable<Events<A>>.mergeLeft(): Events<A> = + EventsInit(constInit(name = null, mergeNodesLeft { map { it.init.connect(evalScope = this) } })) + +/** + * Creates a new [Events] that emits events from all given [Events]. All simultaneous emissions are + * collected into the emitted [List], preserving the input ordering. + * + * @see mergeWith + */ +@ExperimentalKairosApi fun <A> Sequence<Events<A>>.merge(): Events<List<A>> = asIterable().merge() + +/** + * Creates a new [Events] that emits events from all given [Events]. All simultaneous emissions are + * collected into the emitted [Map], and are given the same key of the associated [Events] in the + * input [Map]. + * + * @see mergeWith + */ +@ExperimentalKairosApi +fun <K, A> Map<K, Events<A>>.merge(): Events<Map<K, A>> = + asSequence() + .map { (k, events) -> events.map { a -> k to a } } + .toList() + .merge() + .map { it.toMap() } + +/** + * Returns a [GroupedEvents] that can be used to efficiently split a single [Events] into multiple + * downstream [Events]. + * + * The input [Events] emits [Map] instances that specify which downstream [Events] the associated + * value will be emitted from. These downstream [Events] can be obtained via + * [GroupedEvents.eventsForKey]. + * + * An example: + * ``` + * val fooEvents: Events<Map<String, Foo>> = ... + * val fooById: GroupedEvents<String, Foo> = fooEvents.groupByKey() + * val fooBar: Events<Foo> = fooById["bar"] + * ``` + * + * This is semantically equivalent to `val fooBar = fooEvents.mapNotNull { map -> map["bar"] }` but + * is significantly more efficient; specifically, using [mapNotNull] in this way incurs a `O(n)` + * performance hit, where `n` is the number of different [mapNotNull] operations used to filter on a + * specific key's presence in the emitted [Map]. [groupByKey] internally uses a [HashMap] to lookup + * the appropriate downstream [Events], and so operates in `O(1)`. + * + * Note that the returned [GroupedEvents] should be cached and re-used to gain the performance + * benefit. + * + * @see selector + */ +@ExperimentalKairosApi +fun <K, A> Events<Map<K, A>>.groupByKey(numKeys: Int? = null): GroupedEvents<K, A> = + GroupedEvents(demuxMap({ init.connect(this) }, numKeys)) + +/** + * Shorthand for `map { mapOf(extractKey(it) to it) }.groupByKey()` + * + * @see groupByKey + */ +@ExperimentalKairosApi +fun <K, A> Events<A>.groupBy( + numKeys: Int? = null, + extractKey: TransactionScope.(A) -> K, +): GroupedEvents<K, A> = map { mapOf(extractKey(it) to it) }.groupByKey(numKeys) + +/** + * Returns two new [Events] that contain elements from this [Events] that satisfy or don't satisfy + * [predicate]. + * + * Using this is equivalent to `upstream.filter(predicate) to upstream.filter { !predicate(it) }` + * but is more efficient; specifically, [partition] will only invoke [predicate] once per element. + */ +@ExperimentalKairosApi +fun <A> Events<A>.partition( + predicate: TransactionScope.(A) -> Boolean +): Pair<Events<A>, Events<A>> { + val grouped: GroupedEvents<Boolean, A> = groupBy(numKeys = 2, extractKey = predicate) + return Pair(grouped.eventsForKey(true), grouped.eventsForKey(false)) +} + +/** + * Returns two new [Events] that contain elements from this [Events]; [Pair.first] will contain + * [Left] values, and [Pair.second] will contain [Right] values. + * + * Using this is equivalent to using [filterIsInstance] in conjunction with [map] twice, once for + * [Left]s and once for [Right]s, but is slightly more efficient; specifically, the + * [filterIsInstance] check is only performed once per element. + */ +@ExperimentalKairosApi +fun <A, B> Events<Either<A, B>>.partitionEither(): Pair<Events<A>, Events<B>> { + val (left, right) = partition { it is Left } + return Pair(left.mapCheap { (it as Left).value }, right.mapCheap { (it as Right).value }) +} + +/** + * A mapping from keys of type [K] to [Events] emitting values of type [A]. + * + * @see groupByKey + */ +@ExperimentalKairosApi +class GroupedEvents<in K, out A> internal constructor(internal val impl: DemuxImpl<K, A>) { + /** + * Returns an [Events] that emits values of type [A] that correspond to the given [key]. + * + * @see groupByKey + */ + fun eventsForKey(key: K): Events<A> = EventsInit(constInit(name = null, impl.eventsForKey(key))) + + /** + * Returns an [Events] that emits values of type [A] that correspond to the given [key]. + * + * @see groupByKey + */ + operator fun get(key: K): Events<A> = eventsForKey(key) +} + +/** + * Returns an [Events] that switches to the [Events] contained within this [State] whenever it + * changes. + * + * This switch does take effect until the *next* transaction after [State] changes. For a switch + * that takes effect immediately, see [switchEventsPromptly]. + */ +@ExperimentalKairosApi +fun <A> State<Events<A>>.switchEvents(name: String? = null): Events<A> { + val patches = + mapImpl({ init.connect(this).changes }) { newEvents, _ -> newEvents.init.connect(this) } + return EventsInit( + constInit( + name = null, + switchDeferredImplSingle( + name = name, + getStorage = { + init.connect(this).getCurrentWithEpoch(this).first.init.connect(this) + }, + getPatches = { patches }, + ), + ) + ) +} + +/** + * Returns an [Events] that switches to the [Events] contained within this [State] whenever it + * changes. + * + * This switch takes effect immediately within the same transaction that [State] changes. In + * general, you should prefer [switchEvents] over this method. It is both safer and more performant. + */ +// TODO: parameter to handle coincidental emission from both old and new +@ExperimentalKairosApi +fun <A> State<Events<A>>.switchEventsPromptly(): Events<A> { + val patches = + mapImpl({ init.connect(this).changes }) { newEvents, _ -> newEvents.init.connect(this) } + return EventsInit( + constInit( + name = null, + switchPromptImplSingle( + getStorage = { + init.connect(this).getCurrentWithEpoch(this).first.init.connect(this) + }, + getPatches = { patches }, + ), + ) + ) +} + +/** + * A mutable [Events] that provides the ability to [emit] values to the network, handling + * backpressure by coalescing all emissions into batches. + * + * @see KairosNetwork.coalescingMutableEvents + */ +@ExperimentalKairosApi +class CoalescingMutableEvents<in In, Out> +internal constructor( + internal val name: String?, + internal val coalesce: (old: Lazy<Out>, new: In) -> Out, + internal val network: Network, + private val getInitialValue: () -> Out, + internal val impl: InputNode<Out> = InputNode(), +) : Events<Out>() { + internal val storage = AtomicReference(false to lazy { getInitialValue() }) + + override fun toString(): String = "${this::class.simpleName}@$hashString" + + /** + * Inserts [value] into the current batch, enqueueing it for emission from this [Events] if not + * already pending. + * + * Backpressure occurs when [emit] is called while the Kairos network is currently in a + * transaction; if called multiple times, then emissions will be coalesced into a single batch + * that is then processed when the network is ready. + */ + fun emit(value: In) { + val (scheduled, _) = + storage.getAndUpdate { (_, batch) -> true to CompletableLazy(coalesce(batch, value)) } + if (!scheduled) { + @Suppress("DeferredResultUnused") + network.transaction( + "CoalescingMutableEvents${name?.let { "($name)" }.orEmpty()}.emit" + ) { + val (_, batch) = storage.getAndSet(false to lazy { getInitialValue() }) + impl.visit(this, batch.value) + } + } + } +} + +/** + * A mutable [Events] that provides the ability to [emit] values to the network, handling + * backpressure by suspending the emitter. + * + * @see KairosNetwork.coalescingMutableEvents + */ +@ExperimentalKairosApi +class MutableEvents<T> +internal constructor(internal val network: Network, internal val impl: InputNode<T> = InputNode()) : + Events<T>() { + internal val name: String? = null + + private val storage = AtomicReference<Job?>(null) + + override fun toString(): String = "${this::class.simpleName}@$hashString" + + /** + * Emits a [value] to this [Events], suspending the caller until the Kairos transaction + * containing the emission has completed. + */ + suspend fun emit(value: T) { + coroutineScope { + var jobOrNull: Job? = null + val newEmit = + async(start = CoroutineStart.LAZY) { + jobOrNull?.join() + network.transaction("MutableEvents.emit") { impl.visit(this, value) }.await() + } + jobOrNull = storage.getAndSet(newEmit) + newEmit.await() + } + } +} + +private data object EmptyEvents : Events<Nothing>() + +internal class EventsInit<out A>(val init: Init<EventsImpl<A>>) : Events<A>() { + override fun toString(): String = "${this::class.simpleName}@$hashString" +} + +internal val <A> Events<A>.init: Init<EventsImpl<A>> + get() = + when (this) { + is EmptyEvents -> constInit("EmptyEvents", neverImpl) + is EventsInit -> init + is EventsLoop -> init + is CoalescingMutableEvents<*, A> -> constInit(name, impl.activated()) + is MutableEvents -> constInit(name, impl.activated()) + } + +private inline fun <A> deferInline(crossinline block: InitScope.() -> Events<A>): Events<A> = + EventsInit(init(name = null) { block().init.connect(evalScope = this) }) diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpBuildScope.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpBuildScope.kt deleted file mode 100644 index 209a402bd629..000000000000 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpBuildScope.kt +++ /dev/null @@ -1,885 +0,0 @@ -/* - * 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. - */ - -@file:OptIn(ExperimentalCoroutinesApi::class) - -package com.android.systemui.kairos - -import com.android.systemui.kairos.util.Maybe -import com.android.systemui.kairos.util.just -import com.android.systemui.kairos.util.map -import kotlin.coroutines.CoroutineContext -import kotlin.coroutines.EmptyCoroutineContext -import kotlin.coroutines.RestrictsSuspension -import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Deferred -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.Job -import kotlinx.coroutines.awaitCancellation -import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.FlowCollector -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.SharedFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.dropWhile -import kotlinx.coroutines.flow.scan -import kotlinx.coroutines.launch - -/** A function that modifies the FrpNetwork. */ -typealias FrpSpec<A> = suspend FrpBuildScope.() -> A - -/** - * Constructs an [FrpSpec]. The passed [block] will be invoked with an [FrpBuildScope] that can be - * used to perform network-building operations, including adding new inputs and outputs to the - * network, as well as all operations available in [FrpTransactionScope]. - */ -@ExperimentalFrpApi -@Suppress("NOTHING_TO_INLINE") -inline fun <A> frpSpec(noinline block: suspend FrpBuildScope.() -> A): FrpSpec<A> = block - -/** Applies the [FrpSpec] within this [FrpBuildScope]. */ -@ExperimentalFrpApi -inline operator fun <A> FrpBuildScope.invoke(block: FrpBuildScope.() -> A) = run(block) - -/** Operations that add inputs and outputs to an FRP network. */ -@ExperimentalFrpApi -@RestrictsSuspension -interface FrpBuildScope : FrpStateScope { - - /** TODO: Javadoc */ - @ExperimentalFrpApi - fun <R> deferredBuildScope(block: suspend FrpBuildScope.() -> R): FrpDeferredValue<R> - - /** TODO: Javadoc */ - @ExperimentalFrpApi fun deferredBuildScopeAction(block: suspend FrpBuildScope.() -> Unit) - - /** - * Returns a [TFlow] containing the results of applying [transform] to each value of the - * original [TFlow]. - * - * [transform] can perform modifications to the FRP network via its [FrpBuildScope] receiver. - * Unlike [mapLatestBuild], these modifications are not undone with each subsequent emission of - * the original [TFlow]. - * - * **NOTE:** This API does not [observe] the original [TFlow], meaning that unless the returned - * (or a downstream) [TFlow] is observed separately, [transform] will not be invoked, and no - * internal side-effects will occur. - */ - @ExperimentalFrpApi - fun <A, B> TFlow<A>.mapBuild(transform: suspend FrpBuildScope.(A) -> B): TFlow<B> - - /** - * Invokes [block] whenever this [TFlow] emits a value, allowing side-effects to be safely - * performed in reaction to the emission. - * - * Specifically, [block] is deferred to the end of the transaction, and is only actually - * executed if this [FrpBuildScope] is still active by that time. It can be deactivated due to a - * -Latest combinator, for example. - * - * Shorthand for: - * ```kotlin - * tFlow.observe { effect { ... } } - * ``` - */ - @ExperimentalFrpApi - fun <A> TFlow<A>.observe( - coroutineContext: CoroutineContext = EmptyCoroutineContext, - block: suspend FrpEffectScope.(A) -> Unit = {}, - ): Job - - /** - * Returns a [TFlow] containing the results of applying each [FrpSpec] emitted from the original - * [TFlow], and a [FrpDeferredValue] containing the result of applying [initialSpecs] - * immediately. - * - * When each [FrpSpec] is applied, changes from the previously-active [FrpSpec] with the same - * key are undone (any registered [observers][observe] are unregistered, and any pending - * [side-effects][effect] are cancelled). - * - * If the [Maybe] contained within the value for an associated key is [none], then the - * previously-active [FrpSpec] will be undone with no replacement. - */ - @ExperimentalFrpApi - fun <K, A, B> TFlow<Map<K, Maybe<FrpSpec<A>>>>.applyLatestSpecForKey( - initialSpecs: FrpDeferredValue<Map<K, FrpSpec<B>>>, - numKeys: Int? = null, - ): Pair<TFlow<Map<K, Maybe<A>>>, FrpDeferredValue<Map<K, B>>> - - /** - * Creates an instance of a [TFlow] with elements that are from [builder]. - * - * [builder] is run in its own coroutine, allowing for ongoing work that can emit to the - * provided [MutableTFlow]. - * - * By default, [builder] is only running while the returned [TFlow] is being - * [observed][observe]. If you want it to run at all times, simply add a no-op observer: - * ```kotlin - * tFlow { ... }.apply { observe() } - * ``` - */ - @ExperimentalFrpApi fun <T> tFlow(builder: suspend FrpProducerScope<T>.() -> Unit): TFlow<T> - - /** - * Creates an instance of a [TFlow] with elements that are emitted from [builder]. - * - * [builder] is run in its own coroutine, allowing for ongoing work that can emit to the - * provided [MutableTFlow]. - * - * By default, [builder] is only running while the returned [TFlow] is being - * [observed][observe]. If you want it to run at all times, simply add a no-op observer: - * ```kotlin - * tFlow { ... }.apply { observe() } - * ``` - * - * In the event of backpressure, emissions are *coalesced* into batches. When a value is - * [emitted][FrpCoalescingProducerScope.emit] from [builder], it is merged into the batch via - * [coalesce]. Once the batch is consumed by the frp network in the next transaction, the batch - * is reset back to [getInitialValue]. - */ - @ExperimentalFrpApi - fun <In, Out> coalescingTFlow( - getInitialValue: () -> Out, - coalesce: (old: Out, new: In) -> Out, - builder: suspend FrpCoalescingProducerScope<In>.() -> Unit, - ): TFlow<Out> - - /** - * Creates a new [FrpBuildScope] that is a child of this one. - * - * This new scope can be manually cancelled via the returned [Job], or will be cancelled - * automatically when its parent is cancelled. Cancellation will unregister all - * [observers][observe] and cancel all scheduled [effects][effect]. - * - * The return value from [block] can be accessed via the returned [FrpDeferredValue]. - */ - @ExperimentalFrpApi fun <A> asyncScope(block: FrpSpec<A>): Pair<FrpDeferredValue<A>, Job> - - // TODO: once we have context params, these can all become extensions: - - /** - * Returns a [TFlow] containing the results of applying the given [transform] function to each - * value of the original [TFlow]. - * - * Unlike [TFlow.map], [transform] can perform arbitrary asynchronous code. This code is run - * outside of the current FRP transaction; when [transform] returns, the returned value is - * emitted from the result [TFlow] in a new transaction. - * - * Shorthand for: - * ```kotlin - * tflow.mapLatestBuild { a -> asyncTFlow { transform(a) } }.flatten() - * ``` - */ - @ExperimentalFrpApi - fun <A, B> TFlow<A>.mapAsyncLatest(transform: suspend (A) -> B): TFlow<B> = - mapLatestBuild { a -> asyncTFlow { transform(a) } }.flatten() - - /** - * Invokes [block] whenever this [TFlow] emits a value. [block] receives an [FrpBuildScope] that - * can be used to make further modifications to the FRP network, and/or perform side-effects via - * [effect]. - * - * @see observe - */ - @ExperimentalFrpApi - fun <A> TFlow<A>.observeBuild(block: suspend FrpBuildScope.(A) -> Unit = {}): Job = - mapBuild(block).observe() - - /** - * Returns a [StateFlow] whose [value][StateFlow.value] tracks the current - * [value of this TState][TState.sample], and will emit at the same rate as - * [TState.stateChanges]. - * - * Note that the [value][StateFlow.value] is not available until the *end* of the current - * transaction. If you need the current value before this time, then use [TState.sample]. - */ - @ExperimentalFrpApi - fun <A> TState<A>.toStateFlow(): StateFlow<A> { - val uninitialized = Any() - var initialValue: Any? = uninitialized - val innerStateFlow = MutableStateFlow<Any?>(uninitialized) - deferredBuildScope { - initialValue = sample() - stateChanges.observe { - innerStateFlow.value = it - initialValue = null - } - } - - @Suppress("UNCHECKED_CAST") - fun getValue(innerValue: Any?): A = - when { - innerValue !== uninitialized -> innerValue as A - initialValue !== uninitialized -> initialValue as A - else -> - error( - "Attempted to access StateFlow.value before FRP transaction has completed." - ) - } - - return object : StateFlow<A> { - override val replayCache: List<A> - get() = innerStateFlow.replayCache.map(::getValue) - - override val value: A - get() = getValue(innerStateFlow.value) - - override suspend fun collect(collector: FlowCollector<A>): Nothing { - innerStateFlow.collect { collector.emit(getValue(it)) } - } - } - } - - /** - * Returns a [SharedFlow] configured with a replay cache of size [replay] that emits the current - * [value][TState.sample] of this [TState] followed by all [stateChanges]. - */ - @ExperimentalFrpApi - fun <A> TState<A>.toSharedFlow(replay: Int = 0): SharedFlow<A> { - val result = MutableSharedFlow<A>(replay, extraBufferCapacity = 1) - deferredBuildScope { - result.tryEmit(sample()) - stateChanges.observe { a -> result.tryEmit(a) } - } - return result - } - - /** - * Returns a [SharedFlow] configured with a replay cache of size [replay] that emits values - * whenever this [TFlow] emits. - */ - @ExperimentalFrpApi - fun <A> TFlow<A>.toSharedFlow(replay: Int = 0): SharedFlow<A> { - val result = MutableSharedFlow<A>(replay, extraBufferCapacity = 1) - observe { a -> result.tryEmit(a) } - return result - } - - /** - * Returns a [TState] that holds onto the value returned by applying the most recently emitted - * [FrpSpec] from the original [TFlow], or the value returned by applying [initialSpec] if - * nothing has been emitted since it was constructed. - * - * When each [FrpSpec] is applied, changes from the previously-active [FrpSpec] are undone (any - * registered [observers][observe] are unregistered, and any pending [side-effects][effect] are - * cancelled). - */ - @ExperimentalFrpApi - fun <A> TFlow<FrpSpec<A>>.holdLatestSpec(initialSpec: FrpSpec<A>): TState<A> { - val (changes: TFlow<A>, initApplied: FrpDeferredValue<A>) = applyLatestSpec(initialSpec) - return changes.holdDeferred(initApplied) - } - - /** - * Returns a [TState] containing the value returned by applying the [FrpSpec] held by the - * original [TState]. - * - * When each [FrpSpec] is applied, changes from the previously-active [FrpSpec] are undone (any - * registered [observers][observe] are unregistered, and any pending [side-effects][effect] are - * cancelled). - */ - @ExperimentalFrpApi - fun <A> TState<FrpSpec<A>>.applyLatestSpec(): TState<A> { - val (appliedChanges: TFlow<A>, init: FrpDeferredValue<A>) = - stateChanges.applyLatestSpec(frpSpec { sample().applySpec() }) - return appliedChanges.holdDeferred(init) - } - - /** - * Returns a [TFlow] containing the results of applying each [FrpSpec] emitted from the original - * [TFlow]. - * - * When each [FrpSpec] is applied, changes from the previously-active [FrpSpec] are undone (any - * registered [observers][observe] are unregistered, and any pending [side-effects][effect] are - * cancelled). - */ - @ExperimentalFrpApi - fun <A> TFlow<FrpSpec<A>>.applyLatestSpec(): TFlow<A> = applyLatestSpec(frpSpec {}).first - - /** - * Returns a [TFlow] that switches to a new [TFlow] produced by [transform] every time the - * original [TFlow] emits a value. - * - * [transform] can perform modifications to the FRP network via its [FrpBuildScope] receiver. - * When the original [TFlow] emits a new value, those changes are undone (any registered - * [observers][observe] are unregistered, and any pending [effects][effect] are cancelled). - */ - @ExperimentalFrpApi - fun <A, B> TFlow<A>.flatMapLatestBuild( - transform: suspend FrpBuildScope.(A) -> TFlow<B> - ): TFlow<B> = mapCheap { frpSpec { transform(it) } }.applyLatestSpec().flatten() - - /** - * Returns a [TState] by applying [transform] to the value held by the original [TState]. - * - * [transform] can perform modifications to the FRP network via its [FrpBuildScope] receiver. - * When the value held by the original [TState] changes, those changes are undone (any - * registered [observers][observe] are unregistered, and any pending [effects][effect] are - * cancelled). - */ - @ExperimentalFrpApi - fun <A, B> TState<A>.flatMapLatestBuild( - transform: suspend FrpBuildScope.(A) -> TState<B> - ): TState<B> = mapLatestBuild { transform(it) }.flatten() - - /** - * Returns a [TState] that transforms the value held inside this [TState] by applying it to the - * [transform]. - * - * [transform] can perform modifications to the FRP network via its [FrpBuildScope] receiver. - * When the value held by the original [TState] changes, those changes are undone (any - * registered [observers][observe] are unregistered, and any pending [effects][effect] are - * cancelled). - */ - @ExperimentalFrpApi - fun <A, B> TState<A>.mapLatestBuild(transform: suspend FrpBuildScope.(A) -> B): TState<B> = - mapCheapUnsafe { frpSpec { transform(it) } }.applyLatestSpec() - - /** - * Returns a [TFlow] containing the results of applying each [FrpSpec] emitted from the original - * [TFlow], and a [FrpDeferredValue] containing the result of applying [initialSpec] - * immediately. - * - * When each [FrpSpec] is applied, changes from the previously-active [FrpSpec] are undone (any - * registered [observers][observe] are unregistered, and any pending [side-effects][effect] are - * cancelled). - */ - @ExperimentalFrpApi - fun <A : Any?, B> TFlow<FrpSpec<B>>.applyLatestSpec( - initialSpec: FrpSpec<A> - ): Pair<TFlow<B>, FrpDeferredValue<A>> { - val (flow, result) = - mapCheap { spec -> mapOf(Unit to just(spec)) } - .applyLatestSpecForKey(initialSpecs = mapOf(Unit to initialSpec), numKeys = 1) - val outFlow: TFlow<B> = - flow.mapMaybe { - checkNotNull(it[Unit]) { "applyLatest: expected result, but none present in: $it" } - } - val outInit: FrpDeferredValue<A> = deferredBuildScope { - val initResult: Map<Unit, A> = result.get() - check(Unit in initResult) { - "applyLatest: expected initial result, but none present in: $initResult" - } - @Suppress("UNCHECKED_CAST") - initResult.getOrDefault(Unit) { null } as A - } - return Pair(outFlow, outInit) - } - - /** - * Returns a [TFlow] containing the results of applying [transform] to each value of the - * original [TFlow]. - * - * [transform] can perform modifications to the FRP network via its [FrpBuildScope] receiver. - * With each invocation of [transform], changes from the previous invocation are undone (any - * registered [observers][observe] are unregistered, and any pending [side-effects][effect] are - * cancelled). - */ - @ExperimentalFrpApi - fun <A, B> TFlow<A>.mapLatestBuild(transform: suspend FrpBuildScope.(A) -> B): TFlow<B> = - mapCheap { frpSpec { transform(it) } }.applyLatestSpec() - - /** - * Returns a [TFlow] containing the results of applying [transform] to each value of the - * original [TFlow], and a [FrpDeferredValue] containing the result of applying [transform] to - * [initialValue] immediately. - * - * [transform] can perform modifications to the FRP network via its [FrpBuildScope] receiver. - * With each invocation of [transform], changes from the previous invocation are undone (any - * registered [observers][observe] are unregistered, and any pending [side-effects][effect] are - * cancelled). - */ - @ExperimentalFrpApi - fun <A, B> TFlow<A>.mapLatestBuild( - initialValue: A, - transform: suspend FrpBuildScope.(A) -> B, - ): Pair<TFlow<B>, FrpDeferredValue<B>> = - mapLatestBuildDeferred(deferredOf(initialValue), transform) - - /** - * Returns a [TFlow] containing the results of applying [transform] to each value of the - * original [TFlow], and a [FrpDeferredValue] containing the result of applying [transform] to - * [initialValue] immediately. - * - * [transform] can perform modifications to the FRP network via its [FrpBuildScope] receiver. - * With each invocation of [transform], changes from the previous invocation are undone (any - * registered [observers][observe] are unregistered, and any pending [side-effects][effect] are - * cancelled). - */ - @ExperimentalFrpApi - fun <A, B> TFlow<A>.mapLatestBuildDeferred( - initialValue: FrpDeferredValue<A>, - transform: suspend FrpBuildScope.(A) -> B, - ): Pair<TFlow<B>, FrpDeferredValue<B>> = - mapCheap { frpSpec { transform(it) } } - .applyLatestSpec(initialSpec = frpSpec { transform(initialValue.get()) }) - - /** - * Returns a [TFlow] containing the results of applying each [FrpSpec] emitted from the original - * [TFlow], and a [FrpDeferredValue] containing the result of applying [initialSpecs] - * immediately. - * - * When each [FrpSpec] is applied, changes from the previously-active [FrpSpec] with the same - * key are undone (any registered [observers][observe] are unregistered, and any pending - * [side-effects][effect] are cancelled). - * - * If the [Maybe] contained within the value for an associated key is [none], then the - * previously-active [FrpSpec] will be undone with no replacement. - */ - @ExperimentalFrpApi - fun <K, A, B> TFlow<Map<K, Maybe<FrpSpec<A>>>>.applyLatestSpecForKey( - initialSpecs: Map<K, FrpSpec<B>>, - numKeys: Int? = null, - ): Pair<TFlow<Map<K, Maybe<A>>>, FrpDeferredValue<Map<K, B>>> = - applyLatestSpecForKey(deferredOf(initialSpecs), numKeys) - - /** - * Returns a [TFlow] containing the results of applying each [FrpSpec] emitted from the original - * [TFlow]. - * - * When each [FrpSpec] is applied, changes from the previously-active [FrpSpec] with the same - * key are undone (any registered [observers][observe] are unregistered, and any pending - * [side-effects][effect] are cancelled). - * - * If the [Maybe] contained within the value for an associated key is [none], then the - * previously-active [FrpSpec] will be undone with no replacement. - */ - @ExperimentalFrpApi - fun <K, A> TFlow<Map<K, Maybe<FrpSpec<A>>>>.applyLatestSpecForKey( - numKeys: Int? = null - ): TFlow<Map<K, Maybe<A>>> = - applyLatestSpecForKey<K, A, Nothing>(deferredOf(emptyMap()), numKeys).first - - /** - * Returns a [TState] containing the latest results of applying each [FrpSpec] emitted from the - * original [TFlow]. - * - * When each [FrpSpec] is applied, changes from the previously-active [FrpSpec] with the same - * key are undone (any registered [observers][observe] are unregistered, and any pending - * [side-effects][effect] are cancelled). - * - * If the [Maybe] contained within the value for an associated key is [none], then the - * previously-active [FrpSpec] will be undone with no replacement. - */ - @ExperimentalFrpApi - fun <K, A> TFlow<Map<K, Maybe<FrpSpec<A>>>>.holdLatestSpecForKey( - initialSpecs: FrpDeferredValue<Map<K, FrpSpec<A>>>, - numKeys: Int? = null, - ): TState<Map<K, A>> { - val (changes, initialValues) = applyLatestSpecForKey(initialSpecs, numKeys) - return changes.foldMapIncrementally(initialValues) - } - - /** - * Returns a [TState] containing the latest results of applying each [FrpSpec] emitted from the - * original [TFlow]. - * - * When each [FrpSpec] is applied, changes from the previously-active [FrpSpec] with the same - * key are undone (any registered [observers][observe] are unregistered, and any pending - * [side-effects][effect] are cancelled). - * - * If the [Maybe] contained within the value for an associated key is [none], then the - * previously-active [FrpSpec] will be undone with no replacement. - */ - @ExperimentalFrpApi - fun <K, A> TFlow<Map<K, Maybe<FrpSpec<A>>>>.holdLatestSpecForKey( - initialSpecs: Map<K, FrpSpec<A>> = emptyMap(), - numKeys: Int? = null, - ): TState<Map<K, A>> = holdLatestSpecForKey(deferredOf(initialSpecs), numKeys) - - /** - * Returns a [TFlow] containing the results of applying [transform] to each value of the - * original [TFlow], and a [FrpDeferredValue] containing the result of applying [transform] to - * [initialValues] immediately. - * - * [transform] can perform modifications to the FRP network via its [FrpBuildScope] receiver. - * With each invocation of [transform], changes from the previous invocation are undone (any - * registered [observers][observe] are unregistered, and any pending [side-effects][effect] are - * cancelled). - * - * If the [Maybe] contained within the value for an associated key is [none], then the - * previously-active [FrpBuildScope] will be undone with no replacement. - */ - @ExperimentalFrpApi - fun <K, A, B> TFlow<Map<K, Maybe<A>>>.mapLatestBuildForKey( - initialValues: FrpDeferredValue<Map<K, A>>, - numKeys: Int? = null, - transform: suspend FrpBuildScope.(A) -> B, - ): Pair<TFlow<Map<K, Maybe<B>>>, FrpDeferredValue<Map<K, B>>> = - map { patch -> patch.mapValues { (_, v) -> v.map { frpSpec { transform(it) } } } } - .applyLatestSpecForKey( - deferredBuildScope { - initialValues.get().mapValues { (_, v) -> frpSpec { transform(v) } } - }, - numKeys = numKeys, - ) - - /** - * Returns a [TFlow] containing the results of applying [transform] to each value of the - * original [TFlow], and a [FrpDeferredValue] containing the result of applying [transform] to - * [initialValues] immediately. - * - * [transform] can perform modifications to the FRP network via its [FrpBuildScope] receiver. - * With each invocation of [transform], changes from the previous invocation are undone (any - * registered [observers][observe] are unregistered, and any pending [side-effects][effect] are - * cancelled). - * - * If the [Maybe] contained within the value for an associated key is [none], then the - * previously-active [FrpBuildScope] will be undone with no replacement. - */ - @ExperimentalFrpApi - fun <K, A, B> TFlow<Map<K, Maybe<A>>>.mapLatestBuildForKey( - initialValues: Map<K, A>, - numKeys: Int? = null, - transform: suspend FrpBuildScope.(A) -> B, - ): Pair<TFlow<Map<K, Maybe<B>>>, FrpDeferredValue<Map<K, B>>> = - mapLatestBuildForKey(deferredOf(initialValues), numKeys, transform) - - /** - * Returns a [TFlow] containing the results of applying [transform] to each value of the - * original [TFlow]. - * - * [transform] can perform modifications to the FRP network via its [FrpBuildScope] receiver. - * With each invocation of [transform], changes from the previous invocation are undone (any - * registered [observers][observe] are unregistered, and any pending [side-effects][effect] are - * cancelled). - * - * If the [Maybe] contained within the value for an associated key is [none], then the - * previously-active [FrpBuildScope] will be undone with no replacement. - */ - @ExperimentalFrpApi - fun <K, A, B> TFlow<Map<K, Maybe<A>>>.mapLatestBuildForKey( - numKeys: Int? = null, - transform: suspend FrpBuildScope.(A) -> B, - ): TFlow<Map<K, Maybe<B>>> = mapLatestBuildForKey(emptyMap(), numKeys, transform).first - - /** Returns a [Deferred] containing the next value to be emitted from this [TFlow]. */ - @ExperimentalFrpApi - fun <R> TFlow<R>.nextDeferred(): Deferred<R> { - lateinit var next: CompletableDeferred<R> - val job = nextOnly().observe { next.complete(it) } - next = CompletableDeferred<R>(parent = job) - return next - } - - /** Returns a [TState] that reflects the [StateFlow.value] of this [StateFlow]. */ - @ExperimentalFrpApi - fun <A> StateFlow<A>.toTState(): TState<A> { - val initial = value - return tFlow { dropWhile { it == initial }.collect { emit(it) } }.hold(initial) - } - - /** Returns a [TFlow] that emits whenever this [Flow] emits. */ - @ExperimentalFrpApi fun <A> Flow<A>.toTFlow(): TFlow<A> = tFlow { collect { emit(it) } } - - /** - * Shorthand for: - * ```kotlin - * flow.toTFlow().hold(initialValue) - * ``` - */ - @ExperimentalFrpApi - fun <A> Flow<A>.toTState(initialValue: A): TState<A> = toTFlow().hold(initialValue) - - /** - * Shorthand for: - * ```kotlin - * flow.scan(initialValue, operation).toTFlow().hold(initialValue) - * ``` - */ - @ExperimentalFrpApi - fun <A, B> Flow<A>.scanToTState(initialValue: B, operation: (B, A) -> B): TState<B> = - scan(initialValue, operation).toTFlow().hold(initialValue) - - /** - * Shorthand for: - * ```kotlin - * flow.scan(initialValue) { a, f -> f(a) }.toTFlow().hold(initialValue) - * ``` - */ - @ExperimentalFrpApi - fun <A> Flow<(A) -> A>.scanToTState(initialValue: A): TState<A> = - scanToTState(initialValue) { a, f -> f(a) } - - /** - * Invokes [block] whenever this [TFlow] emits a value. [block] receives an [FrpBuildScope] that - * can be used to make further modifications to the FRP network, and/or perform side-effects via - * [effect]. - * - * With each invocation of [block], changes from the previous invocation are undone (any - * registered [observers][observe] are unregistered, and any pending [side-effects][effect] are - * cancelled). - */ - @ExperimentalFrpApi - fun <A> TFlow<A>.observeLatestBuild(block: suspend FrpBuildScope.(A) -> Unit = {}): Job = - mapLatestBuild { block(it) }.observe() - - /** - * Invokes [block] whenever this [TFlow] emits a value, allowing side-effects to be safely - * performed in reaction to the emission. - * - * With each invocation of [block], running effects from the previous invocation are cancelled. - */ - @ExperimentalFrpApi - fun <A> TFlow<A>.observeLatest(block: suspend FrpEffectScope.(A) -> Unit = {}): Job { - var innerJob: Job? = null - return observeBuild { - innerJob?.cancel() - innerJob = effect { block(it) } - } - } - - /** - * Invokes [block] with the value held by this [TState], allowing side-effects to be safely - * performed in reaction to the state changing. - * - * With each invocation of [block], running effects from the previous invocation are cancelled. - */ - @ExperimentalFrpApi - fun <A> TState<A>.observeLatest(block: suspend FrpEffectScope.(A) -> Unit = {}): Job = - launchScope { - var innerJob = effect { block(sample()) } - stateChanges.observeBuild { - innerJob.cancel() - innerJob = effect { block(it) } - } - } - - /** - * Applies [block] to the value held by this [TState]. [block] receives an [FrpBuildScope] that - * can be used to make further modifications to the FRP network, and/or perform side-effects via - * [effect]. - * - * [block] can perform modifications to the FRP network via its [FrpBuildScope] receiver. With - * each invocation of [block], changes from the previous invocation are undone (any registered - * [observers][observe] are unregistered, and any pending [side-effects][effect] are cancelled). - */ - @ExperimentalFrpApi - fun <A> TState<A>.observeLatestBuild(block: suspend FrpBuildScope.(A) -> Unit = {}): Job = - launchScope { - var innerJob: Job = launchScope { block(sample()) } - stateChanges.observeBuild { - innerJob.cancel() - innerJob = launchScope { block(it) } - } - } - - /** Applies the [FrpSpec] within this [FrpBuildScope]. */ - @ExperimentalFrpApi suspend fun <A> FrpSpec<A>.applySpec(): A = this() - - /** - * Applies the [FrpSpec] within this [FrpBuildScope], returning the result as an - * [FrpDeferredValue]. - */ - @ExperimentalFrpApi - fun <A> FrpSpec<A>.applySpecDeferred(): FrpDeferredValue<A> = deferredBuildScope { applySpec() } - - /** - * Invokes [block] on the value held in this [TState]. [block] receives an [FrpBuildScope] that - * can be used to make further modifications to the FRP network, and/or perform side-effects via - * [effect]. - */ - @ExperimentalFrpApi - fun <A> TState<A>.observeBuild(block: suspend FrpBuildScope.(A) -> Unit = {}): Job = - launchScope { - block(sample()) - stateChanges.observeBuild(block) - } - - /** - * Invokes [block] with the current value of this [TState], re-invoking whenever it changes, - * allowing side-effects to be safely performed in reaction value changing. - * - * Specifically, [block] is deferred to the end of the transaction, and is only actually - * executed if this [FrpBuildScope] is still active by that time. It can be deactivated due to a - * -Latest combinator, for example. - * - * If the [TState] is changing within the *current* transaction (i.e. [stateChanges] is - * presently emitting) then [block] will be invoked for the first time with the new value; - * otherwise, it will be invoked with the [current][sample] value. - */ - @ExperimentalFrpApi - fun <A> TState<A>.observe(block: suspend FrpEffectScope.(A) -> Unit = {}): Job = - now.map { sample() }.mergeWith(stateChanges) { _, new -> new }.observe { block(it) } -} - -/** - * Returns a [TFlow] that emits the result of [block] once it completes. [block] is evaluated - * outside of the current FRP transaction; when it completes, the returned [TFlow] emits in a new - * transaction. - * - * Shorthand for: - * ``` - * tFlow { emitter: MutableTFlow<A> -> - * val a = block() - * emitter.emit(a) - * } - * ``` - */ -@ExperimentalFrpApi -fun <A> FrpBuildScope.asyncTFlow(block: suspend () -> A): TFlow<A> = - tFlow { - // TODO: if block completes synchronously, it would be nice to emit within this - // transaction - emit(block()) - } - .apply { observe() } - -/** - * Performs a side-effect in a safe manner w/r/t the current FRP transaction. - * - * Specifically, [block] is deferred to the end of the current transaction, and is only actually - * executed if this [FrpBuildScope] is still active by that time. It can be deactivated due to a - * -Latest combinator, for example. - * - * Shorthand for: - * ```kotlin - * now.observe { block() } - * ``` - */ -@ExperimentalFrpApi -fun FrpBuildScope.effect(block: suspend FrpEffectScope.() -> Unit): Job = now.observe { block() } - -/** - * Launches [block] in a new coroutine, returning a [Job] bound to the coroutine. - * - * This coroutine is not actually started until the *end* of the current FRP transaction. This is - * done because the current [FrpBuildScope] might be deactivated within this transaction, perhaps - * due to a -Latest combinator. If this happens, then the coroutine will never actually be started. - * - * Shorthand for: - * ```kotlin - * effect { frpCoroutineScope.launch { block() } } - * ``` - */ -@ExperimentalFrpApi -fun FrpBuildScope.launchEffect(block: suspend CoroutineScope.() -> Unit): Job = asyncEffect(block) - -/** - * Launches [block] in a new coroutine, returning the result as a [Deferred]. - * - * This coroutine is not actually started until the *end* of the current FRP transaction. This is - * done because the current [FrpBuildScope] might be deactivated within this transaction, perhaps - * due to a -Latest combinator. If this happens, then the coroutine will never actually be started. - * - * Shorthand for: - * ```kotlin - * CompletableDeferred<R>.apply { - * effect { frpCoroutineScope.launch { complete(coroutineScope { block() }) } } - * } - * .await() - * ``` - */ -@ExperimentalFrpApi -fun <R> FrpBuildScope.asyncEffect(block: suspend CoroutineScope.() -> R): Deferred<R> { - val result = CompletableDeferred<R>() - val job = now.observe { frpCoroutineScope.launch { result.complete(coroutineScope(block)) } } - val handle = job.invokeOnCompletion { result.cancel() } - result.invokeOnCompletion { - handle.dispose() - job.cancel() - } - return result -} - -/** Like [FrpBuildScope.asyncScope], but ignores the result of [block]. */ -@ExperimentalFrpApi fun FrpBuildScope.launchScope(block: FrpSpec<*>): Job = asyncScope(block).second - -/** - * Creates an instance of a [TFlow] with elements that are emitted from [builder]. - * - * [builder] is run in its own coroutine, allowing for ongoing work that can emit to the provided - * [MutableTFlow]. - * - * By default, [builder] is only running while the returned [TFlow] is being - * [observed][FrpBuildScope.observe]. If you want it to run at all times, simply add a no-op - * observer: - * ```kotlin - * tFlow { ... }.apply { observe() } - * ``` - * - * In the event of backpressure, emissions are *coalesced* into batches. When a value is - * [emitted][FrpCoalescingProducerScope.emit] from [builder], it is merged into the batch via - * [coalesce]. Once the batch is consumed by the FRP network in the next transaction, the batch is - * reset back to [initialValue]. - */ -@ExperimentalFrpApi -fun <In, Out> FrpBuildScope.coalescingTFlow( - initialValue: Out, - coalesce: (old: Out, new: In) -> Out, - builder: suspend FrpCoalescingProducerScope<In>.() -> Unit, -): TFlow<Out> = coalescingTFlow(getInitialValue = { initialValue }, coalesce, builder) - -/** - * Creates an instance of a [TFlow] with elements that are emitted from [builder]. - * - * [builder] is run in its own coroutine, allowing for ongoing work that can emit to the provided - * [MutableTFlow]. - * - * By default, [builder] is only running while the returned [TFlow] is being - * [observed][FrpBuildScope.observe]. If you want it to run at all times, simply add a no-op - * observer: - * ```kotlin - * tFlow { ... }.apply { observe() } - * ``` - * - * In the event of backpressure, emissions are *conflated*; any older emissions are dropped and only - * the most recent emission will be used when the FRP network is ready. - */ -@ExperimentalFrpApi -fun <T> FrpBuildScope.conflatedTFlow( - builder: suspend FrpCoalescingProducerScope<T>.() -> Unit -): TFlow<T> = - coalescingTFlow<T, Any?>(initialValue = Any(), coalesce = { _, new -> new }, builder = builder) - .mapCheap { - @Suppress("UNCHECKED_CAST") - it as T - } - -/** Scope for emitting to a [FrpBuildScope.coalescingTFlow]. */ -interface FrpCoalescingProducerScope<in T> { - /** - * Inserts [value] into the current batch, enqueueing it for emission from this [TFlow] if not - * already pending. - * - * Backpressure occurs when [emit] is called while the FRP network is currently in a - * transaction; if called multiple times, then emissions will be coalesced into a single batch - * that is then processed when the network is ready. - */ - fun emit(value: T) -} - -/** Scope for emitting to a [FrpBuildScope.tFlow]. */ -interface FrpProducerScope<in T> { - /** - * Emits a [value] to this [TFlow], suspending the caller until the FRP transaction containing - * the emission has completed. - */ - suspend fun emit(value: T) -} - -/** - * Suspends forever. Upon cancellation, runs [block]. Useful for unregistering callbacks inside of - * [FrpBuildScope.tFlow] and [FrpBuildScope.coalescingTFlow]. - */ -suspend fun awaitClose(block: () -> Unit): Nothing = - try { - awaitCancellation() - } finally { - block() - } diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpEffectScope.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpEffectScope.kt deleted file mode 100644 index b39dcc131b1d..000000000000 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpEffectScope.kt +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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.kairos - -import kotlin.coroutines.RestrictsSuspension -import kotlinx.coroutines.CoroutineScope - -/** - * Scope for external side-effects triggered by the Frp network. This still occurs within the - * context of a transaction, so general suspending calls are disallowed to prevent blocking the - * transaction. You can use [frpCoroutineScope] to [launch][kotlinx.coroutines.launch] new - * coroutines to perform long-running asynchronous work. This scope is alive for the duration of the - * containing [FrpBuildScope] that this side-effect scope is running in. - */ -@RestrictsSuspension -@ExperimentalFrpApi -interface FrpEffectScope : FrpTransactionScope { - /** - * A [CoroutineScope] whose lifecycle lives for as long as this [FrpEffectScope] is alive. This - * is generally until the [Job][kotlinx.coroutines.Job] returned by [FrpBuildScope.effect] is - * cancelled. - */ - @ExperimentalFrpApi val frpCoroutineScope: CoroutineScope - - /** - * A [FrpNetwork] instance that can be used to transactionally query / modify the FRP network. - * - * The lambda passed to [FrpNetwork.transact] on this instance will receive an [FrpBuildScope] - * that is lifetime-bound to this [FrpEffectScope]. Once this [FrpEffectScope] is no longer - * alive, any modifications to the FRP network performed via this [FrpNetwork] instance will be - * undone (any registered [observers][FrpBuildScope.observe] are unregistered, and any pending - * [side-effects][FrpBuildScope.effect] are cancelled). - */ - @ExperimentalFrpApi val frpNetwork: FrpNetwork -} diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpNetwork.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpNetwork.kt deleted file mode 100644 index 97252b4a199a..000000000000 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpNetwork.kt +++ /dev/null @@ -1,196 +0,0 @@ -/* - * 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.kairos - -import com.android.systemui.kairos.internal.BuildScopeImpl -import com.android.systemui.kairos.internal.Network -import com.android.systemui.kairos.internal.StateScopeImpl -import com.android.systemui.kairos.internal.util.awaitCancellationAndThen -import com.android.systemui.kairos.internal.util.childScope -import kotlin.coroutines.CoroutineContext -import kotlin.coroutines.EmptyCoroutineContext -import kotlin.coroutines.coroutineContext -import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.CoroutineName -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Job -import kotlinx.coroutines.job -import kotlinx.coroutines.launch - -/** - * Marks declarations that are still **experimental** and shouldn't be used in general production - * code. - */ -@RequiresOptIn( - message = "This API is experimental and should not be used in general production code." -) -@Retention(AnnotationRetention.BINARY) -annotation class ExperimentalFrpApi - -/** - * External interface to an FRP network. Can be used to make transactional queries and modifications - * to the network. - */ -@ExperimentalFrpApi -interface FrpNetwork { - /** - * Runs [block] inside of a transaction, suspending until the transaction is complete. - * - * The [FrpBuildScope] receiver exposes methods that can be used to query or modify the network. - * If the network is cancelled while the caller of [transact] is suspended, then the call will - * be cancelled. - */ - @ExperimentalFrpApi suspend fun <R> transact(block: suspend FrpTransactionScope.() -> R): R - - /** - * Activates [spec] in a transaction, suspending indefinitely. While suspended, all observers - * and long-running effects are kept alive. When cancelled, observers are unregistered and - * effects are cancelled. - */ - @ExperimentalFrpApi suspend fun activateSpec(spec: FrpSpec<*>) - - /** Returns a [CoalescingMutableTFlow] that can emit values into this [FrpNetwork]. */ - @ExperimentalFrpApi - fun <In, Out> coalescingMutableTFlow( - coalesce: (old: Out, new: In) -> Out, - getInitialValue: () -> Out, - ): CoalescingMutableTFlow<In, Out> - - /** Returns a [MutableTFlow] that can emit values into this [FrpNetwork]. */ - @ExperimentalFrpApi fun <T> mutableTFlow(): MutableTFlow<T> - - /** Returns a [MutableTState]. with initial state [initialValue]. */ - @ExperimentalFrpApi - fun <T> mutableTStateDeferred(initialValue: FrpDeferredValue<T>): MutableTState<T> -} - -/** Returns a [CoalescingMutableTFlow] that can emit values into this [FrpNetwork]. */ -@ExperimentalFrpApi -fun <In, Out> FrpNetwork.coalescingMutableTFlow( - coalesce: (old: Out, new: In) -> Out, - initialValue: Out, -): CoalescingMutableTFlow<In, Out> = - coalescingMutableTFlow(coalesce, getInitialValue = { initialValue }) - -/** Returns a [MutableTState]. with initial state [initialValue]. */ -@ExperimentalFrpApi -fun <T> FrpNetwork.mutableTState(initialValue: T): MutableTState<T> = - mutableTStateDeferred(deferredOf(initialValue)) - -/** Returns a [MutableTState]. with initial state [initialValue]. */ -@ExperimentalFrpApi -fun <T> MutableTState(network: FrpNetwork, initialValue: T): MutableTState<T> = - network.mutableTState(initialValue) - -/** Returns a [MutableTFlow] that can emit values into this [FrpNetwork]. */ -@ExperimentalFrpApi -fun <T> MutableTFlow(network: FrpNetwork): MutableTFlow<T> = network.mutableTFlow() - -/** Returns a [CoalescingMutableTFlow] that can emit values into this [FrpNetwork]. */ -@ExperimentalFrpApi -fun <In, Out> CoalescingMutableTFlow( - network: FrpNetwork, - coalesce: (old: Out, new: In) -> Out, - initialValue: Out, -): CoalescingMutableTFlow<In, Out> = network.coalescingMutableTFlow(coalesce) { initialValue } - -/** Returns a [CoalescingMutableTFlow] that can emit values into this [FrpNetwork]. */ -@ExperimentalFrpApi -fun <In, Out> CoalescingMutableTFlow( - network: FrpNetwork, - coalesce: (old: Out, new: In) -> Out, - getInitialValue: () -> Out, -): CoalescingMutableTFlow<In, Out> = network.coalescingMutableTFlow(coalesce, getInitialValue) - -/** - * Activates [spec] in a transaction and invokes [block] with the result, suspending indefinitely. - * While suspended, all observers and long-running effects are kept alive. When cancelled, observers - * are unregistered and effects are cancelled. - */ -@ExperimentalFrpApi -suspend fun <R> FrpNetwork.activateSpec(spec: FrpSpec<R>, block: suspend (R) -> Unit) { - activateSpec { - val result = spec.applySpec() - launchEffect { block(result) } - } -} - -internal class LocalFrpNetwork( - private val network: Network, - private val scope: CoroutineScope, - private val endSignal: TFlow<Any>, -) : FrpNetwork { - override suspend fun <R> transact(block: suspend FrpTransactionScope.() -> R): R { - val result = CompletableDeferred<R>(coroutineContext[Job]) - @Suppress("DeferredResultUnused") - network.transaction("FrpNetwork.transact") { - val buildScope = - BuildScopeImpl( - stateScope = StateScopeImpl(evalScope = this, endSignal = endSignal), - coroutineScope = scope, - ) - buildScope.runInBuildScope { effect { result.complete(block()) } } - } - return result.await() - } - - override suspend fun activateSpec(spec: FrpSpec<*>) { - val job = - network - .transaction("FrpNetwork.activateSpec") { - val buildScope = - BuildScopeImpl( - stateScope = StateScopeImpl(evalScope = this, endSignal = endSignal), - coroutineScope = scope, - ) - buildScope.runInBuildScope { launchScope(spec) } - } - .await() - awaitCancellationAndThen { job.cancel() } - } - - override fun <In, Out> coalescingMutableTFlow( - coalesce: (old: Out, new: In) -> Out, - getInitialValue: () -> Out, - ): CoalescingMutableTFlow<In, Out> = - CoalescingMutableTFlow(null, coalesce, network, getInitialValue) - - override fun <T> mutableTFlow(): MutableTFlow<T> = MutableTFlow(network) - - override fun <T> mutableTStateDeferred(initialValue: FrpDeferredValue<T>): MutableTState<T> = - MutableTState(network, initialValue.unwrapped) -} - -/** - * Combination of an [FrpNetwork] and a [Job] that, when cancelled, will cancel the entire FRP - * network. - */ -@ExperimentalFrpApi -class RootFrpNetwork -internal constructor(private val network: Network, private val scope: CoroutineScope, job: Job) : - Job by job, FrpNetwork by LocalFrpNetwork(network, scope, emptyTFlow) - -/** Constructs a new [RootFrpNetwork] in the given [CoroutineScope]. */ -@ExperimentalFrpApi -fun CoroutineScope.newFrpNetwork( - context: CoroutineContext = EmptyCoroutineContext -): RootFrpNetwork { - val scope = childScope(context) - val network = Network(scope) - scope.launch(CoroutineName("newFrpNetwork scheduler")) { network.runInputScheduler() } - return RootFrpNetwork(network, scope, scope.coroutineContext.job) -} diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpScope.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpScope.kt deleted file mode 100644 index ad6b2c8d04eb..000000000000 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpScope.kt +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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.kairos - -import kotlin.coroutines.RestrictsSuspension -import kotlin.coroutines.resume -import kotlin.coroutines.resumeWithException -import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.Deferred -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.suspendCancellableCoroutine - -/** Denotes [FrpScope] interfaces as [DSL markers][DslMarker]. */ -@DslMarker annotation class FrpScopeMarker - -/** - * Base scope for all FRP scopes. Used to prevent implicitly capturing other scopes from in lambdas. - */ -@FrpScopeMarker -@RestrictsSuspension -@ExperimentalFrpApi -interface FrpScope { - /** - * Returns the value held by the [FrpDeferredValue], suspending until available if necessary. - */ - @ExperimentalFrpApi - @OptIn(ExperimentalCoroutinesApi::class) - suspend fun <A> FrpDeferredValue<A>.get(): A = suspendCancellableCoroutine { k -> - unwrapped.invokeOnCompletion { ex -> - ex?.let { k.resumeWithException(ex) } ?: k.resume(unwrapped.getCompleted()) - } - } -} - -/** - * A value that may not be immediately (synchronously) available, but is guaranteed to be available - * before this transaction is completed. - * - * @see FrpScope.get - */ -@ExperimentalFrpApi -class FrpDeferredValue<out A> internal constructor(internal val unwrapped: Deferred<A>) - -/** - * Returns the value held by this [FrpDeferredValue], or throws [IllegalStateException] if it is not - * yet available. - * - * This API is not meant for general usage within the FRP network. It is made available mainly for - * debugging and logging. You should always prefer [get][FrpScope.get] if possible. - * - * @see FrpScope.get - */ -@ExperimentalFrpApi -@OptIn(ExperimentalCoroutinesApi::class) -fun <A> FrpDeferredValue<A>.getUnsafe(): A = unwrapped.getCompleted() - -/** Returns an already-available [FrpDeferredValue] containing [value]. */ -@ExperimentalFrpApi -fun <A> deferredOf(value: A): FrpDeferredValue<A> = FrpDeferredValue(CompletableDeferred(value)) diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpStateScope.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpStateScope.kt deleted file mode 100644 index c7ea6808a53e..000000000000 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpStateScope.kt +++ /dev/null @@ -1,780 +0,0 @@ -/* - * 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.kairos - -import com.android.systemui.kairos.combine as combinePure -import com.android.systemui.kairos.map as mapPure -import com.android.systemui.kairos.util.Just -import com.android.systemui.kairos.util.Left -import com.android.systemui.kairos.util.Maybe -import com.android.systemui.kairos.util.Right -import com.android.systemui.kairos.util.WithPrev -import com.android.systemui.kairos.util.just -import com.android.systemui.kairos.util.map -import com.android.systemui.kairos.util.none -import com.android.systemui.kairos.util.partitionEithers -import com.android.systemui.kairos.util.zipWith -import kotlin.coroutines.RestrictsSuspension - -typealias FrpStateful<R> = suspend FrpStateScope.() -> R - -/** - * Returns a [FrpStateful] that, when [applied][FrpStateScope.applyStateful], invokes [block] with - * the applier's [FrpStateScope]. - */ -// TODO: caching story? should each Scope have a cache of applied FrpStateful instances? -@ExperimentalFrpApi -@Suppress("NOTHING_TO_INLINE") -inline fun <A> statefully(noinline block: suspend FrpStateScope.() -> A): FrpStateful<A> = block - -/** - * Operations that accumulate state within the FRP network. - * - * State accumulation is an ongoing process that has a lifetime. Use `-Latest` combinators, such as - * [mapLatestStateful], to create smaller, nested lifecycles so that accumulation isn't running - * longer than needed. - */ -@ExperimentalFrpApi -@RestrictsSuspension -interface FrpStateScope : FrpTransactionScope { - - /** TODO */ - @ExperimentalFrpApi - // TODO: wish this could just be `deferred` but alas - fun <A> deferredStateScope(block: suspend FrpStateScope.() -> A): FrpDeferredValue<A> - - /** - * Returns a [TState] that holds onto the most recently emitted value from this [TFlow], or - * [initialValue] if nothing has been emitted since it was constructed. - * - * Note that the value contained within the [TState] is not updated until *after* all [TFlow]s - * have been processed; this keeps the value of the [TState] consistent during the entire FRP - * transaction. - */ - @ExperimentalFrpApi fun <A> TFlow<A>.holdDeferred(initialValue: FrpDeferredValue<A>): TState<A> - - /** - * Returns a [TFlow] that emits from a merged, incrementally-accumulated collection of [TFlow]s - * emitted from this, following the same "patch" rules as outlined in [foldMapIncrementally]. - * - * Conceptually this is equivalent to: - * ```kotlin - * fun <K, V> TFlow<Map<K, Maybe<TFlow<V>>>>.mergeIncrementally( - * initialTFlows: Map<K, TFlow<V>>, - * ): TFlow<Map<K, V>> = - * foldMapIncrementally(initialTFlows).map { it.merge() }.switch() - * ``` - * - * While the behavior is equivalent to the conceptual definition above, the implementation is - * significantly more efficient. - * - * @see merge - */ - @ExperimentalFrpApi - fun <K : Any, V> TFlow<Map<K, Maybe<TFlow<V>>>>.mergeIncrementally( - initialTFlows: FrpDeferredValue<Map<K, TFlow<V>>> - ): TFlow<Map<K, V>> - - /** - * Returns a [TFlow] that emits from a merged, incrementally-accumulated collection of [TFlow]s - * emitted from this, following the same "patch" rules as outlined in [foldMapIncrementally]. - * - * Conceptually this is equivalent to: - * ```kotlin - * fun <K, V> TFlow<Map<K, Maybe<TFlow<V>>>>.mergeIncrementallyPrompt( - * initialTFlows: Map<K, TFlow<V>>, - * ): TFlow<Map<K, V>> = - * foldMapIncrementally(initialTFlows).map { it.merge() }.switchPromptly() - * ``` - * - * While the behavior is equivalent to the conceptual definition above, the implementation is - * significantly more efficient. - * - * @see merge - */ - @ExperimentalFrpApi - fun <K : Any, V> TFlow<Map<K, Maybe<TFlow<V>>>>.mergeIncrementallyPromptly( - initialTFlows: FrpDeferredValue<Map<K, TFlow<V>>> - ): TFlow<Map<K, V>> - - // TODO: everything below this comment can be made into extensions once we have context params - - /** - * Returns a [TFlow] that emits from a merged, incrementally-accumulated collection of [TFlow]s - * emitted from this, following the same "patch" rules as outlined in [foldMapIncrementally]. - * - * Conceptually this is equivalent to: - * ```kotlin - * fun <K, V> TFlow<Map<K, Maybe<TFlow<V>>>>.mergeIncrementally( - * initialTFlows: Map<K, TFlow<V>>, - * ): TFlow<Map<K, V>> = - * foldMapIncrementally(initialTFlows).map { it.merge() }.switch() - * ``` - * - * While the behavior is equivalent to the conceptual definition above, the implementation is - * significantly more efficient. - * - * @see merge - */ - @ExperimentalFrpApi - fun <K : Any, V> TFlow<Map<K, Maybe<TFlow<V>>>>.mergeIncrementally( - initialTFlows: Map<K, TFlow<V>> = emptyMap() - ): TFlow<Map<K, V>> = mergeIncrementally(deferredOf(initialTFlows)) - - /** - * Returns a [TFlow] that emits from a merged, incrementally-accumulated collection of [TFlow]s - * emitted from this, following the same "patch" rules as outlined in [foldMapIncrementally]. - * - * Conceptually this is equivalent to: - * ```kotlin - * fun <K, V> TFlow<Map<K, Maybe<TFlow<V>>>>.mergeIncrementallyPrompt( - * initialTFlows: Map<K, TFlow<V>>, - * ): TFlow<Map<K, V>> = - * foldMapIncrementally(initialTFlows).map { it.merge() }.switchPromptly() - * ``` - * - * While the behavior is equivalent to the conceptual definition above, the implementation is - * significantly more efficient. - * - * @see merge - */ - @ExperimentalFrpApi - fun <K : Any, V> TFlow<Map<K, Maybe<TFlow<V>>>>.mergeIncrementallyPromptly( - initialTFlows: Map<K, TFlow<V>> = emptyMap() - ): TFlow<Map<K, V>> = mergeIncrementallyPromptly(deferredOf(initialTFlows)) - - /** Applies the [FrpStateful] within this [FrpStateScope]. */ - @ExperimentalFrpApi suspend fun <A> FrpStateful<A>.applyStateful(): A = this() - - /** - * Applies the [FrpStateful] within this [FrpStateScope], returning the result as an - * [FrpDeferredValue]. - */ - @ExperimentalFrpApi - fun <A> FrpStateful<A>.applyStatefulDeferred(): FrpDeferredValue<A> = deferredStateScope { - applyStateful() - } - - /** - * Returns a [TState] that holds onto the most recently emitted value from this [TFlow], or - * [initialValue] if nothing has been emitted since it was constructed. - * - * Note that the value contained within the [TState] is not updated until *after* all [TFlow]s - * have been processed; this keeps the value of the [TState] consistent during the entire FRP - * transaction. - */ - @ExperimentalFrpApi - fun <A> TFlow<A>.hold(initialValue: A): TState<A> = holdDeferred(deferredOf(initialValue)) - - /** - * Returns a [TFlow] the emits the result of applying [FrpStatefuls][FrpStateful] emitted from - * the original [TFlow]. - * - * Unlike [applyLatestStateful], state accumulation is not stopped with each subsequent emission - * of the original [TFlow]. - */ - @ExperimentalFrpApi fun <A> TFlow<FrpStateful<A>>.applyStatefuls(): TFlow<A> - - /** - * Returns a [TFlow] containing the results of applying [transform] to each value of the - * original [TFlow]. - * - * [transform] can perform state accumulation via its [FrpStateScope] receiver. Unlike - * [mapLatestStateful], accumulation is not stopped with each subsequent emission of the - * original [TFlow]. - */ - @ExperimentalFrpApi - fun <A, B> TFlow<A>.mapStateful(transform: suspend FrpStateScope.(A) -> B): TFlow<B> = - mapPure { statefully { transform(it) } }.applyStatefuls() - - /** - * Returns a [TState] the holds the result of applying the [FrpStateful] held by the original - * [TState]. - * - * Unlike [applyLatestStateful], state accumulation is not stopped with each state change. - */ - @ExperimentalFrpApi - fun <A> TState<FrpStateful<A>>.applyStatefuls(): TState<A> = - stateChanges - .applyStatefuls() - .holdDeferred(initialValue = deferredStateScope { sampleDeferred().get()() }) - - /** Returns a [TFlow] that switches to the [TFlow] emitted by the original [TFlow]. */ - @ExperimentalFrpApi fun <A> TFlow<TFlow<A>>.flatten() = hold(emptyTFlow).switch() - - /** - * Returns a [TFlow] containing the results of applying [transform] to each value of the - * original [TFlow]. - * - * [transform] can perform state accumulation via its [FrpStateScope] receiver. With each - * invocation of [transform], state accumulation from previous invocation is stopped. - */ - @ExperimentalFrpApi - fun <A, B> TFlow<A>.mapLatestStateful(transform: suspend FrpStateScope.(A) -> B): TFlow<B> = - mapPure { statefully { transform(it) } }.applyLatestStateful() - - /** - * Returns a [TFlow] that switches to a new [TFlow] produced by [transform] every time the - * original [TFlow] emits a value. - * - * [transform] can perform state accumulation via its [FrpStateScope] receiver. With each - * invocation of [transform], state accumulation from previous invocation is stopped. - */ - @ExperimentalFrpApi - fun <A, B> TFlow<A>.flatMapLatestStateful( - transform: suspend FrpStateScope.(A) -> TFlow<B> - ): TFlow<B> = mapLatestStateful(transform).flatten() - - /** - * Returns a [TFlow] containing the results of applying each [FrpStateful] emitted from the - * original [TFlow]. - * - * When each [FrpStateful] is applied, state accumulation from the previously-active - * [FrpStateful] is stopped. - */ - @ExperimentalFrpApi - fun <A> TFlow<FrpStateful<A>>.applyLatestStateful(): TFlow<A> = applyLatestStateful {}.first - - /** - * Returns a [TState] containing the value returned by applying the [FrpStateful] held by the - * original [TState]. - * - * When each [FrpStateful] is applied, state accumulation from the previously-active - * [FrpStateful] is stopped. - */ - @ExperimentalFrpApi - fun <A> TState<FrpStateful<A>>.applyLatestStateful(): TState<A> { - val (changes, init) = stateChanges.applyLatestStateful { sample()() } - return changes.holdDeferred(init) - } - - /** - * Returns a [TFlow] containing the results of applying each [FrpStateful] emitted from the - * original [TFlow], and a [FrpDeferredValue] containing the result of applying [init] - * immediately. - * - * When each [FrpStateful] is applied, state accumulation from the previously-active - * [FrpStateful] is stopped. - */ - @ExperimentalFrpApi - fun <A, B> TFlow<FrpStateful<B>>.applyLatestStateful( - init: FrpStateful<A> - ): Pair<TFlow<B>, FrpDeferredValue<A>> { - val (flow, result) = - mapCheap { spec -> mapOf(Unit to just(spec)) } - .applyLatestStatefulForKey(init = mapOf(Unit to init), numKeys = 1) - val outFlow: TFlow<B> = - flow.mapMaybe { - checkNotNull(it[Unit]) { "applyLatest: expected result, but none present in: $it" } - } - val outInit: FrpDeferredValue<A> = deferredTransactionScope { - val initResult: Map<Unit, A> = result.get() - check(Unit in initResult) { - "applyLatest: expected initial result, but none present in: $initResult" - } - @Suppress("UNCHECKED_CAST") - initResult.getOrDefault(Unit) { null } as A - } - return Pair(outFlow, outInit) - } - - /** - * Returns a [TFlow] containing the results of applying each [FrpStateful] emitted from the - * original [TFlow], and a [FrpDeferredValue] containing the result of applying [init] - * immediately. - * - * If the [Maybe] contained within the value for an associated key is [none], then the - * previously-active [FrpStateful] will be stopped with no replacement. - * - * When each [FrpStateful] is applied, state accumulation from the previously-active - * [FrpStateful] with the same key is stopped. - */ - @ExperimentalFrpApi - fun <K, A, B> TFlow<Map<K, Maybe<FrpStateful<A>>>>.applyLatestStatefulForKey( - init: FrpDeferredValue<Map<K, FrpStateful<B>>>, - numKeys: Int? = null, - ): Pair<TFlow<Map<K, Maybe<A>>>, FrpDeferredValue<Map<K, B>>> - - /** - * Returns a [TFlow] containing the results of applying each [FrpStateful] emitted from the - * original [TFlow], and a [FrpDeferredValue] containing the result of applying [init] - * immediately. - * - * When each [FrpStateful] is applied, state accumulation from the previously-active - * [FrpStateful] with the same key is stopped. - * - * If the [Maybe] contained within the value for an associated key is [none], then the - * previously-active [FrpStateful] will be stopped with no replacement. - */ - @ExperimentalFrpApi - fun <K, A, B> TFlow<Map<K, Maybe<FrpStateful<A>>>>.applyLatestStatefulForKey( - init: Map<K, FrpStateful<B>>, - numKeys: Int? = null, - ): Pair<TFlow<Map<K, Maybe<A>>>, FrpDeferredValue<Map<K, B>>> = - applyLatestStatefulForKey(deferredOf(init), numKeys) - - /** - * Returns a [TState] containing the latest results of applying each [FrpStateful] emitted from - * the original [TFlow]. - * - * When each [FrpStateful] is applied, state accumulation from the previously-active - * [FrpStateful] with the same key is stopped. - * - * If the [Maybe] contained within the value for an associated key is [none], then the - * previously-active [FrpStateful] will be stopped with no replacement. - */ - @ExperimentalFrpApi - fun <K, A> TFlow<Map<K, Maybe<FrpStateful<A>>>>.holdLatestStatefulForKey( - init: FrpDeferredValue<Map<K, FrpStateful<A>>>, - numKeys: Int? = null, - ): TState<Map<K, A>> { - val (changes, initialValues) = applyLatestStatefulForKey(init, numKeys) - return changes.foldMapIncrementally(initialValues) - } - - /** - * Returns a [TState] containing the latest results of applying each [FrpStateful] emitted from - * the original [TFlow]. - * - * When each [FrpStateful] is applied, state accumulation from the previously-active - * [FrpStateful] with the same key is stopped. - * - * If the [Maybe] contained within the value for an associated key is [none], then the - * previously-active [FrpStateful] will be stopped with no replacement. - */ - @ExperimentalFrpApi - fun <K, A> TFlow<Map<K, Maybe<FrpStateful<A>>>>.holdLatestStatefulForKey( - init: Map<K, FrpStateful<A>> = emptyMap(), - numKeys: Int? = null, - ): TState<Map<K, A>> = holdLatestStatefulForKey(deferredOf(init), numKeys) - - /** - * Returns a [TFlow] containing the results of applying each [FrpStateful] emitted from the - * original [TFlow], and a [FrpDeferredValue] containing the result of applying [init] - * immediately. - * - * When each [FrpStateful] is applied, state accumulation from the previously-active - * [FrpStateful] with the same key is stopped. - * - * If the [Maybe] contained within the value for an associated key is [none], then the - * previously-active [FrpStateful] will be stopped with no replacement. - */ - @ExperimentalFrpApi - fun <K, A> TFlow<Map<K, Maybe<FrpStateful<A>>>>.applyLatestStatefulForKey( - numKeys: Int? = null - ): TFlow<Map<K, Maybe<A>>> = - applyLatestStatefulForKey(init = emptyMap<K, FrpStateful<*>>(), numKeys = numKeys).first - - /** - * Returns a [TFlow] containing the results of applying [transform] to each value of the - * original [TFlow], and a [FrpDeferredValue] containing the result of applying [transform] to - * [initialValues] immediately. - * - * [transform] can perform state accumulation via its [FrpStateScope] receiver. With each - * invocation of [transform], state accumulation from previous invocation is stopped. - * - * If the [Maybe] contained within the value for an associated key is [none], then the - * previously-active [FrpStateScope] will be stopped with no replacement. - */ - @ExperimentalFrpApi - fun <K, A, B> TFlow<Map<K, Maybe<A>>>.mapLatestStatefulForKey( - initialValues: FrpDeferredValue<Map<K, A>>, - numKeys: Int? = null, - transform: suspend FrpStateScope.(A) -> B, - ): Pair<TFlow<Map<K, Maybe<B>>>, FrpDeferredValue<Map<K, B>>> = - mapPure { patch -> patch.mapValues { (_, v) -> v.map { statefully { transform(it) } } } } - .applyLatestStatefulForKey( - deferredStateScope { - initialValues.get().mapValues { (_, v) -> statefully { transform(v) } } - }, - numKeys = numKeys, - ) - - /** - * Returns a [TFlow] containing the results of applying [transform] to each value of the - * original [TFlow], and a [FrpDeferredValue] containing the result of applying [transform] to - * [initialValues] immediately. - * - * [transform] can perform state accumulation via its [FrpStateScope] receiver. With each - * invocation of [transform], state accumulation from previous invocation is stopped. - * - * If the [Maybe] contained within the value for an associated key is [none], then the - * previously-active [FrpStateScope] will be stopped with no replacement. - */ - @ExperimentalFrpApi - fun <K, A, B> TFlow<Map<K, Maybe<A>>>.mapLatestStatefulForKey( - initialValues: Map<K, A>, - numKeys: Int? = null, - transform: suspend FrpStateScope.(A) -> B, - ): Pair<TFlow<Map<K, Maybe<B>>>, FrpDeferredValue<Map<K, B>>> = - mapLatestStatefulForKey(deferredOf(initialValues), numKeys, transform) - - /** - * Returns a [TFlow] containing the results of applying [transform] to each value of the - * original [TFlow]. - * - * [transform] can perform state accumulation via its [FrpStateScope] receiver. With each - * invocation of [transform], state accumulation from previous invocation is stopped. - * - * If the [Maybe] contained within the value for an associated key is [none], then the - * previously-active [FrpStateScope] will be stopped with no replacement. - */ - @ExperimentalFrpApi - fun <K, A, B> TFlow<Map<K, Maybe<A>>>.mapLatestStatefulForKey( - numKeys: Int? = null, - transform: suspend FrpStateScope.(A) -> B, - ): TFlow<Map<K, Maybe<B>>> = mapLatestStatefulForKey(emptyMap(), numKeys, transform).first - - /** - * Returns a [TFlow] that will only emit the next event of the original [TFlow], and then will - * act as [emptyTFlow]. - * - * If the original [TFlow] is emitting an event at this exact time, then it will be the only - * even emitted from the result [TFlow]. - */ - @ExperimentalFrpApi - fun <A> TFlow<A>.nextOnly(): TFlow<A> = - if (this === emptyTFlow) { - this - } else { - TFlowLoop<A>().also { - it.loopback = it.mapCheap { emptyTFlow }.hold(this@nextOnly).switch() - } - } - - /** Returns a [TFlow] that skips the next emission of the original [TFlow]. */ - @ExperimentalFrpApi - fun <A> TFlow<A>.skipNext(): TFlow<A> = - if (this === emptyTFlow) { - this - } else { - nextOnly().mapCheap { this@skipNext }.hold(emptyTFlow).switch() - } - - /** - * Returns a [TFlow] that emits values from the original [TFlow] up until [stop] emits a value. - * - * If the original [TFlow] emits at the same time as [stop], then the returned [TFlow] will emit - * that value. - */ - @ExperimentalFrpApi - fun <A> TFlow<A>.takeUntil(stop: TFlow<*>): TFlow<A> = - if (stop === emptyTFlow) { - this - } else { - stop.mapCheap { emptyTFlow }.nextOnly().hold(this).switch() - } - - /** - * Invokes [stateful] in a new [FrpStateScope] that is a child of this one. - * - * This new scope is stopped when [stop] first emits a value, or when the parent scope is - * stopped. Stopping will end all state accumulation; any [TStates][TState] returned from this - * scope will no longer update. - */ - @ExperimentalFrpApi - fun <A> childStateScope(stop: TFlow<*>, stateful: FrpStateful<A>): FrpDeferredValue<A> { - val (_, init: FrpDeferredValue<Map<Unit, A>>) = - stop - .nextOnly() - .mapPure { mapOf(Unit to none<FrpStateful<A>>()) } - .applyLatestStatefulForKey(init = mapOf(Unit to stateful), numKeys = 1) - return deferredStateScope { init.get().getValue(Unit) } - } - - /** - * Returns a [TFlow] that emits values from the original [TFlow] up to and including a value is - * emitted that satisfies [predicate]. - */ - @ExperimentalFrpApi - fun <A> TFlow<A>.takeUntil(predicate: suspend FrpTransactionScope.(A) -> Boolean): TFlow<A> = - takeUntil(filter(predicate)) - - /** - * Returns a [TState] that is incrementally updated when this [TFlow] emits a value, by applying - * [transform] to both the emitted value and the currently tracked state. - * - * Note that the value contained within the [TState] is not updated until *after* all [TFlow]s - * have been processed; this keeps the value of the [TState] consistent during the entire FRP - * transaction. - */ - @ExperimentalFrpApi - fun <A, B> TFlow<A>.fold( - initialValue: B, - transform: suspend FrpTransactionScope.(A, B) -> B, - ): TState<B> { - lateinit var state: TState<B> - return mapPure { a -> transform(a, state.sample()) }.hold(initialValue).also { state = it } - } - - /** - * Returns a [TState] that is incrementally updated when this [TFlow] emits a value, by applying - * [transform] to both the emitted value and the currently tracked state. - * - * Note that the value contained within the [TState] is not updated until *after* all [TFlow]s - * have been processed; this keeps the value of the [TState] consistent during the entire FRP - * transaction. - */ - @ExperimentalFrpApi - fun <A, B> TFlow<A>.foldDeferred( - initialValue: FrpDeferredValue<B>, - transform: suspend FrpTransactionScope.(A, B) -> B, - ): TState<B> { - lateinit var state: TState<B> - return mapPure { a -> transform(a, state.sample()) } - .holdDeferred(initialValue) - .also { state = it } - } - - /** - * Returns a [TState] that holds onto the result of applying the most recently emitted - * [FrpStateful] this [TFlow], or [init] if nothing has been emitted since it was constructed. - * - * When each [FrpStateful] is applied, state accumulation from the previously-active - * [FrpStateful] is stopped. - * - * Note that the value contained within the [TState] is not updated until *after* all [TFlow]s - * have been processed; this keeps the value of the [TState] consistent during the entire FRP - * transaction. - * - * Shorthand for: - * ```kotlin - * val (changes, initApplied) = applyLatestStateful(init) - * return changes.toTStateDeferred(initApplied) - * ``` - */ - @ExperimentalFrpApi - fun <A> TFlow<FrpStateful<A>>.holdLatestStateful(init: FrpStateful<A>): TState<A> { - val (changes, initApplied) = applyLatestStateful(init) - return changes.holdDeferred(initApplied) - } - - /** - * Returns a [TFlow] that emits the two most recent emissions from the original [TFlow]. - * [initialValue] is used as the previous value for the first emission. - * - * Shorthand for `sample(hold(init)) { new, old -> Pair(old, new) }` - */ - @ExperimentalFrpApi - fun <S, T : S> TFlow<T>.pairwise(initialValue: S): TFlow<WithPrev<S, T>> { - val previous = hold(initialValue) - return mapCheap { new -> WithPrev(previousValue = previous.sample(), newValue = new) } - } - - /** - * Returns a [TFlow] that emits the two most recent emissions from the original [TFlow]. Note - * that the returned [TFlow] will not emit until the original [TFlow] has emitted twice. - */ - @ExperimentalFrpApi - fun <A> TFlow<A>.pairwise(): TFlow<WithPrev<A, A>> = - mapCheap { just(it) } - .pairwise(none) - .mapMaybe { (prev, next) -> prev.zipWith(next, ::WithPrev) } - - /** - * Returns a [TState] that holds both the current and previous values of the original [TState]. - * [initialPreviousValue] is used as the first previous value. - * - * Shorthand for `sample(hold(init)) { new, old -> Pair(old, new) }` - */ - @ExperimentalFrpApi - fun <S, T : S> TState<T>.pairwise(initialPreviousValue: S): TState<WithPrev<S, T>> = - stateChanges - .pairwise(initialPreviousValue) - .holdDeferred(deferredTransactionScope { WithPrev(initialPreviousValue, sample()) }) - - /** - * Returns a [TState] holding a [Map] that is updated incrementally whenever this emits a value. - * - * The value emitted is used as a "patch" for the tracked [Map]; for each key [K] in the emitted - * map, an associated value of [Just] will insert or replace the value in the tracked [Map], and - * an associated value of [none] will remove the key from the tracked [Map]. - */ - @ExperimentalFrpApi - fun <K, V> TFlow<Map<K, Maybe<V>>>.foldMapIncrementally( - initialValues: FrpDeferredValue<Map<K, V>> - ): TState<Map<K, V>> = - foldDeferred(initialValues) { patch, map -> - val (adds: List<Pair<K, V>>, removes: List<K>) = - patch - .asSequence() - .map { (k, v) -> if (v is Just) Left(k to v.value) else Right(k) } - .partitionEithers() - val removed: Map<K, V> = map - removes.toSet() - val updated: Map<K, V> = removed + adds - updated - } - - /** - * Returns a [TState] holding a [Map] that is updated incrementally whenever this emits a value. - * - * The value emitted is used as a "patch" for the tracked [Map]; for each key [K] in the emitted - * map, an associated value of [Just] will insert or replace the value in the tracked [Map], and - * an associated value of [none] will remove the key from the tracked [Map]. - */ - @ExperimentalFrpApi - fun <K, V> TFlow<Map<K, Maybe<V>>>.foldMapIncrementally( - initialValues: Map<K, V> = emptyMap() - ): TState<Map<K, V>> = foldMapIncrementally(deferredOf(initialValues)) - - /** - * Returns a [TFlow] that wraps each emission of the original [TFlow] into an [IndexedValue], - * containing the emitted value and its index (starting from zero). - * - * Shorthand for: - * ``` - * val index = fold(0) { _, oldIdx -> oldIdx + 1 } - * sample(index) { a, idx -> IndexedValue(idx, a) } - * ``` - */ - @ExperimentalFrpApi - fun <A> TFlow<A>.withIndex(): TFlow<IndexedValue<A>> { - val index = fold(0) { _, old -> old + 1 } - return sample(index) { a, idx -> IndexedValue(idx, a) } - } - - /** - * Returns a [TFlow] containing the results of applying [transform] to each value of the - * original [TFlow] and its index (starting from zero). - * - * Shorthand for: - * ``` - * withIndex().map { (idx, a) -> transform(idx, a) } - * ``` - */ - @ExperimentalFrpApi - fun <A, B> TFlow<A>.mapIndexed(transform: suspend FrpTransactionScope.(Int, A) -> B): TFlow<B> { - val index = fold(0) { _, i -> i + 1 } - return sample(index) { a, idx -> transform(idx, a) } - } - - /** Returns a [TFlow] where all subsequent repetitions of the same value are filtered out. */ - @ExperimentalFrpApi - fun <A> TFlow<A>.distinctUntilChanged(): TFlow<A> { - val state: TState<Any?> = hold(Any()) - return filter { it != state.sample() } - } - - /** - * Returns a new [TFlow] that emits at the same rate as the original [TFlow], but combines the - * emitted value with the most recent emission from [other] using [transform]. - * - * Note that the returned [TFlow] will not emit anything until [other] has emitted at least one - * value. - */ - @ExperimentalFrpApi - fun <A, B, C> TFlow<A>.sample( - other: TFlow<B>, - transform: suspend FrpTransactionScope.(A, B) -> C, - ): TFlow<C> { - val state = other.mapCheap { just(it) }.hold(none) - return sample(state) { a, b -> b.map { transform(a, it) } }.filterJust() - } - - /** - * Returns a [TState] that samples the [Transactional] held by the given [TState] within the - * same transaction that the state changes. - */ - @ExperimentalFrpApi - fun <A> TState<Transactional<A>>.sampleTransactionals(): TState<A> = - stateChanges - .sampleTransactionals() - .holdDeferred(deferredTransactionScope { sample().sample() }) - - /** - * Returns a [TState] that transforms the value held inside this [TState] by applying it to the - * given function [transform]. - */ - @ExperimentalFrpApi - fun <A, B> TState<A>.map(transform: suspend FrpTransactionScope.(A) -> B): TState<B> = - mapPure { transactionally { transform(it) } }.sampleTransactionals() - - /** - * Returns a [TState] whose value is generated with [transform] by combining the current values - * of each given [TState]. - * - * @see TState.combineWith - */ - @ExperimentalFrpApi - fun <A, B, Z> combine( - stateA: TState<A>, - stateB: TState<B>, - transform: suspend FrpTransactionScope.(A, B) -> Z, - ): TState<Z> = - com.android.systemui.kairos - .combine(stateA, stateB) { a, b -> transactionally { transform(a, b) } } - .sampleTransactionals() - - /** - * Returns a [TState] whose value is generated with [transform] by combining the current values - * of each given [TState]. - * - * @see TState.combineWith - */ - @ExperimentalFrpApi - fun <A, B, C, D, Z> combine( - stateA: TState<A>, - stateB: TState<B>, - stateC: TState<C>, - stateD: TState<D>, - transform: suspend FrpTransactionScope.(A, B, C, D) -> Z, - ): TState<Z> = - com.android.systemui.kairos - .combine(stateA, stateB, stateC, stateD) { a, b, c, d -> - transactionally { transform(a, b, c, d) } - } - .sampleTransactionals() - - /** Returns a [TState] by applying [transform] to the value held by the original [TState]. */ - @ExperimentalFrpApi - fun <A, B> TState<A>.flatMap( - transform: suspend FrpTransactionScope.(A) -> TState<B> - ): TState<B> = mapPure { transactionally { transform(it) } }.sampleTransactionals().flatten() - - /** - * Returns a [TState] whose value is generated with [transform] by combining the current values - * of each given [TState]. - * - * @see TState.combineWith - */ - @ExperimentalFrpApi - fun <A, Z> combine( - vararg states: TState<A>, - transform: suspend FrpTransactionScope.(List<A>) -> Z, - ): TState<Z> = combinePure(*states).map(transform) - - /** - * Returns a [TState] whose value is generated with [transform] by combining the current values - * of each given [TState]. - * - * @see TState.combineWith - */ - @ExperimentalFrpApi - fun <A, Z> Iterable<TState<A>>.combine( - transform: suspend FrpTransactionScope.(List<A>) -> Z - ): TState<Z> = combinePure().map(transform) - - /** - * Returns a [TState] by combining the values held inside the given [TState]s by applying them - * to the given function [transform]. - */ - @ExperimentalFrpApi - fun <A, B, C> TState<A>.combineWith( - other: TState<B>, - transform: suspend FrpTransactionScope.(A, B) -> C, - ): TState<C> = combine(this, other, transform) -} diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpTransactionScope.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpTransactionScope.kt deleted file mode 100644 index a7ae1d9646b3..000000000000 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/FrpTransactionScope.kt +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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.kairos - -import kotlin.coroutines.RestrictsSuspension - -/** - * FRP operations that are available while a transaction is active. - * - * These operations do not accumulate state, which makes [FrpTransactionScope] weaker than - * [FrpStateScope], but allows them to be used in more places. - */ -@ExperimentalFrpApi -@RestrictsSuspension -interface FrpTransactionScope : FrpScope { - - /** - * Returns the current value of this [Transactional] as a [FrpDeferredValue]. - * - * @see sample - */ - @ExperimentalFrpApi fun <A> Transactional<A>.sampleDeferred(): FrpDeferredValue<A> - - /** - * Returns the current value of this [TState] as a [FrpDeferredValue]. - * - * @see sample - */ - @ExperimentalFrpApi fun <A> TState<A>.sampleDeferred(): FrpDeferredValue<A> - - /** TODO */ - @ExperimentalFrpApi - fun <A> deferredTransactionScope( - block: suspend FrpTransactionScope.() -> A - ): FrpDeferredValue<A> - - /** A [TFlow] that emits once, within this transaction, and then never again. */ - @ExperimentalFrpApi val now: TFlow<Unit> - - /** - * Returns the current value held by this [TState]. Guaranteed to be consistent within the same - * transaction. - */ - @ExperimentalFrpApi suspend fun <A> TState<A>.sample(): A = sampleDeferred().get() - - /** - * Returns the current value held by this [Transactional]. Guaranteed to be consistent within - * the same transaction. - */ - @ExperimentalFrpApi suspend fun <A> Transactional<A>.sample(): A = sampleDeferred().get() -} diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/Incremental.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/Incremental.kt new file mode 100644 index 000000000000..c95b9e83594f --- /dev/null +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/Incremental.kt @@ -0,0 +1,297 @@ +/* + * 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.kairos + +import com.android.systemui.kairos.internal.CompletableLazy +import com.android.systemui.kairos.internal.IncrementalImpl +import com.android.systemui.kairos.internal.Init +import com.android.systemui.kairos.internal.InitScope +import com.android.systemui.kairos.internal.NoScope +import com.android.systemui.kairos.internal.awaitValues +import com.android.systemui.kairos.internal.constIncremental +import com.android.systemui.kairos.internal.constInit +import com.android.systemui.kairos.internal.init +import com.android.systemui.kairos.internal.mapImpl +import com.android.systemui.kairos.internal.mapValuesImpl +import com.android.systemui.kairos.internal.store.ConcurrentHashMapK +import com.android.systemui.kairos.internal.switchDeferredImpl +import com.android.systemui.kairos.internal.switchPromptImpl +import com.android.systemui.kairos.internal.util.hashString +import com.android.systemui.kairos.util.MapPatch +import com.android.systemui.kairos.util.map +import com.android.systemui.kairos.util.mapPatchFromFullDiff +import kotlin.reflect.KProperty + +/** A [State] tracking a [Map] that receives incremental updates. */ +sealed class Incremental<K, out V> : State<Map<K, V>>() { + abstract override val init: Init<IncrementalImpl<K, V>> +} + +/** An [Incremental] that never changes. */ +@ExperimentalKairosApi +fun <K, V> incrementalOf(value: Map<K, V>): Incremental<K, V> { + val operatorName = "stateOf" + val name = "$operatorName($value)" + return IncrementalInit(constInit(name, constIncremental(name, operatorName, value))) +} + +/** + * Returns an [Incremental] that acts as a deferred-reference to the [Incremental] produced by this + * [Lazy]. + * + * When the returned [Incremental] is accessed by the Kairos network, the [Lazy]'s + * [value][Lazy.value] will be queried and used. + * + * Useful for recursive definitions. + */ +@ExperimentalKairosApi +fun <K, V> Lazy<Incremental<K, V>>.defer(): Incremental<K, V> = deferInline { value } + +/** + * Returns an [Incremental] that acts as a deferred-reference to the [Incremental] produced by this + * [DeferredValue]. + * + * When the returned [Incremental] is accessed by the Kairos network, the [DeferredValue] will be + * queried and used. + * + * Useful for recursive definitions. + */ +@ExperimentalKairosApi +fun <K, V> DeferredValue<Incremental<K, V>>.defer(): Incremental<K, V> = deferInline { + unwrapped.value +} + +/** + * Returns an [Incremental] that acts as a deferred-reference to the [Incremental] produced by + * [block]. + * + * When the returned [Incremental] is accessed by the Kairos network, [block] will be invoked and + * the returned [Incremental] will be used. + * + * Useful for recursive definitions. + */ +@ExperimentalKairosApi +fun <K, V> deferredIncremental(block: KairosScope.() -> Incremental<K, V>): Incremental<K, V> = + deferInline { + NoScope.block() + } + +/** + * An [Events] that emits every time this [Incremental] changes, containing the subset of the map + * that has changed. + * + * @see MapPatch + */ +val <K, V> Incremental<K, V>.updates: Events<MapPatch<K, V>> + get() = EventsInit(init("patches") { init.connect(this).patches }) + +internal class IncrementalInit<K, V>(override val init: Init<IncrementalImpl<K, V>>) : + Incremental<K, V>() + +/** + * Returns an [Incremental] that tracks the entries of the original incremental, but values replaced + * with those obtained by applying [transform] to each original entry. + */ +fun <K, V, U> Incremental<K, V>.mapValues( + transform: KairosScope.(Map.Entry<K, V>) -> U +): Incremental<K, U> { + val operatorName = "mapValues" + val name = operatorName + return IncrementalInit( + init(name) { + mapValuesImpl({ init.connect(this) }, name, operatorName) { NoScope.transform(it) } + } + ) +} + +/** + * Returns an [Events] that emits from a merged, incrementally-accumulated collection of [Events] + * emitted from this, following the same "patch" rules as outlined in + * [StateScope.foldStateMapIncrementally]. + * + * Conceptually this is equivalent to: + * ```kotlin + * fun <K, V> State<Map<K, V>>.mergeEventsIncrementally(): Events<Map<K, V>> = + * map { it.merge() }.switchEvents() + * ``` + * + * While the behavior is equivalent to the conceptual definition above, the implementation is + * significantly more efficient. + * + * @see merge + */ +fun <K, V> Incremental<K, Events<V>>.mergeEventsIncrementally(): Events<Map<K, V>> { + val operatorName = "mergeEventsIncrementally" + val name = operatorName + val patches = + mapImpl({ init.connect(this).patches }) { patch, _ -> + patch.mapValues { (_, m) -> m.map { events -> events.init.connect(this) } }.asIterable() + } + return EventsInit( + constInit( + name, + switchDeferredImpl( + name = name, + getStorage = { + init + .connect(this) + .getCurrentWithEpoch(this) + .first + .mapValues { (_, events) -> events.init.connect(this) } + .asIterable() + }, + getPatches = { patches }, + storeFactory = ConcurrentHashMapK.Factory(), + ) + .awaitValues(), + ) + ) +} + +/** + * Returns an [Events] that emits from a merged, incrementally-accumulated collection of [Events] + * emitted from this, following the same "patch" rules as outlined in + * [StateScope.foldStateMapIncrementally]. + * + * Conceptually this is equivalent to: + * ```kotlin + * fun <K, V> State<Map<K, V>>.mergeEventsIncrementallyPromptly(): Events<Map<K, V>> = + * map { it.merge() }.switchEventsPromptly() + * ``` + * + * While the behavior is equivalent to the conceptual definition above, the implementation is + * significantly more efficient. + * + * @see merge + */ +fun <K, V> Incremental<K, Events<V>>.mergeEventsIncrementallyPromptly(): Events<Map<K, V>> { + val operatorName = "mergeEventsIncrementally" + val name = operatorName + val patches = + mapImpl({ init.connect(this).patches }) { patch, _ -> + patch.mapValues { (_, m) -> m.map { events -> events.init.connect(this) } }.asIterable() + } + return EventsInit( + constInit( + name, + switchPromptImpl( + name = name, + getStorage = { + init + .connect(this) + .getCurrentWithEpoch(this) + .first + .mapValues { (_, events) -> events.init.connect(this) } + .asIterable() + }, + getPatches = { patches }, + storeFactory = ConcurrentHashMapK.Factory(), + ) + .awaitValues(), + ) + ) +} + +/** A forward-reference to an [Incremental], allowing for recursive definitions. */ +@ExperimentalKairosApi +class IncrementalLoop<K, V>(private val name: String? = null) : Incremental<K, V>() { + + private val deferred = CompletableLazy<Incremental<K, V>>(name = name) + + override val init: Init<IncrementalImpl<K, V>> = + init(name) { deferred.value.init.connect(evalScope = this) } + + /** The [Incremental] this [IncrementalLoop] will forward to. */ + var loopback: Incremental<K, V>? = null + set(value) { + value?.let { + check(!deferred.isInitialized()) { + "IncrementalLoop($name).loopback has already been set." + } + deferred.setValue(value) + field = value + } + } + + operator fun getValue(thisRef: Any?, property: KProperty<*>): Incremental<K, V> = this + + operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Incremental<K, V>) { + loopback = value + } + + override fun toString(): String = "${this::class.simpleName}($name)@$hashString" +} + +/** + * Returns an [Incremental] whose [updates] are calculated by diffing the given [State]'s + * [transitions]. + */ +fun <K, V> State<Map<K, V>>.asIncremental(): Incremental<K, V> { + if (this is Incremental<K, V>) return this + + val hashState = map { if (it is HashMap) it else HashMap(it) } + + val patches = + transitions.mapNotNull { (old, new) -> + mapPatchFromFullDiff(old, new).takeIf { it.isNotEmpty() } + } + + return IncrementalInit( + init("asIncremental") { + val upstream = hashState.init.connect(this) + IncrementalImpl( + upstream.name, + upstream.operatorName, + upstream.changes, + patches.init.connect(this), + upstream.store, + ) + } + ) +} + +/** Returns an [Incremental] that acts like the current value of the given [State]. */ +fun <K, V> State<Incremental<K, V>>.switchIncremental(): Incremental<K, V> { + val stateChangePatches = + transitions.mapNotNull { (old, new) -> + mapPatchFromFullDiff(old.sample(), new.sample()).takeIf { it.isNotEmpty() } + } + val innerChanges = + map { inner -> + merge(stateChangePatches, inner.updates) { switchPatch, upcomingPatch -> + switchPatch + upcomingPatch + } + } + .switchEventsPromptly() + val flattened = flatten() + return IncrementalInit( + init("switchIncremental") { + val upstream = flattened.init.connect(this) + IncrementalImpl( + "switchIncremental", + "switchIncremental", + upstream.changes, + innerChanges.init.connect(this), + upstream.store, + ) + } + ) +} + +private inline fun <K, V> deferInline( + crossinline block: InitScope.() -> Incremental<K, V> +): Incremental<K, V> = IncrementalInit(init(name = null) { block().init.connect(evalScope = this) }) diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/KairosNetwork.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/KairosNetwork.kt new file mode 100644 index 000000000000..77598b30658a --- /dev/null +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/KairosNetwork.kt @@ -0,0 +1,216 @@ +/* + * 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.kairos + +import com.android.systemui.kairos.internal.BuildScopeImpl +import com.android.systemui.kairos.internal.Network +import com.android.systemui.kairos.internal.StateScopeImpl +import com.android.systemui.kairos.internal.util.awaitCancellationAndThen +import com.android.systemui.kairos.internal.util.childScope +import kotlin.coroutines.CoroutineContext +import kotlin.coroutines.EmptyCoroutineContext +import kotlinx.coroutines.CoroutineName +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.job +import kotlinx.coroutines.launch + +/** + * Marks declarations that are still **experimental** and shouldn't be used in general production + * code. + */ +@RequiresOptIn( + message = "This API is experimental and should not be used in general production code." +) +@Retention(AnnotationRetention.BINARY) +annotation class ExperimentalKairosApi + +/** + * External interface to a Kairos network of reactive components. Can be used to make transactional + * queries and modifications to the network. + */ +@ExperimentalKairosApi +interface KairosNetwork { + /** + * Runs [block] inside of a transaction, suspending until the transaction is complete. + * + * The [BuildScope] receiver exposes methods that can be used to query or modify the network. If + * the network is cancelled while the caller of [transact] is suspended, then the call will be + * cancelled. + */ + suspend fun <R> transact(block: TransactionScope.() -> R): R + + /** + * Activates [spec] in a transaction, suspending indefinitely. While suspended, all observers + * and long-running effects are kept alive. When cancelled, observers are unregistered and + * effects are cancelled. + */ + suspend fun activateSpec(spec: BuildSpec<*>) + + /** Returns a [CoalescingMutableEvents] that can emit values into this [KairosNetwork]. */ + fun <In, Out> coalescingMutableEvents( + coalesce: (old: Out, new: In) -> Out, + getInitialValue: () -> Out, + ): CoalescingMutableEvents<In, Out> + + /** Returns a [MutableState] that can emit values into this [KairosNetwork]. */ + fun <T> mutableEvents(): MutableEvents<T> + + /** Returns a [CoalescingMutableEvents] that can emit values into this [KairosNetwork]. */ + fun <T> conflatedMutableEvents(): CoalescingMutableEvents<T, T> + + /** Returns a [MutableState]. with initial state [initialValue]. */ + fun <T> mutableStateDeferred(initialValue: DeferredValue<T>): MutableState<T> +} + +/** Returns a [CoalescingMutableEvents] that can emit values into this [KairosNetwork]. */ +@ExperimentalKairosApi +fun <In, Out> KairosNetwork.coalescingMutableEvents( + coalesce: (old: Out, new: In) -> Out, + initialValue: Out, +): CoalescingMutableEvents<In, Out> = + coalescingMutableEvents(coalesce, getInitialValue = { initialValue }) + +/** Returns a [MutableState] with initial state [initialValue]. */ +@ExperimentalKairosApi +fun <T> KairosNetwork.mutableState(initialValue: T): MutableState<T> = + mutableStateDeferred(deferredOf(initialValue)) + +/** Returns a [MutableState] with initial state [initialValue]. */ +@ExperimentalKairosApi +fun <T> MutableState(network: KairosNetwork, initialValue: T): MutableState<T> = + network.mutableState(initialValue) + +/** Returns a [MutableEvents] that can emit values into this [KairosNetwork]. */ +@ExperimentalKairosApi +fun <T> MutableEvents(network: KairosNetwork): MutableEvents<T> = network.mutableEvents() + +/** Returns a [CoalescingMutableEvents] that can emit values into this [KairosNetwork]. */ +@ExperimentalKairosApi +fun <In, Out> CoalescingMutableEvents( + network: KairosNetwork, + coalesce: (old: Out, new: In) -> Out, + initialValue: Out, +): CoalescingMutableEvents<In, Out> = network.coalescingMutableEvents(coalesce) { initialValue } + +/** Returns a [CoalescingMutableEvents] that can emit values into this [KairosNetwork]. */ +@ExperimentalKairosApi +fun <In, Out> CoalescingMutableEvents( + network: KairosNetwork, + coalesce: (old: Out, new: In) -> Out, + getInitialValue: () -> Out, +): CoalescingMutableEvents<In, Out> = network.coalescingMutableEvents(coalesce, getInitialValue) + +/** Returns a [CoalescingMutableEvents] that can emit values into this [KairosNetwork]. */ +@ExperimentalKairosApi +fun <T> ConflatedMutableEvents(network: KairosNetwork): CoalescingMutableEvents<T, T> = + network.conflatedMutableEvents() + +/** + * Activates [spec] in a transaction and invokes [block] with the result, suspending indefinitely. + * While suspended, all observers and long-running effects are kept alive. When cancelled, observers + * are unregistered and effects are cancelled. + */ +@ExperimentalKairosApi +suspend fun <R> KairosNetwork.activateSpec(spec: BuildSpec<R>, block: suspend (R) -> Unit) { + activateSpec { + val result = spec.applySpec() + launchEffect { block(result) } + } +} + +internal class LocalNetwork( + private val network: Network, + private val scope: CoroutineScope, + private val endSignal: Events<Any>, +) : KairosNetwork { + override suspend fun <R> transact(block: TransactionScope.() -> R): R = + network.transaction("KairosNetwork.transact") { block() }.await() + + override suspend fun activateSpec(spec: BuildSpec<*>) { + val stopEmitter = + CoalescingMutableEvents( + name = "activateSpec", + coalesce = { _, _: Unit -> }, + network = network, + getInitialValue = {}, + ) + val job = + network + .transaction("KairosNetwork.activateSpec") { + val buildScope = + BuildScopeImpl( + stateScope = + StateScopeImpl( + evalScope = this, + endSignal = mergeLeft(stopEmitter, endSignal), + ), + coroutineScope = scope, + ) + buildScope.launchScope(spec) + } + .await() + awaitCancellationAndThen { + stopEmitter.emit(Unit) + job.cancel() + } + } + + override fun <In, Out> coalescingMutableEvents( + coalesce: (old: Out, new: In) -> Out, + getInitialValue: () -> Out, + ): CoalescingMutableEvents<In, Out> = + CoalescingMutableEvents( + null, + coalesce = { old, new -> coalesce(old.value, new) }, + network, + getInitialValue, + ) + + override fun <T> conflatedMutableEvents(): CoalescingMutableEvents<T, T> = + CoalescingMutableEvents( + null, + coalesce = { _, new -> new }, + network, + { error("WTF: init value accessed for conflatedMutableEvents") }, + ) + + override fun <T> mutableEvents(): MutableEvents<T> = MutableEvents(network) + + override fun <T> mutableStateDeferred(initialValue: DeferredValue<T>): MutableState<T> = + MutableState(network, initialValue.unwrapped) +} + +/** + * Combination of an [KairosNetwork] and a [Job] that, when cancelled, will cancel the entire Kairos + * network. + */ +@ExperimentalKairosApi +class RootKairosNetwork +internal constructor(private val network: Network, private val scope: CoroutineScope, job: Job) : + Job by job, KairosNetwork by LocalNetwork(network, scope, emptyEvents) + +/** Constructs a new [RootKairosNetwork] in the given [CoroutineScope]. */ +@ExperimentalKairosApi +fun CoroutineScope.launchKairosNetwork( + context: CoroutineContext = EmptyCoroutineContext +): RootKairosNetwork { + val scope = childScope(context) + val network = Network(scope) + scope.launch(CoroutineName("launchKairosNetwork scheduler")) { network.runInputScheduler() } + return RootKairosNetwork(network, scope, scope.coroutineContext.job) +} diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/KairosScope.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/KairosScope.kt new file mode 100644 index 000000000000..ce3e9235efa8 --- /dev/null +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/KairosScope.kt @@ -0,0 +1,57 @@ +/* + * 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.kairos + +import com.android.systemui.kairos.internal.CompletableLazy + +/** Denotes [KairosScope] interfaces as [DSL markers][DslMarker]. */ +@DslMarker annotation class KairosScopeMarker + +/** + * Base scope for all Kairos scopes. Used to prevent implicitly capturing other scopes from in + * lambdas. + */ +@KairosScopeMarker +@ExperimentalKairosApi +interface KairosScope { + /** Returns the value held by the [DeferredValue], suspending until available if necessary. */ + fun <A> DeferredValue<A>.get(): A = unwrapped.value +} + +/** + * A value that may not be immediately (synchronously) available, but is guaranteed to be available + * before this transaction is completed. + * + * @see KairosScope.get + */ +@ExperimentalKairosApi +class DeferredValue<out A> internal constructor(internal val unwrapped: Lazy<A>) + +/** + * Returns the value held by this [DeferredValue], or throws [IllegalStateException] if it is not + * yet available. + * + * This API is not meant for general usage within the Kairos network. It is made available mainly + * for debugging and logging. You should always prefer [get][KairosScope.get] if possible. + * + * @see KairosScope.get + */ +@ExperimentalKairosApi fun <A> DeferredValue<A>.getUnsafe(): A = unwrapped.value + +/** Returns an already-available [DeferredValue] containing [value]. */ +@ExperimentalKairosApi +fun <A> deferredOf(value: A): DeferredValue<A> = DeferredValue(CompletableLazy(value)) diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/State.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/State.kt new file mode 100644 index 000000000000..1f0a19d5752b --- /dev/null +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/State.kt @@ -0,0 +1,530 @@ +/* + * 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.kairos + +import com.android.systemui.kairos.internal.CompletableLazy +import com.android.systemui.kairos.internal.DerivedMapCheap +import com.android.systemui.kairos.internal.EventsImpl +import com.android.systemui.kairos.internal.Init +import com.android.systemui.kairos.internal.InitScope +import com.android.systemui.kairos.internal.Network +import com.android.systemui.kairos.internal.NoScope +import com.android.systemui.kairos.internal.Schedulable +import com.android.systemui.kairos.internal.StateImpl +import com.android.systemui.kairos.internal.StateSource +import com.android.systemui.kairos.internal.activated +import com.android.systemui.kairos.internal.cached +import com.android.systemui.kairos.internal.constInit +import com.android.systemui.kairos.internal.constState +import com.android.systemui.kairos.internal.filterImpl +import com.android.systemui.kairos.internal.flatMapStateImpl +import com.android.systemui.kairos.internal.init +import com.android.systemui.kairos.internal.mapImpl +import com.android.systemui.kairos.internal.mapStateImpl +import com.android.systemui.kairos.internal.mapStateImplCheap +import com.android.systemui.kairos.internal.util.hashString +import com.android.systemui.kairos.internal.zipStateMap +import com.android.systemui.kairos.internal.zipStates +import kotlin.reflect.KProperty + +/** + * A time-varying value with discrete changes. Essentially, a combination of a [Transactional] that + * holds a value, and an [Events] that emits when the value changes. + */ +@ExperimentalKairosApi +sealed class State<out A> { + internal abstract val init: Init<StateImpl<A>> +} + +/** A [State] that never changes. */ +@ExperimentalKairosApi +fun <A> stateOf(value: A): State<A> { + val operatorName = "stateOf" + val name = "$operatorName($value)" + return StateInit(constInit(name, constState(name, operatorName, value))) +} + +/** + * Returns a [State] that acts as a deferred-reference to the [State] produced by this [Lazy]. + * + * When the returned [State] is accessed by the Kairos network, the [Lazy]'s [value][Lazy.value] + * will be queried and used. + * + * Useful for recursive definitions. + */ +@ExperimentalKairosApi fun <A> Lazy<State<A>>.defer(): State<A> = deferInline { value } + +/** + * Returns a [State] that acts as a deferred-reference to the [State] produced by this + * [DeferredValue]. + * + * When the returned [State] is accessed by the Kairos network, the [DeferredValue] will be queried + * and used. + * + * Useful for recursive definitions. + */ +@ExperimentalKairosApi +fun <A> DeferredValue<State<A>>.defer(): State<A> = deferInline { unwrapped.value } + +/** + * Returns a [State] that acts as a deferred-reference to the [State] produced by [block]. + * + * When the returned [State] is accessed by the Kairos network, [block] will be invoked and the + * returned [State] will be used. + * + * Useful for recursive definitions. + */ +@ExperimentalKairosApi +fun <A> deferredState(block: KairosScope.() -> State<A>): State<A> = deferInline { NoScope.block() } + +/** + * Returns a [State] containing the results of applying [transform] to the value held by the + * original [State]. + */ +@ExperimentalKairosApi +fun <A, B> State<A>.map(transform: KairosScope.(A) -> B): State<B> { + val operatorName = "map" + val name = operatorName + return StateInit( + init(name) { + mapStateImpl({ init.connect(this) }, name, operatorName) { NoScope.transform(it) } + } + ) +} + +/** + * Returns a [State] that transforms the value held inside this [State] by applying it to the + * [transform]. + * + * Note that unlike [map], the result is not cached. This means that not only should [transform] be + * fast and pure, it should be *monomorphic* (1-to-1). Failure to do this means that [changes] for + * the returned [State] will operate unexpectedly, emitting at rates that do not reflect an + * observable change to the returned [State]. + */ +@ExperimentalKairosApi +fun <A, B> State<A>.mapCheapUnsafe(transform: KairosScope.(A) -> B): State<B> { + val operatorName = "map" + val name = operatorName + return StateInit( + init(name) { mapStateImplCheap(init, name, operatorName) { NoScope.transform(it) } } + ) +} + +/** + * Returns a [State] by combining the values held inside the given [State]s by applying them to the + * given function [transform]. + */ +@ExperimentalKairosApi +fun <A, B, C> State<A>.combineWith(other: State<B>, transform: KairosScope.(A, B) -> C): State<C> = + combine(this, other, transform) + +/** + * Splits a [State] of pairs into a pair of [Events][State], where each returned [State] holds half + * of the original. + * + * Shorthand for: + * ```kotlin + * val lefts = map { it.first } + * val rights = map { it.second } + * return Pair(lefts, rights) + * ``` + */ +@ExperimentalKairosApi +fun <A, B> State<Pair<A, B>>.unzip(): Pair<State<A>, State<B>> { + val left = map { it.first } + val right = map { it.second } + return left to right +} + +/** + * Returns a [State] by combining the values held inside the given [States][State] into a [List]. + * + * @see State.combineWith + */ +@ExperimentalKairosApi +fun <A> Iterable<State<A>>.combine(): State<List<A>> { + val operatorName = "combine" + val name = operatorName + return StateInit( + init(name) { + val states = map { it.init } + zipStates( + name, + operatorName, + states.size, + states = init(null) { states.map { it.connect(this) } }, + ) + } + ) +} + +/** + * Returns a [State] by combining the values held inside the given [States][State] into a [Map]. + * + * @see State.combineWith + */ +@ExperimentalKairosApi +fun <K, A> Map<K, State<A>>.combine(): State<Map<K, A>> { + val operatorName = "combine" + val name = operatorName + return StateInit( + init(name) { + zipStateMap( + name, + operatorName, + size, + states = init(null) { mapValues { it.value.init.connect(evalScope = this) } }, + ) + } + ) +} + +/** + * Returns a [State] whose value is generated with [transform] by combining the current values of + * each given [State]. + * + * @see State.combineWith + */ +@ExperimentalKairosApi +fun <A, B> Iterable<State<A>>.combine(transform: KairosScope.(List<A>) -> B): State<B> = + combine().map(transform) + +/** + * Returns a [State] by combining the values held inside the given [State]s into a [List]. + * + * @see State.combineWith + */ +@ExperimentalKairosApi +fun <A> combine(vararg states: State<A>): State<List<A>> = states.asIterable().combine() + +/** + * Returns a [State] whose value is generated with [transform] by combining the current values of + * each given [State]. + * + * @see State.combineWith + */ +@ExperimentalKairosApi +fun <A, B> combine(vararg states: State<A>, transform: KairosScope.(List<A>) -> B): State<B> = + states.asIterable().combine(transform) + +/** + * Returns a [State] whose value is generated with [transform] by combining the current values of + * each given [State]. + * + * @see State.combineWith + */ +@ExperimentalKairosApi +fun <A, B, Z> combine( + stateA: State<A>, + stateB: State<B>, + transform: KairosScope.(A, B) -> Z, +): State<Z> { + val operatorName = "combine" + val name = operatorName + return StateInit( + init(name) { + zipStates(name, operatorName, stateA.init, stateB.init) { a, b -> + NoScope.transform(a, b) + } + } + ) +} + +/** + * Returns a [State] whose value is generated with [transform] by combining the current values of + * each given [State]. + * + * @see State.combineWith + */ +@ExperimentalKairosApi +fun <A, B, C, Z> combine( + stateA: State<A>, + stateB: State<B>, + stateC: State<C>, + transform: KairosScope.(A, B, C) -> Z, +): State<Z> { + val operatorName = "combine" + val name = operatorName + return StateInit( + init(name) { + zipStates(name, operatorName, stateA.init, stateB.init, stateC.init) { a, b, c -> + NoScope.transform(a, b, c) + } + } + ) +} + +/** + * Returns a [State] whose value is generated with [transform] by combining the current values of + * each given [State]. + * + * @see State.combineWith + */ +@ExperimentalKairosApi +fun <A, B, C, D, Z> combine( + stateA: State<A>, + stateB: State<B>, + stateC: State<C>, + stateD: State<D>, + transform: KairosScope.(A, B, C, D) -> Z, +): State<Z> { + val operatorName = "combine" + val name = operatorName + return StateInit( + init(name) { + zipStates(name, operatorName, stateA.init, stateB.init, stateC.init, stateD.init) { + a, + b, + c, + d -> + NoScope.transform(a, b, c, d) + } + } + ) +} + +/** + * Returns a [State] whose value is generated with [transform] by combining the current values of + * each given [State]. + * + * @see State.combineWith + */ +@ExperimentalKairosApi +fun <A, B, C, D, E, Z> combine( + stateA: State<A>, + stateB: State<B>, + stateC: State<C>, + stateD: State<D>, + stateE: State<E>, + transform: KairosScope.(A, B, C, D, E) -> Z, +): State<Z> { + val operatorName = "combine" + val name = operatorName + return StateInit( + init(name) { + zipStates( + name, + operatorName, + stateA.init, + stateB.init, + stateC.init, + stateD.init, + stateE.init, + ) { a, b, c, d, e -> + NoScope.transform(a, b, c, d, e) + } + } + ) +} + +/** Returns a [State] by applying [transform] to the value held by the original [State]. */ +@ExperimentalKairosApi +fun <A, B> State<A>.flatMap(transform: KairosScope.(A) -> State<B>): State<B> { + val operatorName = "flatMap" + val name = operatorName + return StateInit( + init(name) { + flatMapStateImpl({ init.connect(this) }, name, operatorName) { a -> + NoScope.transform(a).init.connect(this) + } + } + ) +} + +/** Shorthand for `flatMap { it }` */ +@ExperimentalKairosApi fun <A> State<State<A>>.flatten() = flatMap { it } + +/** + * Returns a [StateSelector] that can be used to efficiently check if the input [State] is currently + * holding a specific value. + * + * An example: + * ``` + * val intState: State<Int> = ... + * val intSelector: StateSelector<Int> = intState.selector() + * // Tracks if lInt is holding 1 + * val isOne: State<Boolean> = intSelector.whenSelected(1) + * ``` + * + * This is semantically equivalent to `val isOne = intState.map { i -> i == 1 }`, but is + * significantly more efficient; specifically, using [State.map] in this way incurs a `O(n)` + * performance hit, where `n` is the number of different [State.map] operations used to track a + * specific value. [selector] internally uses a [HashMap] to lookup the appropriate downstream + * [State] to update, and so operates in `O(1)`. + * + * Note that the returned [StateSelector] should be cached and re-used to gain the performance + * benefit. + * + * @see groupByKey + */ +@ExperimentalKairosApi +fun <A> State<A>.selector(numDistinctValues: Int? = null): StateSelector<A> = + StateSelector( + this, + changes + .map { new -> mapOf(new to true, sampleDeferred().get() to false) } + .groupByKey(numDistinctValues), + ) + +/** + * Tracks the currently selected value of type [A] from an upstream [State]. + * + * @see selector + */ +@ExperimentalKairosApi +class StateSelector<in A> +internal constructor( + private val upstream: State<A>, + private val groupedChanges: GroupedEvents<A, Boolean>, +) { + /** + * Returns a [State] that tracks whether the upstream [State] is currently holding the given + * [value]. + * + * @see selector + */ + fun whenSelected(value: A): State<Boolean> { + val operatorName = "StateSelector#whenSelected" + val name = "$operatorName[$value]" + return StateInit( + init(name) { + StateImpl( + name, + operatorName, + groupedChanges.impl.eventsForKey(value), + DerivedMapCheap(upstream.init) { it == value }, + ) + } + ) + } + + operator fun get(value: A): State<Boolean> = whenSelected(value) +} + +/** + * A mutable [State] that provides the ability to manually [set its value][setValue]. + * + * Multiple invocations of [setValue] that occur before a transaction are conflated; only the most + * recent value is used. + * + * Effectively equivalent to: + * ``` kotlin + * ConflatedMutableEvents(kairosNetwork).holdState(initialValue) + * ``` + */ +@ExperimentalKairosApi +class MutableState<T> internal constructor(internal val network: Network, initialValue: Lazy<T>) : + State<T>() { + + private val input: CoalescingMutableEvents<Lazy<T>, Lazy<T>?> = + CoalescingMutableEvents( + name = null, + coalesce = { _, new -> new }, + network = network, + getInitialValue = { null }, + ) + + override val init: Init<StateImpl<T>> + get() = state.init + + internal val state = run { + val changes = input.impl + val name = null + val operatorName = "MutableState" + val state: StateSource<T> = StateSource(initialValue) + val mapImpl = mapImpl(upstream = { changes.activated() }) { it, _ -> it!!.value } + val calm: EventsImpl<T> = + filterImpl({ mapImpl }) { new -> + new != state.getCurrentWithEpoch(evalScope = this).first + } + .cached() + @Suppress("DeferredResultUnused") + network.transaction("MutableState.init") { + calm.activate(evalScope = this, downstream = Schedulable.S(state))?.let { + (connection, needsEval) -> + state.upstreamConnection = connection + if (needsEval) { + schedule(state) + } + } + } + StateInit(constInit(name, StateImpl(name, operatorName, calm, state))) + } + + /** + * Sets the value held by this [State]. + * + * Invoking will cause a [state change event][State.changes] to emit with the new value, which + * will then be applied (and thus returned by [TransactionScope.sample]) after the transaction + * is complete. + * + * Multiple invocations of [setValue] that occur before a transaction are conflated; only the + * most recent value is used. + */ + fun setValue(value: T) = input.emit(CompletableLazy(value)) + + /** + * Sets the value held by this [State]. The [DeferredValue] will not be queried until this + * [State] is explicitly [sampled][TransactionScope.sample] or [observed][BuildScope.observe]. + * + * Invoking will cause a [state change event][State.changes] to emit with the new value, which + * will then be applied (and thus returned by [TransactionScope.sample]) after the transaction + * is complete. + * + * Multiple invocations of [setValue] that occur before a transaction are conflated; only the + * most recent value is used. + */ + fun setValueDeferred(value: DeferredValue<T>) = input.emit(value.unwrapped) +} + +/** A forward-reference to a [State], allowing for recursive definitions. */ +@ExperimentalKairosApi +class StateLoop<A> : State<A>() { + + private val name: String? = null + + private val deferred = CompletableLazy<State<A>>() + + override val init: Init<StateImpl<A>> = + init(name) { deferred.value.init.connect(evalScope = this) } + + /** The [State] this [StateLoop] will forward to. */ + var loopback: State<A>? = null + set(value) { + value?.let { + check(!deferred.isInitialized()) { "StateLoop.loopback has already been set." } + deferred.setValue(value) + field = value + } + } + + operator fun getValue(thisRef: Any?, property: KProperty<*>): State<A> = this + + operator fun setValue(thisRef: Any?, property: KProperty<*>, value: State<A>) { + loopback = value + } + + override fun toString(): String = "${this::class.simpleName}@$hashString" +} + +internal class StateInit<A> internal constructor(override val init: Init<StateImpl<A>>) : + State<A>() { + override fun toString(): String = "${this::class.simpleName}@$hashString" +} + +private inline fun <A> deferInline(crossinline block: InitScope.() -> State<A>): State<A> = + StateInit(init(name = null) { block().init.connect(evalScope = this) }) diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/StateScope.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/StateScope.kt new file mode 100644 index 000000000000..933ff1a75a02 --- /dev/null +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/StateScope.kt @@ -0,0 +1,806 @@ +/* + * 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.kairos + +import com.android.systemui.kairos.util.Maybe +import com.android.systemui.kairos.util.Maybe.Just +import com.android.systemui.kairos.util.WithPrev +import com.android.systemui.kairos.util.just +import com.android.systemui.kairos.util.map +import com.android.systemui.kairos.util.mapMaybeValues +import com.android.systemui.kairos.util.none +import com.android.systemui.kairos.util.zipWith + +// TODO: caching story? should each Scope have a cache of applied Stateful instances? +/** A computation that can accumulate [Events] into [State]. */ +typealias Stateful<R> = StateScope.() -> R + +/** + * Returns a [Stateful] that, when [applied][StateScope.applyStateful], invokes [block] with the + * applier's [StateScope]. + */ +@ExperimentalKairosApi +@Suppress("NOTHING_TO_INLINE") +inline fun <A> statefully(noinline block: StateScope.() -> A): Stateful<A> = block + +/** + * Operations that accumulate state within the Kairos network. + * + * State accumulation is an ongoing process that has a lifetime. Use `-Latest` combinators, such as + * [mapLatestStateful], to create smaller, nested lifecycles so that accumulation isn't running + * longer than needed. + */ +@ExperimentalKairosApi +interface StateScope : TransactionScope { + + /** + * Defers invoking [block] until after the current [StateScope] code-path completes, returning a + * [DeferredValue] that can be used to reference the result. + * + * Useful for recursive definitions. + * + * @see DeferredValue + */ + fun <A> deferredStateScope(block: StateScope.() -> A): DeferredValue<A> + + /** + * Returns a [State] that holds onto the most recently emitted value from this [Events], or + * [initialValue] if nothing has been emitted since it was constructed. + * + * Note that the value contained within the [State] is not updated until *after* all [Events] + * have been processed; this keeps the value of the [State] consistent during the entire Kairos + * transaction. + */ + fun <A> Events<A>.holdStateDeferred(initialValue: DeferredValue<A>): State<A> + + /** + * Returns a [State] holding a [Map] that is updated incrementally whenever this emits a value. + * + * The value emitted is used as a "patch" for the tracked [Map]; for each key [K] in the emitted + * map, an associated value of [Just] will insert or replace the value in the tracked [Map], and + * an associated value of [none] will remove the key from the tracked [Map]. + */ + fun <K, V> Events<Map<K, Maybe<V>>>.foldStateMapIncrementally( + initialValues: DeferredValue<Map<K, V>> + ): Incremental<K, V> + + // TODO: everything below this comment can be made into extensions once we have context params + + /** + * Returns an [Events] that emits from a merged, incrementally-accumulated collection of + * [Events] emitted from this, following the same "patch" rules as outlined in + * [foldStateMapIncrementally]. + * + * Conceptually this is equivalent to: + * ```kotlin + * fun <K, V> Events<Map<K, Maybe<Events<V>>>>.mergeIncrementally( + * initialEvents: Map<K, Events<V>>, + * ): Events<Map<K, V>> = + * foldMapIncrementally(initialEvents).map { it.merge() }.switchEvents() + * ``` + * + * While the behavior is equivalent to the conceptual definition above, the implementation is + * significantly more efficient. + * + * @see merge + */ + fun <K, V> Events<Map<K, Maybe<Events<V>>>>.mergeIncrementally( + name: String? = null, + initialEvents: DeferredValue<Map<K, Events<V>>>, + ): Events<Map<K, V>> = foldStateMapIncrementally(initialEvents).mergeEventsIncrementally() + + /** + * Returns an [Events] that emits from a merged, incrementally-accumulated collection of + * [Events] emitted from this, following the same "patch" rules as outlined in + * [foldStateMapIncrementally]. + * + * Conceptually this is equivalent to: + * ```kotlin + * fun <K, V> Events<Map<K, Maybe<Events<V>>>>.mergeIncrementallyPromptly( + * initialEvents: Map<K, Events<V>>, + * ): Events<Map<K, V>> = + * foldMapIncrementally(initialEvents).map { it.merge() }.switchEventsPromptly() + * ``` + * + * While the behavior is equivalent to the conceptual definition above, the implementation is + * significantly more efficient. + * + * @see merge + */ + fun <K, V> Events<Map<K, Maybe<Events<V>>>>.mergeIncrementallyPromptly( + initialEvents: DeferredValue<Map<K, Events<V>>>, + name: String? = null, + ): Events<Map<K, V>> = + foldStateMapIncrementally(initialEvents).mergeEventsIncrementallyPromptly() + + /** + * Returns an [Events] that emits from a merged, incrementally-accumulated collection of + * [Events] emitted from this, following the same "patch" rules as outlined in + * [foldStateMapIncrementally]. + * + * Conceptually this is equivalent to: + * ```kotlin + * fun <K, V> Events<Map<K, Maybe<Events<V>>>>.mergeIncrementally( + * initialEvents: Map<K, Events<V>>, + * ): Events<Map<K, V>> = + * foldMapIncrementally(initialEvents).map { it.merge() }.switchEvents() + * ``` + * + * While the behavior is equivalent to the conceptual definition above, the implementation is + * significantly more efficient. + * + * @see merge + */ + fun <K, V> Events<Map<K, Maybe<Events<V>>>>.mergeIncrementally( + name: String? = null, + initialEvents: Map<K, Events<V>> = emptyMap(), + ): Events<Map<K, V>> = mergeIncrementally(name, deferredOf(initialEvents)) + + /** + * Returns an [Events] that emits from a merged, incrementally-accumulated collection of + * [Events] emitted from this, following the same "patch" rules as outlined in + * [foldStateMapIncrementally]. + * + * Conceptually this is equivalent to: + * ```kotlin + * fun <K, V> Events<Map<K, Maybe<Events<V>>>>.mergeIncrementallyPromptly( + * initialEvents: Map<K, Events<V>>, + * ): Events<Map<K, V>> = + * foldMapIncrementally(initialEvents).map { it.merge() }.switchEventsPromptly() + * ``` + * + * While the behavior is equivalent to the conceptual definition above, the implementation is + * significantly more efficient. + * + * @see merge + */ + fun <K, V> Events<Map<K, Maybe<Events<V>>>>.mergeIncrementallyPromptly( + initialEvents: Map<K, Events<V>> = emptyMap(), + name: String? = null, + ): Events<Map<K, V>> = mergeIncrementallyPromptly(deferredOf(initialEvents), name) + + /** Applies the [Stateful] within this [StateScope]. */ + fun <A> Stateful<A>.applyStateful(): A = this() + + /** + * Applies the [Stateful] within this [StateScope], returning the result as an [DeferredValue]. + */ + fun <A> Stateful<A>.applyStatefulDeferred(): DeferredValue<A> = deferredStateScope { + applyStateful() + } + + /** + * Returns a [State] that holds onto the most recently emitted value from this [Events], or + * [initialValue] if nothing has been emitted since it was constructed. + * + * Note that the value contained within the [State] is not updated until *after* all [Events] + * have been processed; this keeps the value of the [State] consistent during the entire Kairos + * transaction. + */ + fun <A> Events<A>.holdState(initialValue: A): State<A> = + holdStateDeferred(deferredOf(initialValue)) + + /** + * Returns an [Events] the emits the result of applying [Statefuls][Stateful] emitted from the + * original [Events]. + * + * Unlike [applyLatestStateful], state accumulation is not stopped with each subsequent emission + * of the original [Events]. + */ + fun <A> Events<Stateful<A>>.applyStatefuls(): Events<A> + + /** + * Returns an [Events] containing the results of applying [transform] to each value of the + * original [Events]. + * + * [transform] can perform state accumulation via its [StateScope] receiver. Unlike + * [mapLatestStateful], accumulation is not stopped with each subsequent emission of the + * original [Events]. + */ + fun <A, B> Events<A>.mapStateful(transform: StateScope.(A) -> B): Events<B> = + map { statefully { transform(it) } }.applyStatefuls() + + /** + * Returns a [State] the holds the result of applying the [Stateful] held by the original + * [State]. + * + * Unlike [applyLatestStateful], state accumulation is not stopped with each state change. + */ + fun <A> State<Stateful<A>>.applyStatefuls(): State<A> = + changes + .applyStatefuls() + .holdStateDeferred(initialValue = deferredStateScope { sampleDeferred().get()() }) + + /** Returns an [Events] that switches to the [Events] emitted by the original [Events]. */ + fun <A> Events<Events<A>>.flatten() = holdState(emptyEvents).switchEvents() + + /** + * Returns an [Events] containing the results of applying [transform] to each value of the + * original [Events]. + * + * [transform] can perform state accumulation via its [StateScope] receiver. With each + * invocation of [transform], state accumulation from previous invocation is stopped. + */ + fun <A, B> Events<A>.mapLatestStateful(transform: StateScope.(A) -> B): Events<B> = + map { statefully { transform(it) } }.applyLatestStateful() + + /** + * Returns an [Events] that switches to a new [Events] produced by [transform] every time the + * original [Events] emits a value. + * + * [transform] can perform state accumulation via its [StateScope] receiver. With each + * invocation of [transform], state accumulation from previous invocation is stopped. + */ + fun <A, B> Events<A>.flatMapLatestStateful(transform: StateScope.(A) -> Events<B>): Events<B> = + mapLatestStateful(transform).flatten() + + /** + * Returns an [Events] containing the results of applying each [Stateful] emitted from the + * original [Events]. + * + * When each [Stateful] is applied, state accumulation from the previously-active [Stateful] is + * stopped. + */ + fun <A> Events<Stateful<A>>.applyLatestStateful(): Events<A> = applyLatestStateful {}.first + + /** + * Returns a [State] containing the value returned by applying the [Stateful] held by the + * original [State]. + * + * When each [Stateful] is applied, state accumulation from the previously-active [Stateful] is + * stopped. + */ + fun <A> State<Stateful<A>>.applyLatestStateful(): State<A> { + val (changes, init) = changes.applyLatestStateful { sample()() } + return changes.holdStateDeferred(init) + } + + /** + * Returns an [Events] containing the results of applying each [Stateful] emitted from the + * original [Events], and a [DeferredValue] containing the result of applying [init] + * immediately. + * + * When each [Stateful] is applied, state accumulation from the previously-active [Stateful] is + * stopped. + */ + fun <A, B> Events<Stateful<B>>.applyLatestStateful( + init: Stateful<A> + ): Pair<Events<B>, DeferredValue<A>> { + val (events, result) = + mapCheap { spec -> mapOf(Unit to just(spec)) } + .applyLatestStatefulForKey(init = mapOf(Unit to init), numKeys = 1) + val outEvents: Events<B> = + events.mapMaybe { + checkNotNull(it[Unit]) { "applyLatest: expected result, but none present in: $it" } + } + val outInit: DeferredValue<A> = deferredTransactionScope { + val initResult: Map<Unit, A> = result.get() + check(Unit in initResult) { + "applyLatest: expected initial result, but none present in: $initResult" + } + @Suppress("UNCHECKED_CAST") + initResult.getOrDefault(Unit) { null } as A + } + return Pair(outEvents, outInit) + } + + /** + * Returns an [Events] containing the results of applying each [Stateful] emitted from the + * original [Events], and a [DeferredValue] containing the result of applying [init] + * immediately. + * + * If the [Maybe] contained within the value for an associated key is [none], then the + * previously-active [Stateful] will be stopped with no replacement. + * + * When each [Stateful] is applied, state accumulation from the previously-active [Stateful] + * with the same key is stopped. + */ + fun <K, A, B> Events<Map<K, Maybe<Stateful<A>>>>.applyLatestStatefulForKey( + init: DeferredValue<Map<K, Stateful<B>>>, + numKeys: Int? = null, + ): Pair<Events<Map<K, Maybe<A>>>, DeferredValue<Map<K, B>>> + + /** + * Returns an [Events] containing the results of applying each [Stateful] emitted from the + * original [Events], and a [DeferredValue] containing the result of applying [init] + * immediately. + * + * When each [Stateful] is applied, state accumulation from the previously-active [Stateful] + * with the same key is stopped. + * + * If the [Maybe] contained within the value for an associated key is [none], then the + * previously-active [Stateful] will be stopped with no replacement. + */ + fun <K, A, B> Events<Map<K, Maybe<Stateful<A>>>>.applyLatestStatefulForKey( + init: Map<K, Stateful<B>>, + numKeys: Int? = null, + ): Pair<Events<Map<K, Maybe<A>>>, DeferredValue<Map<K, B>>> = + applyLatestStatefulForKey(deferredOf(init), numKeys) + + fun <K, V> Incremental<K, Stateful<V>>.applyLatestStatefulForKey( + numKeys: Int? = null + ): Incremental<K, V> { + val (events, init) = updates.applyLatestStatefulForKey(sampleDeferred()) + return events.foldStateMapIncrementally(init) + } + + /** + * Returns a [State] containing the latest results of applying each [Stateful] emitted from the + * original [Events]. + * + * When each [Stateful] is applied, state accumulation from the previously-active [Stateful] + * with the same key is stopped. + * + * If the [Maybe] contained within the value for an associated key is [none], then the + * previously-active [Stateful] will be stopped with no replacement. + */ + fun <K, A> Events<Map<K, Maybe<Stateful<A>>>>.holdLatestStatefulForKey( + init: DeferredValue<Map<K, Stateful<A>>>, + numKeys: Int? = null, + ): Incremental<K, A> { + val (changes, initialValues) = applyLatestStatefulForKey(init, numKeys) + return changes.foldStateMapIncrementally(initialValues) + } + + /** + * Returns a [State] containing the latest results of applying each [Stateful] emitted from the + * original [Events]. + * + * When each [Stateful] is applied, state accumulation from the previously-active [Stateful] + * with the same key is stopped. + * + * If the [Maybe] contained within the value for an associated key is [none], then the + * previously-active [Stateful] will be stopped with no replacement. + */ + fun <K, A> Events<Map<K, Maybe<Stateful<A>>>>.holdLatestStatefulForKey( + init: Map<K, Stateful<A>> = emptyMap(), + numKeys: Int? = null, + ): Incremental<K, A> = holdLatestStatefulForKey(deferredOf(init), numKeys) + + /** + * Returns an [Events] containing the results of applying each [Stateful] emitted from the + * original [Events], and a [DeferredValue] containing the result of applying [stateInit] + * immediately. + * + * When each [Stateful] is applied, state accumulation from the previously-active [Stateful] + * with the same key is stopped. + * + * If the [Maybe] contained within the value for an associated key is [none], then the + * previously-active [Stateful] will be stopped with no replacement. + */ + fun <K, A> Events<Map<K, Maybe<Stateful<A>>>>.applyLatestStatefulForKey( + numKeys: Int? = null + ): Events<Map<K, Maybe<A>>> = + applyLatestStatefulForKey(init = emptyMap<K, Stateful<*>>(), numKeys = numKeys).first + + /** + * Returns an [Events] containing the results of applying [transform] to each value of the + * original [Events], and a [DeferredValue] containing the result of applying [transform] to + * [initialValues] immediately. + * + * [transform] can perform state accumulation via its [StateScope] receiver. With each + * invocation of [transform], state accumulation from previous invocation is stopped. + * + * If the [Maybe] contained within the value for an associated key is [none], then the + * previously-active [StateScope] will be stopped with no replacement. + */ + fun <K, A, B> Events<Map<K, Maybe<A>>>.mapLatestStatefulForKey( + initialValues: DeferredValue<Map<K, A>>, + numKeys: Int? = null, + transform: StateScope.(A) -> B, + ): Pair<Events<Map<K, Maybe<B>>>, DeferredValue<Map<K, B>>> = + map { patch -> patch.mapValues { (_, v) -> v.map { statefully { transform(it) } } } } + .applyLatestStatefulForKey( + deferredStateScope { + initialValues.get().mapValues { (_, v) -> statefully { transform(v) } } + }, + numKeys = numKeys, + ) + + /** + * Returns an [Events] containing the results of applying [transform] to each value of the + * original [Events], and a [DeferredValue] containing the result of applying [transform] to + * [initialValues] immediately. + * + * [transform] can perform state accumulation via its [StateScope] receiver. With each + * invocation of [transform], state accumulation from previous invocation is stopped. + * + * If the [Maybe] contained within the value for an associated key is [none], then the + * previously-active [StateScope] will be stopped with no replacement. + */ + fun <K, A, B> Events<Map<K, Maybe<A>>>.mapLatestStatefulForKey( + initialValues: Map<K, A>, + numKeys: Int? = null, + transform: StateScope.(A) -> B, + ): Pair<Events<Map<K, Maybe<B>>>, DeferredValue<Map<K, B>>> = + mapLatestStatefulForKey(deferredOf(initialValues), numKeys, transform) + + /** + * Returns an [Events] containing the results of applying [transform] to each value of the + * original [Events]. + * + * [transform] can perform state accumulation via its [StateScope] receiver. With each + * invocation of [transform], state accumulation from previous invocation is stopped. + * + * If the [Maybe] contained within the value for an associated key is [none], then the + * previously-active [StateScope] will be stopped with no replacement. + */ + fun <K, A, B> Events<Map<K, Maybe<A>>>.mapLatestStatefulForKey( + numKeys: Int? = null, + transform: StateScope.(A) -> B, + ): Events<Map<K, Maybe<B>>> = mapLatestStatefulForKey(emptyMap(), numKeys, transform).first + + /** + * Returns an [Events] that will only emit the next event of the original [Events], and then + * will act as [emptyEvents]. + * + * If the original [Events] is emitting an event at this exact time, then it will be the only + * even emitted from the result [Events]. + */ + fun <A> Events<A>.nextOnly(name: String? = null): Events<A> = + if (this === emptyEvents) { + this + } else { + EventsLoop<A>().also { + it.loopback = + it.mapCheap { emptyEvents }.holdState(this@nextOnly).switchEvents(name) + } + } + + /** Returns an [Events] that skips the next emission of the original [Events]. */ + fun <A> Events<A>.skipNext(): Events<A> = + if (this === emptyEvents) { + this + } else { + nextOnly().mapCheap { this@skipNext }.holdState(emptyEvents).switchEvents() + } + + /** + * Returns an [Events] that emits values from the original [Events] up until [stop] emits a + * value. + * + * If the original [Events] emits at the same time as [stop], then the returned [Events] will + * emit that value. + */ + fun <A> Events<A>.takeUntil(stop: Events<*>): Events<A> = + if (stop === emptyEvents) { + this + } else { + stop.mapCheap { emptyEvents }.nextOnly().holdState(this).switchEvents() + } + + /** + * Invokes [stateful] in a new [StateScope] that is a child of this one. + * + * This new scope is stopped when [stop] first emits a value, or when the parent scope is + * stopped. Stopping will end all state accumulation; any [States][State] returned from this + * scope will no longer update. + */ + fun <A> childStateScope(stop: Events<*>, stateful: Stateful<A>): DeferredValue<A> { + val (_, init: DeferredValue<Map<Unit, A>>) = + stop + .nextOnly() + .map { mapOf(Unit to none<Stateful<A>>()) } + .applyLatestStatefulForKey(init = mapOf(Unit to stateful), numKeys = 1) + return deferredStateScope { init.get().getValue(Unit) } + } + + /** + * Returns an [Events] that emits values from the original [Events] up to and including a value + * is emitted that satisfies [predicate]. + */ + fun <A> Events<A>.takeUntil(predicate: TransactionScope.(A) -> Boolean): Events<A> = + takeUntil(filter(predicate)) + + /** + * Returns a [State] that is incrementally updated when this [Events] emits a value, by applying + * [transform] to both the emitted value and the currently tracked state. + * + * Note that the value contained within the [State] is not updated until *after* all [Events] + * have been processed; this keeps the value of the [State] consistent during the entire Kairos + * transaction. + */ + fun <A, B> Events<A>.foldState( + initialValue: B, + transform: TransactionScope.(A, B) -> B, + ): State<B> { + lateinit var state: State<B> + return map { a -> transform(a, state.sample()) }.holdState(initialValue).also { state = it } + } + + /** + * Returns a [State] that is incrementally updated when this [Events] emits a value, by applying + * [transform] to both the emitted value and the currently tracked state. + * + * Note that the value contained within the [State] is not updated until *after* all [Events] + * have been processed; this keeps the value of the [State] consistent during the entire Kairos + * transaction. + */ + fun <A, B> Events<A>.foldStateDeferred( + initialValue: DeferredValue<B>, + transform: TransactionScope.(A, B) -> B, + ): State<B> { + lateinit var state: State<B> + return map { a -> transform(a, state.sample()) } + .holdStateDeferred(initialValue) + .also { state = it } + } + + /** + * Returns a [State] that holds onto the result of applying the most recently emitted [Stateful] + * this [Events], or [init] if nothing has been emitted since it was constructed. + * + * When each [Stateful] is applied, state accumulation from the previously-active [Stateful] is + * stopped. + * + * Note that the value contained within the [State] is not updated until *after* all [Events] + * have been processed; this keeps the value of the [State] consistent during the entire Kairos + * transaction. + * + * Shorthand for: + * ```kotlin + * val (changes, initApplied) = applyLatestStateful(init) + * return changes.holdStateDeferred(initApplied) + * ``` + */ + fun <A> Events<Stateful<A>>.holdLatestStateful(init: Stateful<A>): State<A> { + val (changes, initApplied) = applyLatestStateful(init) + return changes.holdStateDeferred(initApplied) + } + + /** + * Returns an [Events] that emits the two most recent emissions from the original [Events]. + * [initialValue] is used as the previous value for the first emission. + * + * Shorthand for `sample(hold(init)) { new, old -> Pair(old, new) }` + */ + fun <S, T : S> Events<T>.pairwise(initialValue: S): Events<WithPrev<S, T>> { + val previous = holdState(initialValue) + return mapCheap { new -> WithPrev(previousValue = previous.sample(), newValue = new) } + } + + /** + * Returns an [Events] that emits the two most recent emissions from the original [Events]. Note + * that the returned [Events] will not emit until the original [Events] has emitted twice. + */ + fun <A> Events<A>.pairwise(): Events<WithPrev<A, A>> = + mapCheap { just(it) } + .pairwise(none) + .mapMaybe { (prev, next) -> prev.zipWith(next, ::WithPrev) } + + /** + * Returns a [State] that holds both the current and previous values of the original [State]. + * [initialPreviousValue] is used as the first previous value. + * + * Shorthand for `sample(hold(init)) { new, old -> Pair(old, new) }` + */ + fun <S, T : S> State<T>.pairwise(initialPreviousValue: S): State<WithPrev<S, T>> = + changes + .pairwise(initialPreviousValue) + .holdStateDeferred( + deferredTransactionScope { WithPrev(initialPreviousValue, sample()) } + ) + + /** + * Returns a [State] holding a [Map] that is updated incrementally whenever this emits a value. + * + * The value emitted is used as a "patch" for the tracked [Map]; for each key [K] in the emitted + * map, an associated value of [Just] will insert or replace the value in the tracked [Map], and + * an associated value of [none] will remove the key from the tracked [Map]. + */ + fun <K, V> Events<Map<K, Maybe<V>>>.foldStateMapIncrementally( + initialValues: Map<K, V> = emptyMap() + ): Incremental<K, V> = foldStateMapIncrementally(deferredOf(initialValues)) + + /** + * Returns an [Events] that wraps each emission of the original [Events] into an [IndexedValue], + * containing the emitted value and its index (starting from zero). + * + * Shorthand for: + * ``` + * val index = fold(0) { _, oldIdx -> oldIdx + 1 } + * sample(index) { a, idx -> IndexedValue(idx, a) } + * ``` + */ + fun <A> Events<A>.withIndex(): Events<IndexedValue<A>> { + val index = foldState(0) { _, old -> old + 1 } + return sample(index) { a, idx -> IndexedValue(idx, a) } + } + + /** + * Returns an [Events] containing the results of applying [transform] to each value of the + * original [Events] and its index (starting from zero). + * + * Shorthand for: + * ``` + * withIndex().map { (idx, a) -> transform(idx, a) } + * ``` + */ + fun <A, B> Events<A>.mapIndexed(transform: TransactionScope.(Int, A) -> B): Events<B> { + val index = foldState(0) { _, i -> i + 1 } + return sample(index) { a, idx -> transform(idx, a) } + } + + /** Returns an [Events] where all subsequent repetitions of the same value are filtered out. */ + fun <A> Events<A>.distinctUntilChanged(): Events<A> { + val state: State<Any?> = holdState(Any()) + return filter { it != state.sample() } + } + + /** + * Returns a new [Events] that emits at the same rate as the original [Events], but combines the + * emitted value with the most recent emission from [other] using [transform]. + * + * Note that the returned [Events] will not emit anything until [other] has emitted at least one + * value. + */ + fun <A, B, C> Events<A>.sample( + other: Events<B>, + transform: TransactionScope.(A, B) -> C, + ): Events<C> { + val state = other.mapCheap { just(it) }.holdState(none) + return sample(state) { a, b -> b.map { transform(a, it) } }.filterJust() + } + + /** + * Returns a [State] that samples the [Transactional] held by the given [State] within the same + * transaction that the state changes. + */ + fun <A> State<Transactional<A>>.sampleTransactionals(): State<A> = + changes + .sampleTransactionals() + .holdStateDeferred(deferredTransactionScope { sample().sample() }) + + /** + * Returns a [State] that transforms the value held inside this [State] by applying it to the + * given function [transform]. + */ + fun <A, B> State<A>.mapTransactionally(transform: TransactionScope.(A) -> B): State<B> = + map { transactionally { transform(it) } }.sampleTransactionals() + + /** + * Returns a [State] whose value is generated with [transform] by combining the current values + * of each given [State]. + * + * @see State.combineWithTransactionally + */ + fun <A, B, Z> combineTransactionally( + stateA: State<A>, + stateB: State<B>, + transform: TransactionScope.(A, B) -> Z, + ): State<Z> = + combine(stateA, stateB) { a, b -> transactionally { transform(a, b) } } + .sampleTransactionals() + + /** + * Returns a [State] whose value is generated with [transform] by combining the current values + * of each given [State]. + * + * @see State.combineWithTransactionally + */ + fun <A, B, C, Z> combineTransactionally( + stateA: State<A>, + stateB: State<B>, + stateC: State<C>, + transform: TransactionScope.(A, B, C) -> Z, + ): State<Z> = + combine(stateA, stateB, stateC) { a, b, c -> transactionally { transform(a, b, c) } } + .sampleTransactionals() + + /** + * Returns a [State] whose value is generated with [transform] by combining the current values + * of each given [State]. + * + * @see State.combineWithTransactionally + */ + fun <A, B, C, D, Z> combineTransactionally( + stateA: State<A>, + stateB: State<B>, + stateC: State<C>, + stateD: State<D>, + transform: TransactionScope.(A, B, C, D) -> Z, + ): State<Z> = + combine(stateA, stateB, stateC, stateD) { a, b, c, d -> + transactionally { transform(a, b, c, d) } + } + .sampleTransactionals() + + /** Returns a [State] by applying [transform] to the value held by the original [State]. */ + fun <A, B> State<A>.flatMapTransactionally( + transform: TransactionScope.(A) -> State<B> + ): State<B> = map { transactionally { transform(it) } }.sampleTransactionals().flatten() + + /** + * Returns a [State] whose value is generated with [transform] by combining the current values + * of each given [State]. + * + * @see State.combineWithTransactionally + */ + fun <A, Z> combineTransactionally( + vararg states: State<A>, + transform: TransactionScope.(List<A>) -> Z, + ): State<Z> = combine(*states).mapTransactionally(transform) + + /** + * Returns a [State] whose value is generated with [transform] by combining the current values + * of each given [State]. + * + * @see State.combineWithTransactionally + */ + fun <A, Z> Iterable<State<A>>.combineTransactionally( + transform: TransactionScope.(List<A>) -> Z + ): State<Z> = combine().mapTransactionally(transform) + + /** + * Returns a [State] by combining the values held inside the given [State]s by applying them to + * the given function [transform]. + */ + fun <A, B, C> State<A>.combineWithTransactionally( + other: State<B>, + transform: TransactionScope.(A, B) -> C, + ): State<C> = combineTransactionally(this, other, transform) + + /** + * Returns an [Incremental] that reflects the state of the original [Incremental], but also adds + * / removes entries based on the state of the original's values. + */ + fun <K, V> Incremental<K, State<Maybe<V>>>.applyStateIncrementally(): Incremental<K, V> = + mapValues { (_, v) -> v.changes } + .mergeEventsIncrementallyPromptly() + .foldStateMapIncrementally( + deferredStateScope { sample().mapMaybeValues { (_, s) -> s.sample() } } + ) + + /** + * Returns an [Incremental] that reflects the state of the original [Incremental], but also adds + * / removes entries based on the [State] returned from applying [transform] to the original's + * entries. + */ + fun <K, V, U> Incremental<K, V>.mapIncrementalState( + transform: KairosScope.(Map.Entry<K, V>) -> State<Maybe<U>> + ): Incremental<K, U> = mapValues { transform(it) }.applyStateIncrementally() + + /** + * Returns an [Incremental] that reflects the state of the original [Incremental], but also adds + * / removes entries based on the [State] returned from applying [transform] to the original's + * entries, such that entries are added when that state is `true`, and removed when `false`. + */ + fun <K, V> Incremental<K, V>.filterIncrementally( + transform: KairosScope.(Map.Entry<K, V>) -> State<Boolean> + ): Incremental<K, V> = mapIncrementalState { entry -> + transform(entry).map { if (it) just(entry.value) else none } + } + + /** + * Returns an [Incremental] that samples the [Transactionals][Transactional] held by the + * original within the same transaction that the incremental [updates]. + */ + fun <K, V> Incremental<K, Transactional<V>>.sampleTransactionals(): Incremental<K, V> = + updates + .map { patch -> patch.mapValues { (k, mv) -> mv.map { it.sample() } } } + .foldStateMapIncrementally( + deferredStateScope { sample().mapValues { (k, v) -> v.sample() } } + ) + + /** + * Returns an [Incremental] that tracks the entries of the original incremental, but values + * replaced with those obtained by applying [transform] to each original entry. + */ + fun <K, V, U> Incremental<K, V>.mapValuesTransactionally( + transform: TransactionScope.(Map.Entry<K, V>) -> U + ): Incremental<K, U> = mapValues { transactionally { transform(it) } }.sampleTransactionals() +} diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/TFlow.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/TFlow.kt deleted file mode 100644 index a175e2e20e46..000000000000 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/TFlow.kt +++ /dev/null @@ -1,560 +0,0 @@ -/* - * 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.kairos - -import com.android.systemui.kairos.internal.DemuxImpl -import com.android.systemui.kairos.internal.Init -import com.android.systemui.kairos.internal.InitScope -import com.android.systemui.kairos.internal.InputNode -import com.android.systemui.kairos.internal.Network -import com.android.systemui.kairos.internal.NoScope -import com.android.systemui.kairos.internal.TFlowImpl -import com.android.systemui.kairos.internal.activated -import com.android.systemui.kairos.internal.cached -import com.android.systemui.kairos.internal.constInit -import com.android.systemui.kairos.internal.filterNode -import com.android.systemui.kairos.internal.init -import com.android.systemui.kairos.internal.map -import com.android.systemui.kairos.internal.mapImpl -import com.android.systemui.kairos.internal.mapMaybeNode -import com.android.systemui.kairos.internal.mergeNodes -import com.android.systemui.kairos.internal.mergeNodesLeft -import com.android.systemui.kairos.internal.neverImpl -import com.android.systemui.kairos.internal.switchDeferredImplSingle -import com.android.systemui.kairos.internal.switchPromptImpl -import com.android.systemui.kairos.internal.util.hashString -import com.android.systemui.kairos.util.Either -import com.android.systemui.kairos.util.Left -import com.android.systemui.kairos.util.Maybe -import com.android.systemui.kairos.util.Right -import com.android.systemui.kairos.util.just -import com.android.systemui.kairos.util.map -import com.android.systemui.kairos.util.toMaybe -import java.util.concurrent.atomic.AtomicReference -import kotlin.reflect.KProperty -import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.CoroutineStart -import kotlinx.coroutines.Job -import kotlinx.coroutines.async -import kotlinx.coroutines.coroutineScope - -/** A series of values of type [A] available at discrete points in time. */ -@ExperimentalFrpApi -sealed class TFlow<out A> { - companion object { - /** A [TFlow] with no values. */ - val empty: TFlow<Nothing> = EmptyFlow - } -} - -/** A [TFlow] with no values. */ -@ExperimentalFrpApi val emptyTFlow: TFlow<Nothing> = TFlow.empty - -/** - * A forward-reference to a [TFlow]. Useful for recursive definitions. - * - * This reference can be used like a standard [TFlow], but will hold up evaluation of the FRP - * network until the [loopback] reference is set. - */ -@ExperimentalFrpApi -class TFlowLoop<A> : TFlow<A>() { - private val deferred = CompletableDeferred<TFlow<A>>() - - internal val init: Init<TFlowImpl<A>> = - init(name = null) { deferred.await().init.connect(evalScope = this) } - - /** The [TFlow] this reference is referring to. */ - @ExperimentalFrpApi - var loopback: TFlow<A>? = null - set(value) { - value?.let { - check(deferred.complete(value)) { "TFlowLoop.loopback has already been set." } - field = value - } - } - - operator fun getValue(thisRef: Any?, property: KProperty<*>): TFlow<A> = this - - operator fun setValue(thisRef: Any?, property: KProperty<*>, value: TFlow<A>) { - loopback = value - } - - override fun toString(): String = "${this::class.simpleName}@$hashString" -} - -/** TODO */ -@ExperimentalFrpApi fun <A> Lazy<TFlow<A>>.defer(): TFlow<A> = deferInline { value } - -/** TODO */ -@ExperimentalFrpApi -fun <A> FrpDeferredValue<TFlow<A>>.defer(): TFlow<A> = deferInline { unwrapped.await() } - -/** TODO */ -@ExperimentalFrpApi -fun <A> deferTFlow(block: suspend FrpScope.() -> TFlow<A>): TFlow<A> = deferInline { - NoScope.runInFrpScope(block) -} - -/** Returns a [TFlow] that emits the new value of this [TState] when it changes. */ -@ExperimentalFrpApi -val <A> TState<A>.stateChanges: TFlow<A> - get() = TFlowInit(init(name = null) { init.connect(evalScope = this).changes }) - -/** - * Returns a [TFlow] that contains only the [just] results of applying [transform] to each value of - * the original [TFlow]. - * - * @see mapNotNull - */ -@ExperimentalFrpApi -fun <A, B> TFlow<A>.mapMaybe(transform: suspend FrpTransactionScope.(A) -> Maybe<B>): TFlow<B> { - val pulse = - mapMaybeNode({ init.connect(evalScope = this) }) { runInTransactionScope { transform(it) } } - return TFlowInit(constInit(name = null, pulse)) -} - -/** - * Returns a [TFlow] that contains only the non-null results of applying [transform] to each value - * of the original [TFlow]. - * - * @see mapMaybe - */ -@ExperimentalFrpApi -fun <A, B> TFlow<A>.mapNotNull(transform: suspend FrpTransactionScope.(A) -> B?): TFlow<B> = - mapMaybe { - transform(it).toMaybe() - } - -/** Returns a [TFlow] containing only values of the original [TFlow] that are not null. */ -@ExperimentalFrpApi fun <A> TFlow<A?>.filterNotNull(): TFlow<A> = mapNotNull { it } - -/** Shorthand for `mapNotNull { it as? A }`. */ -@ExperimentalFrpApi -inline fun <reified A> TFlow<*>.filterIsInstance(): TFlow<A> = mapNotNull { it as? A } - -/** Shorthand for `mapMaybe { it }`. */ -@ExperimentalFrpApi fun <A> TFlow<Maybe<A>>.filterJust(): TFlow<A> = mapMaybe { it } - -/** - * Returns a [TFlow] containing the results of applying [transform] to each value of the original - * [TFlow]. - */ -@ExperimentalFrpApi -fun <A, B> TFlow<A>.map(transform: suspend FrpTransactionScope.(A) -> B): TFlow<B> { - val mapped: TFlowImpl<B> = - mapImpl({ init.connect(evalScope = this) }) { a -> runInTransactionScope { transform(a) } } - return TFlowInit(constInit(name = null, mapped.cached())) -} - -/** - * Like [map], but the emission is not cached during the transaction. Use only if [transform] is - * fast and pure. - * - * @see map - */ -@ExperimentalFrpApi -fun <A, B> TFlow<A>.mapCheap(transform: suspend FrpTransactionScope.(A) -> B): TFlow<B> = - TFlowInit( - constInit( - name = null, - mapImpl({ init.connect(evalScope = this) }) { a -> - runInTransactionScope { transform(a) } - }, - ) - ) - -/** - * Returns a [TFlow] that invokes [action] before each value of the original [TFlow] is emitted. - * Useful for logging and debugging. - * - * ``` - * pulse.onEach { foo(it) } == pulse.map { foo(it); it } - * ``` - * - * Note that the side effects performed in [onEach] are only performed while the resulting [TFlow] - * is connected to an output of the FRP network. If your goal is to reliably perform side effects in - * response to a [TFlow], use the output combinators available in [FrpBuildScope], such as - * [FrpBuildScope.toSharedFlow] or [FrpBuildScope.observe]. - */ -@ExperimentalFrpApi -fun <A> TFlow<A>.onEach(action: suspend FrpTransactionScope.(A) -> Unit): TFlow<A> = map { - action(it) - it -} - -/** - * Returns a [TFlow] containing only values of the original [TFlow] that satisfy the given - * [predicate]. - */ -@ExperimentalFrpApi -fun <A> TFlow<A>.filter(predicate: suspend FrpTransactionScope.(A) -> Boolean): TFlow<A> { - val pulse = - filterNode({ init.connect(evalScope = this) }) { runInTransactionScope { predicate(it) } } - return TFlowInit(constInit(name = null, pulse.cached())) -} - -/** - * Splits a [TFlow] of pairs into a pair of [TFlows][TFlow], where each returned [TFlow] emits half - * of the original. - * - * Shorthand for: - * ```kotlin - * val lefts = map { it.first } - * val rights = map { it.second } - * return Pair(lefts, rights) - * ``` - */ -@ExperimentalFrpApi -fun <A, B> TFlow<Pair<A, B>>.unzip(): Pair<TFlow<A>, TFlow<B>> { - val lefts = map { it.first } - val rights = map { it.second } - return lefts to rights -} - -/** - * Merges the given [TFlows][TFlow] into a single [TFlow] that emits events from both. - * - * Because [TFlow]s can only emit one value per transaction, the provided [transformCoincidence] - * function is used to combine coincident emissions to produce the result value to be emitted by the - * merged [TFlow]. - */ -@ExperimentalFrpApi -fun <A> TFlow<A>.mergeWith( - other: TFlow<A>, - transformCoincidence: suspend FrpTransactionScope.(A, A) -> A = { a, _ -> a }, -): TFlow<A> { - val node = - mergeNodes( - getPulse = { init.connect(evalScope = this) }, - getOther = { other.init.connect(evalScope = this) }, - ) { a, b -> - runInTransactionScope { transformCoincidence(a, b) } - } - return TFlowInit(constInit(name = null, node)) -} - -/** - * Merges the given [TFlows][TFlow] into a single [TFlow] that emits events from all. All coincident - * emissions are collected into the emitted [List], preserving the input ordering. - * - * @see mergeWith - * @see mergeLeft - */ -@ExperimentalFrpApi -fun <A> merge(vararg flows: TFlow<A>): TFlow<List<A>> = flows.asIterable().merge() - -/** - * Merges the given [TFlows][TFlow] into a single [TFlow] that emits events from all. In the case of - * coincident emissions, the emission from the left-most [TFlow] is emitted. - * - * @see merge - */ -@ExperimentalFrpApi -fun <A> mergeLeft(vararg flows: TFlow<A>): TFlow<A> = flows.asIterable().mergeLeft() - -/** - * Merges the given [TFlows][TFlow] into a single [TFlow] that emits events from all. - * - * Because [TFlow]s can only emit one value per transaction, the provided [transformCoincidence] - * function is used to combine coincident emissions to produce the result value to be emitted by the - * merged [TFlow]. - */ -// TODO: can be optimized to avoid creating the intermediate list -fun <A> merge(vararg flows: TFlow<A>, transformCoincidence: (A, A) -> A): TFlow<A> = - merge(*flows).map { l -> l.reduce(transformCoincidence) } - -/** - * Merges the given [TFlows][TFlow] into a single [TFlow] that emits events from all. All coincident - * emissions are collected into the emitted [List], preserving the input ordering. - * - * @see mergeWith - * @see mergeLeft - */ -@ExperimentalFrpApi -fun <A> Iterable<TFlow<A>>.merge(): TFlow<List<A>> = - TFlowInit(constInit(name = null, mergeNodes { map { it.init.connect(evalScope = this) } })) - -/** - * Merges the given [TFlows][TFlow] into a single [TFlow] that emits events from all. In the case of - * coincident emissions, the emission from the left-most [TFlow] is emitted. - * - * @see merge - */ -@ExperimentalFrpApi -fun <A> Iterable<TFlow<A>>.mergeLeft(): TFlow<A> = - TFlowInit(constInit(name = null, mergeNodesLeft { map { it.init.connect(evalScope = this) } })) - -/** - * Creates a new [TFlow] that emits events from all given [TFlow]s. All simultaneous emissions are - * collected into the emitted [List], preserving the input ordering. - * - * @see mergeWith - */ -@ExperimentalFrpApi fun <A> Sequence<TFlow<A>>.merge(): TFlow<List<A>> = asIterable().merge() - -/** - * Creates a new [TFlow] that emits events from all given [TFlow]s. All simultaneous emissions are - * collected into the emitted [Map], and are given the same key of the associated [TFlow] in the - * input [Map]. - * - * @see mergeWith - */ -@ExperimentalFrpApi -fun <K, A> Map<K, TFlow<A>>.merge(): TFlow<Map<K, A>> = - asSequence().map { (k, flowA) -> flowA.map { a -> k to a } }.toList().merge().map { it.toMap() } - -/** - * Returns a [GroupedTFlow] that can be used to efficiently split a single [TFlow] into multiple - * downstream [TFlow]s. - * - * The input [TFlow] emits [Map] instances that specify which downstream [TFlow] the associated - * value will be emitted from. These downstream [TFlow]s can be obtained via - * [GroupedTFlow.eventsForKey]. - * - * An example: - * ``` - * val sFoo: TFlow<Map<String, Foo>> = ... - * val fooById: GroupedTFlow<String, Foo> = sFoo.groupByKey() - * val fooBar: TFlow<Foo> = fooById["bar"] - * ``` - * - * This is semantically equivalent to `val fooBar = sFoo.mapNotNull { map -> map["bar"] }` but is - * significantly more efficient; specifically, using [mapNotNull] in this way incurs a `O(n)` - * performance hit, where `n` is the number of different [mapNotNull] operations used to filter on a - * specific key's presence in the emitted [Map]. [groupByKey] internally uses a [HashMap] to lookup - * the appropriate downstream [TFlow], and so operates in `O(1)`. - * - * Note that the result [GroupedTFlow] should be cached and re-used to gain the performance benefit. - * - * @see selector - */ -@ExperimentalFrpApi -fun <K, A> TFlow<Map<K, A>>.groupByKey(numKeys: Int? = null): GroupedTFlow<K, A> = - GroupedTFlow(DemuxImpl({ init.connect(this) }, numKeys)) - -/** - * Shorthand for `map { mapOf(extractKey(it) to it) }.groupByKey()` - * - * @see groupByKey - */ -@ExperimentalFrpApi -fun <K, A> TFlow<A>.groupBy( - numKeys: Int? = null, - extractKey: suspend FrpTransactionScope.(A) -> K, -): GroupedTFlow<K, A> = map { mapOf(extractKey(it) to it) }.groupByKey(numKeys) - -/** - * Returns two new [TFlow]s that contain elements from this [TFlow] that satisfy or don't satisfy - * [predicate]. - * - * Using this is equivalent to `upstream.filter(predicate) to upstream.filter { !predicate(it) }` - * but is more efficient; specifically, [partition] will only invoke [predicate] once per element. - */ -@ExperimentalFrpApi -fun <A> TFlow<A>.partition( - predicate: suspend FrpTransactionScope.(A) -> Boolean -): Pair<TFlow<A>, TFlow<A>> { - val grouped: GroupedTFlow<Boolean, A> = groupBy(numKeys = 2, extractKey = predicate) - return Pair(grouped.eventsForKey(true), grouped.eventsForKey(false)) -} - -/** - * Returns two new [TFlow]s that contain elements from this [TFlow]; [Pair.first] will contain - * [Left] values, and [Pair.second] will contain [Right] values. - * - * Using this is equivalent to using [filterIsInstance] in conjunction with [map] twice, once for - * [Left]s and once for [Right]s, but is slightly more efficient; specifically, the - * [filterIsInstance] check is only performed once per element. - */ -@ExperimentalFrpApi -fun <A, B> TFlow<Either<A, B>>.partitionEither(): Pair<TFlow<A>, TFlow<B>> { - val (left, right) = partition { it is Left } - return Pair(left.mapCheap { (it as Left).value }, right.mapCheap { (it as Right).value }) -} - -/** - * A mapping from keys of type [K] to [TFlow]s emitting values of type [A]. - * - * @see groupByKey - */ -@ExperimentalFrpApi -class GroupedTFlow<in K, out A> internal constructor(internal val impl: DemuxImpl<K, A>) { - /** - * Returns a [TFlow] that emits values of type [A] that correspond to the given [key]. - * - * @see groupByKey - */ - @ExperimentalFrpApi - fun eventsForKey(key: K): TFlow<A> = TFlowInit(constInit(name = null, impl.eventsForKey(key))) - - /** - * Returns a [TFlow] that emits values of type [A] that correspond to the given [key]. - * - * @see groupByKey - */ - @ExperimentalFrpApi operator fun get(key: K): TFlow<A> = eventsForKey(key) -} - -/** - * Returns a [TFlow] that switches to the [TFlow] contained within this [TState] whenever it - * changes. - * - * This switch does take effect until the *next* transaction after [TState] changes. For a switch - * that takes effect immediately, see [switchPromptly]. - */ -@ExperimentalFrpApi -fun <A> TState<TFlow<A>>.switch(): TFlow<A> { - return TFlowInit( - constInit( - name = null, - switchDeferredImplSingle( - getStorage = { - init.connect(this).getCurrentWithEpoch(this).first.init.connect(this) - }, - getPatches = { - mapImpl({ init.connect(this).changes }) { newFlow -> - newFlow.init.connect(this) - } - }, - ), - ) - ) -} - -/** - * Returns a [TFlow] that switches to the [TFlow] contained within this [TState] whenever it - * changes. - * - * This switch takes effect immediately within the same transaction that [TState] changes. In - * general, you should prefer [switch] over this method. It is both safer and more performant. - */ -// TODO: parameter to handle coincidental emission from both old and new -@ExperimentalFrpApi -fun <A> TState<TFlow<A>>.switchPromptly(): TFlow<A> { - val switchNode = - switchPromptImpl( - getStorage = { - mapOf(Unit to init.connect(this).getCurrentWithEpoch(this).first.init.connect(this)) - }, - getPatches = { - val patches = init.connect(this).changes - mapImpl({ patches }) { newFlow -> mapOf(Unit to just(newFlow.init.connect(this))) } - }, - ) - return TFlowInit(constInit(name = null, mapImpl({ switchNode }) { it.getValue(Unit) })) -} - -/** - * A mutable [TFlow] that provides the ability to [emit] values to the flow, handling backpressure - * by coalescing all emissions into batches. - * - * @see FrpNetwork.coalescingMutableTFlow - */ -@ExperimentalFrpApi -class CoalescingMutableTFlow<In, Out> -internal constructor( - internal val name: String?, - internal val coalesce: (old: Out, new: In) -> Out, - internal val network: Network, - private val getInitialValue: () -> Out, - internal val impl: InputNode<Out> = InputNode(), -) : TFlow<Out>() { - internal val storage = AtomicReference(false to getInitialValue()) - - override fun toString(): String = "${this::class.simpleName}@$hashString" - - /** - * Inserts [value] into the current batch, enqueueing it for emission from this [TFlow] if not - * already pending. - * - * Backpressure occurs when [emit] is called while the FRP network is currently in a - * transaction; if called multiple times, then emissions will be coalesced into a single batch - * that is then processed when the network is ready. - */ - @ExperimentalFrpApi - fun emit(value: In) { - val (scheduled, _) = storage.getAndUpdate { (_, old) -> true to coalesce(old, value) } - if (!scheduled) { - @Suppress("DeferredResultUnused") - network.transaction("CoalescingMutableTFlow${name?.let { "($name)" }.orEmpty()}.emit") { - impl.visit(this, storage.getAndSet(false to getInitialValue()).second) - } - } - } -} - -/** - * A mutable [TFlow] that provides the ability to [emit] values to the flow, handling backpressure - * by suspending the emitter. - * - * @see FrpNetwork.coalescingMutableTFlow - */ -@ExperimentalFrpApi -class MutableTFlow<T> -internal constructor(internal val network: Network, internal val impl: InputNode<T> = InputNode()) : - TFlow<T>() { - internal val name: String? = null - - private val storage = AtomicReference<Job?>(null) - - override fun toString(): String = "${this::class.simpleName}@$hashString" - - /** - * Emits a [value] to this [TFlow], suspending the caller until the FRP transaction containing - * the emission has completed. - */ - @ExperimentalFrpApi - suspend fun emit(value: T) { - coroutineScope { - var jobOrNull: Job? = null - val newEmit = - async(start = CoroutineStart.LAZY) { - jobOrNull?.join() - network - .transaction("MutableTFlow($name).emit") { impl.visit(this, value) } - .await() - } - jobOrNull = storage.getAndSet(newEmit) - newEmit.await() - } - } - - // internal suspend fun emitInCurrentTransaction(value: T, evalScope: EvalScope) { - // if (storage.getAndSet(just(value)) is None) { - // impl.visit(evalScope) - // } - // } -} - -private data object EmptyFlow : TFlow<Nothing>() - -internal class TFlowInit<out A>(val init: Init<TFlowImpl<A>>) : TFlow<A>() { - override fun toString(): String = "${this::class.simpleName}@$hashString" -} - -internal val <A> TFlow<A>.init: Init<TFlowImpl<A>> - get() = - when (this) { - is EmptyFlow -> constInit("EmptyFlow", neverImpl) - is TFlowInit -> init - is TFlowLoop -> init - is CoalescingMutableTFlow<*, A> -> constInit(name, impl.activated()) - is MutableTFlow -> constInit(name, impl.activated()) - } - -private inline fun <A> deferInline(crossinline block: suspend InitScope.() -> TFlow<A>): TFlow<A> = - TFlowInit(init(name = null) { block().init.connect(evalScope = this) }) diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/TState.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/TState.kt deleted file mode 100644 index 80e74748a375..000000000000 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/TState.kt +++ /dev/null @@ -1,544 +0,0 @@ -/* - * 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.kairos - -import com.android.systemui.kairos.internal.DerivedMapCheap -import com.android.systemui.kairos.internal.Init -import com.android.systemui.kairos.internal.InitScope -import com.android.systemui.kairos.internal.Network -import com.android.systemui.kairos.internal.NoScope -import com.android.systemui.kairos.internal.Schedulable -import com.android.systemui.kairos.internal.TFlowImpl -import com.android.systemui.kairos.internal.TStateImpl -import com.android.systemui.kairos.internal.TStateSource -import com.android.systemui.kairos.internal.activated -import com.android.systemui.kairos.internal.cached -import com.android.systemui.kairos.internal.constInit -import com.android.systemui.kairos.internal.constS -import com.android.systemui.kairos.internal.filterNode -import com.android.systemui.kairos.internal.flatMap -import com.android.systemui.kairos.internal.init -import com.android.systemui.kairos.internal.map -import com.android.systemui.kairos.internal.mapCheap -import com.android.systemui.kairos.internal.mapImpl -import com.android.systemui.kairos.internal.util.hashString -import com.android.systemui.kairos.internal.zipStates -import kotlin.reflect.KProperty -import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.Deferred -import kotlinx.coroutines.async -import kotlinx.coroutines.coroutineScope - -/** - * A time-varying value with discrete changes. Essentially, a combination of a [Transactional] that - * holds a value, and a [TFlow] that emits when the value changes. - */ -@ExperimentalFrpApi sealed class TState<out A> - -/** A [TState] that never changes. */ -@ExperimentalFrpApi -fun <A> tStateOf(value: A): TState<A> { - val operatorName = "tStateOf" - val name = "$operatorName($value)" - return TStateInit(constInit(name, constS(name, operatorName, value))) -} - -/** TODO */ -@ExperimentalFrpApi fun <A> Lazy<TState<A>>.defer(): TState<A> = deferInline { value } - -/** TODO */ -@ExperimentalFrpApi -fun <A> FrpDeferredValue<TState<A>>.defer(): TState<A> = deferInline { unwrapped.await() } - -/** TODO */ -@ExperimentalFrpApi -fun <A> deferTState(block: suspend FrpScope.() -> TState<A>): TState<A> = deferInline { - NoScope.runInFrpScope(block) -} - -/** - * Returns a [TState] containing the results of applying [transform] to the value held by the - * original [TState]. - */ -@ExperimentalFrpApi -fun <A, B> TState<A>.map(transform: suspend FrpScope.(A) -> B): TState<B> { - val operatorName = "map" - val name = operatorName - return TStateInit( - init(name) { - init.connect(evalScope = this).map(name, operatorName) { - NoScope.runInFrpScope { transform(it) } - } - } - ) -} - -/** - * Returns a [TState] that transforms the value held inside this [TState] by applying it to the - * [transform]. - * - * Note that unlike [map], the result is not cached. This means that not only should [transform] be - * fast and pure, it should be *monomorphic* (1-to-1). Failure to do this means that [stateChanges] - * for the returned [TState] will operate unexpectedly, emitting at rates that do not reflect an - * observable change to the returned [TState]. - */ -@ExperimentalFrpApi -fun <A, B> TState<A>.mapCheapUnsafe(transform: suspend FrpScope.(A) -> B): TState<B> { - val operatorName = "map" - val name = operatorName - return TStateInit( - init(name) { - init.connect(evalScope = this).mapCheap(name, operatorName) { - NoScope.runInFrpScope { transform(it) } - } - } - ) -} - -/** - * Returns a [TState] by combining the values held inside the given [TState]s by applying them to - * the given function [transform]. - */ -@ExperimentalFrpApi -fun <A, B, C> TState<A>.combineWith( - other: TState<B>, - transform: suspend FrpScope.(A, B) -> C, -): TState<C> = combine(this, other, transform) - -/** - * Splits a [TState] of pairs into a pair of [TFlows][TState], where each returned [TState] holds - * half of the original. - * - * Shorthand for: - * ```kotlin - * val lefts = map { it.first } - * val rights = map { it.second } - * return Pair(lefts, rights) - * ``` - */ -@ExperimentalFrpApi -fun <A, B> TState<Pair<A, B>>.unzip(): Pair<TState<A>, TState<B>> { - val left = map { it.first } - val right = map { it.second } - return left to right -} - -/** - * Returns a [TState] by combining the values held inside the given [TStates][TState] into a [List]. - * - * @see TState.combineWith - */ -@ExperimentalFrpApi -fun <A> Iterable<TState<A>>.combine(): TState<List<A>> { - val operatorName = "combine" - val name = operatorName - return TStateInit( - init(name) { - zipStates(name, operatorName, states = map { it.init.connect(evalScope = this) }) - } - ) -} - -/** - * Returns a [TState] by combining the values held inside the given [TStates][TState] into a [Map]. - * - * @see TState.combineWith - */ -@ExperimentalFrpApi -fun <K : Any, A> Map<K, TState<A>>.combine(): TState<Map<K, A>> { - val operatorName = "combine" - val name = operatorName - return TStateInit( - init(name) { - zipStates( - name, - operatorName, - states = mapValues { it.value.init.connect(evalScope = this) }, - ) - } - ) -} - -/** - * Returns a [TState] whose value is generated with [transform] by combining the current values of - * each given [TState]. - * - * @see TState.combineWith - */ -@ExperimentalFrpApi -fun <A, B> Iterable<TState<A>>.combine(transform: suspend FrpScope.(List<A>) -> B): TState<B> = - combine().map(transform) - -/** - * Returns a [TState] by combining the values held inside the given [TState]s into a [List]. - * - * @see TState.combineWith - */ -@ExperimentalFrpApi -fun <A> combine(vararg states: TState<A>): TState<List<A>> = states.asIterable().combine() - -/** - * Returns a [TState] whose value is generated with [transform] by combining the current values of - * each given [TState]. - * - * @see TState.combineWith - */ -@ExperimentalFrpApi -fun <A, B> combine( - vararg states: TState<A>, - transform: suspend FrpScope.(List<A>) -> B, -): TState<B> = states.asIterable().combine(transform) - -/** - * Returns a [TState] whose value is generated with [transform] by combining the current values of - * each given [TState]. - * - * @see TState.combineWith - */ -@ExperimentalFrpApi -fun <A, B, Z> combine( - stateA: TState<A>, - stateB: TState<B>, - transform: suspend FrpScope.(A, B) -> Z, -): TState<Z> { - val operatorName = "combine" - val name = operatorName - return TStateInit( - init(name) { - coroutineScope { - val dl1: Deferred<TStateImpl<A>> = async { - stateA.init.connect(evalScope = this@init) - } - val dl2: Deferred<TStateImpl<B>> = async { - stateB.init.connect(evalScope = this@init) - } - zipStates(name, operatorName, dl1.await(), dl2.await()) { a, b -> - NoScope.runInFrpScope { transform(a, b) } - } - } - } - ) -} - -/** - * Returns a [TState] whose value is generated with [transform] by combining the current values of - * each given [TState]. - * - * @see TState.combineWith - */ -@ExperimentalFrpApi -fun <A, B, C, Z> combine( - stateA: TState<A>, - stateB: TState<B>, - stateC: TState<C>, - transform: suspend FrpScope.(A, B, C) -> Z, -): TState<Z> { - val operatorName = "combine" - val name = operatorName - return TStateInit( - init(name) { - coroutineScope { - val dl1: Deferred<TStateImpl<A>> = async { - stateA.init.connect(evalScope = this@init) - } - val dl2: Deferred<TStateImpl<B>> = async { - stateB.init.connect(evalScope = this@init) - } - val dl3: Deferred<TStateImpl<C>> = async { - stateC.init.connect(evalScope = this@init) - } - zipStates(name, operatorName, dl1.await(), dl2.await(), dl3.await()) { a, b, c -> - NoScope.runInFrpScope { transform(a, b, c) } - } - } - } - ) -} - -/** - * Returns a [TState] whose value is generated with [transform] by combining the current values of - * each given [TState]. - * - * @see TState.combineWith - */ -@ExperimentalFrpApi -fun <A, B, C, D, Z> combine( - stateA: TState<A>, - stateB: TState<B>, - stateC: TState<C>, - stateD: TState<D>, - transform: suspend FrpScope.(A, B, C, D) -> Z, -): TState<Z> { - val operatorName = "combine" - val name = operatorName - return TStateInit( - init(name) { - coroutineScope { - val dl1: Deferred<TStateImpl<A>> = async { - stateA.init.connect(evalScope = this@init) - } - val dl2: Deferred<TStateImpl<B>> = async { - stateB.init.connect(evalScope = this@init) - } - val dl3: Deferred<TStateImpl<C>> = async { - stateC.init.connect(evalScope = this@init) - } - val dl4: Deferred<TStateImpl<D>> = async { - stateD.init.connect(evalScope = this@init) - } - zipStates(name, operatorName, dl1.await(), dl2.await(), dl3.await(), dl4.await()) { - a, - b, - c, - d -> - NoScope.runInFrpScope { transform(a, b, c, d) } - } - } - } - ) -} - -/** - * Returns a [TState] whose value is generated with [transform] by combining the current values of - * each given [TState]. - * - * @see TState.combineWith - */ -@ExperimentalFrpApi -fun <A, B, C, D, E, Z> combine( - stateA: TState<A>, - stateB: TState<B>, - stateC: TState<C>, - stateD: TState<D>, - stateE: TState<E>, - transform: suspend FrpScope.(A, B, C, D, E) -> Z, -): TState<Z> { - val operatorName = "combine" - val name = operatorName - return TStateInit( - init(name) { - coroutineScope { - val dl1: Deferred<TStateImpl<A>> = async { - stateA.init.connect(evalScope = this@init) - } - val dl2: Deferred<TStateImpl<B>> = async { - stateB.init.connect(evalScope = this@init) - } - val dl3: Deferred<TStateImpl<C>> = async { - stateC.init.connect(evalScope = this@init) - } - val dl4: Deferred<TStateImpl<D>> = async { - stateD.init.connect(evalScope = this@init) - } - val dl5: Deferred<TStateImpl<E>> = async { - stateE.init.connect(evalScope = this@init) - } - zipStates( - name, - operatorName, - dl1.await(), - dl2.await(), - dl3.await(), - dl4.await(), - dl5.await(), - ) { a, b, c, d, e -> - NoScope.runInFrpScope { transform(a, b, c, d, e) } - } - } - } - ) -} - -/** Returns a [TState] by applying [transform] to the value held by the original [TState]. */ -@ExperimentalFrpApi -fun <A, B> TState<A>.flatMap(transform: suspend FrpScope.(A) -> TState<B>): TState<B> { - val operatorName = "flatMap" - val name = operatorName - return TStateInit( - init(name) { - init.connect(this).flatMap(name, operatorName) { a -> - NoScope.runInFrpScope { transform(a) }.init.connect(this) - } - } - ) -} - -/** Shorthand for `flatMap { it }` */ -@ExperimentalFrpApi fun <A> TState<TState<A>>.flatten() = flatMap { it } - -/** - * Returns a [TStateSelector] that can be used to efficiently check if the input [TState] is - * currently holding a specific value. - * - * An example: - * ``` - * val lInt: TState<Int> = ... - * val intSelector: TStateSelector<Int> = lInt.selector() - * // Tracks if lInt is holding 1 - * val isOne: TState<Boolean> = intSelector.whenSelected(1) - * ``` - * - * This is semantically equivalent to `val isOne = lInt.map { i -> i == 1 }`, but is significantly - * more efficient; specifically, using [TState.map] in this way incurs a `O(n)` performance hit, - * where `n` is the number of different [TState.map] operations used to track a specific value. - * [selector] internally uses a [HashMap] to lookup the appropriate downstream [TState] to update, - * and so operates in `O(1)`. - * - * Note that the result [TStateSelector] should be cached and re-used to gain the performance - * benefit. - * - * @see groupByKey - */ -@ExperimentalFrpApi -fun <A> TState<A>.selector(numDistinctValues: Int? = null): TStateSelector<A> = - TStateSelector( - this, - stateChanges - .map { new -> mapOf(new to true, sampleDeferred().get() to false) } - .groupByKey(numDistinctValues), - ) - -/** - * Tracks the currently selected value of type [A] from an upstream [TState]. - * - * @see selector - */ -@ExperimentalFrpApi -class TStateSelector<in A> -internal constructor( - private val upstream: TState<A>, - private val groupedChanges: GroupedTFlow<A, Boolean>, -) { - /** - * Returns a [TState] that tracks whether the upstream [TState] is currently holding the given - * [value]. - * - * @see selector - */ - @ExperimentalFrpApi - fun whenSelected(value: A): TState<Boolean> { - val operatorName = "TStateSelector#whenSelected" - val name = "$operatorName[$value]" - return TStateInit( - init(name) { - DerivedMapCheap( - name, - operatorName, - upstream = upstream.init.connect(evalScope = this), - changes = groupedChanges.impl.eventsForKey(value), - ) { - it == value - } - } - ) - } - - @ExperimentalFrpApi operator fun get(value: A): TState<Boolean> = whenSelected(value) -} - -/** TODO */ -@ExperimentalFrpApi -class MutableTState<T> -internal constructor(internal val network: Network, initialValue: Deferred<T>) : TState<T>() { - - private val input: CoalescingMutableTFlow<Deferred<T>, Deferred<T>?> = - CoalescingMutableTFlow( - name = null, - coalesce = { _, new -> new }, - network = network, - getInitialValue = { null }, - ) - - internal val tState = run { - val changes = input.impl - val name = null - val operatorName = "MutableTState" - lateinit var state: TStateSource<T> - val calm: TFlowImpl<T> = - filterNode({ mapImpl(upstream = { changes.activated() }) { it!!.await() } }) { new -> - new != state.getCurrentWithEpoch(evalScope = this).first - } - .cached() - state = TStateSource(name, operatorName, initialValue, calm) - @Suppress("DeferredResultUnused") - network.transaction("MutableTState.init") { - calm.activate(evalScope = this, downstream = Schedulable.S(state))?.let { - (connection, needsEval) -> - state.upstreamConnection = connection - if (needsEval) { - schedule(state) - } - } - } - TStateInit(constInit(name, state)) - } - - /** TODO */ - @ExperimentalFrpApi fun setValue(value: T) = input.emit(CompletableDeferred(value)) - - @ExperimentalFrpApi - fun setValueDeferred(value: FrpDeferredValue<T>) = input.emit(value.unwrapped) -} - -/** A forward-reference to a [TState], allowing for recursive definitions. */ -@ExperimentalFrpApi -class TStateLoop<A> : TState<A>() { - - private val name: String? = null - - private val deferred = CompletableDeferred<TState<A>>() - - internal val init: Init<TStateImpl<A>> = - init(name) { deferred.await().init.connect(evalScope = this) } - - /** The [TState] this [TStateLoop] will forward to. */ - @ExperimentalFrpApi - var loopback: TState<A>? = null - set(value) { - value?.let { - check(deferred.complete(value)) { "TStateLoop.loopback has already been set." } - field = value - } - } - - @ExperimentalFrpApi - operator fun getValue(thisRef: Any?, property: KProperty<*>): TState<A> = this - - @ExperimentalFrpApi - operator fun setValue(thisRef: Any?, property: KProperty<*>, value: TState<A>) { - loopback = value - } - - override fun toString(): String = "${this::class.simpleName}@$hashString" -} - -internal class TStateInit<A> internal constructor(internal val init: Init<TStateImpl<A>>) : - TState<A>() { - override fun toString(): String = "${this::class.simpleName}@$hashString" -} - -internal val <A> TState<A>.init: Init<TStateImpl<A>> - get() = - when (this) { - is TStateInit -> init - is TStateLoop -> init - is MutableTState -> tState.init - } - -private inline fun <A> deferInline( - crossinline block: suspend InitScope.() -> TState<A> -): TState<A> = TStateInit(init(name = null) { block().init.connect(evalScope = this) }) diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/TransactionScope.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/TransactionScope.kt new file mode 100644 index 000000000000..225416992d52 --- /dev/null +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/TransactionScope.kt @@ -0,0 +1,78 @@ +/* + * 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.kairos + +/** + * Kairos operations that are available while a transaction is active. + * + * These operations do not accumulate state, which makes [TransactionScope] weaker than + * [StateScope], but allows them to be used in more places. + */ +@ExperimentalKairosApi +interface TransactionScope : KairosScope { + + /** + * Returns the current value of this [Transactional] as a [DeferredValue]. + * + * Compared to [sample], you may want to use this instead if you do not need to inspect the + * sampled value, but instead want to pass it to another Kairos API that accepts a + * [DeferredValue]. In this case, [sampleDeferred] is both safer and more performant. + * + * @see sample + */ + fun <A> Transactional<A>.sampleDeferred(): DeferredValue<A> + + /** + * Returns the current value of this [State] as a [DeferredValue]. + * + * Compared to [sample], you may want to use this instead if you do not need to inspect the + * sampled value, but instead want to pass it to another Kairos API that accepts a + * [DeferredValue]. In this case, [sampleDeferred] is both safer and more performant. + * + * @see sample + */ + fun <A> State<A>.sampleDeferred(): DeferredValue<A> + + /** + * Defers invoking [block] until after the current [TransactionScope] code-path completes, + * returning a [DeferredValue] that can be used to reference the result. + * + * Useful for recursive definitions. + * + * @see DeferredValue + */ + fun <A> deferredTransactionScope(block: TransactionScope.() -> A): DeferredValue<A> + + /** An [Events] that emits once, within this transaction, and then never again. */ + val now: Events<Unit> + + /** + * Returns the current value held by this [State]. Guaranteed to be consistent within the same + * transaction. + * + * @see sampleDeferred + */ + fun <A> State<A>.sample(): A = sampleDeferred().get() + + /** + * Returns the current value held by this [Transactional]. Guaranteed to be consistent within + * the same transaction. + * + * @see sampleDeferred + */ + fun <A> Transactional<A>.sample(): A = sampleDeferred().get() +} diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/Transactional.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/Transactional.kt index 6b1c8c8fc3e5..9485cd212603 100644 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/Transactional.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/Transactional.kt @@ -16,57 +16,80 @@ package com.android.systemui.kairos +import com.android.systemui.kairos.internal.CompletableLazy import com.android.systemui.kairos.internal.InitScope import com.android.systemui.kairos.internal.NoScope import com.android.systemui.kairos.internal.TransactionalImpl import com.android.systemui.kairos.internal.init import com.android.systemui.kairos.internal.transactionalImpl import com.android.systemui.kairos.internal.util.hashString -import kotlinx.coroutines.CompletableDeferred /** * A time-varying value. A [Transactional] encapsulates the idea of some continuous state; each time * it is "sampled", a new result may be produced. * - * Because FRP operates over an "idealized" model of Time that can be passed around as a data type, - * [Transactional]s are guaranteed to produce the same result if queried multiple times at the same - * (conceptual) time, in order to preserve _referential transparency_. + * Because Kairos operates over an "idealized" model of Time that can be passed around as a data + * type, [Transactional]s are guaranteed to produce the same result if queried multiple times at the + * same (conceptual) time, in order to preserve _referential transparency_. */ -@ExperimentalFrpApi -class Transactional<out A> internal constructor(internal val impl: TState<TransactionalImpl<A>>) { +@ExperimentalKairosApi +class Transactional<out A> internal constructor(internal val impl: State<TransactionalImpl<A>>) { override fun toString(): String = "${this::class.simpleName}@$hashString" } /** A constant [Transactional] that produces [value] whenever it is sampled. */ -@ExperimentalFrpApi +@ExperimentalKairosApi fun <A> transactionalOf(value: A): Transactional<A> = - Transactional(tStateOf(TransactionalImpl.Const(CompletableDeferred(value)))) + Transactional(stateOf(TransactionalImpl.Const(CompletableLazy(value)))) -/** TODO */ -@ExperimentalFrpApi -fun <A> FrpDeferredValue<Transactional<A>>.defer(): Transactional<A> = deferInline { - unwrapped.await() -} +/** + * Returns a [Transactional] that acts as a deferred-reference to the [Transactional] produced by + * this [DeferredValue]. + * + * When the returned [Transactional] is accessed by the Kairos network, the [DeferredValue] will be + * queried and used. + * + * Useful for recursive definitions. + */ +@ExperimentalKairosApi +fun <A> DeferredValue<Transactional<A>>.defer(): Transactional<A> = deferInline { unwrapped.value } -/** TODO */ -@ExperimentalFrpApi fun <A> Lazy<Transactional<A>>.defer(): Transactional<A> = deferInline { value } +/** + * Returns a [Transactional] that acts as a deferred-reference to the [Transactional] produced by + * this [Lazy]. + * + * When the returned [Transactional] is accessed by the Kairos network, the [Lazy]'s + * [value][Lazy.value] will be queried and used. + * + * Useful for recursive definitions. + */ +@ExperimentalKairosApi +fun <A> Lazy<Transactional<A>>.defer(): Transactional<A> = deferInline { value } -/** TODO */ -@ExperimentalFrpApi -fun <A> deferTransactional(block: suspend FrpScope.() -> Transactional<A>): Transactional<A> = +/** + * Returns a [Transactional] that acts as a deferred-reference to the [Transactional] produced by + * [block]. + * + * When the returned [Transactional] is accessed by the Kairos network, [block] will be invoked and + * the returned [Transactional] will be used. + * + * Useful for recursive definitions. + */ +@ExperimentalKairosApi +fun <A> deferredTransactional(block: KairosScope.() -> Transactional<A>): Transactional<A> = deferInline { - NoScope.runInFrpScope(block) + NoScope.block() } private inline fun <A> deferInline( - crossinline block: suspend InitScope.() -> Transactional<A> + crossinline block: InitScope.() -> Transactional<A> ): Transactional<A> = - Transactional(TStateInit(init(name = null) { block().impl.init.connect(evalScope = this) })) + Transactional(StateInit(init(name = null) { block().impl.init.connect(evalScope = this) })) /** * Returns a [Transactional]. The passed [block] will be evaluated on demand at most once per * transaction; any subsequent sampling within the same transaction will receive a cached value. */ -@ExperimentalFrpApi -fun <A> transactionally(block: suspend FrpTransactionScope.() -> A): Transactional<A> = - Transactional(tStateOf(transactionalImpl { runInTransactionScope(block) })) +@ExperimentalKairosApi +fun <A> transactionally(block: TransactionScope.() -> A): Transactional<A> = + Transactional(stateOf(transactionalImpl { block() })) diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/debug/Debug.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/debug/Debug.kt deleted file mode 100644 index 0674a2e75659..000000000000 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/debug/Debug.kt +++ /dev/null @@ -1,203 +0,0 @@ -/* - * 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.kairos.debug - -import com.android.systemui.kairos.MutableTState -import com.android.systemui.kairos.TState -import com.android.systemui.kairos.TStateInit -import com.android.systemui.kairos.TStateLoop -import com.android.systemui.kairos.internal.DerivedFlatten -import com.android.systemui.kairos.internal.DerivedMap -import com.android.systemui.kairos.internal.DerivedMapCheap -import com.android.systemui.kairos.internal.DerivedZipped -import com.android.systemui.kairos.internal.Init -import com.android.systemui.kairos.internal.TStateDerived -import com.android.systemui.kairos.internal.TStateImpl -import com.android.systemui.kairos.internal.TStateSource -import com.android.systemui.kairos.util.Just -import com.android.systemui.kairos.util.Maybe -import com.android.systemui.kairos.util.None -import com.android.systemui.kairos.util.flatMap -import com.android.systemui.kairos.util.map -import com.android.systemui.kairos.util.none -import com.android.systemui.kairos.util.orElseGet - -// object IdGen { -// private val counter = AtomicLong() -// fun getId() = counter.getAndIncrement() -// } - -typealias StateGraph = Graph<ActivationInfo> - -sealed class StateInfo( - val name: String, - val value: Maybe<Any?>, - val operator: String, - val epoch: Long?, -) - -class Source(name: String, value: Maybe<Any?>, operator: String, epoch: Long) : - StateInfo(name, value, operator, epoch) - -class Derived( - name: String, - val type: DerivedStateType, - value: Maybe<Any?>, - operator: String, - epoch: Long?, -) : StateInfo(name, value, operator, epoch) - -sealed interface DerivedStateType - -data object Flatten : DerivedStateType - -data class Mapped(val cheap: Boolean) : DerivedStateType - -data object Combine : DerivedStateType - -sealed class InitInfo(val name: String) - -class Uninitialized(name: String) : InitInfo(name) - -class Initialized(val state: StateInfo) : InitInfo(state.name) - -sealed interface ActivationInfo - -class Inactive(val name: String) : ActivationInfo - -class Active(val nodeInfo: StateInfo) : ActivationInfo - -class Dead(val name: String) : ActivationInfo - -data class Edge(val upstream: Any, val downstream: Any, val tag: Any? = null) - -data class Graph<T>(val nodes: Map<Any, T>, val edges: List<Edge>) - -internal fun TState<*>.dump(infoMap: MutableMap<Any, InitInfo>, edges: MutableList<Edge>) { - val init: Init<TStateImpl<Any?>> = - when (this) { - is TStateInit -> init - is TStateLoop -> init - is MutableTState -> tState.init - } - when (val stateMaybe = init.getUnsafe()) { - None -> { - infoMap[this] = Uninitialized(init.name ?: init.toString()) - } - is Just -> { - stateMaybe.value.dump(infoMap, edges) - } - } -} - -internal fun TStateImpl<*>.dump(infoById: MutableMap<Any, InitInfo>, edges: MutableList<Edge>) { - val state = this - if (state in infoById) return - val stateInfo = - when (state) { - is TStateDerived -> { - val type = - when (state) { - is DerivedFlatten -> { - state.upstream.dump(infoById, edges) - edges.add( - Edge(upstream = state.upstream, downstream = state, tag = "outer") - ) - state.upstream - .getUnsafe() - .orElseGet { null } - ?.let { - edges.add( - Edge(upstream = it, downstream = state, tag = "inner") - ) - it.dump(infoById, edges) - } - Flatten - } - is DerivedMap<*, *> -> { - state.upstream.dump(infoById, edges) - edges.add(Edge(upstream = state.upstream, downstream = state)) - Mapped(cheap = false) - } - is DerivedZipped<*, *> -> { - state.upstream.forEach { (key, upstream) -> - edges.add( - Edge(upstream = upstream, downstream = state, tag = "key=$key") - ) - upstream.dump(infoById, edges) - } - Combine - } - } - Derived( - state.name ?: state.operatorName, - type, - state.getCachedUnsafe(), - state.operatorName, - state.invalidatedEpoch, - ) - } - is TStateSource -> - Source( - state.name ?: state.operatorName, - state.getStorageUnsafe(), - state.operatorName, - state.writeEpoch, - ) - is DerivedMapCheap<*, *> -> { - state.upstream.dump(infoById, edges) - edges.add(Edge(upstream = state.upstream, downstream = state)) - val type = Mapped(cheap = true) - Derived( - state.name ?: state.operatorName, - type, - state.getUnsafe(), - state.operatorName, - null, - ) - } - } - infoById[state] = Initialized(stateInfo) -} - -private fun <A> TStateImpl<A>.getUnsafe(): Maybe<A> = - when (this) { - is TStateDerived -> getCachedUnsafe() - is TStateSource -> getStorageUnsafe() - is DerivedMapCheap<*, *> -> none - } - -private fun <A> TStateImpl<A>.getUnsafeWithEpoch(): Maybe<Pair<A, Long>> = - when (this) { - is TStateDerived -> getCachedUnsafe().map { it to invalidatedEpoch } - is TStateSource -> getStorageUnsafe().map { it to writeEpoch } - is DerivedMapCheap<*, *> -> none - } - -/** - * Returns the current value held in this [TState], or [none] if the [TState] has not been - * initialized. - * - * The returned [Long] is the *epoch* at which the internal cache was last updated. This can be used - * to identify values which are out-of-date. - */ -fun <A> TState<A>.sampleUnsafe(): Maybe<Pair<A, Long>> = - when (this) { - is MutableTState -> tState.init.getUnsafe().flatMap { it.getUnsafeWithEpoch() } - is TStateInit -> init.getUnsafe().flatMap { it.getUnsafeWithEpoch() } - is TStateLoop -> this.init.getUnsafe().flatMap { it.getUnsafeWithEpoch() } - } diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/BuildScopeImpl.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/BuildScopeImpl.kt index 7e6384925f38..b20e77a31dab 100644 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/BuildScopeImpl.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/BuildScopeImpl.kt @@ -16,154 +16,115 @@ package com.android.systemui.kairos.internal -import com.android.systemui.kairos.CoalescingMutableTFlow -import com.android.systemui.kairos.FrpBuildScope -import com.android.systemui.kairos.FrpCoalescingProducerScope -import com.android.systemui.kairos.FrpDeferredValue -import com.android.systemui.kairos.FrpEffectScope -import com.android.systemui.kairos.FrpNetwork -import com.android.systemui.kairos.FrpProducerScope -import com.android.systemui.kairos.FrpSpec -import com.android.systemui.kairos.FrpStateScope -import com.android.systemui.kairos.FrpTransactionScope -import com.android.systemui.kairos.GroupedTFlow -import com.android.systemui.kairos.LocalFrpNetwork -import com.android.systemui.kairos.MutableTFlow -import com.android.systemui.kairos.TFlow -import com.android.systemui.kairos.TFlowInit +import com.android.systemui.kairos.BuildScope +import com.android.systemui.kairos.BuildSpec +import com.android.systemui.kairos.CoalescingEventProducerScope +import com.android.systemui.kairos.CoalescingMutableEvents +import com.android.systemui.kairos.DeferredValue +import com.android.systemui.kairos.EffectScope +import com.android.systemui.kairos.EventProducerScope +import com.android.systemui.kairos.Events +import com.android.systemui.kairos.EventsInit +import com.android.systemui.kairos.GroupedEvents +import com.android.systemui.kairos.KairosNetwork +import com.android.systemui.kairos.LocalNetwork +import com.android.systemui.kairos.MutableEvents +import com.android.systemui.kairos.TransactionScope import com.android.systemui.kairos.groupByKey import com.android.systemui.kairos.init import com.android.systemui.kairos.internal.util.childScope -import com.android.systemui.kairos.internal.util.mapValuesParallel +import com.android.systemui.kairos.internal.util.launchImmediate import com.android.systemui.kairos.launchEffect import com.android.systemui.kairos.mergeLeft -import com.android.systemui.kairos.util.Just import com.android.systemui.kairos.util.Maybe -import com.android.systemui.kairos.util.None +import com.android.systemui.kairos.util.Maybe.Just +import com.android.systemui.kairos.util.Maybe.None import com.android.systemui.kairos.util.just import com.android.systemui.kairos.util.map import java.util.concurrent.atomic.AtomicReference -import kotlin.coroutines.Continuation import kotlin.coroutines.CoroutineContext -import kotlin.coroutines.EmptyCoroutineContext -import kotlin.coroutines.startCoroutine -import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CompletableJob import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Deferred +import kotlinx.coroutines.DisposableHandle import kotlinx.coroutines.Job import kotlinx.coroutines.cancel -import kotlinx.coroutines.completeWith import kotlinx.coroutines.job internal class BuildScopeImpl(val stateScope: StateScopeImpl, val coroutineScope: CoroutineScope) : - BuildScope, StateScope by stateScope { + InternalBuildScope, InternalStateScope by stateScope { private val job: Job get() = coroutineScope.coroutineContext.job - override val frpScope: FrpBuildScope = FrpBuildScopeImpl() - - override suspend fun <R> runInBuildScope(block: suspend FrpBuildScope.() -> R): R { - val complete = CompletableDeferred<R>(parent = coroutineContext.job) - block.startCoroutine( - frpScope, - object : Continuation<R> { - override val context: CoroutineContext - get() = EmptyCoroutineContext - - override fun resumeWith(result: Result<R>) { - complete.completeWith(result) - } - }, - ) - return complete.await() + override val kairosNetwork: KairosNetwork by lazy { + LocalNetwork(network, coroutineScope, endSignal) } - private fun <A, T : TFlow<A>, S> buildTFlow( - constructFlow: (InputNode<A>) -> Pair<T, S>, - builder: suspend S.() -> Unit, - ): TFlow<A> { - var job: Job? = null - val stopEmitter = newStopEmitter("buildTFlow") - // Create a child scope that will be kept alive beyond the end of this transaction. - val childScope = coroutineScope.childScope() - lateinit var emitter: Pair<T, S> - val inputNode = - InputNode<A>( - activate = { - check(job == null) { "already activated" } - job = - reenterBuildScope(this@BuildScopeImpl, childScope).runInBuildScope { - launchEffect { - builder(emitter.second) - stopEmitter.emit(Unit) - } - } - }, - deactivate = { - checkNotNull(job) { "already deactivated" }.cancel() - job = null - }, - ) - emitter = constructFlow(inputNode) - return with(frpScope) { emitter.first.takeUntil(mergeLeft(stopEmitter, endSignal)) } - } - - private fun <T> tFlowInternal(builder: suspend FrpProducerScope<T>.() -> Unit): TFlow<T> = - buildTFlow( - constructFlow = { inputNode -> - val flow = MutableTFlow(network, inputNode) - flow to - object : FrpProducerScope<T> { + override fun <T> events( + name: String?, + builder: suspend EventProducerScope<T>.() -> Unit, + ): Events<T> = + buildEvents( + name, + constructEvents = { inputNode -> + val events = MutableEvents(network, inputNode) + events to + object : EventProducerScope<T> { override suspend fun emit(value: T) { - flow.emit(value) + events.emit(value) } } }, builder = builder, ) - private fun <In, Out> coalescingTFlowInternal( + override fun <In, Out> coalescingEvents( getInitialValue: () -> Out, coalesce: (old: Out, new: In) -> Out, - builder: suspend FrpCoalescingProducerScope<In>.() -> Unit, - ): TFlow<Out> = - buildTFlow( - constructFlow = { inputNode -> - val flow = - CoalescingMutableTFlow(null, coalesce, network, getInitialValue, inputNode) - flow to - object : FrpCoalescingProducerScope<In> { + builder: suspend CoalescingEventProducerScope<In>.() -> Unit, + ): Events<Out> = + buildEvents( + constructEvents = { inputNode -> + val events = + CoalescingMutableEvents( + null, + coalesce = { old, new: In -> coalesce(old.value, new) }, + network, + getInitialValue, + inputNode, + ) + events to + object : CoalescingEventProducerScope<In> { override fun emit(value: In) { - flow.emit(value) + events.emit(value) } } }, builder = builder, ) - private fun <A> asyncScopeInternal(block: FrpSpec<A>): Pair<FrpDeferredValue<A>, Job> { + override fun <A> asyncScope(block: BuildSpec<A>): Pair<DeferredValue<A>, Job> { val childScope = mutableChildBuildScope() - return FrpDeferredValue(deferAsync { childScope.runInBuildScope(block) }) to childScope.job + return DeferredValue(deferAsync { block(childScope) }) to childScope.job } - private fun <R> deferredInternal(block: suspend FrpBuildScope.() -> R): FrpDeferredValue<R> = - FrpDeferredValue(deferAsync { runInBuildScope(block) }) + override fun <R> deferredBuildScope(block: BuildScope.() -> R): DeferredValue<R> = + DeferredValue(deferAsync { block() }) - private fun deferredActionInternal(block: suspend FrpBuildScope.() -> Unit) { - deferAction { runInBuildScope(block) } + override fun deferredBuildScopeAction(block: BuildScope.() -> Unit) { + deferAction { block() } } - private fun <A> TFlow<A>.observeEffectInternal( - context: CoroutineContext, - block: suspend FrpEffectScope.(A) -> Unit, - ): Job { + override fun <A> Events<A>.observe( + coroutineContext: CoroutineContext, + block: EffectScope.(A) -> Unit, + ): DisposableHandle { val subRef = AtomicReference<Maybe<Output<A>>>(null) val childScope = coroutineScope.childScope() - // When our scope is cancelled, deactivate this observer. - childScope.coroutineContext.job.invokeOnCompletion { + lateinit var cancelHandle: DisposableHandle + val handle = DisposableHandle { subRef.getAndSet(None)?.let { output -> + cancelHandle.dispose() if (output is Just) { @Suppress("DeferredResultUnused") network.transaction("observeEffect cancelled") { @@ -172,38 +133,30 @@ internal class BuildScopeImpl(val stateScope: StateScopeImpl, val coroutineScope } } } - // Defer so that we don't suspend the caller + // When our scope is cancelled, deactivate this observer. + cancelHandle = childScope.coroutineContext.job.invokeOnCompletion { handle.dispose() } + val localNetwork = LocalNetwork(network, childScope, endSignal) + val outputNode = + Output<A>( + context = coroutineContext, + onDeath = { subRef.set(None) }, + onEmit = { output -> + if (subRef.get() is Just) { + // Not cancelled, safe to emit + val scope = + object : EffectScope, TransactionScope by this { + override val effectCoroutineScope: CoroutineScope = childScope + override val kairosNetwork: KairosNetwork = localNetwork + } + scope.block(output) + } + }, + ) + // Defer, in case any EventsLoops / StateLoops still need to be set deferAction { - val outputNode = - Output<A>( - context = context, - onDeath = { subRef.getAndSet(None)?.let { childScope.cancel() } }, - onEmit = { output -> - if (subRef.get() is Just) { - // Not cancelled, safe to emit - val coroutine: suspend FrpEffectScope.() -> Unit = { block(output) } - val complete = CompletableDeferred<Unit>(parent = coroutineContext.job) - coroutine.startCoroutine( - object : FrpEffectScope, FrpTransactionScope by frpScope { - override val frpCoroutineScope: CoroutineScope = childScope - override val frpNetwork: FrpNetwork = - LocalFrpNetwork(network, childScope, endSignal) - }, - completion = - object : Continuation<Unit> { - override val context: CoroutineContext - get() = EmptyCoroutineContext - - override fun resumeWith(result: Result<Unit>) { - complete.completeWith(result) - } - }, - ) - complete.await() - } - }, - ) - with(frpScope) { this@observeEffectInternal.takeUntil(endSignal) } + // Check for immediate cancellation + if (subRef.get() != null) return@deferAction + this@observe.takeUntil(endSignal) .init .connect(evalScope = stateScope.evalScope) .activate(evalScope = stateScope.evalScope, outputNode.schedulable) @@ -213,71 +166,110 @@ internal class BuildScopeImpl(val stateScope: StateScopeImpl, val coroutineScope // Job's already been cancelled, schedule deactivation scheduleDeactivation(outputNode) } else if (needsEval) { - outputNode.schedule(evalScope = stateScope.evalScope) + outputNode.schedule(0, evalScope = stateScope.evalScope) } } ?: run { childScope.cancel() } } - return childScope.coroutineContext.job + return handle } - private fun <A, B> TFlow<A>.mapBuildInternal( - transform: suspend FrpBuildScope.(A) -> B - ): TFlow<B> { + override fun <A, B> Events<A>.mapBuild(transform: BuildScope.(A) -> B): Events<B> { val childScope = coroutineScope.childScope() - return TFlowInit( + return EventsInit( constInit( "mapBuild", - mapImpl({ init.connect(evalScope = this) }) { spec -> + mapImpl({ init.connect(evalScope = this) }) { spec, _ -> reenterBuildScope(outerScope = this@BuildScopeImpl, childScope) - .runInBuildScope { transform(spec) } + .transform(spec) } .cached(), ) ) } - private fun <K, A, B> TFlow<Map<K, Maybe<FrpSpec<A>>>>.applyLatestForKeyInternal( - init: FrpDeferredValue<Map<K, FrpSpec<B>>>, + override fun <K, A, B> Events<Map<K, Maybe<BuildSpec<A>>>>.applyLatestSpecForKey( + initialSpecs: DeferredValue<Map<K, BuildSpec<B>>>, numKeys: Int?, - ): Pair<TFlow<Map<K, Maybe<A>>>, FrpDeferredValue<Map<K, B>>> { - val eventsByKey: GroupedTFlow<K, Maybe<FrpSpec<A>>> = groupByKey(numKeys) - val initOut: Deferred<Map<K, B>> = deferAsync { - init.unwrapped.await().mapValuesParallel { (k, spec) -> - val newEnd = with(frpScope) { eventsByKey[k].skipNext() } + ): Pair<Events<Map<K, Maybe<A>>>, DeferredValue<Map<K, B>>> { + val eventsByKey: GroupedEvents<K, Maybe<BuildSpec<A>>> = groupByKey(numKeys) + val initOut: Lazy<Map<K, B>> = deferAsync { + initialSpecs.unwrapped.value.mapValues { (k, spec) -> + val newEnd = eventsByKey[k] val newScope = childBuildScope(newEnd) - newScope.runInBuildScope(spec) + newScope.spec() } } val childScope = coroutineScope.childScope() - val changesNode: TFlowImpl<Map<K, Maybe<A>>> = - mapImpl(upstream = { this@applyLatestForKeyInternal.init.connect(evalScope = this) }) { - upstreamMap -> + val changesNode: EventsImpl<Map<K, Maybe<A>>> = + mapImpl(upstream = { this@applyLatestSpecForKey.init.connect(evalScope = this) }) { + upstreamMap, + _ -> reenterBuildScope(this@BuildScopeImpl, childScope).run { - upstreamMap.mapValuesParallel { (k: K, ma: Maybe<FrpSpec<A>>) -> + upstreamMap.mapValues { (k: K, ma: Maybe<BuildSpec<A>>) -> ma.map { spec -> - val newEnd = with(frpScope) { eventsByKey[k].skipNext() } + val newEnd = eventsByKey[k].skipNext() val newScope = childBuildScope(newEnd) - newScope.runInBuildScope(spec) + newScope.spec() } } } } - val changes: TFlow<Map<K, Maybe<A>>> = - TFlowInit(constInit("applyLatestForKey", changesNode.cached())) + val changes: Events<Map<K, Maybe<A>>> = + EventsInit(constInit("applyLatestForKey", changesNode.cached())) // Ensure effects are observed; otherwise init will stay alive longer than expected - changes.observeEffectInternal(EmptyCoroutineContext) {} - return changes to FrpDeferredValue(initOut) + changes.observe() + return changes to DeferredValue(initOut) + } + + private fun <A, T : Events<A>, S> buildEvents( + name: String? = null, + constructEvents: (InputNode<A>) -> Pair<T, S>, + builder: suspend S.() -> Unit, + ): Events<A> { + var job: Job? = null + val stopEmitter = newStopEmitter("buildEvents[$name]") + // Create a child scope that will be kept alive beyond the end of this transaction. + val childScope = coroutineScope.childScope() + lateinit var emitter: Pair<T, S> + val inputNode = + InputNode<A>( + activate = { + // It's possible that activation occurs after all effects have been run, due + // to a MuxDeferred switch-in. For this reason, we need to activate in a new + // transaction. + check(job == null) { "[$name] already activated" } + job = + childScope.launchImmediate { + network + .transaction("buildEvents") { + reenterBuildScope(this@BuildScopeImpl, childScope) + .launchEffect { + builder(emitter.second) + stopEmitter.emit(Unit) + } + } + .await() + .join() + } + }, + deactivate = { + checkNotNull(job) { "[$name] already deactivated" }.cancel() + job = null + }, + ) + emitter = constructEvents(inputNode) + return emitter.first.takeUntil(mergeLeft(stopEmitter, endSignal)) } - private fun newStopEmitter(name: String): CoalescingMutableTFlow<Unit, Unit> = - CoalescingMutableTFlow( + private fun newStopEmitter(name: String): CoalescingMutableEvents<Unit, Unit> = + CoalescingMutableEvents( name = name, coalesce = { _, _: Unit -> }, network = network, getInitialValue = {}, ) - private suspend fun childBuildScope(newEnd: TFlow<Any>): BuildScopeImpl { + private fun childBuildScope(newEnd: Events<Any>): BuildScopeImpl { val newCoroutineScope: CoroutineScope = coroutineScope.childScope() return BuildScopeImpl( stateScope = stateScope.childStateScope(newEnd), @@ -292,7 +284,7 @@ internal class BuildScopeImpl(val stateScope: StateScopeImpl, val coroutineScope (newCoroutineScope.coroutineContext.job as CompletableJob).complete() } ) - runInBuildScope { endSignal.nextOnly().observe { newCoroutineScope.cancel() } } + endSignalOnce.observe { newCoroutineScope.cancel() } } } @@ -315,42 +307,6 @@ internal class BuildScopeImpl(val stateScope: StateScopeImpl, val coroutineScope coroutineScope = childScope, ) } - - private inner class FrpBuildScopeImpl : FrpBuildScope, FrpStateScope by stateScope.frpScope { - - override fun <T> tFlow(builder: suspend FrpProducerScope<T>.() -> Unit): TFlow<T> = - tFlowInternal(builder) - - override fun <In, Out> coalescingTFlow( - getInitialValue: () -> Out, - coalesce: (old: Out, new: In) -> Out, - builder: suspend FrpCoalescingProducerScope<In>.() -> Unit, - ): TFlow<Out> = coalescingTFlowInternal(getInitialValue, coalesce, builder) - - override fun <A> asyncScope(block: FrpSpec<A>): Pair<FrpDeferredValue<A>, Job> = - asyncScopeInternal(block) - - override fun <R> deferredBuildScope( - block: suspend FrpBuildScope.() -> R - ): FrpDeferredValue<R> = deferredInternal(block) - - override fun deferredBuildScopeAction(block: suspend FrpBuildScope.() -> Unit) = - deferredActionInternal(block) - - override fun <A> TFlow<A>.observe( - coroutineContext: CoroutineContext, - block: suspend FrpEffectScope.(A) -> Unit, - ): Job = observeEffectInternal(coroutineContext, block) - - override fun <A, B> TFlow<A>.mapBuild(transform: suspend FrpBuildScope.(A) -> B): TFlow<B> = - mapBuildInternal(transform) - - override fun <K, A, B> TFlow<Map<K, Maybe<FrpSpec<A>>>>.applyLatestSpecForKey( - initialSpecs: FrpDeferredValue<Map<K, FrpSpec<B>>>, - numKeys: Int?, - ): Pair<TFlow<Map<K, Maybe<A>>>, FrpDeferredValue<Map<K, B>>> = - applyLatestForKeyInternal(initialSpecs, numKeys) - } } private fun EvalScope.reenterBuildScope( diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/DeferScope.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/DeferScope.kt index f65307c6106f..d2c154f05b37 100644 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/DeferScope.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/DeferScope.kt @@ -16,33 +16,51 @@ package com.android.systemui.kairos.internal -import com.android.systemui.kairos.internal.util.asyncImmediate -import com.android.systemui.kairos.internal.util.launchImmediate -import kotlinx.coroutines.CoroutineName -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.CoroutineStart -import kotlinx.coroutines.Deferred -import kotlinx.coroutines.Job -import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.isActive - -internal typealias DeferScope = CoroutineScope - -internal inline fun DeferScope.deferAction( - start: CoroutineStart = CoroutineStart.UNDISPATCHED, - crossinline block: suspend () -> Unit, -): Job { - check(isActive) { "Cannot perform deferral, scope already closed." } - return launchImmediate(start, CoroutineName("deferAction")) { block() } +internal interface DeferScope { + fun deferAction(block: () -> Unit) + + fun <R> deferAsync(block: () -> R): Lazy<R> } -internal inline fun <R> DeferScope.deferAsync( - start: CoroutineStart = CoroutineStart.UNDISPATCHED, - crossinline block: suspend () -> R, -): Deferred<R> { - check(isActive) { "Cannot perform deferral, scope already closed." } - return asyncImmediate(start, CoroutineName("deferAsync")) { block() } +internal inline fun <A> deferScope(block: DeferScope.() -> A): A { + val scope = + object : DeferScope { + val deferrals = ArrayDeque<() -> Unit>() // TODO: store lazies instead? + + fun drainDeferrals() { + while (deferrals.isNotEmpty()) { + deferrals.removeFirst().invoke() + } + } + + override fun deferAction(block: () -> Unit) { + deferrals.add(block) + } + + override fun <R> deferAsync(block: () -> R): Lazy<R> = + lazy(block).also { deferrals.add { it.value } } + } + return scope.block().also { scope.drainDeferrals() } } -internal suspend inline fun <A> deferScope(noinline block: suspend DeferScope.() -> A): A = - coroutineScope(block) +internal object NoValue + +internal class CompletableLazy<T>( + private var _value: Any? = NoValue, + private val name: String? = null, +) : Lazy<T> { + + fun setValue(value: T) { + check(_value === NoValue) { "CompletableLazy value already set" } + _value = value + } + + override val value: T + get() { + check(_value !== NoValue) { "CompletableLazy($name) accessed before initialized" } + @Suppress("UNCHECKED_CAST") + return _value as T + } + + override fun isInitialized(): Boolean = _value !== NoValue +} diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Demux.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Demux.kt index e7b99528fdfc..4cf24580fa32 100644 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Demux.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Demux.kt @@ -14,270 +14,242 @@ * limitations under the License. */ -@file:Suppress("NOTHING_TO_INLINE") - package com.android.systemui.kairos.internal +import com.android.systemui.kairos.internal.store.ConcurrentHashMapK +import com.android.systemui.kairos.internal.store.MapHolder +import com.android.systemui.kairos.internal.store.MapK +import com.android.systemui.kairos.internal.store.MutableMapK import com.android.systemui.kairos.internal.util.hashString -import com.android.systemui.kairos.util.Just -import com.android.systemui.kairos.util.Maybe -import com.android.systemui.kairos.util.flatMap -import com.android.systemui.kairos.util.getMaybe -import java.util.concurrent.ConcurrentHashMap -import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.async -import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.launch +import com.android.systemui.kairos.internal.util.logDuration import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock -internal class DemuxNode<K, A>( - private val branchNodeByKey: ConcurrentHashMap<K, DemuxBranchNode<K, A>>, +internal class DemuxNode<W, K, A>( + private val branchNodeByKey: MutableMapK<W, K, DemuxNode<W, K, A>.BranchNode>, val lifecycle: DemuxLifecycle<K, A>, - private val spec: DemuxActivator<K, A>, + private val spec: DemuxActivator<W, K, A>, ) : SchedulableNode { val schedulable = Schedulable.N(this) - inline val mutex - get() = lifecycle.mutex - - lateinit var upstreamConnection: NodeConnection<Map<K, A>> - - fun getAndMaybeAddDownstream(key: K): DemuxBranchNode<K, A> = - branchNodeByKey.getOrPut(key) { DemuxBranchNode(key, this) } - - override suspend fun schedule(evalScope: EvalScope) { - val upstreamResult = upstreamConnection.getPushEvent(evalScope) - if (upstreamResult is Just) { - coroutineScope { - val outerScope = this - mutex.withLock { - coroutineScope { - for ((key, _) in upstreamResult.value) { - launch { - branchNodeByKey[key]?.let { branch -> - outerScope.launch { branch.schedule(evalScope) } - } - } - } - } + lateinit var upstreamConnection: NodeConnection<MapK<W, K, A>> + + @Volatile private var epoch: Long = Long.MIN_VALUE + + fun hasCurrentValueLocked(logIndent: Int, evalScope: EvalScope, key: K): Boolean = + evalScope.epoch == epoch && + upstreamConnection.getPushEvent(logIndent, evalScope).contains(key) + + fun hasCurrentValue(logIndent: Int, evalScope: EvalScope, key: K): Boolean = + hasCurrentValueLocked(logIndent, evalScope, key) + + fun getAndMaybeAddDownstream(key: K): BranchNode = + branchNodeByKey.getOrPut(key) { BranchNode(key) } + + override fun schedule(logIndent: Int, evalScope: EvalScope) = + logDuration(logIndent, "DemuxNode.schedule") { + val upstreamResult = + logDuration("upstream.getPushEvent") { + upstreamConnection.getPushEvent(currentLogIndent, evalScope) } + updateEpoch(evalScope) + for ((key, _) in upstreamResult) { + if (!branchNodeByKey.contains(key)) continue + val branch = branchNodeByKey.getValue(key) + branch.schedule(currentLogIndent, evalScope) } } - } - override suspend fun adjustDirectUpstream(scheduler: Scheduler, oldDepth: Int, newDepth: Int) { - coroutineScope { - mutex.withLock { - for ((_, branchNode) in branchNodeByKey) { - branchNode.downstreamSet.adjustDirectUpstream( - coroutineScope = this, - scheduler, - oldDepth, - newDepth, - ) - } - } + override fun adjustDirectUpstream(scheduler: Scheduler, oldDepth: Int, newDepth: Int) { + for ((_, branchNode) in branchNodeByKey) { + branchNode.downstreamSet.adjustDirectUpstream(scheduler, oldDepth, newDepth) } } - override suspend fun moveIndirectUpstreamToDirect( + override fun moveIndirectUpstreamToDirect( scheduler: Scheduler, oldIndirectDepth: Int, - oldIndirectSet: Set<MuxDeferredNode<*, *>>, + oldIndirectSet: Set<MuxDeferredNode<*, *, *>>, newDirectDepth: Int, ) { - coroutineScope { - mutex.withLock { - for ((_, branchNode) in branchNodeByKey) { - branchNode.downstreamSet.moveIndirectUpstreamToDirect( - coroutineScope = this, - scheduler, - oldIndirectDepth, - oldIndirectSet, - newDirectDepth, - ) - } - } + for ((_, branchNode) in branchNodeByKey) { + branchNode.downstreamSet.moveIndirectUpstreamToDirect( + scheduler, + oldIndirectDepth, + oldIndirectSet, + newDirectDepth, + ) } } - override suspend fun adjustIndirectUpstream( + override fun adjustIndirectUpstream( scheduler: Scheduler, oldDepth: Int, newDepth: Int, - removals: Set<MuxDeferredNode<*, *>>, - additions: Set<MuxDeferredNode<*, *>>, + removals: Set<MuxDeferredNode<*, *, *>>, + additions: Set<MuxDeferredNode<*, *, *>>, ) { - coroutineScope { - mutex.withLock { - for ((_, branchNode) in branchNodeByKey) { - branchNode.downstreamSet.adjustIndirectUpstream( - coroutineScope = this, - scheduler, - oldDepth, - newDepth, - removals, - additions, - ) - } - } + for ((_, branchNode) in branchNodeByKey) { + branchNode.downstreamSet.adjustIndirectUpstream( + scheduler, + oldDepth, + newDepth, + removals, + additions, + ) } } - override suspend fun moveDirectUpstreamToIndirect( + override fun moveDirectUpstreamToIndirect( scheduler: Scheduler, oldDirectDepth: Int, newIndirectDepth: Int, - newIndirectSet: Set<MuxDeferredNode<*, *>>, + newIndirectSet: Set<MuxDeferredNode<*, *, *>>, ) { - coroutineScope { - mutex.withLock { - for ((_, branchNode) in branchNodeByKey) { - branchNode.downstreamSet.moveDirectUpstreamToIndirect( - coroutineScope = this, - scheduler, - oldDirectDepth, - newIndirectDepth, - newIndirectSet, - ) - } - } + for ((_, branchNode) in branchNodeByKey) { + branchNode.downstreamSet.moveDirectUpstreamToIndirect( + scheduler, + oldDirectDepth, + newIndirectDepth, + newIndirectSet, + ) } } - override suspend fun removeIndirectUpstream( + override fun removeIndirectUpstream( scheduler: Scheduler, depth: Int, - indirectSet: Set<MuxDeferredNode<*, *>>, + indirectSet: Set<MuxDeferredNode<*, *, *>>, ) { - coroutineScope { - mutex.withLock { - lifecycle.lifecycleState = DemuxLifecycleState.Dead - for ((_, branchNode) in branchNodeByKey) { - branchNode.downstreamSet.removeIndirectUpstream( - coroutineScope = this, - scheduler, - depth, - indirectSet, - ) - } - } + lifecycle.lifecycleState = DemuxLifecycleState.Dead + for ((_, branchNode) in branchNodeByKey) { + branchNode.downstreamSet.removeIndirectUpstream(scheduler, depth, indirectSet) } } - override suspend fun removeDirectUpstream(scheduler: Scheduler, depth: Int) { - coroutineScope { - mutex.withLock { - lifecycle.lifecycleState = DemuxLifecycleState.Dead - for ((_, branchNode) in branchNodeByKey) { - branchNode.downstreamSet.removeDirectUpstream( - coroutineScope = this, - scheduler, - depth, - ) - } - } + override fun removeDirectUpstream(scheduler: Scheduler, depth: Int) { + lifecycle.lifecycleState = DemuxLifecycleState.Dead + for ((_, branchNode) in branchNodeByKey) { + branchNode.downstreamSet.removeDirectUpstream(scheduler, depth) } } - suspend fun removeDownstreamAndDeactivateIfNeeded(key: K) { - val deactivate = - mutex.withLock { - branchNodeByKey.remove(key) - branchNodeByKey.isEmpty() - } + fun removeDownstreamAndDeactivateIfNeeded(key: K) { + branchNodeByKey.remove(key) + val deactivate = branchNodeByKey.isEmpty() if (deactivate) { // No need for mutex here; no more concurrent changes to can occur during this phase lifecycle.lifecycleState = DemuxLifecycleState.Inactive(spec) upstreamConnection.removeDownstreamAndDeactivateIfNeeded(downstream = schedulable) } } -} -internal class DemuxBranchNode<K, A>(val key: K, private val demuxNode: DemuxNode<K, A>) : - PushNode<A> { + fun updateEpoch(evalScope: EvalScope) { + epoch = evalScope.epoch + } - private val mutex = Mutex() + fun getPushEvent(logIndent: Int, evalScope: EvalScope, key: K): A = + logDuration(logIndent, "Demux.getPushEvent($key)") { + upstreamConnection.getPushEvent(currentLogIndent, evalScope).getValue(key) + } - val downstreamSet = DownstreamSet() + inner class BranchNode(val key: K) : PushNode<A> { - override val depthTracker: DepthTracker - get() = demuxNode.upstreamConnection.depthTracker + val downstreamSet = DownstreamSet() - override suspend fun hasCurrentValue(transactionStore: TransactionStore): Boolean = - demuxNode.upstreamConnection.hasCurrentValue(transactionStore) + override val depthTracker: DepthTracker + get() = upstreamConnection.depthTracker - override suspend fun getPushEvent(evalScope: EvalScope): Maybe<A> = - demuxNode.upstreamConnection.getPushEvent(evalScope).flatMap { it.getMaybe(key) } + override fun hasCurrentValue(logIndent: Int, evalScope: EvalScope): Boolean = + hasCurrentValue(logIndent, evalScope, key) - override suspend fun addDownstream(downstream: Schedulable) { - mutex.withLock { downstreamSet.add(downstream) } - } + override fun getPushEvent(logIndent: Int, evalScope: EvalScope): A = + getPushEvent(logIndent, evalScope, key) - override suspend fun removeDownstream(downstream: Schedulable) { - mutex.withLock { downstreamSet.remove(downstream) } - } + override fun addDownstream(downstream: Schedulable) { + downstreamSet.add(downstream) + } + + override fun removeDownstream(downstream: Schedulable) { + downstreamSet.remove(downstream) + } - override suspend fun removeDownstreamAndDeactivateIfNeeded(downstream: Schedulable) { - val canDeactivate = - mutex.withLock { - downstreamSet.remove(downstream) - downstreamSet.isEmpty() + override fun removeDownstreamAndDeactivateIfNeeded(downstream: Schedulable) { + downstreamSet.remove(downstream) + val canDeactivate = downstreamSet.isEmpty() + if (canDeactivate) { + removeDownstreamAndDeactivateIfNeeded(key) } - if (canDeactivate) { - demuxNode.removeDownstreamAndDeactivateIfNeeded(key) } - } - override suspend fun deactivateIfNeeded() { - if (mutex.withLock { downstreamSet.isEmpty() }) { - demuxNode.removeDownstreamAndDeactivateIfNeeded(key) + override fun deactivateIfNeeded() { + if (downstreamSet.isEmpty()) { + removeDownstreamAndDeactivateIfNeeded(key) + } } - } - override suspend fun scheduleDeactivationIfNeeded(evalScope: EvalScope) { - if (mutex.withLock { downstreamSet.isEmpty() }) { - evalScope.scheduleDeactivation(this) + override fun scheduleDeactivationIfNeeded(evalScope: EvalScope) { + if (downstreamSet.isEmpty()) { + evalScope.scheduleDeactivation(this) + } } - } - suspend fun schedule(evalScope: EvalScope) { - if (!coroutineScope { mutex.withLock { scheduleAll(downstreamSet, evalScope) } }) { - evalScope.scheduleDeactivation(this) + fun schedule(logIndent: Int, evalScope: EvalScope) { + logDuration(logIndent, "DemuxBranchNode($key).schedule") { + if (!scheduleAll(currentLogIndent, downstreamSet, evalScope)) { + evalScope.scheduleDeactivation(this@BranchNode) + } + } } } } -internal fun <K, A> DemuxImpl( - upstream: suspend EvalScope.() -> TFlowImpl<Map<K, A>>, +internal fun <W, K, A> DemuxImpl( + upstream: EventsImpl<MapK<W, K, A>>, numKeys: Int?, + storeFactory: MutableMapK.Factory<W, K>, ): DemuxImpl<K, A> = DemuxImpl( DemuxLifecycle( - object : DemuxActivator<K, A> { - override suspend fun activate( - evalScope: EvalScope, - lifecycle: DemuxLifecycle<K, A>, - ): Pair<DemuxNode<K, A>, Boolean>? { - val dmux = DemuxNode(ConcurrentHashMap(numKeys ?: 16), lifecycle, this) - return upstream - .invoke(evalScope) - .activate(evalScope, downstream = dmux.schedulable) - ?.let { (conn, needsEval) -> - dmux.apply { upstreamConnection = conn } to needsEval - } - } - } + DemuxLifecycleState.Inactive(DemuxActivator(numKeys, upstream, storeFactory)) ) ) +internal fun <K, A> demuxMap( + upstream: EvalScope.() -> EventsImpl<Map<K, A>>, + numKeys: Int?, +): DemuxImpl<K, A> = + DemuxImpl(mapImpl(upstream) { it, _ -> MapHolder(it) }, numKeys, ConcurrentHashMapK.Factory()) + +internal class DemuxActivator<W, K, A>( + private val numKeys: Int?, + private val upstream: EventsImpl<MapK<W, K, A>>, + private val storeFactory: MutableMapK.Factory<W, K>, +) { + fun activate( + evalScope: EvalScope, + lifecycle: DemuxLifecycle<K, A>, + ): Pair<DemuxNode<W, K, A>, Set<K>>? { + val demux = DemuxNode(storeFactory.create(numKeys), lifecycle, this) + return upstream.activate(evalScope, demux.schedulable)?.let { (conn, needsEval) -> + Pair( + demux.apply { upstreamConnection = conn }, + if (needsEval) { + demux.updateEpoch(evalScope) + conn.getPushEvent(0, evalScope).keys + } else { + emptySet() + }, + ) + } + } +} + internal class DemuxImpl<in K, out A>(private val dmux: DemuxLifecycle<K, A>) { - fun eventsForKey(key: K): TFlowImpl<A> = TFlowCheap { downstream -> + fun eventsForKey(key: K): EventsImpl<A> = EventsImplCheap { downstream -> dmux.activate(evalScope = this, key)?.let { (branchNode, needsEval) -> branchNode.addDownstream(downstream) - val branchNeedsEval = needsEval && branchNode.getPushEvent(evalScope = this) is Just + val branchNeedsEval = needsEval && branchNode.hasCurrentValue(0, evalScope = this) ActivationResult( connection = NodeConnection(branchNode, branchNode), needsEval = branchNeedsEval, @@ -289,61 +261,45 @@ internal class DemuxImpl<in K, out A>(private val dmux: DemuxLifecycle<K, A>) { internal class DemuxLifecycle<K, A>(@Volatile var lifecycleState: DemuxLifecycleState<K, A>) { val mutex = Mutex() - override fun toString(): String = "TFlowDmuxState[$hashString][$lifecycleState][$mutex]" - - suspend fun activate(evalScope: EvalScope, key: K): Pair<DemuxBranchNode<K, A>, Boolean>? = - coroutineScope { - mutex - .withLock { - when (val state = lifecycleState) { - is DemuxLifecycleState.Dead -> null - is DemuxLifecycleState.Active -> - state.node.getAndMaybeAddDownstream(key) to - async { - state.node.upstreamConnection.hasCurrentValue( - evalScope.transactionStore - ) - } - is DemuxLifecycleState.Inactive -> { - state.spec - .activate(evalScope, this@DemuxLifecycle) - .also { result -> - lifecycleState = - if (result == null) { - DemuxLifecycleState.Dead - } else { - DemuxLifecycleState.Active(result.first) - } - } - ?.let { (node, needsEval) -> - node.getAndMaybeAddDownstream(key) to - CompletableDeferred(needsEval) - } - } + override fun toString(): String = "EventsDmuxState[$hashString][$lifecycleState][$mutex]" + + fun activate(evalScope: EvalScope, key: K): Pair<DemuxNode<*, K, A>.BranchNode, Boolean>? = + when (val state = lifecycleState) { + is DemuxLifecycleState.Dead -> { + null + } + + is DemuxLifecycleState.Active -> { + state.node.getAndMaybeAddDownstream(key) to + state.node.hasCurrentValueLocked(0, evalScope, key) + } + + is DemuxLifecycleState.Inactive -> { + state.spec + .activate(evalScope, this@DemuxLifecycle) + .also { result -> + lifecycleState = + if (result == null) { + DemuxLifecycleState.Dead + } else { + DemuxLifecycleState.Active(result.first) + } } - } - ?.let { (branch, result) -> branch to result.await() } + ?.let { (node, needsEval) -> + node.getAndMaybeAddDownstream(key) to (key in needsEval) + } + } } } internal sealed interface DemuxLifecycleState<out K, out A> { - class Inactive<K, A>(val spec: DemuxActivator<K, A>) : DemuxLifecycleState<K, A> { + class Inactive<K, A>(val spec: DemuxActivator<*, K, A>) : DemuxLifecycleState<K, A> { override fun toString(): String = "Inactive" } - class Active<K, A>(val node: DemuxNode<K, A>) : DemuxLifecycleState<K, A> { + class Active<K, A>(val node: DemuxNode<*, K, A>) : DemuxLifecycleState<K, A> { override fun toString(): String = "Active(node=$node)" } data object Dead : DemuxLifecycleState<Nothing, Nothing> } - -internal interface DemuxActivator<K, A> { - suspend fun activate( - evalScope: EvalScope, - lifecycle: DemuxLifecycle<K, A>, - ): Pair<DemuxNode<K, A>, Boolean>? -} - -internal inline fun <K, A> DemuxLifecycle(onSubscribe: DemuxActivator<K, A>) = - DemuxLifecycle(DemuxLifecycleState.Inactive(onSubscribe)) diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/EvalScopeImpl.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/EvalScopeImpl.kt index 815473fe900f..80a294819fac 100644 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/EvalScopeImpl.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/EvalScopeImpl.kt @@ -16,57 +16,54 @@ package com.android.systemui.kairos.internal -import com.android.systemui.kairos.FrpDeferredValue -import com.android.systemui.kairos.FrpTransactionScope -import com.android.systemui.kairos.TFlow -import com.android.systemui.kairos.TFlowInit -import com.android.systemui.kairos.TFlowLoop -import com.android.systemui.kairos.TState -import com.android.systemui.kairos.TStateInit +import com.android.systemui.kairos.DeferredValue +import com.android.systemui.kairos.Events +import com.android.systemui.kairos.EventsInit +import com.android.systemui.kairos.EventsLoop +import com.android.systemui.kairos.State +import com.android.systemui.kairos.StateInit +import com.android.systemui.kairos.TransactionScope import com.android.systemui.kairos.Transactional -import com.android.systemui.kairos.emptyTFlow +import com.android.systemui.kairos.emptyEvents import com.android.systemui.kairos.init import com.android.systemui.kairos.mapCheap -import com.android.systemui.kairos.switch -import kotlin.coroutines.Continuation -import kotlin.coroutines.CoroutineContext -import kotlin.coroutines.EmptyCoroutineContext -import kotlin.coroutines.startCoroutine -import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.completeWith -import kotlinx.coroutines.job +import com.android.systemui.kairos.switchEvents internal class EvalScopeImpl(networkScope: NetworkScope, deferScope: DeferScope) : - EvalScope, NetworkScope by networkScope, DeferScope by deferScope { - - private suspend fun <A> Transactional<A>.sample(): A = - impl.sample().sample(this@EvalScopeImpl).await() - - private suspend fun <A> TState<A>.sample(): A = - init.connect(evalScope = this@EvalScopeImpl).getCurrentWithEpoch(this@EvalScopeImpl).first - - private val <A> Transactional<A>.deferredValue: FrpDeferredValue<A> - get() = FrpDeferredValue(deferAsync { sample() }) + EvalScope, NetworkScope by networkScope, DeferScope by deferScope, TransactionScope { + + override fun <A> Transactional<A>.sampleDeferred(): DeferredValue<A> = + DeferredValue(deferAsync { impl.sample().sample(this@EvalScopeImpl).value }) + + override fun <A> State<A>.sampleDeferred(): DeferredValue<A> = + DeferredValue( + deferAsync { + init + .connect(evalScope = this@EvalScopeImpl) + .getCurrentWithEpoch(this@EvalScopeImpl) + .first + } + ) - private val <A> TState<A>.deferredValue: FrpDeferredValue<A> - get() = FrpDeferredValue(deferAsync { sample() }) + override fun <R> deferredTransactionScope(block: TransactionScope.() -> R): DeferredValue<R> = + DeferredValue(deferAsync { block() }) - private val nowInternal: TFlow<Unit> by lazy { - var result by TFlowLoop<Unit>() + override val now: Events<Unit> by lazy { + var result by EventsLoop<Unit>() result = - TStateInit( + StateInit( constInit( "now", - mkState( + activatedStateSource( "now", "now", this, - { result.mapCheap { emptyTFlow }.init.connect(evalScope = this) }, - CompletableDeferred( - TFlowInit( + { result.mapCheap { emptyEvents }.init.connect(evalScope = this) }, + CompletableLazy( + EventsInit( constInit( "now", - TFlowCheap { + EventsImplCheap { ActivationResult( connection = NodeConnection(AlwaysNode, AlwaysNode), needsEval = true, @@ -78,42 +75,7 @@ internal class EvalScopeImpl(networkScope: NetworkScope, deferScope: DeferScope) ), ) ) - .switch() + .switchEvents() result } - - private fun <R> deferredInternal( - block: suspend FrpTransactionScope.() -> R - ): FrpDeferredValue<R> = FrpDeferredValue(deferAsync { runInTransactionScope(block) }) - - override suspend fun <R> runInTransactionScope(block: suspend FrpTransactionScope.() -> R): R { - val complete = CompletableDeferred<R>(parent = coroutineContext.job) - block.startCoroutine( - frpScope, - object : Continuation<R> { - override val context: CoroutineContext - get() = EmptyCoroutineContext - - override fun resumeWith(result: Result<R>) { - complete.completeWith(result) - } - }, - ) - return complete.await() - } - - override val frpScope: FrpTransactionScope = FrpTransactionScopeImpl() - - inner class FrpTransactionScopeImpl : FrpTransactionScope { - override fun <A> Transactional<A>.sampleDeferred(): FrpDeferredValue<A> = deferredValue - - override fun <A> TState<A>.sampleDeferred(): FrpDeferredValue<A> = deferredValue - - override fun <R> deferredTransactionScope( - block: suspend FrpTransactionScope.() -> R - ): FrpDeferredValue<R> = deferredInternal(block) - - override val now: TFlow<Unit> - get() = nowInternal - } } diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/TFlowImpl.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/EventsImpl.kt index b904b48f7f9c..59c5e7244aa2 100644 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/TFlowImpl.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/EventsImpl.kt @@ -16,11 +16,9 @@ package com.android.systemui.kairos.internal -import com.android.systemui.kairos.util.Maybe - -/* Initialized TFlow */ -internal fun interface TFlowImpl<out A> { - suspend fun activate(evalScope: EvalScope, downstream: Schedulable): ActivationResult<A>? +/* Initialized Events */ +internal fun interface EventsImpl<out A> { + fun activate(evalScope: EvalScope, downstream: Schedulable): ActivationResult<A>? } internal data class ActivationResult<out A>( @@ -28,35 +26,33 @@ internal data class ActivationResult<out A>( val needsEval: Boolean, ) -internal inline fun <A> TFlowCheap(crossinline cheap: CheapNodeSubscribe<A>) = - TFlowImpl { scope, ds -> +internal inline fun <A> EventsImplCheap(crossinline cheap: CheapNodeSubscribe<A>) = + EventsImpl { scope, ds -> scope.cheap(ds) } internal typealias CheapNodeSubscribe<A> = - suspend EvalScope.(downstream: Schedulable) -> ActivationResult<A>? + EvalScope.(downstream: Schedulable) -> ActivationResult<A>? internal data class NodeConnection<out A>( val directUpstream: PullNode<A>, val schedulerUpstream: PushNode<*>, ) -internal suspend fun <A> NodeConnection<A>.hasCurrentValue( - transactionStore: TransactionStore -): Boolean = schedulerUpstream.hasCurrentValue(transactionStore) +internal fun <A> NodeConnection<A>.hasCurrentValue(logIndent: Int, evalScope: EvalScope): Boolean = + schedulerUpstream.hasCurrentValue(logIndent, evalScope) -internal suspend fun <A> NodeConnection<A>.removeDownstreamAndDeactivateIfNeeded( - downstream: Schedulable -) = schedulerUpstream.removeDownstreamAndDeactivateIfNeeded(downstream) +internal fun <A> NodeConnection<A>.removeDownstreamAndDeactivateIfNeeded(downstream: Schedulable) = + schedulerUpstream.removeDownstreamAndDeactivateIfNeeded(downstream) -internal suspend fun <A> NodeConnection<A>.scheduleDeactivationIfNeeded(evalScope: EvalScope) = +internal fun <A> NodeConnection<A>.scheduleDeactivationIfNeeded(evalScope: EvalScope) = schedulerUpstream.scheduleDeactivationIfNeeded(evalScope) -internal suspend fun <A> NodeConnection<A>.removeDownstream(downstream: Schedulable) = +internal fun <A> NodeConnection<A>.removeDownstream(downstream: Schedulable) = schedulerUpstream.removeDownstream(downstream) -internal suspend fun <A> NodeConnection<A>.getPushEvent(evalScope: EvalScope): Maybe<A> = - directUpstream.getPushEvent(evalScope) +internal fun <A> NodeConnection<A>.getPushEvent(logIndent: Int, evalScope: EvalScope): A = + directUpstream.getPushEvent(logIndent, evalScope) internal val <A> NodeConnection<A>.depthTracker: DepthTracker get() = schedulerUpstream.depthTracker diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/FilterNode.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/FilterNode.kt index bc06a3679d5c..9496b06c6bd1 100644 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/FilterNode.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/FilterNode.kt @@ -16,32 +16,33 @@ package com.android.systemui.kairos.internal -import com.android.systemui.kairos.util.Just +import com.android.systemui.kairos.internal.store.Single +import com.android.systemui.kairos.internal.store.SingletonMapK import com.android.systemui.kairos.util.Maybe +import com.android.systemui.kairos.util.Maybe.Just import com.android.systemui.kairos.util.just import com.android.systemui.kairos.util.none -internal inline fun <A, B> mapMaybeNode( - crossinline getPulse: suspend EvalScope.() -> TFlowImpl<A>, - crossinline f: suspend EvalScope.(A) -> Maybe<B>, -): TFlowImpl<B> { - return DemuxImpl( - { - mapImpl(getPulse) { - val maybeResult = f(it) - if (maybeResult is Just) { - mapOf(Unit to maybeResult.value) - } else { - emptyMap() - } +internal inline fun <A> filterJustImpl( + crossinline getPulse: EvalScope.() -> EventsImpl<Maybe<A>> +): EventsImpl<A> = + DemuxImpl( + mapImpl(getPulse) { maybeResult, _ -> + if (maybeResult is Just) { + Single(maybeResult.value) + } else { + Single<A>() } }, numKeys = 1, + storeFactory = SingletonMapK.Factory(), ) .eventsForKey(Unit) -} -internal inline fun <A> filterNode( - crossinline getPulse: suspend EvalScope.() -> TFlowImpl<A>, - crossinline f: suspend EvalScope.(A) -> Boolean, -): TFlowImpl<A> = mapMaybeNode(getPulse) { if (f(it)) just(it) else none } +internal inline fun <A> filterImpl( + crossinline getPulse: EvalScope.() -> EventsImpl<A>, + crossinline f: EvalScope.(A) -> Boolean, +): EventsImpl<A> { + val mapped = mapImpl(getPulse) { it, _ -> if (f(it)) just(it) else none }.cached() + return filterJustImpl { mapped } +} diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Graph.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Graph.kt index 04ce5b6d8785..b956e44e0618 100644 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Graph.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Graph.kt @@ -18,8 +18,6 @@ package com.android.systemui.kairos.internal import com.android.systemui.kairos.internal.util.Bag import java.util.TreeMap -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.launch /** * Tracks all upstream connections for Mux nodes. @@ -72,15 +70,15 @@ internal class DepthTracker { @Volatile var snapshotIndirectDepth: Int = 0 @Volatile var snapshotDirectDepth: Int = 0 - private val _snapshotIndirectRoots = HashSet<MuxDeferredNode<*, *>>() + private val _snapshotIndirectRoots = HashSet<MuxDeferredNode<*, *, *>>() val snapshotIndirectRoots get() = _snapshotIndirectRoots.toSet() - private val indirectAdditions = HashSet<MuxDeferredNode<*, *>>() - private val indirectRemovals = HashSet<MuxDeferredNode<*, *>>() + private val indirectAdditions = HashSet<MuxDeferredNode<*, *, *>>() + private val indirectRemovals = HashSet<MuxDeferredNode<*, *, *>>() private val dirty_directUpstreamDepths = TreeMap<Int, Int>() private val dirty_indirectUpstreamDepths = TreeMap<Int, Int>() - private val dirty_indirectUpstreamRoots = Bag<MuxDeferredNode<*, *>>() + private val dirty_indirectUpstreamRoots = Bag<MuxDeferredNode<*, *, *>>() @Volatile var dirty_directDepth = 0 @Volatile private var dirty_indirectDepth = 0 @Volatile private var dirty_depthIsDirect = true @@ -161,9 +159,9 @@ internal class DepthTracker { } fun updateIndirectRoots( - additions: Set<MuxDeferredNode<*, *>>? = null, - removals: Set<MuxDeferredNode<*, *>>? = null, - butNot: MuxDeferredNode<*, *>? = null, + additions: Set<MuxDeferredNode<*, *, *>>? = null, + removals: Set<MuxDeferredNode<*, *, *>>? = null, + butNot: MuxDeferredNode<*, *, *>? = null, ): Boolean { val addsChanged = additions @@ -192,14 +190,13 @@ internal class DepthTracker { return remainder } - suspend fun propagateChanges(scheduler: Scheduler, muxNode: MuxNode<*, *, *>) { + fun propagateChanges(scheduler: Scheduler, muxNode: MuxNode<*, *, *>) { if (isDirty()) { schedule(scheduler, muxNode) } } fun applyChanges( - coroutineScope: CoroutineScope, scheduler: Scheduler, downstreamSet: DownstreamSet, muxNode: MuxNode<*, *, *>, @@ -208,21 +205,19 @@ internal class DepthTracker { dirty_depthIsDirect -> { if (snapshotIsDirect) { downstreamSet.adjustDirectUpstream( - coroutineScope, scheduler, oldDepth = snapshotDirectDepth, newDepth = dirty_directDepth, ) } else { downstreamSet.moveIndirectUpstreamToDirect( - coroutineScope, scheduler, oldIndirectDepth = snapshotIndirectDepth, oldIndirectSet = buildSet { addAll(snapshotIndirectRoots) if (snapshotIsIndirectRoot) { - add(muxNode as MuxDeferredNode<*, *>) + add(muxNode as MuxDeferredNode<*, *, *>) } }, newDirectDepth = dirty_directDepth, @@ -233,7 +228,6 @@ internal class DepthTracker { dirty_hasIndirectUpstream() || dirty_isIndirectRoot -> { if (snapshotIsDirect) { downstreamSet.moveDirectUpstreamToIndirect( - coroutineScope, scheduler, oldDirectDepth = snapshotDirectDepth, newIndirectDepth = dirty_indirectDepth, @@ -241,13 +235,12 @@ internal class DepthTracker { buildSet { addAll(dirty_indirectUpstreamRoots) if (dirty_isIndirectRoot) { - add(muxNode as MuxDeferredNode<*, *>) + add(muxNode as MuxDeferredNode<*, *, *>) } }, ) } else { downstreamSet.adjustIndirectUpstream( - coroutineScope, scheduler, oldDepth = snapshotIndirectDepth, newDepth = dirty_indirectDepth, @@ -255,14 +248,14 @@ internal class DepthTracker { buildSet { addAll(indirectRemovals) if (snapshotIsIndirectRoot && !dirty_isIndirectRoot) { - add(muxNode as MuxDeferredNode<*, *>) + add(muxNode as MuxDeferredNode<*, *, *>) } }, additions = buildSet { addAll(indirectAdditions) if (!snapshotIsIndirectRoot && dirty_isIndirectRoot) { - add(muxNode as MuxDeferredNode<*, *>) + add(muxNode as MuxDeferredNode<*, *, *>) } }, ) @@ -274,21 +267,16 @@ internal class DepthTracker { muxNode.lifecycle.lifecycleState = MuxLifecycleState.Dead if (snapshotIsDirect) { - downstreamSet.removeDirectUpstream( - coroutineScope, - scheduler, - depth = snapshotDirectDepth, - ) + downstreamSet.removeDirectUpstream(scheduler, depth = snapshotDirectDepth) } else { downstreamSet.removeIndirectUpstream( - coroutineScope, scheduler, depth = snapshotIndirectDepth, indirectSet = buildSet { addAll(snapshotIndirectRoots) if (snapshotIsIndirectRoot) { - add(muxNode as MuxDeferredNode<*, *>) + add(muxNode as MuxDeferredNode<*, *, *>) } }, ) @@ -352,8 +340,8 @@ internal class DepthTracker { internal class DownstreamSet { val outputs = HashSet<Output<*>>() - val stateWriters = mutableListOf<TStateSource<*>>() - val muxMovers = HashSet<MuxDeferredNode<*, *>>() + val stateWriters = mutableListOf<StateSource<*>>() + val muxMovers = HashSet<MuxDeferredNode<*, *, *>>() val nodes = HashSet<SchedulableNode>() fun add(schedulable: Schedulable) { @@ -374,125 +362,92 @@ internal class DownstreamSet { } } - fun adjustDirectUpstream( - coroutineScope: CoroutineScope, - scheduler: Scheduler, - oldDepth: Int, - newDepth: Int, - ) = - coroutineScope.run { - for (node in nodes) { - launch { node.adjustDirectUpstream(scheduler, oldDepth, newDepth) } - } + fun adjustDirectUpstream(scheduler: Scheduler, oldDepth: Int, newDepth: Int) { + for (node in nodes) { + node.adjustDirectUpstream(scheduler, oldDepth, newDepth) } + } fun moveIndirectUpstreamToDirect( - coroutineScope: CoroutineScope, scheduler: Scheduler, oldIndirectDepth: Int, - oldIndirectSet: Set<MuxDeferredNode<*, *>>, + oldIndirectSet: Set<MuxDeferredNode<*, *, *>>, newDirectDepth: Int, - ) = - coroutineScope.run { - for (node in nodes) { - launch { - node.moveIndirectUpstreamToDirect( - scheduler, - oldIndirectDepth, - oldIndirectSet, - newDirectDepth, - ) - } - } - for (mover in muxMovers) { - launch { - mover.moveIndirectPatchNodeToDirect(scheduler, oldIndirectDepth, oldIndirectSet) - } - } + ) { + for (node in nodes) { + node.moveIndirectUpstreamToDirect( + scheduler, + oldIndirectDepth, + oldIndirectSet, + newDirectDepth, + ) + } + for (mover in muxMovers) { + mover.moveIndirectPatchNodeToDirect(scheduler, oldIndirectDepth, oldIndirectSet) } + } fun adjustIndirectUpstream( - coroutineScope: CoroutineScope, scheduler: Scheduler, oldDepth: Int, newDepth: Int, - removals: Set<MuxDeferredNode<*, *>>, - additions: Set<MuxDeferredNode<*, *>>, - ) = - coroutineScope.run { - for (node in nodes) { - launch { - node.adjustIndirectUpstream(scheduler, oldDepth, newDepth, removals, additions) - } - } - for (mover in muxMovers) { - launch { - mover.adjustIndirectPatchNode( - scheduler, - oldDepth, - newDepth, - removals, - additions, - ) - } - } + removals: Set<MuxDeferredNode<*, *, *>>, + additions: Set<MuxDeferredNode<*, *, *>>, + ) { + for (node in nodes) { + node.adjustIndirectUpstream(scheduler, oldDepth, newDepth, removals, additions) + } + for (mover in muxMovers) { + mover.adjustIndirectPatchNode(scheduler, oldDepth, newDepth, removals, additions) } + } fun moveDirectUpstreamToIndirect( - coroutineScope: CoroutineScope, scheduler: Scheduler, oldDirectDepth: Int, newIndirectDepth: Int, - newIndirectSet: Set<MuxDeferredNode<*, *>>, - ) = - coroutineScope.run { - for (node in nodes) { - launch { - node.moveDirectUpstreamToIndirect( - scheduler, - oldDirectDepth, - newIndirectDepth, - newIndirectSet, - ) - } - } - for (mover in muxMovers) { - launch { - mover.moveDirectPatchNodeToIndirect(scheduler, newIndirectDepth, newIndirectSet) - } - } + newIndirectSet: Set<MuxDeferredNode<*, *, *>>, + ) { + for (node in nodes) { + node.moveDirectUpstreamToIndirect( + scheduler, + oldDirectDepth, + newIndirectDepth, + newIndirectSet, + ) + } + for (mover in muxMovers) { + mover.moveDirectPatchNodeToIndirect(scheduler, newIndirectDepth, newIndirectSet) } + } fun removeIndirectUpstream( - coroutineScope: CoroutineScope, scheduler: Scheduler, depth: Int, - indirectSet: Set<MuxDeferredNode<*, *>>, - ) = - coroutineScope.run { - for (node in nodes) { - launch { node.removeIndirectUpstream(scheduler, depth, indirectSet) } - } - for (mover in muxMovers) { - launch { mover.removeIndirectPatchNode(scheduler, depth, indirectSet) } - } - for (output in outputs) { - launch { output.kill() } - } + indirectSet: Set<MuxDeferredNode<*, *, *>>, + ) { + for (node in nodes) { + node.removeIndirectUpstream(scheduler, depth, indirectSet) + } + for (mover in muxMovers) { + mover.removeIndirectPatchNode(scheduler, depth, indirectSet) } + for (output in outputs) { + output.kill() + } + } - fun removeDirectUpstream(coroutineScope: CoroutineScope, scheduler: Scheduler, depth: Int) = - coroutineScope.run { - for (node in nodes) { - launch { node.removeDirectUpstream(scheduler, depth) } - } - for (mover in muxMovers) { - launch { mover.removeDirectPatchNode(scheduler) } - } - for (output in outputs) { - launch { output.kill() } - } + fun removeDirectUpstream(scheduler: Scheduler, depth: Int) { + for (node in nodes) { + node.removeDirectUpstream(scheduler, depth) + } + for (mover in muxMovers) { + mover.removeDirectPatchNode(scheduler) } + for (output in outputs) { + output.kill() + } + } fun clear() { outputs.clear() @@ -504,9 +459,9 @@ internal class DownstreamSet { // TODO: remove this indirection internal sealed interface Schedulable { - data class S constructor(val state: TStateSource<*>) : Schedulable + data class S constructor(val state: StateSource<*>) : Schedulable - data class M constructor(val muxMover: MuxDeferredNode<*, *>) : Schedulable + data class M constructor(val muxMover: MuxDeferredNode<*, *, *>) : Schedulable data class N constructor(val node: SchedulableNode) : Schedulable @@ -518,13 +473,14 @@ internal fun DownstreamSet.isEmpty() = @Suppress("NOTHING_TO_INLINE") internal inline fun DownstreamSet.isNotEmpty() = !isEmpty() -internal fun CoroutineScope.scheduleAll( +internal fun scheduleAll( + logIndent: Int, downstreamSet: DownstreamSet, evalScope: EvalScope, ): Boolean { - downstreamSet.nodes.forEach { launch { it.schedule(evalScope) } } - downstreamSet.muxMovers.forEach { launch { it.scheduleMover(evalScope) } } - downstreamSet.outputs.forEach { launch { it.schedule(evalScope) } } + downstreamSet.nodes.forEach { it.schedule(logIndent, evalScope) } + downstreamSet.muxMovers.forEach { it.scheduleMover(logIndent, evalScope) } + downstreamSet.outputs.forEach { it.schedule(logIndent, evalScope) } downstreamSet.stateWriters.forEach { evalScope.schedule(it) } return downstreamSet.isNotEmpty() } diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/IncrementalImpl.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/IncrementalImpl.kt new file mode 100644 index 000000000000..8a3e01af6565 --- /dev/null +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/IncrementalImpl.kt @@ -0,0 +1,108 @@ +/* + * 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.kairos.internal + +import com.android.systemui.kairos.internal.store.StoreEntry +import com.android.systemui.kairos.util.Maybe +import com.android.systemui.kairos.util.applyPatch +import com.android.systemui.kairos.util.just +import com.android.systemui.kairos.util.map +import com.android.systemui.kairos.util.none + +internal class IncrementalImpl<K, out V>( + name: String?, + operatorName: String, + changes: EventsImpl<Map<K, V>>, + val patches: EventsImpl<Map<K, Maybe<V>>>, + store: StateStore<Map<K, V>>, +) : StateImpl<Map<K, V>>(name, operatorName, changes, store) + +internal fun <K, V> constIncremental( + name: String?, + operatorName: String, + init: Map<K, V>, +): IncrementalImpl<K, V> = + IncrementalImpl(name, operatorName, neverImpl, neverImpl, StateSource(init)) + +internal inline fun <K, V> activatedIncremental( + name: String?, + operatorName: String, + evalScope: EvalScope, + crossinline getPatches: EvalScope.() -> EventsImpl<Map<K, Maybe<V>>>, + init: Lazy<Map<K, V>>, +): IncrementalImpl<K, V> { + val store = StateSource(init) + val maybeChanges = + mapImpl(getPatches) { patch, _ -> + val (old, _) = store.getCurrentWithEpoch(evalScope = this) + val new = old.applyPatch(patch) + if (new != old) just(patch to new) else none + } + .cached() + val calm = filterJustImpl { maybeChanges } + val changes = mapImpl({ calm }) { (_, change), _ -> change } + val patches = mapImpl({ calm }) { (patch, _), _ -> patch } + evalScope.scheduleOutput( + OneShot { + changes.activate(evalScope = this, downstream = Schedulable.S(store))?.let { + (connection, needsEval) -> + store.upstreamConnection = connection + if (needsEval) { + schedule(store) + } + } + } + ) + return IncrementalImpl(name, operatorName, changes, patches, store) +} + +internal inline fun <K, V> EventsImpl<Map<K, Maybe<V>>>.calmUpdates( + state: StateDerived<Map<K, V>> +): Pair<EventsImpl<Map<K, Maybe<V>>>, EventsImpl<Map<K, V>>> { + val maybeUpdate = + mapImpl({ this@calmUpdates }) { patch, _ -> + val (current, _) = state.getCurrentWithEpoch(evalScope = this) + val new = current.applyPatch(patch) + if (new != current) { + state.setCacheFromPush(new, epoch) + just(patch to new) + } else { + none + } + } + .cached() + val calm = filterJustImpl { maybeUpdate } + val patches = mapImpl({ calm }) { (p, _), _ -> p } + val changes = mapImpl({ calm }) { (_, s), _ -> s } + return patches to changes +} + +internal fun <K, A, B> mapValuesImpl( + incrementalImpl: InitScope.() -> IncrementalImpl<K, A>, + name: String?, + operatorName: String, + transform: EvalScope.(Map.Entry<K, A>) -> B, +): IncrementalImpl<K, B> { + val store = DerivedMap(incrementalImpl) { map -> map.mapValues { transform(it) } } + val mappedPatches = + mapImpl({ incrementalImpl().patches }) { patch, _ -> + patch.mapValues { (k, mv) -> mv.map { v -> transform(StoreEntry(k, v)) } } + } + .cached() + val (calmPatches, calmChanges) = mappedPatches.calmUpdates(store) + return IncrementalImpl(name, operatorName, calmChanges, calmPatches, store) +} diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Init.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Init.kt index 57db9a493e21..640c561a21eb 100644 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Init.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Init.kt @@ -19,42 +19,40 @@ package com.android.systemui.kairos.internal import com.android.systemui.kairos.util.Maybe import com.android.systemui.kairos.util.just import com.android.systemui.kairos.util.none -import java.util.concurrent.atomic.AtomicBoolean -import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.ExperimentalCoroutinesApi /** Performs actions once, when the reactive component is first connected to the network. */ -internal class Init<out A>(val name: String?, private val block: suspend InitScope.() -> A) { - - /** Has the initialization logic been evaluated yet? */ - private val initialized = AtomicBoolean() +internal class Init<out A>(val name: String?, private val block: InitScope.() -> A) { /** * Stores the result after initialization, as well as the id of the [Network] it's been * initialized with. */ - private val cache = CompletableDeferred<Pair<Any, A>>() + private val cache = CompletableLazy<Pair<Any, A>>() - suspend fun connect(evalScope: InitScope): A = - if (initialized.getAndSet(true)) { + fun connect(evalScope: InitScope): A = + if (cache.isInitialized()) { // Read from cache - val (networkId, result) = cache.await() + val (networkId, result) = cache.value check(networkId == evalScope.networkId) { "Network mismatch" } result } else { // Write to cache - block(evalScope).also { cache.complete(evalScope.networkId to it) } + block(evalScope).also { cache.setValue(evalScope.networkId to it) } } @OptIn(ExperimentalCoroutinesApi::class) fun getUnsafe(): Maybe<A> = - if (cache.isCompleted) { - just(cache.getCompleted().second) + if (cache.isInitialized()) { + just(cache.value.second) } else { none } } -internal fun <A> init(name: String?, block: suspend InitScope.() -> A) = Init(name, block) +@Suppress("NOTHING_TO_INLINE") +internal inline fun <A> init(name: String?, noinline block: InitScope.() -> A): Init<A> = + Init(name, block) -internal fun <A> constInit(name: String?, value: A) = init(name) { value } +@Suppress("NOTHING_TO_INLINE") +internal inline fun <A> constInit(name: String?, value: A): Init<A> = init(name) { value } diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Inputs.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Inputs.kt index 8efaf79b18b2..d7cbe8087f52 100644 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Inputs.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Inputs.kt @@ -16,105 +16,103 @@ package com.android.systemui.kairos.internal -import com.android.systemui.kairos.internal.util.Key -import com.android.systemui.kairos.util.Maybe -import com.android.systemui.kairos.util.just +import com.android.systemui.kairos.internal.util.logDuration import java.util.concurrent.atomic.AtomicBoolean -import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock internal class InputNode<A>( - private val activate: suspend EvalScope.() -> Unit = {}, + private val activate: EvalScope.() -> Unit = {}, private val deactivate: () -> Unit = {}, -) : PushNode<A>, Key<A> { +) : PushNode<A> { - internal val downstreamSet = DownstreamSet() - private val mutex = Mutex() - private val activated = AtomicBoolean(false) + private val downstreamSet = DownstreamSet() + val activated = AtomicBoolean(false) + + private val transactionCache = TransactionCache<A>() + private val epoch + get() = transactionCache.epoch override val depthTracker: DepthTracker = DepthTracker() - override suspend fun hasCurrentValue(transactionStore: TransactionStore): Boolean = - transactionStore.contains(this) + override fun hasCurrentValue(logIndent: Int, evalScope: EvalScope): Boolean = + epoch == evalScope.epoch - suspend fun visit(evalScope: EvalScope, value: A) { - evalScope.setResult(this, value) - coroutineScope { - if (!mutex.withLock { scheduleAll(downstreamSet, evalScope) }) { - evalScope.scheduleDeactivation(this@InputNode) - } + fun visit(evalScope: EvalScope, value: A) { + transactionCache.put(evalScope, value) + if (!scheduleAll(0, downstreamSet, evalScope)) { + evalScope.scheduleDeactivation(this@InputNode) } } - override suspend fun removeDownstream(downstream: Schedulable) { - mutex.withLock { downstreamSet.remove(downstream) } + override fun removeDownstream(downstream: Schedulable) { + downstreamSet.remove(downstream) } - override suspend fun deactivateIfNeeded() { - if (mutex.withLock { downstreamSet.isEmpty() && activated.getAndSet(false) }) { + override fun deactivateIfNeeded() { + if (downstreamSet.isEmpty() && activated.getAndSet(false)) { deactivate() } } - override suspend fun scheduleDeactivationIfNeeded(evalScope: EvalScope) { - if (mutex.withLock { downstreamSet.isEmpty() }) { + override fun scheduleDeactivationIfNeeded(evalScope: EvalScope) { + if (downstreamSet.isEmpty()) { evalScope.scheduleDeactivation(this) } } - override suspend fun addDownstream(downstream: Schedulable) { - mutex.withLock { downstreamSet.add(downstream) } + override fun addDownstream(downstream: Schedulable) { + downstreamSet.add(downstream) } - suspend fun addDownstreamAndActivateIfNeeded(downstream: Schedulable, evalScope: EvalScope) { - val needsActivation = - mutex.withLock { - val wasEmpty = downstreamSet.isEmpty() - downstreamSet.add(downstream) - wasEmpty && !activated.getAndSet(true) - } + fun addDownstreamAndActivateIfNeeded(downstream: Schedulable, evalScope: EvalScope) { + val needsActivation = run { + val wasEmpty = downstreamSet.isEmpty() + downstreamSet.add(downstream) + wasEmpty && !activated.getAndSet(true) + } if (needsActivation) { activate(evalScope) } } - override suspend fun removeDownstreamAndDeactivateIfNeeded(downstream: Schedulable) { - val needsDeactivation = - mutex.withLock { - downstreamSet.remove(downstream) - downstreamSet.isEmpty() && activated.getAndSet(false) - } + override fun removeDownstreamAndDeactivateIfNeeded(downstream: Schedulable) { + downstreamSet.remove(downstream) + val needsDeactivation = downstreamSet.isEmpty() && activated.getAndSet(false) if (needsDeactivation) { deactivate() } } - override suspend fun getPushEvent(evalScope: EvalScope): Maybe<A> = - evalScope.getCurrentValue(this) + override fun getPushEvent(logIndent: Int, evalScope: EvalScope): A = + logDuration(logIndent, "Input.getPushEvent", false) { + transactionCache.getCurrentValue(evalScope) + } } -internal fun <A> InputNode<A>.activated() = TFlowCheap { downstream -> +internal fun <A> InputNode<A>.activated() = EventsImplCheap { downstream -> val input = this@activated addDownstreamAndActivateIfNeeded(downstream, evalScope = this) - ActivationResult(connection = NodeConnection(input, input), needsEval = hasCurrentValue(input)) + ActivationResult( + connection = NodeConnection(input, input), + needsEval = input.hasCurrentValue(0, evalScope = this), + ) } internal data object AlwaysNode : PushNode<Unit> { override val depthTracker = DepthTracker() - override suspend fun hasCurrentValue(transactionStore: TransactionStore): Boolean = true + override fun hasCurrentValue(logIndent: Int, evalScope: EvalScope): Boolean = true - override suspend fun removeDownstream(downstream: Schedulable) {} + override fun removeDownstream(downstream: Schedulable) {} - override suspend fun deactivateIfNeeded() {} + override fun deactivateIfNeeded() {} - override suspend fun scheduleDeactivationIfNeeded(evalScope: EvalScope) {} + override fun scheduleDeactivationIfNeeded(evalScope: EvalScope) {} - override suspend fun addDownstream(downstream: Schedulable) {} + override fun addDownstream(downstream: Schedulable) {} - override suspend fun removeDownstreamAndDeactivateIfNeeded(downstream: Schedulable) {} + override fun removeDownstreamAndDeactivateIfNeeded(downstream: Schedulable) {} - override suspend fun getPushEvent(evalScope: EvalScope): Maybe<Unit> = just(Unit) + override fun getPushEvent(logIndent: Int, evalScope: EvalScope) = + logDuration(logIndent, "Always.getPushEvent", false) { Unit } } diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/InternalScopes.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/InternalScopes.kt index 69994ba6e866..cd2214370d62 100644 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/InternalScopes.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/InternalScopes.kt @@ -16,39 +16,25 @@ package com.android.systemui.kairos.internal -import com.android.systemui.kairos.FrpBuildScope -import com.android.systemui.kairos.FrpStateScope -import com.android.systemui.kairos.FrpTransactionScope -import com.android.systemui.kairos.TFlow -import com.android.systemui.kairos.internal.util.HeteroMap -import com.android.systemui.kairos.internal.util.Key -import com.android.systemui.kairos.util.Maybe +import com.android.systemui.kairos.BuildScope +import com.android.systemui.kairos.Events +import com.android.systemui.kairos.StateScope +import com.android.systemui.kairos.TransactionScope internal interface InitScope { val networkId: Any } -internal interface EvalScope : NetworkScope, DeferScope { - val frpScope: FrpTransactionScope +internal interface EvalScope : NetworkScope, DeferScope, TransactionScope - suspend fun <R> runInTransactionScope(block: suspend FrpTransactionScope.() -> R): R -} - -internal interface StateScope : EvalScope { - override val frpScope: FrpStateScope - - suspend fun <R> runInStateScope(block: suspend FrpStateScope.() -> R): R +internal interface InternalStateScope : EvalScope, StateScope { + val endSignal: Events<Any> + val endSignalOnce: Events<Any> - val endSignal: TFlow<Any> - - fun childStateScope(newEnd: TFlow<Any>): StateScope + fun childStateScope(newEnd: Events<Any>): InternalStateScope } -internal interface BuildScope : StateScope { - override val frpScope: FrpBuildScope - - suspend fun <R> runInBuildScope(block: suspend FrpBuildScope.() -> R): R -} +internal interface InternalBuildScope : InternalStateScope, BuildScope internal interface NetworkScope : InitScope { @@ -58,23 +44,15 @@ internal interface NetworkScope : InitScope { val compactor: Scheduler val scheduler: Scheduler - val transactionStore: HeteroMap + val transactionStore: TransactionStore fun scheduleOutput(output: Output<*>) - fun scheduleMuxMover(muxMover: MuxDeferredNode<*, *>) + fun scheduleMuxMover(muxMover: MuxDeferredNode<*, *, *>) - fun schedule(state: TStateSource<*>) + fun schedule(state: StateSource<*>) fun scheduleDeactivation(node: PushNode<*>) fun scheduleDeactivation(output: Output<*>) } - -internal fun <A> NetworkScope.setResult(node: Key<A>, result: A) { - transactionStore[node] = result -} - -internal fun <A> NetworkScope.getCurrentValue(key: Key<A>): Maybe<A> = transactionStore[key] - -internal fun NetworkScope.hasCurrentValue(key: Key<*>): Boolean = transactionStore.contains(key) diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Mux.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Mux.kt index af68a1e3d83c..268fec4fa486 100644 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Mux.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Mux.kt @@ -18,31 +18,43 @@ package com.android.systemui.kairos.internal -import com.android.systemui.kairos.internal.util.ConcurrentNullableHashMap +import com.android.systemui.kairos.internal.store.MapHolder +import com.android.systemui.kairos.internal.store.MapK +import com.android.systemui.kairos.internal.store.MutableMapK +import com.android.systemui.kairos.internal.store.asMapHolder import com.android.systemui.kairos.internal.util.hashString -import com.android.systemui.kairos.util.Just -import java.util.concurrent.ConcurrentHashMap -import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock - -/** Base class for muxing nodes, which have a potentially dynamic collection of upstream nodes. */ -internal sealed class MuxNode<K : Any, V, Output>(val lifecycle: MuxLifecycle<Output>) : - PushNode<Output> { - - inline val mutex - get() = lifecycle.mutex - - // TODO: preserve insertion order? - val upstreamData = ConcurrentNullableHashMap<K, V>() - val switchedIn = ConcurrentHashMap<K, MuxBranchNode<K, V>>() +import com.android.systemui.kairos.internal.util.logDuration + +internal typealias MuxResult<W, K, V> = MapK<W, K, PullNode<V>> + +/** Base class for muxing nodes, which have a (potentially dynamic) collection of upstream nodes. */ +internal sealed class MuxNode<W, K, V>( + val lifecycle: MuxLifecycle<W, K, V>, + protected val storeFactory: MutableMapK.Factory<W, K>, +) : PushNode<MuxResult<W, K, V>> { + + lateinit var upstreamData: MutableMapK<W, K, PullNode<V>> + lateinit var switchedIn: MutableMapK<W, K, BranchNode> + + @Volatile var markedForCompaction = false + @Volatile var markedForEvaluation = false + val downstreamSet: DownstreamSet = DownstreamSet() // TODO: inline DepthTracker? would need to be added to PushNode signature final override val depthTracker = DepthTracker() - final override suspend fun addDownstream(downstream: Schedulable) { - mutex.withLock { addDownstreamLocked(downstream) } + val transactionCache = TransactionCache<MuxResult<W, K, V>>() + val epoch + get() = transactionCache.epoch + + inline fun hasCurrentValueLocked(evalScope: EvalScope): Boolean = epoch == evalScope.epoch + + override fun hasCurrentValue(logIndent: Int, evalScope: EvalScope): Boolean = + hasCurrentValueLocked(evalScope) + + final override fun addDownstream(downstream: Schedulable) { + addDownstreamLocked(downstream) } /** @@ -55,140 +67,124 @@ internal sealed class MuxNode<K : Any, V, Output>(val lifecycle: MuxLifecycle<Ou downstreamSet.add(downstream) } - final override suspend fun removeDownstream(downstream: Schedulable) { + final override fun removeDownstream(downstream: Schedulable) { // TODO: return boolean? - mutex.withLock { downstreamSet.remove(downstream) } + downstreamSet.remove(downstream) } - final override suspend fun removeDownstreamAndDeactivateIfNeeded(downstream: Schedulable) { - val deactivate = - mutex.withLock { - downstreamSet.remove(downstream) - downstreamSet.isEmpty() - } + final override fun removeDownstreamAndDeactivateIfNeeded(downstream: Schedulable) { + downstreamSet.remove(downstream) + val deactivate = downstreamSet.isEmpty() if (deactivate) { doDeactivate() } } - final override suspend fun deactivateIfNeeded() { - if (mutex.withLock { downstreamSet.isEmpty() }) { + final override fun deactivateIfNeeded() { + if (downstreamSet.isEmpty()) { doDeactivate() } } /** visit this node from the scheduler (push eval) */ - abstract suspend fun visit(evalScope: EvalScope) + abstract fun visit(logIndent: Int, evalScope: EvalScope) /** perform deactivation logic, propagating to all upstream nodes. */ - protected abstract suspend fun doDeactivate() + protected abstract fun doDeactivate() - final override suspend fun scheduleDeactivationIfNeeded(evalScope: EvalScope) { - if (mutex.withLock { downstreamSet.isEmpty() }) { + final override fun scheduleDeactivationIfNeeded(evalScope: EvalScope) { + if (downstreamSet.isEmpty()) { evalScope.scheduleDeactivation(this) } } - suspend fun adjustDirectUpstream(scheduler: Scheduler, oldDepth: Int, newDepth: Int) { - mutex.withLock { - if (depthTracker.addDirectUpstream(oldDepth, newDepth)) { - depthTracker.schedule(scheduler, this) - } + fun adjustDirectUpstream(scheduler: Scheduler, oldDepth: Int, newDepth: Int) { + + if (depthTracker.addDirectUpstream(oldDepth, newDepth)) { + depthTracker.schedule(scheduler, this) } } - suspend fun moveIndirectUpstreamToDirect( + fun moveIndirectUpstreamToDirect( scheduler: Scheduler, oldIndirectDepth: Int, - oldIndirectRoots: Set<MuxDeferredNode<*, *>>, + oldIndirectRoots: Set<MuxDeferredNode<*, *, *>>, newDepth: Int, ) { - mutex.withLock { - if ( - depthTracker.addDirectUpstream(oldDepth = null, newDepth) or - depthTracker.removeIndirectUpstream(depth = oldIndirectDepth) or - depthTracker.updateIndirectRoots(removals = oldIndirectRoots) - ) { - depthTracker.schedule(scheduler, this) - } + if ( + depthTracker.addDirectUpstream(oldDepth = null, newDepth) or + depthTracker.removeIndirectUpstream(depth = oldIndirectDepth) or + depthTracker.updateIndirectRoots(removals = oldIndirectRoots) + ) { + depthTracker.schedule(scheduler, this) } } - suspend fun adjustIndirectUpstream( + fun adjustIndirectUpstream( scheduler: Scheduler, oldDepth: Int, newDepth: Int, - removals: Set<MuxDeferredNode<*, *>>, - additions: Set<MuxDeferredNode<*, *>>, + removals: Set<MuxDeferredNode<*, *, *>>, + additions: Set<MuxDeferredNode<*, *, *>>, ) { - mutex.withLock { - if ( - depthTracker.addIndirectUpstream(oldDepth, newDepth) or - depthTracker.updateIndirectRoots( - additions, - removals, - butNot = this as? MuxDeferredNode<*, *>, - ) - ) { - depthTracker.schedule(scheduler, this) - } + if ( + depthTracker.addIndirectUpstream(oldDepth, newDepth) or + depthTracker.updateIndirectRoots( + additions, + removals, + butNot = this as? MuxDeferredNode<*, *, *>, + ) + ) { + depthTracker.schedule(scheduler, this) } } - suspend fun moveDirectUpstreamToIndirect( + fun moveDirectUpstreamToIndirect( scheduler: Scheduler, oldDepth: Int, newDepth: Int, - newIndirectSet: Set<MuxDeferredNode<*, *>>, + newIndirectSet: Set<MuxDeferredNode<*, *, *>>, ) { - mutex.withLock { - if ( - depthTracker.addIndirectUpstream(oldDepth = null, newDepth) or - depthTracker.removeDirectUpstream(oldDepth) or - depthTracker.updateIndirectRoots( - additions = newIndirectSet, - butNot = this as? MuxDeferredNode<*, *>, - ) - ) { - depthTracker.schedule(scheduler, this) - } + if ( + depthTracker.addIndirectUpstream(oldDepth = null, newDepth) or + depthTracker.removeDirectUpstream(oldDepth) or + depthTracker.updateIndirectRoots( + additions = newIndirectSet, + butNot = this as? MuxDeferredNode<*, *, *>, + ) + ) { + depthTracker.schedule(scheduler, this) } } - suspend fun removeDirectUpstream(scheduler: Scheduler, depth: Int, key: K) { - mutex.withLock { - switchedIn.remove(key) - if (depthTracker.removeDirectUpstream(depth)) { - depthTracker.schedule(scheduler, this) - } + fun removeDirectUpstream(scheduler: Scheduler, depth: Int, key: K) { + switchedIn.remove(key) + if (depthTracker.removeDirectUpstream(depth)) { + depthTracker.schedule(scheduler, this) } } - suspend fun removeIndirectUpstream( + fun removeIndirectUpstream( scheduler: Scheduler, oldDepth: Int, - indirectSet: Set<MuxDeferredNode<*, *>>, + indirectSet: Set<MuxDeferredNode<*, *, *>>, key: K, ) { - mutex.withLock { - switchedIn.remove(key) - if ( - depthTracker.removeIndirectUpstream(oldDepth) or - depthTracker.updateIndirectRoots(removals = indirectSet) - ) { - depthTracker.schedule(scheduler, this) - } + switchedIn.remove(key) + if ( + depthTracker.removeIndirectUpstream(oldDepth) or + depthTracker.updateIndirectRoots(removals = indirectSet) + ) { + depthTracker.schedule(scheduler, this) } } - suspend fun visitCompact(scheduler: Scheduler) = coroutineScope { + fun visitCompact(scheduler: Scheduler) { if (depthTracker.isDirty()) { - depthTracker.applyChanges(coroutineScope = this, scheduler, downstreamSet, this@MuxNode) + depthTracker.applyChanges(scheduler, downstreamSet, this@MuxNode) } } - abstract fun hasCurrentValueLocked(transactionStore: TransactionStore): Boolean - fun schedule(evalScope: EvalScope) { // TODO: Potential optimization // Detect if this node is guaranteed to have a single upstream within this transaction, @@ -196,139 +192,202 @@ internal sealed class MuxNode<K : Any, V, Output>(val lifecycle: MuxLifecycle<Ou // MuxNode as a Pull (effectively making it a mapCheap). depthTracker.schedule(evalScope.scheduler, this) } -} -/** An input branch of a mux node, associated with a key. */ -internal class MuxBranchNode<K : Any, V>(private val muxNode: MuxNode<K, V, *>, val key: K) : - SchedulableNode { + /** An input branch of a mux node, associated with a key. */ + inner class BranchNode(val key: K) : SchedulableNode { - val schedulable = Schedulable.N(this) + val schedulable = Schedulable.N(this) - @Volatile lateinit var upstream: NodeConnection<V> + lateinit var upstream: NodeConnection<V> - override suspend fun schedule(evalScope: EvalScope) { - val upstreamResult = upstream.getPushEvent(evalScope) - if (upstreamResult is Just) { - muxNode.upstreamData[key] = upstreamResult.value - muxNode.schedule(evalScope) + override fun schedule(logIndent: Int, evalScope: EvalScope) { + logDuration(logIndent, "MuxBranchNode.schedule") { + if (this@MuxNode is MuxPromptNode && this@MuxNode.name != null) { + logLn("[${this@MuxNode}] scheduling $key") + } + upstreamData[key] = upstream.directUpstream + this@MuxNode.schedule(evalScope) + } } - } - override suspend fun adjustDirectUpstream(scheduler: Scheduler, oldDepth: Int, newDepth: Int) { - muxNode.adjustDirectUpstream(scheduler, oldDepth, newDepth) - } + override fun adjustDirectUpstream(scheduler: Scheduler, oldDepth: Int, newDepth: Int) { + this@MuxNode.adjustDirectUpstream(scheduler, oldDepth, newDepth) + } - override suspend fun moveIndirectUpstreamToDirect( - scheduler: Scheduler, - oldIndirectDepth: Int, - oldIndirectSet: Set<MuxDeferredNode<*, *>>, - newDirectDepth: Int, - ) { - muxNode.moveIndirectUpstreamToDirect( - scheduler, - oldIndirectDepth, - oldIndirectSet, - newDirectDepth, - ) - } + override fun moveIndirectUpstreamToDirect( + scheduler: Scheduler, + oldIndirectDepth: Int, + oldIndirectSet: Set<MuxDeferredNode<*, *, *>>, + newDirectDepth: Int, + ) { + this@MuxNode.moveIndirectUpstreamToDirect( + scheduler, + oldIndirectDepth, + oldIndirectSet, + newDirectDepth, + ) + } - override suspend fun adjustIndirectUpstream( - scheduler: Scheduler, - oldDepth: Int, - newDepth: Int, - removals: Set<MuxDeferredNode<*, *>>, - additions: Set<MuxDeferredNode<*, *>>, - ) { - muxNode.adjustIndirectUpstream(scheduler, oldDepth, newDepth, removals, additions) - } + override fun adjustIndirectUpstream( + scheduler: Scheduler, + oldDepth: Int, + newDepth: Int, + removals: Set<MuxDeferredNode<*, *, *>>, + additions: Set<MuxDeferredNode<*, *, *>>, + ) { + this@MuxNode.adjustIndirectUpstream(scheduler, oldDepth, newDepth, removals, additions) + } - override suspend fun moveDirectUpstreamToIndirect( - scheduler: Scheduler, - oldDirectDepth: Int, - newIndirectDepth: Int, - newIndirectSet: Set<MuxDeferredNode<*, *>>, - ) { - muxNode.moveDirectUpstreamToIndirect( - scheduler, - oldDirectDepth, - newIndirectDepth, - newIndirectSet, - ) - } + override fun moveDirectUpstreamToIndirect( + scheduler: Scheduler, + oldDirectDepth: Int, + newIndirectDepth: Int, + newIndirectSet: Set<MuxDeferredNode<*, *, *>>, + ) { + this@MuxNode.moveDirectUpstreamToIndirect( + scheduler, + oldDirectDepth, + newIndirectDepth, + newIndirectSet, + ) + } - override suspend fun removeDirectUpstream(scheduler: Scheduler, depth: Int) { - muxNode.removeDirectUpstream(scheduler, depth, key) - } + override fun removeDirectUpstream(scheduler: Scheduler, depth: Int) { + removeDirectUpstream(scheduler, depth, key) + } - override suspend fun removeIndirectUpstream( - scheduler: Scheduler, - depth: Int, - indirectSet: Set<MuxDeferredNode<*, *>>, - ) { - muxNode.removeIndirectUpstream(scheduler, depth, indirectSet, key) - } + override fun removeIndirectUpstream( + scheduler: Scheduler, + depth: Int, + indirectSet: Set<MuxDeferredNode<*, *, *>>, + ) { + removeIndirectUpstream(scheduler, depth, indirectSet, key) + } - override fun toString(): String = "MuxBranchNode(key=$key, mux=$muxNode)" + override fun toString(): String = "MuxBranchNode(key=$key, mux=${this@MuxNode})" + } } +internal typealias BranchNode<W, K, V> = MuxNode<W, K, V>.BranchNode + /** Tracks lifecycle of MuxNode in the network. Essentially a mutable ref for MuxLifecycleState. */ -internal class MuxLifecycle<A>(@Volatile var lifecycleState: MuxLifecycleState<A>) : TFlowImpl<A> { - val mutex = Mutex() +internal class MuxLifecycle<W, K, V>(var lifecycleState: MuxLifecycleState<W, K, V>) : + EventsImpl<MuxResult<W, K, V>> { - override fun toString(): String = "TFlowLifecycle[$hashString][$lifecycleState][$mutex]" + override fun toString(): String = "MuxLifecycle[$hashString][$lifecycleState]" - override suspend fun activate( + override fun activate( evalScope: EvalScope, downstream: Schedulable, - ): ActivationResult<A>? = - mutex.withLock { - when (val state = lifecycleState) { - is MuxLifecycleState.Dead -> null - is MuxLifecycleState.Active -> { - state.node.addDownstreamLocked(downstream) - ActivationResult( - connection = NodeConnection(state.node, state.node), - needsEval = state.node.hasCurrentValueLocked(evalScope.transactionStore), - ) - } - is MuxLifecycleState.Inactive -> { - state.spec - .activate(evalScope, this@MuxLifecycle) - .also { node -> - lifecycleState = - if (node == null) { - MuxLifecycleState.Dead - } else { - MuxLifecycleState.Active(node) - } - } - ?.let { node -> - node.addDownstreamLocked(downstream) - ActivationResult( - connection = NodeConnection(node, node), - needsEval = false, - ) - } - } + ): ActivationResult<MuxResult<W, K, V>>? = + when (val state = lifecycleState) { + is MuxLifecycleState.Dead -> { + null + } + is MuxLifecycleState.Active -> { + state.node.addDownstreamLocked(downstream) + ActivationResult( + connection = NodeConnection(state.node, state.node), + needsEval = state.node.hasCurrentValueLocked(evalScope), + ) + } + is MuxLifecycleState.Inactive -> { + state.spec + .activate(evalScope, this@MuxLifecycle) + .also { node -> + lifecycleState = + if (node == null) { + MuxLifecycleState.Dead + } else { + MuxLifecycleState.Active(node.first) + } + } + ?.let { (node, postActivate) -> + postActivate?.invoke() + node.addDownstreamLocked(downstream) + ActivationResult(connection = NodeConnection(node, node), needsEval = false) + } } } } -internal sealed interface MuxLifecycleState<out A> { - class Inactive<A>(val spec: MuxActivator<A>) : MuxLifecycleState<A> { +internal sealed interface MuxLifecycleState<out W, out K, out V> { + class Inactive<W, K, V>(val spec: MuxActivator<W, K, V>) : MuxLifecycleState<W, K, V> { override fun toString(): String = "Inactive" } - class Active<A>(val node: MuxNode<*, *, A>) : MuxLifecycleState<A> { + class Active<W, K, V>(val node: MuxNode<W, K, V>) : MuxLifecycleState<W, K, V> { override fun toString(): String = "Active(node=$node)" } - data object Dead : MuxLifecycleState<Nothing> + data object Dead : MuxLifecycleState<Nothing, Nothing, Nothing> } -internal interface MuxActivator<A> { - suspend fun activate(evalScope: EvalScope, lifecycle: MuxLifecycle<A>): MuxNode<*, *, A>? +internal interface MuxActivator<W, K, V> { + fun activate( + evalScope: EvalScope, + lifecycle: MuxLifecycle<W, K, V>, + ): Pair<MuxNode<W, K, V>, (() -> Unit)?>? } -internal inline fun <A> MuxLifecycle(onSubscribe: MuxActivator<A>): TFlowImpl<A> = - MuxLifecycle(MuxLifecycleState.Inactive(onSubscribe)) +internal inline fun <W, K, V> MuxLifecycle( + onSubscribe: MuxActivator<W, K, V> +): EventsImpl<MuxResult<W, K, V>> = MuxLifecycle(MuxLifecycleState.Inactive(onSubscribe)) + +internal fun <K, V> EventsImpl<MuxResult<MapHolder.W, K, V>>.awaitValues(): EventsImpl<Map<K, V>> = + mapImpl({ this@awaitValues }) { results, logIndent -> + results.asMapHolder().unwrapped.mapValues { it.value.getPushEvent(logIndent, this) } + } + +// activation logic + +internal fun <W, K, V> MuxNode<W, K, V>.initializeUpstream( + evalScope: EvalScope, + getStorage: EvalScope.() -> Iterable<Map.Entry<K, EventsImpl<V>>>, + storeFactory: MutableMapK.Factory<W, K>, +) { + val storage = getStorage(evalScope) + val initUpstream = buildList { + storage.forEach { (key, events) -> + val branchNode = BranchNode(key) + add( + events.activate(evalScope, branchNode.schedulable)?.let { (conn, needsEval) -> + Triple( + key, + branchNode.apply { upstream = conn }, + if (needsEval) conn.directUpstream else null, + ) + } + ) + } + } + switchedIn = storeFactory.create(initUpstream.size) + upstreamData = storeFactory.create(initUpstream.size) + for (triple in initUpstream) { + triple?.let { (key, branch, upstream) -> + switchedIn[key] = branch + upstream?.let { upstreamData[key] = upstream } + } + } +} + +internal fun <W, K, V> MuxNode<W, K, V>.initializeDepth() { + switchedIn.forEach { (_, branch) -> + val conn = branch.upstream + if (conn.depthTracker.snapshotIsDirect) { + depthTracker.addDirectUpstream( + oldDepth = null, + newDepth = conn.depthTracker.snapshotDirectDepth, + ) + } else { + depthTracker.addIndirectUpstream( + oldDepth = null, + newDepth = conn.depthTracker.snapshotIndirectDepth, + ) + depthTracker.updateIndirectRoots( + additions = conn.depthTracker.snapshotIndirectRoots, + butNot = null, + ) + } + } +} diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/MuxDeferred.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/MuxDeferred.kt index 3b9502a5d812..cf74f755c98b 100644 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/MuxDeferred.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/MuxDeferred.kt @@ -16,16 +16,20 @@ package com.android.systemui.kairos.internal -import com.android.systemui.kairos.internal.util.Key -import com.android.systemui.kairos.internal.util.associateByIndexTo +import com.android.systemui.kairos.internal.store.MapK +import com.android.systemui.kairos.internal.store.MutableArrayMapK +import com.android.systemui.kairos.internal.store.MutableMapK +import com.android.systemui.kairos.internal.store.SingletonMapK +import com.android.systemui.kairos.internal.store.StoreEntry +import com.android.systemui.kairos.internal.store.asArrayHolder +import com.android.systemui.kairos.internal.store.asSingle +import com.android.systemui.kairos.internal.store.singleOf import com.android.systemui.kairos.internal.util.hashString -import com.android.systemui.kairos.internal.util.mapParallel -import com.android.systemui.kairos.internal.util.mapValuesNotNullParallelTo -import com.android.systemui.kairos.util.Just -import com.android.systemui.kairos.util.Left +import com.android.systemui.kairos.internal.util.logDuration +import com.android.systemui.kairos.internal.util.logLn import com.android.systemui.kairos.util.Maybe -import com.android.systemui.kairos.util.None -import com.android.systemui.kairos.util.Right +import com.android.systemui.kairos.util.Maybe.Just +import com.android.systemui.kairos.util.Maybe.None import com.android.systemui.kairos.util.These import com.android.systemui.kairos.util.flatMap import com.android.systemui.kairos.util.getMaybe @@ -33,49 +37,51 @@ import com.android.systemui.kairos.util.just import com.android.systemui.kairos.util.maybeThat import com.android.systemui.kairos.util.maybeThis import com.android.systemui.kairos.util.merge -import com.android.systemui.kairos.util.orElseGet -import com.android.systemui.kairos.util.partitionEithers +import com.android.systemui.kairos.util.orError import com.android.systemui.kairos.util.these -import java.util.TreeMap -import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.launch -import kotlinx.coroutines.sync.withLock -internal class MuxDeferredNode<K : Any, V>( - lifecycle: MuxLifecycle<Map<K, V>>, - val spec: MuxActivator<Map<K, V>>, -) : MuxNode<K, V, Map<K, V>>(lifecycle), Key<Map<K, V>> { +internal class MuxDeferredNode<W, K, V>( + val name: String?, + lifecycle: MuxLifecycle<W, K, V>, + val spec: MuxActivator<W, K, V>, + factory: MutableMapK.Factory<W, K>, +) : MuxNode<W, K, V>(lifecycle, factory) { val schedulable = Schedulable.M(this) - - @Volatile var patches: NodeConnection<Map<K, Maybe<TFlowImpl<V>>>>? = null - @Volatile var patchData: Map<K, Maybe<TFlowImpl<V>>>? = null - - override fun hasCurrentValueLocked(transactionStore: TransactionStore): Boolean = - transactionStore.contains(this) - - override suspend fun hasCurrentValue(transactionStore: TransactionStore): Boolean = - mutex.withLock { hasCurrentValueLocked(transactionStore) } - - override suspend fun visit(evalScope: EvalScope) { - val result = upstreamData.toMap() - upstreamData.clear() - val scheduleDownstream = result.isNotEmpty() - val compactDownstream = depthTracker.isDirty() - if (scheduleDownstream || compactDownstream) { - coroutineScope { - mutex.withLock { - if (compactDownstream) { + var patches: NodeConnection<Iterable<Map.Entry<K, Maybe<EventsImpl<V>>>>>? = null + var patchData: Iterable<Map.Entry<K, Maybe<EventsImpl<V>>>>? = null + + override fun visit(logIndent: Int, evalScope: EvalScope) { + check(epoch < evalScope.epoch) { "node unexpectedly visited multiple times in transaction" } + logDuration(logIndent, "MuxDeferred[$name].visit") { + val scheduleDownstream: Boolean + val result: MapK<W, K, PullNode<V>> + logDuration("copying upstream data", false) { + scheduleDownstream = upstreamData.isNotEmpty() + result = upstreamData.readOnlyCopy() + upstreamData.clear() + } + if (name != null) { + logLn("[${this@MuxDeferredNode}] result = $result") + } + val compactDownstream = depthTracker.isDirty() + if (scheduleDownstream || compactDownstream) { + if (compactDownstream) { + logDuration("compactDownstream", false) { depthTracker.applyChanges( - coroutineScope = this, evalScope.scheduler, downstreamSet, muxNode = this@MuxDeferredNode, ) } - if (scheduleDownstream) { - evalScope.setResult(this@MuxDeferredNode, result) - if (!scheduleAll(downstreamSet, evalScope)) { + } + if (scheduleDownstream) { + logDuration("scheduleDownstream") { + if (name != null) { + logLn("[${this@MuxDeferredNode}] scheduling") + } + transactionCache.put(evalScope, result) + if (!scheduleAll(currentLogIndent, downstreamSet, evalScope)) { evalScope.scheduleDeactivation(this@MuxDeferredNode) } } @@ -84,26 +90,26 @@ internal class MuxDeferredNode<K : Any, V>( } } - override suspend fun getPushEvent(evalScope: EvalScope): Maybe<Map<K, V>> = - evalScope.getCurrentValue(key = this) + override fun getPushEvent(logIndent: Int, evalScope: EvalScope): MuxResult<W, K, V> = + logDuration(logIndent, "MuxDeferred.getPushEvent") { + transactionCache.getCurrentValue(evalScope).also { + if (name != null) { + logLn("[${this@MuxDeferredNode}] getPushEvent = $it") + } + } + } - private suspend fun compactIfNeeded(evalScope: EvalScope) { + private fun compactIfNeeded(evalScope: EvalScope) { depthTracker.propagateChanges(evalScope.compactor, this) } - override suspend fun doDeactivate() { + override fun doDeactivate() { // Update lifecycle - lifecycle.mutex.withLock { - if (lifecycle.lifecycleState !is MuxLifecycleState.Active) return@doDeactivate - lifecycle.lifecycleState = MuxLifecycleState.Inactive(spec) - } + if (lifecycle.lifecycleState !is MuxLifecycleState.Active) return@doDeactivate + lifecycle.lifecycleState = MuxLifecycleState.Inactive(spec) // Process branch nodes - coroutineScope { - switchedIn.values.forEach { branchNode -> - branchNode.upstream.let { - launch { it.removeDownstreamAndDeactivateIfNeeded(branchNode.schedulable) } - } - } + switchedIn.forEach { (_, branchNode) -> + branchNode.upstream.removeDownstreamAndDeactivateIfNeeded(branchNode.schedulable) } // Process patch node patches?.removeDownstreamAndDeactivateIfNeeded(schedulable) @@ -112,362 +118,343 @@ internal class MuxDeferredNode<K : Any, V>( // MOVE phase // - concurrent moves may be occurring, but no more evals. all depth recalculations are // deferred to the end of this phase. - suspend fun performMove(evalScope: EvalScope) { + fun performMove(logIndent: Int, evalScope: EvalScope) { + if (name != null) { + logLn(logIndent, "[${this@MuxDeferredNode}] performMove (patchData = $patchData)") + } + val patch = patchData ?: return patchData = null - // TODO: this logic is very similar to what's in MuxPromptMoving, maybe turn into an inline - // fun? + // TODO: this logic is very similar to what's in MuxPrompt, maybe turn into an inline fun? // We have a patch, process additions/updates and removals - val (adds, removes) = - patch - .asSequence() - .map { (k, newUpstream: Maybe<TFlowImpl<V>>) -> - when (newUpstream) { - is Just -> Left(k to newUpstream.value) - None -> Right(k) - } - } - .partitionEithers() + val adds = mutableListOf<Pair<K, EventsImpl<V>>>() + val removes = mutableListOf<K>() + patch.forEach { (k, newUpstream) -> + when (newUpstream) { + is Just -> adds.add(k to newUpstream.value) + None -> removes.add(k) + } + } val severed = mutableListOf<NodeConnection<*>>() - coroutineScope { - // remove and sever - removes.forEach { k -> - switchedIn.remove(k)?.let { branchNode: MuxBranchNode<K, V> -> - val conn = branchNode.upstream - severed.add(conn) - launch { conn.removeDownstream(downstream = branchNode.schedulable) } - depthTracker.removeDirectUpstream(conn.depthTracker.snapshotDirectDepth) - } + // remove and sever + removes.forEach { k -> + switchedIn.remove(k)?.let { branchNode: BranchNode -> + val conn = branchNode.upstream + severed.add(conn) + conn.removeDownstream(downstream = branchNode.schedulable) + depthTracker.removeDirectUpstream(conn.depthTracker.snapshotDirectDepth) } + } - // add or replace - adds - .mapParallel { (k, newUpstream: TFlowImpl<V>) -> - val branchNode = MuxBranchNode(this@MuxDeferredNode, k) - k to - newUpstream.activate(evalScope, branchNode.schedulable)?.let { (conn, _) -> - branchNode.apply { upstream = conn } - } - } - .forEach { (k, newBranch: MuxBranchNode<K, V>?) -> - // remove old and sever, if present - switchedIn.remove(k)?.let { branchNode -> - val conn = branchNode.upstream - severed.add(conn) - launch { conn.removeDownstream(downstream = branchNode.schedulable) } - depthTracker.removeDirectUpstream(conn.depthTracker.snapshotDirectDepth) - } + // add or replace + adds.forEach { (k, newUpstream: EventsImpl<V>) -> + // remove old and sever, if present + switchedIn.remove(k)?.let { branchNode -> + val conn = branchNode.upstream + severed.add(conn) + conn.removeDownstream(downstream = branchNode.schedulable) + depthTracker.removeDirectUpstream(conn.depthTracker.snapshotDirectDepth) + } - // add new - newBranch?.let { - switchedIn[k] = newBranch - val branchDepthTracker = newBranch.upstream.depthTracker - if (branchDepthTracker.snapshotIsDirect) { - depthTracker.addDirectUpstream( - oldDepth = null, - newDepth = branchDepthTracker.snapshotDirectDepth, - ) - } else { - depthTracker.addIndirectUpstream( - oldDepth = null, - newDepth = branchDepthTracker.snapshotIndirectDepth, - ) - depthTracker.updateIndirectRoots( - additions = branchDepthTracker.snapshotIndirectRoots, - butNot = this@MuxDeferredNode, - ) - } - } + // add new + val newBranch = BranchNode(k) + newUpstream.activate(evalScope, newBranch.schedulable)?.let { (conn, _) -> + newBranch.upstream = conn + switchedIn[k] = newBranch + val branchDepthTracker = newBranch.upstream.depthTracker + if (branchDepthTracker.snapshotIsDirect) { + depthTracker.addDirectUpstream( + oldDepth = null, + newDepth = branchDepthTracker.snapshotDirectDepth, + ) + } else { + depthTracker.addIndirectUpstream( + oldDepth = null, + newDepth = branchDepthTracker.snapshotIndirectDepth, + ) + depthTracker.updateIndirectRoots( + additions = branchDepthTracker.snapshotIndirectRoots, + butNot = this@MuxDeferredNode, + ) } + } } - coroutineScope { - for (severedNode in severed) { - launch { severedNode.scheduleDeactivationIfNeeded(evalScope) } - } + for (severedNode in severed) { + severedNode.scheduleDeactivationIfNeeded(evalScope) } compactIfNeeded(evalScope) } - suspend fun removeDirectPatchNode(scheduler: Scheduler) { - mutex.withLock { - if ( - depthTracker.removeIndirectUpstream(depth = 0) or - depthTracker.setIsIndirectRoot(false) - ) { - depthTracker.schedule(scheduler, this) - } - patches = null + fun removeDirectPatchNode(scheduler: Scheduler) { + if ( + depthTracker.removeIndirectUpstream(depth = 0) or depthTracker.setIsIndirectRoot(false) + ) { + depthTracker.schedule(scheduler, this) } + patches = null } - suspend fun removeIndirectPatchNode( + fun removeIndirectPatchNode( scheduler: Scheduler, depth: Int, - indirectSet: Set<MuxDeferredNode<*, *>>, + indirectSet: Set<MuxDeferredNode<*, *, *>>, ) { // indirectly connected patches forward the indirectSet - mutex.withLock { - if ( - depthTracker.updateIndirectRoots(removals = indirectSet) or - depthTracker.removeIndirectUpstream(depth) - ) { - depthTracker.schedule(scheduler, this) - } - patches = null + if ( + depthTracker.updateIndirectRoots(removals = indirectSet) or + depthTracker.removeIndirectUpstream(depth) + ) { + depthTracker.schedule(scheduler, this) } + patches = null } - suspend fun moveIndirectPatchNodeToDirect( + fun moveIndirectPatchNodeToDirect( scheduler: Scheduler, oldIndirectDepth: Int, - oldIndirectSet: Set<MuxDeferredNode<*, *>>, + oldIndirectSet: Set<MuxDeferredNode<*, *, *>>, ) { // directly connected patches are stored as an indirect singleton set of the patchNode - mutex.withLock { - if ( - depthTracker.updateIndirectRoots(removals = oldIndirectSet) or - depthTracker.removeIndirectUpstream(oldIndirectDepth) or - depthTracker.setIsIndirectRoot(true) - ) { - depthTracker.schedule(scheduler, this) - } + if ( + depthTracker.updateIndirectRoots(removals = oldIndirectSet) or + depthTracker.removeIndirectUpstream(oldIndirectDepth) or + depthTracker.setIsIndirectRoot(true) + ) { + depthTracker.schedule(scheduler, this) } } - suspend fun moveDirectPatchNodeToIndirect( + fun moveDirectPatchNodeToIndirect( scheduler: Scheduler, newIndirectDepth: Int, - newIndirectSet: Set<MuxDeferredNode<*, *>>, + newIndirectSet: Set<MuxDeferredNode<*, *, *>>, ) { // indirectly connected patches forward the indirectSet - mutex.withLock { - if ( - depthTracker.setIsIndirectRoot(false) or - depthTracker.updateIndirectRoots(additions = newIndirectSet, butNot = this) or - depthTracker.addIndirectUpstream(oldDepth = null, newDepth = newIndirectDepth) - ) { - depthTracker.schedule(scheduler, this) - } + if ( + depthTracker.setIsIndirectRoot(false) or + depthTracker.updateIndirectRoots(additions = newIndirectSet, butNot = this) or + depthTracker.addIndirectUpstream(oldDepth = null, newDepth = newIndirectDepth) + ) { + depthTracker.schedule(scheduler, this) } } - suspend fun adjustIndirectPatchNode( + fun adjustIndirectPatchNode( scheduler: Scheduler, oldDepth: Int, newDepth: Int, - removals: Set<MuxDeferredNode<*, *>>, - additions: Set<MuxDeferredNode<*, *>>, + removals: Set<MuxDeferredNode<*, *, *>>, + additions: Set<MuxDeferredNode<*, *, *>>, ) { // indirectly connected patches forward the indirectSet - mutex.withLock { - if ( - depthTracker.updateIndirectRoots( - additions = additions, - removals = removals, - butNot = this, - ) or depthTracker.addIndirectUpstream(oldDepth = oldDepth, newDepth = newDepth) - ) { - depthTracker.schedule(scheduler, this) - } + if ( + depthTracker.updateIndirectRoots( + additions = additions, + removals = removals, + butNot = this, + ) or depthTracker.addIndirectUpstream(oldDepth = oldDepth, newDepth = newDepth) + ) { + depthTracker.schedule(scheduler, this) } } - suspend fun scheduleMover(evalScope: EvalScope) { - patchData = - checkNotNull(patches) { "mux mover scheduled with unset patches upstream node" } - .getPushEvent(evalScope) - .orElseGet { null } - evalScope.scheduleMuxMover(this) + fun scheduleMover(logIndent: Int, evalScope: EvalScope) { + logDuration(logIndent, "MuxDeferred.scheduleMover") { + patchData = + checkNotNull(patches) { "mux mover scheduled with unset patches upstream node" } + .getPushEvent(currentLogIndent, evalScope) + evalScope.scheduleMuxMover(this@MuxDeferredNode) + } } - override fun toString(): String = "${this::class.simpleName}@$hashString" + override fun toString(): String = + "${this::class.simpleName}@$hashString${name?.let { "[$it]" }.orEmpty()}" } internal inline fun <A> switchDeferredImplSingle( - crossinline getStorage: suspend EvalScope.() -> TFlowImpl<A>, - crossinline getPatches: suspend EvalScope.() -> TFlowImpl<TFlowImpl<A>>, -): TFlowImpl<A> = - mapImpl({ + name: String? = null, + crossinline getStorage: EvalScope.() -> EventsImpl<A>, + crossinline getPatches: EvalScope.() -> EventsImpl<EventsImpl<A>>, +): EventsImpl<A> { + val patches = mapImpl(getPatches) { newEvents, _ -> singleOf(just(newEvents)).asIterable() } + val switchDeferredImpl = switchDeferredImpl( - getStorage = { mapOf(Unit to getStorage()) }, - getPatches = { mapImpl(getPatches) { newFlow -> mapOf(Unit to just(newFlow)) } }, + name = name, + getStorage = { singleOf(getStorage()).asIterable() }, + getPatches = { patches }, + storeFactory = SingletonMapK.Factory(), ) - }) { map -> - map.getValue(Unit) + return mapImpl({ switchDeferredImpl }) { map, logIndent -> + map.asSingle().getValue(Unit).getPushEvent(logIndent, this).also { + if (name != null) { + logLn(logIndent, "[$name] extracting single mux: $it") + } + } } +} -internal fun <K : Any, A> switchDeferredImpl( - getStorage: suspend EvalScope.() -> Map<K, TFlowImpl<A>>, - getPatches: suspend EvalScope.() -> TFlowImpl<Map<K, Maybe<TFlowImpl<A>>>>, -): TFlowImpl<Map<K, A>> = - MuxLifecycle( - object : MuxActivator<Map<K, A>> { - override suspend fun activate( - evalScope: EvalScope, - lifecycle: MuxLifecycle<Map<K, A>>, - ): MuxNode<*, *, Map<K, A>>? { - val storage: Map<K, TFlowImpl<A>> = getStorage(evalScope) - // Initialize mux node and switched-in connections. - val muxNode = - MuxDeferredNode(lifecycle, this).apply { - storage.mapValuesNotNullParallelTo(switchedIn) { (key, flow) -> - val branchNode = MuxBranchNode(this@apply, key) - flow.activate(evalScope, branchNode.schedulable)?.let { - (conn, needsEval) -> - branchNode - .apply { upstream = conn } - .also { - if (needsEval) { - val result = conn.getPushEvent(evalScope) - if (result is Just) { - upstreamData[key] = result.value - } - } - } - } - } - } +internal fun <W, K, V> switchDeferredImpl( + name: String? = null, + getStorage: EvalScope.() -> Iterable<Map.Entry<K, EventsImpl<V>>>, + getPatches: EvalScope.() -> EventsImpl<Iterable<Map.Entry<K, Maybe<EventsImpl<V>>>>>, + storeFactory: MutableMapK.Factory<W, K>, +): EventsImpl<MuxResult<W, K, V>> = + MuxLifecycle(MuxDeferredActivator(name, getStorage, storeFactory, getPatches)) + +private class MuxDeferredActivator<W, K, V>( + private val name: String?, + private val getStorage: EvalScope.() -> Iterable<Map.Entry<K, EventsImpl<V>>>, + private val storeFactory: MutableMapK.Factory<W, K>, + private val getPatches: EvalScope.() -> EventsImpl<Iterable<Map.Entry<K, Maybe<EventsImpl<V>>>>>, +) : MuxActivator<W, K, V> { + override fun activate( + evalScope: EvalScope, + lifecycle: MuxLifecycle<W, K, V>, + ): Pair<MuxNode<W, K, V>, (() -> Unit)?>? { + // Initialize mux node and switched-in connections. + val muxNode = + MuxDeferredNode(name, lifecycle, this, storeFactory).apply { + initializeUpstream(evalScope, getStorage, storeFactory) // Update depth based on all initial switched-in nodes. - muxNode.switchedIn.values.forEach { branch -> - val conn = branch.upstream - if (conn.depthTracker.snapshotIsDirect) { - muxNode.depthTracker.addDirectUpstream( - oldDepth = null, - newDepth = conn.depthTracker.snapshotDirectDepth, - ) - } else { - muxNode.depthTracker.addIndirectUpstream( - oldDepth = null, - newDepth = conn.depthTracker.snapshotIndirectDepth, - ) - muxNode.depthTracker.updateIndirectRoots( - additions = conn.depthTracker.snapshotIndirectRoots, - butNot = muxNode, - ) - } - } + initializeDepth() // We don't have our patches connection established yet, so for now pretend we have // a direct connection to patches. We will update downstream nodes later if this // turns out to be a lie. - muxNode.depthTracker.setIsIndirectRoot(true) - muxNode.depthTracker.reset() + depthTracker.setIsIndirectRoot(true) + depthTracker.reset() + } + + // Schedule for evaluation if any switched-in nodes have already emitted within + // this transaction. + if (muxNode.upstreamData.isNotEmpty()) { + muxNode.schedule(evalScope) + } + return muxNode to + fun() { // Setup patches connection; deferring allows for a recursive connection, where // muxNode is downstream of itself via patches. - var isIndirect = true - evalScope.deferAction { - val (patchesConn, needsEval) = - getPatches(evalScope).activate(evalScope, downstream = muxNode.schedulable) - ?: run { - isIndirect = false - // Turns out we can't connect to patches, so update our depth and - // propagate - muxNode.mutex.withLock { - if (muxNode.depthTracker.setIsIndirectRoot(false)) { - muxNode.depthTracker.schedule(evalScope.scheduler, muxNode) - } - } - return@deferAction - } - muxNode.patches = patchesConn - - if (!patchesConn.schedulerUpstream.depthTracker.snapshotIsDirect) { - // Turns out patches is indirect, so we are not a root. Update depth and - // propagate. - muxNode.mutex.withLock { - if ( - muxNode.depthTracker.setIsIndirectRoot(false) or - muxNode.depthTracker.addIndirectUpstream( - oldDepth = null, - newDepth = patchesConn.depthTracker.snapshotIndirectDepth, - ) or - muxNode.depthTracker.updateIndirectRoots( - additions = patchesConn.depthTracker.snapshotIndirectRoots - ) - ) { + val (patchesConn, needsEval) = + getPatches(evalScope).activate(evalScope, downstream = muxNode.schedulable) + ?: run { + // Turns out we can't connect to patches, so update our depth and + // propagate + if (muxNode.depthTracker.setIsIndirectRoot(false)) { + // TODO: schedules might not be necessary now that we're not + // parallel? muxNode.depthTracker.schedule(evalScope.scheduler, muxNode) } + return } - } - // Schedule mover to process patch emission at the end of this transaction, if - // needed. - if (needsEval) { - val result = patchesConn.getPushEvent(evalScope) - if (result is Just) { - muxNode.patchData = result.value - evalScope.scheduleMuxMover(muxNode) - } + muxNode.patches = patchesConn + + if (!patchesConn.schedulerUpstream.depthTracker.snapshotIsDirect) { + // Turns out patches is indirect, so we are not a root. Update depth and + // propagate. + if ( + muxNode.depthTracker.setIsIndirectRoot(false) or + muxNode.depthTracker.addIndirectUpstream( + oldDepth = null, + newDepth = patchesConn.depthTracker.snapshotIndirectDepth, + ) or + muxNode.depthTracker.updateIndirectRoots( + additions = patchesConn.depthTracker.snapshotIndirectRoots + ) + ) { + muxNode.depthTracker.schedule(evalScope.scheduler, muxNode) } } - - // Schedule for evaluation if any switched-in nodes have already emitted within - // this transaction. - if (muxNode.upstreamData.isNotEmpty()) { - muxNode.schedule(evalScope) + // Schedule mover to process patch emission at the end of this transaction, if + // needed. + if (needsEval) { + muxNode.patchData = patchesConn.getPushEvent(0, evalScope) + evalScope.scheduleMuxMover(muxNode) } - return muxNode.takeUnless { muxNode.switchedIn.isEmpty() && !isIndirect } } - } - ) + } +} internal inline fun <A> mergeNodes( - crossinline getPulse: suspend EvalScope.() -> TFlowImpl<A>, - crossinline getOther: suspend EvalScope.() -> TFlowImpl<A>, - crossinline f: suspend EvalScope.(A, A) -> A, -): TFlowImpl<A> { + crossinline getPulse: EvalScope.() -> EventsImpl<A>, + crossinline getOther: EvalScope.() -> EventsImpl<A>, + name: String? = null, + crossinline f: EvalScope.(A, A) -> A, +): EventsImpl<A> { + val mergedThese = mergeNodes(name, getPulse, getOther) val merged = - mapImpl({ mergeNodes(getPulse, getOther) }) { these -> - these.merge { thiz, that -> f(thiz, that) } - } + mapImpl({ mergedThese }) { these, _ -> these.merge { thiz, that -> f(thiz, that) } } return merged.cached() } +internal fun <T> Iterable<T>.asIterableWithIndex(): Iterable<Map.Entry<Int, T>> = + asSequence().mapIndexed { i, t -> StoreEntry(i, t) }.asIterable() + internal inline fun <A, B> mergeNodes( - crossinline getPulse: suspend EvalScope.() -> TFlowImpl<A>, - crossinline getOther: suspend EvalScope.() -> TFlowImpl<B>, -): TFlowImpl<These<A, B>> { + name: String? = null, + crossinline getPulse: EvalScope.() -> EventsImpl<A>, + crossinline getOther: EvalScope.() -> EventsImpl<B>, +): EventsImpl<These<A, B>> { val storage = - mapOf( - 0 to mapImpl(getPulse) { These.thiz<A, B>(it) }, - 1 to mapImpl(getOther) { These.that(it) }, + listOf( + mapImpl(getPulse) { it, _ -> These.thiz(it) }, + mapImpl(getOther) { it, _ -> These.that(it) }, + ) + .asIterableWithIndex() + val switchNode = + switchDeferredImpl( + name = name, + getStorage = { storage }, + getPatches = { neverImpl }, + storeFactory = MutableArrayMapK.Factory(), ) - val switchNode = switchDeferredImpl(getStorage = { storage }, getPatches = { neverImpl }) val merged = - mapImpl({ switchNode }) { mergeResults -> - val first = mergeResults.getMaybe(0).flatMap { it.maybeThis() } - val second = mergeResults.getMaybe(1).flatMap { it.maybeThat() } - these(first, second).orElseGet { error("unexpected missing merge result") } + mapImpl({ switchNode }) { it, logIndent -> + val mergeResults = it.asArrayHolder() + val first = + mergeResults.getMaybe(0).flatMap { it.getPushEvent(logIndent, this).maybeThis() } + val second = + mergeResults.getMaybe(1).flatMap { it.getPushEvent(logIndent, this).maybeThat() } + these(first, second).orError { "unexpected missing merge result" } } return merged.cached() } internal inline fun <A> mergeNodes( - crossinline getPulses: suspend EvalScope.() -> Iterable<TFlowImpl<A>> -): TFlowImpl<List<A>> { + crossinline getPulses: EvalScope.() -> Iterable<EventsImpl<A>> +): EventsImpl<List<A>> { val switchNode = switchDeferredImpl( - getStorage = { getPulses().associateByIndexTo(TreeMap()) }, + getStorage = { getPulses().asIterableWithIndex() }, getPatches = { neverImpl }, + storeFactory = MutableArrayMapK.Factory(), ) - val merged = mapImpl({ switchNode }) { mergeResults -> mergeResults.values.toList() } + val merged = + mapImpl({ switchNode }) { it, logIndent -> + val mergeResults = it.asArrayHolder() + mergeResults.map { (_, node) -> node.getPushEvent(logIndent, this) } + } return merged.cached() } internal inline fun <A> mergeNodesLeft( - crossinline getPulses: suspend EvalScope.() -> Iterable<TFlowImpl<A>> -): TFlowImpl<A> { + crossinline getPulses: EvalScope.() -> Iterable<EventsImpl<A>> +): EventsImpl<A> { val switchNode = switchDeferredImpl( - getStorage = { getPulses().associateByIndexTo(TreeMap()) }, + getStorage = { getPulses().asIterableWithIndex() }, getPatches = { neverImpl }, + storeFactory = MutableArrayMapK.Factory(), ) val merged = - mapImpl({ switchNode }) { mergeResults: Map<Int, A> -> mergeResults.values.first() } + mapImpl({ switchNode }) { it, logIndent -> + val mergeResults = it.asArrayHolder() + mergeResults.values.first().getPushEvent(logIndent, this) + } return merged.cached() } diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/MuxPrompt.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/MuxPrompt.kt index b291c879b449..32aef5c7041b 100644 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/MuxPrompt.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/MuxPrompt.kt @@ -16,217 +16,184 @@ package com.android.systemui.kairos.internal -import com.android.systemui.kairos.internal.util.Key -import com.android.systemui.kairos.internal.util.launchImmediate -import com.android.systemui.kairos.internal.util.mapParallel -import com.android.systemui.kairos.internal.util.mapValuesNotNullParallelTo -import com.android.systemui.kairos.util.Just -import com.android.systemui.kairos.util.Left +import com.android.systemui.kairos.internal.store.MutableMapK +import com.android.systemui.kairos.internal.store.SingletonMapK +import com.android.systemui.kairos.internal.store.asSingle +import com.android.systemui.kairos.internal.store.singleOf +import com.android.systemui.kairos.internal.util.LogIndent +import com.android.systemui.kairos.internal.util.hashString +import com.android.systemui.kairos.internal.util.logDuration import com.android.systemui.kairos.util.Maybe -import com.android.systemui.kairos.util.None -import com.android.systemui.kairos.util.Right -import com.android.systemui.kairos.util.filterJust -import com.android.systemui.kairos.util.map -import com.android.systemui.kairos.util.partitionEithers -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.async -import kotlinx.coroutines.awaitAll -import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.launch -import kotlinx.coroutines.sync.withLock - -internal class MuxPromptMovingNode<K : Any, V>( - lifecycle: MuxLifecycle<Pair<Map<K, V>, Map<K, PullNode<V>>?>>, - private val spec: MuxActivator<Pair<Map<K, V>, Map<K, PullNode<V>>?>>, -) : - MuxNode<K, V, Pair<Map<K, V>, Map<K, PullNode<V>>?>>(lifecycle), - Key<Pair<Map<K, V>, Map<K, PullNode<V>>?>> { - - @Volatile var patchData: Map<K, Maybe<TFlowImpl<V>>>? = null - @Volatile var patches: MuxPromptPatchNode<K, V>? = null - - @Volatile private var reEval: Pair<Map<K, V>, Map<K, PullNode<V>>?>? = null - - override fun hasCurrentValueLocked(transactionStore: TransactionStore): Boolean = - transactionStore.contains(this) - - override suspend fun hasCurrentValue(transactionStore: TransactionStore): Boolean = - mutex.withLock { hasCurrentValueLocked(transactionStore) } - - override suspend fun visit(evalScope: EvalScope) { - val preSwitchResults: Map<K, V> = upstreamData.toMap() - upstreamData.clear() - - val patch: Map<K, Maybe<TFlowImpl<V>>>? = patchData - patchData = null - - val (reschedule, evalResult) = - reEval?.let { false to it } - ?: if (preSwitchResults.isNotEmpty() || patch?.isNotEmpty() == true) { - doEval(preSwitchResults, patch, evalScope) - } else { - false to null +import com.android.systemui.kairos.util.Maybe.Just +import com.android.systemui.kairos.util.Maybe.None +import com.android.systemui.kairos.util.just + +internal class MuxPromptNode<W, K, V>( + val name: String?, + lifecycle: MuxLifecycle<W, K, V>, + private val spec: MuxActivator<W, K, V>, + factory: MutableMapK.Factory<W, K>, +) : MuxNode<W, K, V>(lifecycle, factory) { + + var patchData: Iterable<Map.Entry<K, Maybe<EventsImpl<V>>>>? = null + var patches: PatchNode? = null + + override fun visit(logIndent: Int, evalScope: EvalScope) { + check(epoch < evalScope.epoch) { "node unexpectedly visited multiple times in transaction" } + logDuration(logIndent, "MuxPrompt.visit") { + val patch: Iterable<Map.Entry<K, Maybe<EventsImpl<V>>>>? = patchData + patchData = null + + // If there's a patch, process it. + patch?.let { + val needsReschedule = processPatch(patch, evalScope) + // We may need to reschedule if newly-switched-in nodes have not yet been + // visited within this transaction. + val depthIncreased = depthTracker.dirty_depthIncreased() + if (needsReschedule || depthIncreased) { + if (depthIncreased) { + depthTracker.schedule(evalScope.compactor, this@MuxPromptNode) + } + if (name != null) { + logLn( + "[${this@MuxPromptNode}] rescheduling (reschedule=$needsReschedule, depthIncrease=$depthIncreased)" + ) + } + schedule(evalScope) + return } - reEval = null - - if (reschedule || depthTracker.dirty_depthIncreased()) { - reEval = evalResult - // Can't schedule downstream yet, need to compact first - if (depthTracker.dirty_depthIncreased()) { - depthTracker.schedule(evalScope.compactor, node = this) } - schedule(evalScope) - } else { + val results = upstreamData.readOnlyCopy().also { upstreamData.clear() } + + // If we don't need to reschedule, or there wasn't a patch at all, then we proceed + // with merging pre-switch and post-switch results + val hasResult = results.isNotEmpty() val compactDownstream = depthTracker.isDirty() - if (evalResult != null || compactDownstream) { - coroutineScope { - mutex.withLock { - if (compactDownstream) { - adjustDownstreamDepths(evalScope, coroutineScope = this) - } - if (evalResult != null) { - evalScope.setResult(this@MuxPromptMovingNode, evalResult) - if (!scheduleAll(downstreamSet, evalScope)) { - evalScope.scheduleDeactivation(this@MuxPromptMovingNode) - } - } + if (hasResult || compactDownstream) { + if (compactDownstream) { + adjustDownstreamDepths(evalScope) + } + if (hasResult) { + transactionCache.put(evalScope, results) + if (!scheduleAll(currentLogIndent, downstreamSet, evalScope)) { + evalScope.scheduleDeactivation(this@MuxPromptNode) } } } } } - private suspend fun doEval( - preSwitchResults: Map<K, V>, - patch: Map<K, Maybe<TFlowImpl<V>>>?, + // side-effect: this will populate `upstreamData` with any immediately available results + private fun LogIndent.processPatch( + patch: Iterable<Map.Entry<K, Maybe<EventsImpl<V>>>>, evalScope: EvalScope, - ): Pair<Boolean, Pair<Map<K, V>, Map<K, PullNode<V>>?>?> { - val newlySwitchedIn: Map<K, PullNode<V>>? = - patch?.let { - // We have a patch, process additions/updates and removals - val (adds, removes) = - patch - .asSequence() - .map { (k, newUpstream: Maybe<TFlowImpl<V>>) -> - when (newUpstream) { - is Just -> Left(k to newUpstream.value) - None -> Right(k) - } - } - .partitionEithers() - - val additionsAndUpdates = mutableMapOf<K, PullNode<V>>() - val severed = mutableListOf<NodeConnection<*>>() - - coroutineScope { - // remove and sever - removes.forEach { k -> - switchedIn.remove(k)?.let { branchNode: MuxBranchNode<K, V> -> - val conn: NodeConnection<V> = branchNode.upstream - severed.add(conn) - launchImmediate { - conn.removeDownstream(downstream = branchNode.schedulable) - } - depthTracker.removeDirectUpstream(conn.depthTracker.snapshotDirectDepth) - } - } + ): Boolean { + var needsReschedule = false + // We have a patch, process additions/updates and removals + val adds = mutableListOf<Pair<K, EventsImpl<V>>>() + val removes = mutableListOf<K>() + patch.forEach { (k, newUpstream) -> + when (newUpstream) { + is Just -> adds.add(k to newUpstream.value) + None -> removes.add(k) + } + } - // add or replace - adds - .mapParallel { (k, newUpstream: TFlowImpl<V>) -> - val branchNode = MuxBranchNode(this@MuxPromptMovingNode, k) - k to - newUpstream.activate(evalScope, branchNode.schedulable)?.let { - (conn, _) -> - branchNode.apply { upstream = conn } - } - } - .forEach { (k, newBranch: MuxBranchNode<K, V>?) -> - // remove old and sever, if present - switchedIn.remove(k)?.let { oldBranch: MuxBranchNode<K, V> -> - val conn: NodeConnection<V> = oldBranch.upstream - severed.add(conn) - launchImmediate { - conn.removeDownstream(downstream = oldBranch.schedulable) - } - depthTracker.removeDirectUpstream( - conn.depthTracker.snapshotDirectDepth - ) - } - - // add new - newBranch?.let { - switchedIn[k] = newBranch - additionsAndUpdates[k] = newBranch.upstream.directUpstream - val branchDepthTracker = newBranch.upstream.depthTracker - if (branchDepthTracker.snapshotIsDirect) { - depthTracker.addDirectUpstream( - oldDepth = null, - newDepth = branchDepthTracker.snapshotDirectDepth, - ) - } else { - depthTracker.addIndirectUpstream( - oldDepth = null, - newDepth = branchDepthTracker.snapshotIndirectDepth, - ) - depthTracker.updateIndirectRoots( - additions = branchDepthTracker.snapshotIndirectRoots, - butNot = null, - ) - } - } - } + val severed = mutableListOf<NodeConnection<*>>() + + // remove and sever + removes.forEach { k -> + switchedIn.remove(k)?.let { branchNode: BranchNode -> + if (name != null) { + logLn("[${this@MuxPromptNode}] removing $k") } + val conn: NodeConnection<V> = branchNode.upstream + severed.add(conn) + conn.removeDownstream(downstream = branchNode.schedulable) + depthTracker.removeDirectUpstream(conn.depthTracker.snapshotDirectDepth) + } + } - coroutineScope { - for (severedNode in severed) { - launch { severedNode.scheduleDeactivationIfNeeded(evalScope) } - } + // add or replace + adds.forEach { (k, newUpstream: EventsImpl<V>) -> + // remove old and sever, if present + switchedIn.remove(k)?.let { oldBranch: BranchNode -> + if (name != null) { + logLn("[${this@MuxPromptNode}] replacing $k") } + val conn: NodeConnection<V> = oldBranch.upstream + severed.add(conn) + conn.removeDownstream(downstream = oldBranch.schedulable) + depthTracker.removeDirectUpstream(conn.depthTracker.snapshotDirectDepth) + } - additionsAndUpdates.takeIf { it.isNotEmpty() } + // add new + val newBranch = BranchNode(k) + newUpstream.activate(evalScope, newBranch.schedulable)?.let { (conn, needsEval) -> + newBranch.upstream = conn + if (name != null) { + logLn("[${this@MuxPromptNode}] switching in $k") + } + switchedIn[k] = newBranch + if (needsEval) { + upstreamData[k] = newBranch.upstream.directUpstream + } else { + needsReschedule = true + } + val branchDepthTracker = newBranch.upstream.depthTracker + if (branchDepthTracker.snapshotIsDirect) { + depthTracker.addDirectUpstream( + oldDepth = null, + newDepth = branchDepthTracker.snapshotDirectDepth, + ) + } else { + depthTracker.addIndirectUpstream( + oldDepth = null, + newDepth = branchDepthTracker.snapshotIndirectDepth, + ) + depthTracker.updateIndirectRoots( + additions = branchDepthTracker.snapshotIndirectRoots, + butNot = null, + ) + } } + } - return if (preSwitchResults.isNotEmpty() || newlySwitchedIn != null) { - (newlySwitchedIn != null) to (preSwitchResults to newlySwitchedIn) - } else { - false to null + for (severedNode in severed) { + severedNode.scheduleDeactivationIfNeeded(evalScope) } + + return needsReschedule } - private suspend fun adjustDownstreamDepths( - evalScope: EvalScope, - coroutineScope: CoroutineScope, - ) { + private fun adjustDownstreamDepths(evalScope: EvalScope) { if (depthTracker.dirty_depthIncreased()) { // schedule downstream nodes on the compaction scheduler; this scheduler is drained at // the end of this eval depth, so that all depth increases are applied before we advance // the eval step - depthTracker.schedule(evalScope.compactor, node = this@MuxPromptMovingNode) + depthTracker.schedule(evalScope.compactor, node = this@MuxPromptNode) } else if (depthTracker.isDirty()) { // schedule downstream nodes on the eval scheduler; this is more efficient and is only // safe if the depth hasn't increased depthTracker.applyChanges( - coroutineScope, evalScope.scheduler, downstreamSet, - muxNode = this@MuxPromptMovingNode, + muxNode = this@MuxPromptNode, ) } } - override suspend fun getPushEvent( - evalScope: EvalScope - ): Maybe<Pair<Map<K, V>, Map<K, PullNode<V>>?>> = evalScope.getCurrentValue(key = this) + override fun getPushEvent(logIndent: Int, evalScope: EvalScope): MuxResult<W, K, V> = + logDuration(logIndent, "MuxPrompt.getPushEvent") { + transactionCache.getCurrentValue(evalScope) + } - override suspend fun doDeactivate() { + override fun doDeactivate() { // Update lifecycle - lifecycle.mutex.withLock { - if (lifecycle.lifecycleState !is MuxLifecycleState.Active) return@doDeactivate - lifecycle.lifecycleState = MuxLifecycleState.Inactive(spec) - } + if (lifecycle.lifecycleState !is MuxLifecycleState.Active) return + lifecycle.lifecycleState = MuxLifecycleState.Inactive(spec) // Process branch nodes - switchedIn.values.forEach { branchNode -> + switchedIn.forEach { (_, branchNode) -> branchNode.upstream.removeDownstreamAndDeactivateIfNeeded( downstream = branchNode.schedulable ) @@ -237,236 +204,189 @@ internal class MuxPromptMovingNode<K : Any, V>( } } - suspend fun removeIndirectPatchNode( + fun removeIndirectPatchNode( scheduler: Scheduler, oldDepth: Int, - indirectSet: Set<MuxDeferredNode<*, *>>, + indirectSet: Set<MuxDeferredNode<*, *, *>>, ) { - mutex.withLock { - patches = null - if ( - depthTracker.removeIndirectUpstream(oldDepth) or - depthTracker.updateIndirectRoots(removals = indirectSet) - ) { - depthTracker.schedule(scheduler, this) - } + patches = null + if ( + depthTracker.removeIndirectUpstream(oldDepth) or + depthTracker.updateIndirectRoots(removals = indirectSet) + ) { + depthTracker.schedule(scheduler, this) } } - suspend fun removeDirectPatchNode(scheduler: Scheduler, depth: Int) { - mutex.withLock { - patches = null - if (depthTracker.removeDirectUpstream(depth)) { - depthTracker.schedule(scheduler, this) - } + fun removeDirectPatchNode(scheduler: Scheduler, depth: Int) { + patches = null + if (depthTracker.removeDirectUpstream(depth)) { + depthTracker.schedule(scheduler, this) } } -} -internal class MuxPromptEvalNode<K, V>( - private val movingNode: PullNode<Pair<Map<K, V>, Map<K, PullNode<V>>?>> -) : PullNode<Map<K, V>> { - override suspend fun getPushEvent(evalScope: EvalScope): Maybe<Map<K, V>> = - movingNode.getPushEvent(evalScope).map { (preSwitchResults, newlySwitchedIn) -> - coroutineScope { - newlySwitchedIn - ?.map { (k, v) -> async { v.getPushEvent(evalScope).map { k to it } } } - ?.awaitAll() - ?.asSequence() - ?.filterJust() - ?.toMap(preSwitchResults.toMutableMap()) ?: preSwitchResults - } - } -} + override fun toString(): String = + "${this::class.simpleName}@$hashString${name?.let { "[$it]" }.orEmpty()}" -// TODO: inner class? -internal class MuxPromptPatchNode<K : Any, V>(private val muxNode: MuxPromptMovingNode<K, V>) : - SchedulableNode { + inner class PatchNode : SchedulableNode { - val schedulable = Schedulable.N(this) + val schedulable = Schedulable.N(this) - lateinit var upstream: NodeConnection<Map<K, Maybe<TFlowImpl<V>>>> + lateinit var upstream: NodeConnection<Iterable<Map.Entry<K, Maybe<EventsImpl<V>>>>> - override suspend fun schedule(evalScope: EvalScope) { - val upstreamResult = upstream.getPushEvent(evalScope) - if (upstreamResult is Just) { - muxNode.patchData = upstreamResult.value - muxNode.schedule(evalScope) + override fun schedule(logIndent: Int, evalScope: EvalScope) { + logDuration(logIndent, "MuxPromptPatchNode.schedule") { + patchData = upstream.getPushEvent(currentLogIndent, evalScope) + this@MuxPromptNode.schedule(evalScope) + } } - } - override suspend fun adjustDirectUpstream(scheduler: Scheduler, oldDepth: Int, newDepth: Int) { - muxNode.adjustDirectUpstream(scheduler, oldDepth, newDepth) - } + override fun adjustDirectUpstream(scheduler: Scheduler, oldDepth: Int, newDepth: Int) { + this@MuxPromptNode.adjustDirectUpstream(scheduler, oldDepth, newDepth) + } - override suspend fun moveIndirectUpstreamToDirect( - scheduler: Scheduler, - oldIndirectDepth: Int, - oldIndirectSet: Set<MuxDeferredNode<*, *>>, - newDirectDepth: Int, - ) { - muxNode.moveIndirectUpstreamToDirect( - scheduler, - oldIndirectDepth, - oldIndirectSet, - newDirectDepth, - ) - } + override fun moveIndirectUpstreamToDirect( + scheduler: Scheduler, + oldIndirectDepth: Int, + oldIndirectSet: Set<MuxDeferredNode<*, *, *>>, + newDirectDepth: Int, + ) { + this@MuxPromptNode.moveIndirectUpstreamToDirect( + scheduler, + oldIndirectDepth, + oldIndirectSet, + newDirectDepth, + ) + } - override suspend fun adjustIndirectUpstream( - scheduler: Scheduler, - oldDepth: Int, - newDepth: Int, - removals: Set<MuxDeferredNode<*, *>>, - additions: Set<MuxDeferredNode<*, *>>, - ) { - muxNode.adjustIndirectUpstream(scheduler, oldDepth, newDepth, removals, additions) - } + override fun adjustIndirectUpstream( + scheduler: Scheduler, + oldDepth: Int, + newDepth: Int, + removals: Set<MuxDeferredNode<*, *, *>>, + additions: Set<MuxDeferredNode<*, *, *>>, + ) { + this@MuxPromptNode.adjustIndirectUpstream( + scheduler, + oldDepth, + newDepth, + removals, + additions, + ) + } - override suspend fun moveDirectUpstreamToIndirect( - scheduler: Scheduler, - oldDirectDepth: Int, - newIndirectDepth: Int, - newIndirectSet: Set<MuxDeferredNode<*, *>>, - ) { - muxNode.moveDirectUpstreamToIndirect( - scheduler, - oldDirectDepth, - newIndirectDepth, - newIndirectSet, - ) - } + override fun moveDirectUpstreamToIndirect( + scheduler: Scheduler, + oldDirectDepth: Int, + newIndirectDepth: Int, + newIndirectSet: Set<MuxDeferredNode<*, *, *>>, + ) { + this@MuxPromptNode.moveDirectUpstreamToIndirect( + scheduler, + oldDirectDepth, + newIndirectDepth, + newIndirectSet, + ) + } - override suspend fun removeDirectUpstream(scheduler: Scheduler, depth: Int) { - muxNode.removeDirectPatchNode(scheduler, depth) + override fun removeDirectUpstream(scheduler: Scheduler, depth: Int) { + this@MuxPromptNode.removeDirectPatchNode(scheduler, depth) + } + + override fun removeIndirectUpstream( + scheduler: Scheduler, + depth: Int, + indirectSet: Set<MuxDeferredNode<*, *, *>>, + ) { + this@MuxPromptNode.removeIndirectPatchNode(scheduler, depth, indirectSet) + } } +} - override suspend fun removeIndirectUpstream( - scheduler: Scheduler, - depth: Int, - indirectSet: Set<MuxDeferredNode<*, *>>, - ) { - muxNode.removeIndirectPatchNode(scheduler, depth, indirectSet) +internal inline fun <A> switchPromptImplSingle( + crossinline getStorage: EvalScope.() -> EventsImpl<A>, + crossinline getPatches: EvalScope.() -> EventsImpl<EventsImpl<A>>, +): EventsImpl<A> { + val switchPromptImpl = + switchPromptImpl( + getStorage = { singleOf(getStorage()).asIterable() }, + getPatches = { + mapImpl(getPatches) { newEvents, _ -> singleOf(just(newEvents)).asIterable() } + }, + storeFactory = SingletonMapK.Factory(), + ) + return mapImpl({ switchPromptImpl }) { map, logIndent -> + map.asSingle().getValue(Unit).getPushEvent(logIndent, this) } } -internal fun <K : Any, A> switchPromptImpl( - getStorage: suspend EvalScope.() -> Map<K, TFlowImpl<A>>, - getPatches: suspend EvalScope.() -> TFlowImpl<Map<K, Maybe<TFlowImpl<A>>>>, -): TFlowImpl<Map<K, A>> { - val moving = - MuxLifecycle( - object : MuxActivator<Pair<Map<K, A>, Map<K, PullNode<A>>?>> { - override suspend fun activate( - evalScope: EvalScope, - lifecycle: MuxLifecycle<Pair<Map<K, A>, Map<K, PullNode<A>>?>>, - ): MuxNode<*, *, Pair<Map<K, A>, Map<K, PullNode<A>>?>>? { - val storage: Map<K, TFlowImpl<A>> = getStorage(evalScope) - // Initialize mux node and switched-in connections. - val movingNode = - MuxPromptMovingNode(lifecycle, this).apply { - coroutineScope { - launch { - storage.mapValuesNotNullParallelTo(switchedIn) { (key, flow) -> - val branchNode = MuxBranchNode(this@apply, key) - flow - .activate( - evalScope = evalScope, - downstream = branchNode.schedulable, - ) - ?.let { (conn, needsEval) -> - branchNode - .apply { upstream = conn } - .also { - if (needsEval) { - val result = - conn.getPushEvent(evalScope) - if (result is Just) { - upstreamData[key] = result.value - } - } - } - } - } - } - // Setup patches connection - val patchNode = MuxPromptPatchNode(this@apply) - getPatches(evalScope) - .activate( - evalScope = evalScope, - downstream = patchNode.schedulable, - ) - ?.let { (conn, needsEval) -> - patchNode.upstream = conn - patches = patchNode - - if (needsEval) { - val result = conn.getPushEvent(evalScope) - if (result is Just) { - patchData = result.value - } - } - } - } - } - // Update depth based on all initial switched-in nodes. - movingNode.switchedIn.values.forEach { branch -> - val conn = branch.upstream - if (conn.depthTracker.snapshotIsDirect) { - movingNode.depthTracker.addDirectUpstream( - oldDepth = null, - newDepth = conn.depthTracker.snapshotDirectDepth, - ) - } else { - movingNode.depthTracker.addIndirectUpstream( - oldDepth = null, - newDepth = conn.depthTracker.snapshotIndirectDepth, - ) - movingNode.depthTracker.updateIndirectRoots( - additions = conn.depthTracker.snapshotIndirectRoots, - butNot = null, - ) +internal fun <W, K, V> switchPromptImpl( + name: String? = null, + getStorage: EvalScope.() -> Iterable<Map.Entry<K, EventsImpl<V>>>, + getPatches: EvalScope.() -> EventsImpl<Iterable<Map.Entry<K, Maybe<EventsImpl<V>>>>>, + storeFactory: MutableMapK.Factory<W, K>, +): EventsImpl<MuxResult<W, K, V>> = + MuxLifecycle(MuxPromptActivator(name, getStorage, storeFactory, getPatches)) + +private class MuxPromptActivator<W, K, V>( + private val name: String?, + private val getStorage: EvalScope.() -> Iterable<Map.Entry<K, EventsImpl<V>>>, + private val storeFactory: MutableMapK.Factory<W, K>, + private val getPatches: EvalScope.() -> EventsImpl<Iterable<Map.Entry<K, Maybe<EventsImpl<V>>>>>, +) : MuxActivator<W, K, V> { + override fun activate( + evalScope: EvalScope, + lifecycle: MuxLifecycle<W, K, V>, + ): Pair<MuxNode<W, K, V>, (() -> Unit)?>? { + // Initialize mux node and switched-in connections. + val movingNode = + MuxPromptNode(name, lifecycle, this, storeFactory).apply { + initializeUpstream(evalScope, getStorage, storeFactory) + // Setup patches connection + val patchNode = PatchNode() + getPatches(evalScope) + .activate(evalScope = evalScope, downstream = patchNode.schedulable) + ?.let { (conn, needsEval) -> + patchNode.upstream = conn + patches = patchNode + if (needsEval) { + patchData = conn.getPushEvent(0, evalScope) } } - // Update depth based on patches node. - movingNode.patches?.upstream?.let { conn -> - if (conn.depthTracker.snapshotIsDirect) { - movingNode.depthTracker.addDirectUpstream( - oldDepth = null, - newDepth = conn.depthTracker.snapshotDirectDepth, - ) - } else { - movingNode.depthTracker.addIndirectUpstream( - oldDepth = null, - newDepth = conn.depthTracker.snapshotIndirectDepth, - ) - movingNode.depthTracker.updateIndirectRoots( - additions = conn.depthTracker.snapshotIndirectRoots, - butNot = null, - ) - } + // Update depth based on all initial switched-in nodes. + initializeDepth() + // Update depth based on patches node. + patches?.upstream?.let { conn -> + if (conn.depthTracker.snapshotIsDirect) { + depthTracker.addDirectUpstream( + oldDepth = null, + newDepth = conn.depthTracker.snapshotDirectDepth, + ) + } else { + depthTracker.addIndirectUpstream( + oldDepth = null, + newDepth = conn.depthTracker.snapshotIndirectDepth, + ) + depthTracker.updateIndirectRoots( + additions = conn.depthTracker.snapshotIndirectRoots, + butNot = null, + ) } - movingNode.depthTracker.reset() - - // Schedule for evaluation if any switched-in nodes or the patches node have - // already emitted within this transaction. - if (movingNode.patchData != null || movingNode.upstreamData.isNotEmpty()) { - movingNode.schedule(evalScope) - } - - return movingNode.takeUnless { it.patches == null && it.switchedIn.isEmpty() } } + // Reset all depth adjustments, since no downstream has been notified + depthTracker.reset() } - ) - val eval = TFlowCheap { downstream -> - moving.activate(evalScope = this, downstream)?.let { (connection, needsEval) -> - val evalNode = MuxPromptEvalNode(connection.directUpstream) - ActivationResult( - connection = NodeConnection(evalNode, connection.schedulerUpstream), - needsEval = needsEval, - ) + // Schedule for evaluation if any switched-in nodes or the patches node have + // already emitted within this transaction. + if (movingNode.patchData != null || movingNode.upstreamData.isNotEmpty()) { + movingNode.schedule(evalScope) + } + + return if (movingNode.patches == null && movingNode.switchedIn.isEmpty()) { + null + } else { + movingNode to null } } - return eval.cached() } diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Network.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Network.kt index 599b18695034..fbc2b3644701 100644 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Network.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Network.kt @@ -16,17 +16,17 @@ package com.android.systemui.kairos.internal -import com.android.systemui.kairos.TState +import com.android.systemui.kairos.State import com.android.systemui.kairos.internal.util.HeteroMap -import com.android.systemui.kairos.util.Just +import com.android.systemui.kairos.internal.util.logDuration +import com.android.systemui.kairos.internal.util.logLn import com.android.systemui.kairos.util.Maybe +import com.android.systemui.kairos.util.Maybe.Just import com.android.systemui.kairos.util.just import com.android.systemui.kairos.util.none -import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.ConcurrentLinkedDeque -import java.util.concurrent.ConcurrentLinkedQueue import java.util.concurrent.atomic.AtomicLong import kotlin.coroutines.ContinuationInterceptor +import kotlin.time.measureTime import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Deferred @@ -52,32 +52,41 @@ internal class Network(val coroutineScope: CoroutineScope) : NetworkScope { override val network get() = this - override val compactor = SchedulerImpl() - override val scheduler = SchedulerImpl() - override val transactionStore = HeteroMap() + override val compactor = SchedulerImpl { + if (it.markedForCompaction) false + else { + it.markedForCompaction = true + true + } + } + override val scheduler = SchedulerImpl { + if (it.markedForEvaluation) false + else { + it.markedForEvaluation = true + true + } + } + override val transactionStore = TransactionStore() - private val stateWrites = ConcurrentLinkedQueue<TStateSource<*>>() - private val outputsByDispatcher = - ConcurrentHashMap<ContinuationInterceptor, ConcurrentLinkedQueue<Output<*>>>() - private val muxMovers = ConcurrentLinkedQueue<MuxDeferredNode<*, *>>() - private val deactivations = ConcurrentLinkedDeque<PushNode<*>>() - private val outputDeactivations = ConcurrentLinkedQueue<Output<*>>() + private val stateWrites = ArrayDeque<StateSource<*>>() + private val outputsByDispatcher = HashMap<ContinuationInterceptor, ArrayDeque<Output<*>>>() + private val muxMovers = ArrayDeque<MuxDeferredNode<*, *, *>>() + private val deactivations = ArrayDeque<PushNode<*>>() + private val outputDeactivations = ArrayDeque<Output<*>>() private val transactionMutex = Mutex() private val inputScheduleChan = Channel<ScheduledAction<*>>() override fun scheduleOutput(output: Output<*>) { val continuationInterceptor = output.context[ContinuationInterceptor] ?: Dispatchers.Unconfined - outputsByDispatcher - .computeIfAbsent(continuationInterceptor) { ConcurrentLinkedQueue() } - .add(output) + outputsByDispatcher.computeIfAbsent(continuationInterceptor) { ArrayDeque() }.add(output) } - override fun scheduleMuxMover(muxMover: MuxDeferredNode<*, *>) { + override fun scheduleMuxMover(muxMover: MuxDeferredNode<*, *, *>) { muxMovers.add(muxMover) } - override fun schedule(state: TStateSource<*>) { + override fun schedule(state: StateSource<*>) { stateWrites.add(state) } @@ -89,7 +98,7 @@ internal class Network(val coroutineScope: CoroutineScope) : NetworkScope { outputDeactivations.add(output) } - /** Listens for external events and starts FRP transactions. Runs forever. */ + /** Listens for external events and starts Kairos transactions. Runs forever. */ suspend fun runInputScheduler() { val actions = mutableListOf<ScheduledAction<*>>() for (first in inputScheduleChan) { @@ -101,18 +110,37 @@ internal class Network(val coroutineScope: CoroutineScope) : NetworkScope { actions.add(func) } transactionMutex.withLock { - // Run all actions - evalScope { - for (action in actions) { - launch { action.started(evalScope = this@evalScope) } + val e = epoch + val duration = measureTime { + logLn(0, "===starting transaction $e===") + try { + logDuration(1, "init actions") { + // Run all actions + evalScope { + for (action in actions) { + action.started(evalScope = this@evalScope) + } + } + } + // Step through the network + doTransaction(1) + } catch (e: Exception) { + // Signal failure + while (actions.isNotEmpty()) { + actions.removeLast().fail(e) + } + // re-throw, cancelling this coroutine + throw e + } finally { + logDuration(1, "signal completions") { + // Signal completion + while (actions.isNotEmpty()) { + actions.removeLast().completed() + } + } } } - // Step through the network - doTransaction() - // Signal completion - while (actions.isNotEmpty()) { - actions.removeLast().completed() - } + logLn(0, "===transaction $e took $duration===") } } } @@ -129,33 +157,47 @@ internal class Network(val coroutineScope: CoroutineScope) : NetworkScope { onResult.invokeOnCompletion { job.cancel() } } - suspend fun <R> evalScope(block: suspend EvalScope.() -> R): R = deferScope { + inline fun <R> evalScope(block: EvalScope.() -> R): R = deferScope { block(EvalScopeImpl(this@Network, this)) } - /** Performs a transactional update of the FRP network. */ - private suspend fun doTransaction() { + /** Performs a transactional update of the Kairos network. */ + private suspend fun doTransaction(logIndent: Int) { // Traverse network, then run outputs - do { - scheduler.drainEval(this) - } while (evalScope { evalOutputs(this) }) + logDuration(logIndent, "traverse network") { + do { + val numNodes = + logDuration("drainEval") { scheduler.drainEval(currentLogIndent, this@Network) } + logLn("drained $numNodes nodes") + } while (logDuration("evalOutputs") { evalScope { evalOutputs(this) } }) + } // Update states - evalScope { evalStateWriters(this) } - transactionStore.clear() + logDuration(logIndent, "update states") { + evalScope { evalStateWriters(currentLogIndent, this) } + } + // Invalidate caches + // Note: this needs to occur before deferred switches + logDuration(logIndent, "clear store") { transactionStore.clear() } + epoch++ // Perform deferred switches - evalScope { evalMuxMovers(this) } + logDuration(logIndent, "evalMuxMovers") { + evalScope { evalMuxMovers(currentLogIndent, this) } + } // Compact depths - scheduler.drainCompact() - compactor.drainCompact() + logDuration(logIndent, "compact") { + scheduler.drainCompact(currentLogIndent) + compactor.drainCompact(currentLogIndent) + } // Deactivate nodes with no downstream - evalDeactivations() - epoch++ + logDuration(logIndent, "deactivations") { evalDeactivations() } } /** Invokes all [Output]s that have received data within this transaction. */ private suspend fun evalOutputs(evalScope: EvalScope): Boolean { + if (outputsByDispatcher.isEmpty()) { + return false + } // Outputs can enqueue other outputs, so we need two loops - if (outputsByDispatcher.isEmpty()) return false while (outputsByDispatcher.isNotEmpty()) { var launchedAny = false coroutineScope { @@ -164,57 +206,50 @@ internal class Network(val coroutineScope: CoroutineScope) : NetworkScope { launchedAny = true launch(key) { while (outputs.isNotEmpty()) { - val output = outputs.remove() + val output = outputs.removeFirst() launch { output.visit(evalScope) } } } } } } - if (!launchedAny) outputsByDispatcher.clear() + if (!launchedAny) { + outputsByDispatcher.clear() + } } return true } - private suspend fun evalMuxMovers(evalScope: EvalScope) { + private fun evalMuxMovers(logIndent: Int, evalScope: EvalScope) { while (muxMovers.isNotEmpty()) { - coroutineScope { - val toMove = muxMovers.remove() - launch { toMove.performMove(evalScope) } - } + val toMove = muxMovers.removeFirst() + toMove.performMove(logIndent, evalScope) } } - /** Updates all [TState]es that have changed within this transaction. */ - private suspend fun evalStateWriters(evalScope: EvalScope) { - coroutineScope { - while (stateWrites.isNotEmpty()) { - val latch = stateWrites.remove() - launch { latch.updateState(evalScope) } - } + /** Updates all [State]es that have changed within this transaction. */ + private fun evalStateWriters(logIndent: Int, evalScope: EvalScope) { + while (stateWrites.isNotEmpty()) { + val latch = stateWrites.removeFirst() + latch.updateState(logIndent, evalScope) } } - private suspend fun evalDeactivations() { - coroutineScope { - launch { - while (deactivations.isNotEmpty()) { - // traverse in reverse order - // - deactivations are added in depth-order during the node traversal phase - // - perform deactivations in reverse order, in case later ones propagate to - // earlier ones - val toDeactivate = deactivations.removeLast() - launch { toDeactivate.deactivateIfNeeded() } - } - } - while (outputDeactivations.isNotEmpty()) { - val toDeactivate = outputDeactivations.remove() - launch { - toDeactivate.upstream?.removeDownstreamAndDeactivateIfNeeded( - downstream = toDeactivate.schedulable - ) - } - } + private fun evalDeactivations() { + while (deactivations.isNotEmpty()) { + // traverse in reverse order + // - deactivations are added in depth-order during the node traversal phase + // - perform deactivations in reverse order, in case later ones propagate to + // earlier ones + val toDeactivate = deactivations.removeLast() + toDeactivate.deactivateIfNeeded() + } + + while (outputDeactivations.isNotEmpty()) { + val toDeactivate = outputDeactivations.removeFirst() + toDeactivate.upstream?.removeDownstreamAndDeactivateIfNeeded( + downstream = toDeactivate.schedulable + ) } check(deactivations.isEmpty()) { "unexpected lingering deactivations" } check(outputDeactivations.isEmpty()) { "unexpected lingering output deactivations" } @@ -232,6 +267,11 @@ internal class ScheduledAction<T>( result = just(onStartTransaction(evalScope)) } + fun fail(ex: Exception) { + result = none + onResult?.completeExceptionally(ex) + } + fun completed() { if (onResult != null) { when (val result = result) { @@ -243,4 +283,39 @@ internal class ScheduledAction<T>( } } -internal typealias TransactionStore = HeteroMap +internal class TransactionStore private constructor(private val storage: HeteroMap) { + constructor(capacity: Int) : this(HeteroMap(capacity)) + + constructor() : this(HeteroMap()) + + operator fun <A> get(key: HeteroMap.Key<A>): A = + storage.getOrError(key) { "no value for $key in this transaction" } + + operator fun <A> set(key: HeteroMap.Key<A>, value: A) { + storage[key] = value + } + + fun clear() = storage.clear() +} + +internal class TransactionCache<A> { + private val key = object : HeteroMap.Key<A> {} + @Volatile + var epoch: Long = Long.MIN_VALUE + private set + + fun getOrPut(evalScope: EvalScope, block: () -> A): A = + if (epoch < evalScope.epoch) { + epoch = evalScope.epoch + block().also { evalScope.transactionStore[key] = it } + } else { + evalScope.transactionStore[key] + } + + fun put(evalScope: EvalScope, value: A) { + epoch = evalScope.epoch + evalScope.transactionStore[key] = value + } + + fun getCurrentValue(evalScope: EvalScope): A = evalScope.transactionStore[key] +} diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/NoScope.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/NoScope.kt index fbd9689eb1d0..f662f1907069 100644 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/NoScope.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/NoScope.kt @@ -16,32 +16,6 @@ package com.android.systemui.kairos.internal -import com.android.systemui.kairos.FrpScope -import kotlin.coroutines.Continuation -import kotlin.coroutines.CoroutineContext -import kotlin.coroutines.EmptyCoroutineContext -import kotlin.coroutines.coroutineContext -import kotlin.coroutines.startCoroutine -import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.completeWith -import kotlinx.coroutines.job +import com.android.systemui.kairos.KairosScope -internal object NoScope { - private object FrpScopeImpl : FrpScope - - suspend fun <R> runInFrpScope(block: suspend FrpScope.() -> R): R { - val complete = CompletableDeferred<R>(coroutineContext.job) - block.startCoroutine( - FrpScopeImpl, - object : Continuation<R> { - override val context: CoroutineContext - get() = EmptyCoroutineContext - - override fun resumeWith(result: Result<R>) { - complete.completeWith(result) - } - }, - ) - return complete.await() - } -} +internal object NoScope : KairosScope diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/NodeTypes.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/NodeTypes.kt index 000240796a82..39b8bfe540d2 100644 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/NodeTypes.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/NodeTypes.kt @@ -16,47 +16,45 @@ package com.android.systemui.kairos.internal -import com.android.systemui.kairos.util.Maybe - /* Dmux Muxes + Branch */ internal sealed interface SchedulableNode { /** schedule this node w/ given NodeEvalScope */ - suspend fun schedule(evalScope: EvalScope) + fun schedule(logIndent: Int, evalScope: EvalScope) - suspend fun adjustDirectUpstream(scheduler: Scheduler, oldDepth: Int, newDepth: Int) + fun adjustDirectUpstream(scheduler: Scheduler, oldDepth: Int, newDepth: Int) - suspend fun moveIndirectUpstreamToDirect( + fun moveIndirectUpstreamToDirect( scheduler: Scheduler, oldIndirectDepth: Int, - oldIndirectSet: Set<MuxDeferredNode<*, *>>, + oldIndirectSet: Set<MuxDeferredNode<*, *, *>>, newDirectDepth: Int, ) - suspend fun adjustIndirectUpstream( + fun adjustIndirectUpstream( scheduler: Scheduler, oldDepth: Int, newDepth: Int, - removals: Set<MuxDeferredNode<*, *>>, - additions: Set<MuxDeferredNode<*, *>>, + removals: Set<MuxDeferredNode<*, *, *>>, + additions: Set<MuxDeferredNode<*, *, *>>, ) - suspend fun moveDirectUpstreamToIndirect( + fun moveDirectUpstreamToIndirect( scheduler: Scheduler, oldDirectDepth: Int, newIndirectDepth: Int, - newIndirectSet: Set<MuxDeferredNode<*, *>>, + newIndirectSet: Set<MuxDeferredNode<*, *, *>>, ) - suspend fun removeIndirectUpstream( + fun removeIndirectUpstream( scheduler: Scheduler, depth: Int, - indirectSet: Set<MuxDeferredNode<*, *>>, + indirectSet: Set<MuxDeferredNode<*, *, *>>, ) - suspend fun removeDirectUpstream(scheduler: Scheduler, depth: Int) + fun removeDirectUpstream(scheduler: Scheduler, depth: Int) } /* @@ -68,7 +66,7 @@ internal sealed interface PullNode<out A> { * will read from the cache, otherwise it will perform a full evaluation, even if invoked * multiple times within a transaction. */ - suspend fun getPushEvent(evalScope: EvalScope): Maybe<A> + fun getPushEvent(logIndent: Int, evalScope: EvalScope): A } /* @@ -76,19 +74,19 @@ Muxes + DmuxBranch */ internal sealed interface PushNode<A> : PullNode<A> { - suspend fun hasCurrentValue(transactionStore: TransactionStore): Boolean + fun hasCurrentValue(logIndent: Int, evalScope: EvalScope): Boolean val depthTracker: DepthTracker - suspend fun removeDownstream(downstream: Schedulable) + fun removeDownstream(downstream: Schedulable) /** called during cleanup phase */ - suspend fun deactivateIfNeeded() + fun deactivateIfNeeded() /** called from mux nodes after severs */ - suspend fun scheduleDeactivationIfNeeded(evalScope: EvalScope) + fun scheduleDeactivationIfNeeded(evalScope: EvalScope) - suspend fun addDownstream(downstream: Schedulable) + fun addDownstream(downstream: Schedulable) - suspend fun removeDownstreamAndDeactivateIfNeeded(downstream: Schedulable) + fun removeDownstreamAndDeactivateIfNeeded(downstream: Schedulable) } diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Output.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Output.kt index a3af2d304f7f..38d8cf70b36e 100644 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Output.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Output.kt @@ -16,14 +16,13 @@ package com.android.systemui.kairos.internal -import com.android.systemui.kairos.util.Just import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext internal class Output<A>( val context: CoroutineContext = EmptyCoroutineContext, - val onDeath: suspend () -> Unit = {}, - val onEmit: suspend EvalScope.(A) -> Unit, + val onDeath: () -> Unit = {}, + val onEmit: EvalScope.(A) -> Unit, ) { val schedulable = Schedulable.O(this) @@ -34,26 +33,24 @@ internal class Output<A>( private object NoResult // invoked by network - suspend fun visit(evalScope: EvalScope) { + fun visit(evalScope: EvalScope) { val upstreamResult = result check(upstreamResult !== NoResult) { "output visited with null upstream result" } - result = null + result = NoResult @Suppress("UNCHECKED_CAST") evalScope.onEmit(upstreamResult as A) } - suspend fun kill() { + fun kill() { onDeath() } - suspend fun schedule(evalScope: EvalScope) { - val upstreamResult = - checkNotNull(upstream) { "output scheduled with null upstream" }.getPushEvent(evalScope) - if (upstreamResult is Just) { - result = upstreamResult.value - evalScope.scheduleOutput(this) - } + fun schedule(logIndent: Int, evalScope: EvalScope) { + result = + checkNotNull(upstream) { "output scheduled with null upstream" } + .getPushEvent(logIndent, evalScope) + evalScope.scheduleOutput(this) } } -internal inline fun OneShot(crossinline onEmit: suspend EvalScope.() -> Unit): Output<Unit> = +internal inline fun OneShot(crossinline onEmit: EvalScope.() -> Unit): Output<Unit> = Output<Unit>(onEmit = { onEmit() }).apply { result = Unit } diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/PullNodes.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/PullNodes.kt index dac98e0e807c..517e54f57833 100644 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/PullNodes.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/PullNodes.kt @@ -16,24 +16,24 @@ package com.android.systemui.kairos.internal -import com.android.systemui.kairos.internal.util.Key -import com.android.systemui.kairos.util.Maybe -import com.android.systemui.kairos.util.map -import kotlinx.coroutines.CoroutineStart -import kotlinx.coroutines.Deferred +import com.android.systemui.kairos.internal.util.logDuration -internal val neverImpl: TFlowImpl<Nothing> = TFlowCheap { null } +internal val neverImpl: EventsImpl<Nothing> = EventsImplCheap { null } -internal class MapNode<A, B>(val upstream: PullNode<A>, val transform: suspend EvalScope.(A) -> B) : +internal class MapNode<A, B>(val upstream: PullNode<A>, val transform: EvalScope.(A, Int) -> B) : PullNode<B> { - override suspend fun getPushEvent(evalScope: EvalScope): Maybe<B> = - upstream.getPushEvent(evalScope).map { evalScope.transform(it) } + override fun getPushEvent(logIndent: Int, evalScope: EvalScope): B = + logDuration(logIndent, "MapNode.getPushEvent") { + val upstream = + logDuration("upstream event") { upstream.getPushEvent(currentLogIndent, evalScope) } + logDuration("transform") { evalScope.transform(upstream, currentLogIndent) } + } } internal inline fun <A, B> mapImpl( - crossinline upstream: suspend EvalScope.() -> TFlowImpl<A>, - noinline transform: suspend EvalScope.(A) -> B, -): TFlowImpl<B> = TFlowCheap { downstream -> + crossinline upstream: EvalScope.() -> EventsImpl<A>, + noinline transform: EvalScope.(A, Int) -> B, +): EventsImpl<B> = EventsImplCheap { downstream -> upstream().activate(evalScope = this, downstream)?.let { (connection, needsEval) -> ActivationResult( connection = @@ -46,20 +46,29 @@ internal inline fun <A, B> mapImpl( } } -internal class CachedNode<A>(val key: Key<Deferred<Maybe<A>>>, val upstream: PullNode<A>) : - PullNode<A> { - override suspend fun getPushEvent(evalScope: EvalScope): Maybe<A> { - val deferred = - evalScope.transactionStore.getOrPut(key) { - evalScope.deferAsync(CoroutineStart.LAZY) { upstream.getPushEvent(evalScope) } - } - return deferred.await() - } +internal class CachedNode<A>( + private val transactionCache: TransactionCache<Lazy<A>>, + val upstream: PullNode<A>, +) : PullNode<A> { + override fun getPushEvent(logIndent: Int, evalScope: EvalScope): A = + logDuration(logIndent, "CachedNode.getPushEvent") { + val deferred = + logDuration("CachedNode.getOrPut", false) { + transactionCache.getOrPut(evalScope) { + evalScope.deferAsync { + logDuration("CachedNode.getUpstreamEvent") { + upstream.getPushEvent(currentLogIndent, evalScope) + } + } + } + } + logDuration("await") { deferred.value } + } } -internal fun <A> TFlowImpl<A>.cached(): TFlowImpl<A> { - val key = object : Key<Deferred<Maybe<A>>> {} - return TFlowCheap { +internal fun <A> EventsImpl<A>.cached(): EventsImpl<A> { + val key = TransactionCache<Lazy<A>>() + return EventsImplCheap { it -> activate(this, it)?.let { (connection, needsEval) -> ActivationResult( connection = diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Scheduler.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Scheduler.kt index c12ef6ae6a5d..0529bcb63c07 100644 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Scheduler.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/Scheduler.kt @@ -14,15 +14,10 @@ * limitations under the License. */ -@file:OptIn(ExperimentalCoroutinesApi::class) - package com.android.systemui.kairos.internal -import java.util.concurrent.ConcurrentHashMap -import java.util.concurrent.PriorityBlockingQueue -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.launch +import com.android.systemui.kairos.internal.util.LogIndent +import java.util.PriorityQueue internal interface Scheduler { fun schedule(depth: Int, node: MuxNode<*, *, *>) @@ -30,12 +25,11 @@ internal interface Scheduler { fun scheduleIndirect(indirectDepth: Int, node: MuxNode<*, *, *>) } -internal class SchedulerImpl : Scheduler { - val enqueued = ConcurrentHashMap<MuxNode<*, *, *>, Any>() - val scheduledQ = PriorityBlockingQueue<Pair<Int, MuxNode<*, *, *>>>(16, compareBy { it.first }) +internal class SchedulerImpl(private val enqueue: (MuxNode<*, *, *>) -> Boolean) : Scheduler { + private val scheduledQ = PriorityQueue<Pair<Int, MuxNode<*, *, *>>>(compareBy { it.first }) override fun schedule(depth: Int, node: MuxNode<*, *, *>) { - if (enqueued.putIfAbsent(node, node) == null) { + if (enqueue(node)) { scheduledQ.add(Pair(depth, node)) } } @@ -44,33 +38,52 @@ internal class SchedulerImpl : Scheduler { schedule(Int.MIN_VALUE + indirectDepth, node) } - internal suspend fun drainEval(network: Network) { - drain { runStep -> - runStep { muxNode -> network.evalScope { muxNode.visit(this) } } + internal fun drainEval(logIndent: Int, network: Network): Int = + drain(logIndent) { runStep -> + runStep { muxNode -> + network.evalScope { + muxNode.markedForEvaluation = false + muxNode.visit(currentLogIndent, this) + } + } // If any visited MuxPromptNodes had their depths increased, eagerly propagate those // depth changes now before performing further network evaluation. - network.compactor.drainCompact() + val numNodes = network.compactor.drainCompact(currentLogIndent) + logLn("promptly compacted $numNodes nodes") } - } - internal suspend fun drainCompact() { - drain { runStep -> runStep { muxNode -> muxNode.visitCompact(scheduler = this) } } - } + internal fun drainCompact(logIndent: Int): Int = + drain(logIndent) { runStep -> + runStep { muxNode -> + muxNode.markedForCompaction = false + muxNode.visitCompact(scheduler = this@SchedulerImpl) + } + } - private suspend inline fun drain( + private inline fun drain( + logIndent: Int, crossinline onStep: - suspend (runStep: suspend (visit: suspend (MuxNode<*, *, *>) -> Unit) -> Unit) -> Unit - ): Unit = coroutineScope { + LogIndent.( + runStep: LogIndent.(visit: LogIndent.(MuxNode<*, *, *>) -> Unit) -> Unit + ) -> Unit, + ): Int { + var total = 0 while (scheduledQ.isNotEmpty()) { val maxDepth = scheduledQ.peek()?.first ?: error("Unexpected empty scheduler") - onStep { visit -> runStep(maxDepth, visit) } + LogIndent(logIndent).onStep { visit -> + logDuration("step $maxDepth") { + val subtotal = runStep(maxDepth) { visit(it) } + logLn("visited $subtotal nodes") + total += subtotal + } + } } + return total } - private suspend inline fun runStep( - maxDepth: Int, - crossinline visit: suspend (MuxNode<*, *, *>) -> Unit, - ) = coroutineScope { + private inline fun runStep(maxDepth: Int, crossinline visit: (MuxNode<*, *, *>) -> Unit): Int { + var total = 0 + val toVisit = mutableListOf<MuxNode<*, *, *>>() while (scheduledQ.peek()?.first?.let { it <= maxDepth } == true) { val (d, node) = scheduledQ.remove() if ( @@ -79,11 +92,15 @@ internal class SchedulerImpl : Scheduler { ) { scheduledQ.add(node.depthTracker.dirty_directDepth to node) } else { - launch { - enqueued.remove(node) - visit(node) - } + total++ + toVisit.add(node) } } + + for (node in toVisit) { + visit(node) + } + + return total } } diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/StateImpl.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/StateImpl.kt new file mode 100644 index 000000000000..46127cb2276b --- /dev/null +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/StateImpl.kt @@ -0,0 +1,467 @@ +/* + * 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.kairos.internal + +import com.android.systemui.kairos.internal.store.ConcurrentHashMapK +import com.android.systemui.kairos.internal.store.MutableArrayMapK +import com.android.systemui.kairos.internal.store.MutableMapK +import com.android.systemui.kairos.internal.store.StoreEntry +import com.android.systemui.kairos.internal.util.hashString +import com.android.systemui.kairos.util.Maybe +import com.android.systemui.kairos.util.just +import com.android.systemui.kairos.util.none + +internal open class StateImpl<out A>( + val name: String?, + val operatorName: String, + val changes: EventsImpl<A>, + val store: StateStore<A>, +) { + fun getCurrentWithEpoch(evalScope: EvalScope): Pair<A, Long> = + store.getCurrentWithEpoch(evalScope) +} + +internal sealed class StateDerived<A> : StateStore<A>() { + + @Volatile + var invalidatedEpoch = Long.MIN_VALUE + private set + + @Volatile + protected var validatedEpoch = Long.MIN_VALUE + private set + + @Volatile + protected var cache: Any? = EmptyCache + private set + + private val transactionCache = TransactionCache<Lazy<Pair<A, Long>>>() + + override fun getCurrentWithEpoch(evalScope: EvalScope): Pair<A, Long> = + transactionCache.getOrPut(evalScope) { evalScope.deferAsync { pull(evalScope) } }.value + + fun pull(evalScope: EvalScope): Pair<A, Long> { + @Suppress("UNCHECKED_CAST") + val result = + recalc(evalScope)?.let { (newValue, epoch) -> + newValue.also { + if (epoch > validatedEpoch) { + validatedEpoch = epoch + if (cache != newValue) { + cache = newValue + invalidatedEpoch = epoch + } + } + } + } ?: (cache as A) + return result to invalidatedEpoch + } + + fun getCachedUnsafe(): Maybe<A> { + @Suppress("UNCHECKED_CAST") + return if (cache == EmptyCache) none else just(cache as A) + } + + protected abstract fun recalc(evalScope: EvalScope): Pair<A, Long>? + + fun setCacheFromPush(value: A, epoch: Long) { + cache = value + validatedEpoch = epoch + 1 + invalidatedEpoch = epoch + 1 + } + + private data object EmptyCache +} + +internal sealed class StateStore<out S> { + abstract fun getCurrentWithEpoch(evalScope: EvalScope): Pair<S, Long> +} + +internal class StateSource<S>(init: Lazy<S>) : StateStore<S>() { + constructor(init: S) : this(CompletableLazy(init)) + + lateinit var upstreamConnection: NodeConnection<S> + + // Note: Don't need to synchronize; we will never interleave reads and writes, since all writes + // are performed at the end of a network step, after any reads would have taken place. + + @Volatile private var _current: Lazy<S> = init + + @Volatile + var writeEpoch = 0L + private set + + override fun getCurrentWithEpoch(evalScope: EvalScope): Pair<S, Long> = + _current.value to writeEpoch + + /** called by network after eval phase has completed */ + fun updateState(logIndent: Int, evalScope: EvalScope) { + // write the latch + _current = CompletableLazy(upstreamConnection.getPushEvent(logIndent, evalScope)) + writeEpoch = evalScope.epoch + 1 + } + + override fun toString(): String = "StateImpl(current=$_current, writeEpoch=$writeEpoch)" + + fun getStorageUnsafe(): Maybe<S> = if (_current.isInitialized()) just(_current.value) else none +} + +internal fun <A> constState(name: String?, operatorName: String, init: A): StateImpl<A> = + StateImpl(name, operatorName, neverImpl, StateSource(init)) + +internal inline fun <A> activatedStateSource( + name: String?, + operatorName: String, + evalScope: EvalScope, + crossinline getChanges: EvalScope.() -> EventsImpl<A>, + init: Lazy<A>, +): StateImpl<A> { + val store = StateSource(init) + val calm: EventsImpl<A> = + filterImpl(getChanges) { new -> new != store.getCurrentWithEpoch(evalScope = this).first } + evalScope.scheduleOutput( + OneShot { + calm.activate(evalScope = this, downstream = Schedulable.S(store))?.let { + (connection, needsEval) -> + store.upstreamConnection = connection + if (needsEval) { + schedule(store) + } + } + } + ) + return StateImpl(name, operatorName, calm, store) +} + +private inline fun <A> EventsImpl<A>.calm(state: StateDerived<A>): EventsImpl<A> = + filterImpl({ this@calm }) { new -> + val (current, _) = state.getCurrentWithEpoch(evalScope = this) + if (new != current) { + state.setCacheFromPush(new, epoch) + true + } else { + false + } + } + .cached() + +internal fun <A, B> mapStateImplCheap( + stateImpl: Init<StateImpl<A>>, + name: String?, + operatorName: String, + transform: EvalScope.(A) -> B, +): StateImpl<B> = + StateImpl( + name = name, + operatorName = operatorName, + changes = mapImpl({ stateImpl.connect(this).changes }) { it, _ -> transform(it) }, + store = DerivedMapCheap(stateImpl, transform), + ) + +internal class DerivedMapCheap<A, B>( + val upstream: Init<StateImpl<A>>, + private val transform: EvalScope.(A) -> B, +) : StateStore<B>() { + + override fun getCurrentWithEpoch(evalScope: EvalScope): Pair<B, Long> { + val (a, epoch) = upstream.connect(evalScope).getCurrentWithEpoch(evalScope) + return evalScope.transform(a) to epoch + } + + override fun toString(): String = "${this::class.simpleName}@$hashString" +} + +internal fun <A, B> mapStateImpl( + stateImpl: InitScope.() -> StateImpl<A>, + name: String?, + operatorName: String, + transform: EvalScope.(A) -> B, +): StateImpl<B> { + val store = DerivedMap(stateImpl, transform) + val mappedChanges = + mapImpl({ stateImpl().changes }) { it, _ -> transform(it) }.cached().calm(store) + return StateImpl(name, operatorName, mappedChanges, store) +} + +internal class DerivedMap<A, B>( + val upstream: InitScope.() -> StateImpl<A>, + private val transform: EvalScope.(A) -> B, +) : StateDerived<B>() { + override fun toString(): String = "${this::class.simpleName}@$hashString" + + override fun recalc(evalScope: EvalScope): Pair<B, Long>? { + val (a, epoch) = evalScope.upstream().getCurrentWithEpoch(evalScope) + return if (epoch > validatedEpoch) { + evalScope.transform(a) to epoch + } else { + null + } + } +} + +internal fun <A> flattenStateImpl( + stateImpl: InitScope.() -> StateImpl<StateImpl<A>>, + name: String?, + operator: String, +): StateImpl<A> { + // emits the current value of the new inner state, when that state is emitted + val switchEvents = + mapImpl({ stateImpl().changes }) { newInner, _ -> newInner.getCurrentWithEpoch(this).first } + // emits the new value of the new inner state when that state is emitted, or + // falls back to the current value if a new state is *not* being emitted this + // transaction + val innerChanges = + mapImpl({ stateImpl().changes }) { newInner, _ -> + mergeNodes({ switchEvents }, { newInner.changes }) { _, new -> new } + } + val switchedChanges: EventsImpl<A> = + switchPromptImplSingle( + getStorage = { stateImpl().getCurrentWithEpoch(evalScope = this).first.changes }, + getPatches = { innerChanges }, + ) + val store: DerivedFlatten<A> = DerivedFlatten(stateImpl) + return StateImpl(name, operator, switchedChanges.calm(store), store) +} + +internal class DerivedFlatten<A>(val upstream: InitScope.() -> StateImpl<StateImpl<A>>) : + StateDerived<A>() { + override fun recalc(evalScope: EvalScope): Pair<A, Long> { + val (inner, epoch0) = evalScope.upstream().getCurrentWithEpoch(evalScope) + val (a, epoch1) = inner.getCurrentWithEpoch(evalScope) + return a to maxOf(epoch0, epoch1) + } + + override fun toString(): String = "${this::class.simpleName}@$hashString" +} + +@Suppress("NOTHING_TO_INLINE") +internal inline fun <A, B> flatMapStateImpl( + noinline stateImpl: InitScope.() -> StateImpl<A>, + name: String?, + operatorName: String, + noinline transform: EvalScope.(A) -> StateImpl<B>, +): StateImpl<B> { + val mapped = mapStateImpl(stateImpl, null, operatorName, transform) + return flattenStateImpl({ mapped }, name, operatorName) +} + +internal fun <A, B, Z> zipStates( + name: String?, + operatorName: String, + l1: Init<StateImpl<A>>, + l2: Init<StateImpl<B>>, + transform: EvalScope.(A, B) -> Z, +): StateImpl<Z> { + val zipped = + zipStateList( + null, + operatorName, + 2, + init(null) { listOf(l1.connect(this), l2.connect(this)) }, + ) + return mapStateImpl({ zipped }, name, operatorName) { + @Suppress("UNCHECKED_CAST") transform(it[0] as A, it[1] as B) + } +} + +internal fun <A, B, C, Z> zipStates( + name: String?, + operatorName: String, + l1: Init<StateImpl<A>>, + l2: Init<StateImpl<B>>, + l3: Init<StateImpl<C>>, + transform: EvalScope.(A, B, C) -> Z, +): StateImpl<Z> { + val zipped = + zipStateList( + null, + operatorName, + 3, + init(null) { listOf(l1.connect(this), l2.connect(this), l3.connect(this)) }, + ) + return mapStateImpl({ zipped }, name, operatorName) { + @Suppress("UNCHECKED_CAST") transform(it[0] as A, it[1] as B, it[2] as C) + } +} + +internal fun <A, B, C, D, Z> zipStates( + name: String?, + operatorName: String, + l1: Init<StateImpl<A>>, + l2: Init<StateImpl<B>>, + l3: Init<StateImpl<C>>, + l4: Init<StateImpl<D>>, + transform: EvalScope.(A, B, C, D) -> Z, +): StateImpl<Z> { + val zipped = + zipStateList( + null, + operatorName, + 4, + init(null) { + listOf(l1.connect(this), l2.connect(this), l3.connect(this), l4.connect(this)) + }, + ) + return mapStateImpl({ zipped }, name, operatorName) { + @Suppress("UNCHECKED_CAST") transform(it[0] as A, it[1] as B, it[2] as C, it[3] as D) + } +} + +internal fun <A, B, C, D, E, Z> zipStates( + name: String?, + operatorName: String, + l1: Init<StateImpl<A>>, + l2: Init<StateImpl<B>>, + l3: Init<StateImpl<C>>, + l4: Init<StateImpl<D>>, + l5: Init<StateImpl<E>>, + transform: EvalScope.(A, B, C, D, E) -> Z, +): StateImpl<Z> { + val zipped = + zipStateList( + null, + operatorName, + 5, + init(null) { + listOf( + l1.connect(this), + l2.connect(this), + l3.connect(this), + l4.connect(this), + l5.connect(this), + ) + }, + ) + return mapStateImpl({ zipped }, name, operatorName) { + @Suppress("UNCHECKED_CAST") + transform(it[0] as A, it[1] as B, it[2] as C, it[3] as D, it[4] as E) + } +} + +internal fun <K, V> zipStateMap( + name: String?, + operatorName: String, + numStates: Int, + states: Init<Map<K, StateImpl<V>>>, +): StateImpl<Map<K, V>> = + zipStates( + name = name, + operatorName = operatorName, + numStates = numStates, + states = init(null) { states.connect(this).asIterable() }, + storeFactory = ConcurrentHashMapK.Factory(), + ) + +internal fun <V> zipStateList( + name: String?, + operatorName: String, + numStates: Int, + states: Init<List<StateImpl<V>>>, +): StateImpl<List<V>> { + val zipped = + zipStates( + name = name, + operatorName = operatorName, + numStates = numStates, + states = init(name) { states.connect(this).asIterableWithIndex() }, + storeFactory = MutableArrayMapK.Factory(), + ) + // Like mapCheap, but with caching (or like map, but without the calm changes, as they are not + // necessary). + return StateImpl( + name = name, + operatorName = operatorName, + changes = mapImpl({ zipped.changes }) { arrayStore, _ -> arrayStore.values.toList() }, + DerivedMap(upstream = { zipped }, transform = { arrayStore -> arrayStore.values.toList() }), + ) +} + +internal fun <W, K, A> zipStates( + name: String?, + operatorName: String, + numStates: Int, + states: Init<Iterable<Map.Entry<K, StateImpl<A>>>>, + storeFactory: MutableMapK.Factory<W, K>, +): StateImpl<MutableMapK<W, K, A>> { + if (numStates == 0) { + return constState(name, operatorName, storeFactory.create(0)) + } + val stateStore = DerivedZipped(numStates, states, storeFactory) + // No need for calm; invariant ensures that changes will only emit when there's a difference + val switchDeferredImpl = + switchDeferredImpl( + getStorage = { + states + .connect(this) + .asSequence() + .map { (k, v) -> StoreEntry(k, v.changes) } + .asIterable() + }, + getPatches = { neverImpl }, + storeFactory = storeFactory, + ) + val changes = + mapImpl({ switchDeferredImpl }) { patch, logIndent -> + val muxStore = storeFactory.create<A>(numStates) + states.connect(this).forEach { (k, state) -> + muxStore[k] = + if (patch.contains(k)) { + patch.getValue(k).getPushEvent(logIndent, evalScope = this@mapImpl) + } else { + state.getCurrentWithEpoch(evalScope = this@mapImpl).first + } + } + // Read the current value so that it is cached in this transaction and won't be + // clobbered by the cache write + stateStore.getCurrentWithEpoch(evalScope = this) + muxStore.also { stateStore.setCacheFromPush(it, epoch) } + } + .cached() + return StateImpl(name, operatorName, changes, stateStore) +} + +internal class DerivedZipped<W, K, A>( + private val upstreamSize: Int, + val upstream: Init<Iterable<Map.Entry<K, StateImpl<A>>>>, + private val storeFactory: MutableMapK.Factory<W, K>, +) : StateDerived<MutableMapK<W, K, A>>() { + override fun recalc(evalScope: EvalScope): Pair<MutableMapK<W, K, A>, Long> { + var newEpoch = 0L + val store = storeFactory.create<A>(upstreamSize) + for ((key, value) in upstream.connect(evalScope)) { + val (a, epoch) = value.getCurrentWithEpoch(evalScope) + newEpoch = maxOf(newEpoch, epoch) + store[key] = a + } + return store to newEpoch + } + + override fun toString(): String = "${this::class.simpleName}@$hashString" +} + +@Suppress("NOTHING_TO_INLINE") +internal inline fun <A> zipStates( + name: String?, + operatorName: String, + numStates: Int, + states: Init<List<StateImpl<A>>>, +): StateImpl<List<A>> = + if (numStates <= 0) { + constState(name, operatorName, emptyList()) + } else { + zipStateList(null, operatorName, numStates, states) + } diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/StateScopeImpl.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/StateScopeImpl.kt index baf4101d52ef..bd1f94fca22f 100644 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/StateScopeImpl.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/StateScopeImpl.kt @@ -16,241 +16,152 @@ package com.android.systemui.kairos.internal -import com.android.systemui.kairos.FrpDeferredValue -import com.android.systemui.kairos.FrpStateScope -import com.android.systemui.kairos.FrpStateful -import com.android.systemui.kairos.FrpTransactionScope -import com.android.systemui.kairos.GroupedTFlow -import com.android.systemui.kairos.TFlow -import com.android.systemui.kairos.TFlowInit -import com.android.systemui.kairos.TFlowLoop -import com.android.systemui.kairos.TState -import com.android.systemui.kairos.TStateInit -import com.android.systemui.kairos.emptyTFlow +import com.android.systemui.kairos.DeferredValue +import com.android.systemui.kairos.Events +import com.android.systemui.kairos.EventsInit +import com.android.systemui.kairos.EventsLoop +import com.android.systemui.kairos.GroupedEvents +import com.android.systemui.kairos.Incremental +import com.android.systemui.kairos.IncrementalInit +import com.android.systemui.kairos.State +import com.android.systemui.kairos.StateInit +import com.android.systemui.kairos.StateScope +import com.android.systemui.kairos.Stateful +import com.android.systemui.kairos.emptyEvents import com.android.systemui.kairos.groupByKey import com.android.systemui.kairos.init -import com.android.systemui.kairos.internal.util.mapValuesParallel import com.android.systemui.kairos.mapCheap import com.android.systemui.kairos.merge -import com.android.systemui.kairos.switch +import com.android.systemui.kairos.switchEvents import com.android.systemui.kairos.util.Maybe import com.android.systemui.kairos.util.map -import kotlin.coroutines.Continuation -import kotlin.coroutines.CoroutineContext -import kotlin.coroutines.EmptyCoroutineContext -import kotlin.coroutines.startCoroutine -import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.Deferred -import kotlinx.coroutines.completeWith -import kotlinx.coroutines.job -internal class StateScopeImpl(val evalScope: EvalScope, override val endSignal: TFlow<Any>) : - StateScope, EvalScope by evalScope { +internal class StateScopeImpl(val evalScope: EvalScope, override val endSignal: Events<Any>) : + InternalStateScope, EvalScope by evalScope { - private val endSignalOnce: TFlow<Any> = endSignal.nextOnlyInternal("StateScope.endSignal") + override val endSignalOnce: Events<Any> = endSignal.nextOnlyInternal("StateScope.endSignal") - private fun <A> TFlow<A>.truncateToScope(operatorName: String): TFlow<A> = - if (endSignalOnce === emptyTFlow) { - this - } else { - endSignalOnce.mapCheap { emptyTFlow }.toTStateInternal(operatorName, this).switch() - } + override fun <A> deferredStateScope(block: StateScope.() -> A): DeferredValue<A> = + DeferredValue(deferAsync { block() }) - private fun <A> TFlow<A>.nextOnlyInternal(operatorName: String): TFlow<A> = - if (this === emptyTFlow) { - this - } else { - TFlowLoop<A>().apply { - loopback = - mapCheap { emptyTFlow } - .toTStateInternal(operatorName, this@nextOnlyInternal) - .switch() - } - } - - private fun <A> TFlow<A>.toTStateInternal(operatorName: String, init: A): TState<A> = - toTStateInternalDeferred(operatorName, CompletableDeferred(init)) - - private fun <A> TFlow<A>.toTStateInternalDeferred( - operatorName: String, - init: Deferred<A>, - ): TState<A> { - val changes = this@toTStateInternalDeferred - val name = operatorName - val impl = - mkState(name, operatorName, evalScope, { changes.init.connect(evalScope = this) }, init) - return TStateInit(constInit(name, impl)) - } - - private fun <R> deferredInternal(block: suspend FrpStateScope.() -> R): FrpDeferredValue<R> = - FrpDeferredValue(deferAsync { runInStateScope(block) }) - - private fun <A> TFlow<A>.toTStateDeferredInternal( - initialValue: FrpDeferredValue<A> - ): TState<A> { - val operatorName = "toTStateDeferred" + override fun <A> Events<A>.holdStateDeferred(initialValue: DeferredValue<A>): State<A> { + val operatorName = "holdStateDeferred" // Ensure state is only collected until the end of this scope return truncateToScope(operatorName) - .toTStateInternalDeferred(operatorName, initialValue.unwrapped) + .holdStateInternalDeferred(operatorName, initialValue.unwrapped) } - private fun <K : Any, V> TFlow<Map<K, Maybe<TFlow<V>>>>.mergeIncrementallyInternal( - storage: TState<Map<K, TFlow<V>>> - ): TFlow<Map<K, V>> { - val name = "mergeIncrementally" - return TFlowInit( + override fun <K, V> Events<Map<K, Maybe<V>>>.foldStateMapIncrementally( + initialValues: DeferredValue<Map<K, V>> + ): Incremental<K, V> { + val operatorName = "foldStateMapIncrementally" + val name = operatorName + return IncrementalInit( constInit( - name, - switchDeferredImpl( - getStorage = { - storage.init - .connect(this) - .getCurrentWithEpoch(this) - .first - .mapValuesParallel { (_, flow) -> flow.init.connect(this) } - }, - getPatches = { - mapImpl({ init.connect(this) }) { patch -> - patch.mapValuesParallel { (_, m) -> - m.map { flow -> flow.init.connect(this) } - } - } - }, + operatorName, + activatedIncremental( + name, + operatorName, + evalScope, + { init.connect(this) }, + initialValues.unwrapped, ), ) ) } - private fun <K : Any, V> TFlow<Map<K, Maybe<TFlow<V>>>>.mergeIncrementallyPromptInternal( - storage: TState<Map<K, TFlow<V>>> - ): TFlow<Map<K, V>> { - val name = "mergeIncrementallyPrompt" - return TFlowInit( - constInit( - name, - switchPromptImpl( - getStorage = { - storage.init - .connect(this) - .getCurrentWithEpoch(this) - .first - .mapValuesParallel { (_, flow) -> flow.init.connect(this) } - }, - getPatches = { - mapImpl({ init.connect(this) }) { patch -> - patch.mapValuesParallel { (_, m) -> - m.map { flow -> flow.init.connect(this) } - } - } - }, - ), - ) - ) - } - - private fun <K, A, B> TFlow<Map<K, Maybe<FrpStateful<A>>>>.applyLatestStatefulForKeyInternal( - init: FrpDeferredValue<Map<K, FrpStateful<B>>>, + override fun <K, A, B> Events<Map<K, Maybe<Stateful<A>>>>.applyLatestStatefulForKey( + init: DeferredValue<Map<K, Stateful<B>>>, numKeys: Int?, - ): Pair<TFlow<Map<K, Maybe<A>>>, FrpDeferredValue<Map<K, B>>> { - val eventsByKey: GroupedTFlow<K, Maybe<FrpStateful<A>>> = groupByKey(numKeys) - val initOut: Deferred<Map<K, B>> = deferAsync { - init.unwrapped.await().mapValuesParallel { (k, stateful) -> - val newEnd = with(frpScope) { eventsByKey[k].skipNext() } + ): Pair<Events<Map<K, Maybe<A>>>, DeferredValue<Map<K, B>>> { + val eventsByKey: GroupedEvents<K, Maybe<Stateful<A>>> = groupByKey(numKeys) + val initOut: Lazy<Map<K, B>> = deferAsync { + init.unwrapped.value.mapValues { (k, stateful) -> + val newEnd = eventsByKey[k] val newScope = childStateScope(newEnd) - newScope.runInStateScope(stateful) + newScope.stateful() } } - val changesNode: TFlowImpl<Map<K, Maybe<A>>> = - mapImpl( - upstream = { this@applyLatestStatefulForKeyInternal.init.connect(evalScope = this) } - ) { upstreamMap -> - upstreamMap.mapValuesParallel { (k: K, ma: Maybe<FrpStateful<A>>) -> + val changesNode: EventsImpl<Map<K, Maybe<A>>> = + mapImpl(upstream = { this@applyLatestStatefulForKey.init.connect(evalScope = this) }) { + upstreamMap, + _ -> + upstreamMap.mapValues { (k: K, ma: Maybe<Stateful<A>>) -> reenterStateScope(this@StateScopeImpl).run { ma.map { stateful -> - val newEnd = with(frpScope) { eventsByKey[k].skipNext() } + val newEnd = eventsByKey[k].skipNext() val newScope = childStateScope(newEnd) - newScope.runInStateScope(stateful) + newScope.stateful() } } } } val operatorName = "applyLatestStatefulForKey" val name = operatorName - val changes: TFlow<Map<K, Maybe<A>>> = TFlowInit(constInit(name, changesNode.cached())) - return changes to FrpDeferredValue(initOut) + val changes: Events<Map<K, Maybe<A>>> = EventsInit(constInit(name, changesNode.cached())) + return changes to DeferredValue(initOut) } - private fun <A> TFlow<FrpStateful<A>>.observeStatefulsInternal(): TFlow<A> { - val operatorName = "observeStatefuls" + override fun <A> Events<Stateful<A>>.applyStatefuls(): Events<A> { + val operatorName = "applyStatefuls" val name = operatorName - return TFlowInit( + return EventsInit( constInit( name, - mapImpl( - upstream = { this@observeStatefulsInternal.init.connect(evalScope = this) } - ) { stateful -> - reenterStateScope(outerScope = this@StateScopeImpl) - .runInStateScope(stateful) + mapImpl(upstream = { this@applyStatefuls.init.connect(evalScope = this) }) { + stateful, + _ -> + reenterStateScope(outerScope = this@StateScopeImpl).stateful() } .cached(), ) ) } - override val frpScope: FrpStateScope = FrpStateScopeImpl() - - private inner class FrpStateScopeImpl : - FrpStateScope, FrpTransactionScope by evalScope.frpScope { - - override fun <A> deferredStateScope( - block: suspend FrpStateScope.() -> A - ): FrpDeferredValue<A> = deferredInternal(block) - - override fun <A> TFlow<A>.holdDeferred(initialValue: FrpDeferredValue<A>): TState<A> = - toTStateDeferredInternal(initialValue) + override fun childStateScope(newEnd: Events<Any>) = + StateScopeImpl(evalScope, merge(newEnd, endSignal)) - override fun <K : Any, V> TFlow<Map<K, Maybe<TFlow<V>>>>.mergeIncrementally( - initialTFlows: FrpDeferredValue<Map<K, TFlow<V>>> - ): TFlow<Map<K, V>> { - val storage: TState<Map<K, TFlow<V>>> = foldMapIncrementally(initialTFlows) - return mergeIncrementallyInternal(storage) + private fun <A> Events<A>.truncateToScope(operatorName: String): Events<A> = + if (endSignalOnce === emptyEvents) { + this + } else { + endSignalOnce + .mapCheap { emptyEvents } + .holdStateInternal(operatorName, this) + .switchEvents() } - override fun <K : Any, V> TFlow<Map<K, Maybe<TFlow<V>>>>.mergeIncrementallyPromptly( - initialTFlows: FrpDeferredValue<Map<K, TFlow<V>>> - ): TFlow<Map<K, V>> { - val storage: TState<Map<K, TFlow<V>>> = foldMapIncrementally(initialTFlows) - return mergeIncrementallyPromptInternal(storage) + private fun <A> Events<A>.nextOnlyInternal(operatorName: String): Events<A> = + if (this === emptyEvents) { + this + } else { + EventsLoop<A>().apply { + loopback = + mapCheap { emptyEvents } + .holdStateInternal(operatorName, this@nextOnlyInternal) + .switchEvents() + } } - override fun <K, A, B> TFlow<Map<K, Maybe<FrpStateful<A>>>>.applyLatestStatefulForKey( - init: FrpDeferredValue<Map<K, FrpStateful<B>>>, - numKeys: Int?, - ): Pair<TFlow<Map<K, Maybe<A>>>, FrpDeferredValue<Map<K, B>>> = - applyLatestStatefulForKeyInternal(init, numKeys) + private fun <A> Events<A>.holdStateInternal(operatorName: String, init: A): State<A> = + holdStateInternalDeferred(operatorName, CompletableLazy(init)) - override fun <A> TFlow<FrpStateful<A>>.applyStatefuls(): TFlow<A> = - observeStatefulsInternal() - } - - override suspend fun <R> runInStateScope(block: suspend FrpStateScope.() -> R): R { - val complete = CompletableDeferred<R>(parent = coroutineContext.job) - block.startCoroutine( - frpScope, - object : Continuation<R> { - override val context: CoroutineContext - get() = EmptyCoroutineContext - - override fun resumeWith(result: Result<R>) { - complete.completeWith(result) - } - }, - ) - return complete.await() + private fun <A> Events<A>.holdStateInternalDeferred( + operatorName: String, + init: Lazy<A>, + ): State<A> { + val changes = this@holdStateInternalDeferred + val name = operatorName + val impl = + activatedStateSource( + name, + operatorName, + evalScope, + { changes.init.connect(evalScope = this) }, + init, + ) + return StateInit(constInit(name, impl)) } - - override fun childStateScope(newEnd: TFlow<Any>) = - StateScopeImpl(evalScope, merge(newEnd, endSignal)) } private fun EvalScope.reenterStateScope(outerScope: StateScopeImpl) = diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/TStateImpl.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/TStateImpl.kt deleted file mode 100644 index c68b4c366776..000000000000 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/TStateImpl.kt +++ /dev/null @@ -1,399 +0,0 @@ -/* - * 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.kairos.internal - -import com.android.systemui.kairos.internal.util.Key -import com.android.systemui.kairos.internal.util.associateByIndex -import com.android.systemui.kairos.internal.util.hashString -import com.android.systemui.kairos.internal.util.mapValuesParallel -import com.android.systemui.kairos.util.Just -import com.android.systemui.kairos.util.Maybe -import com.android.systemui.kairos.util.just -import com.android.systemui.kairos.util.none -import java.util.concurrent.atomic.AtomicLong -import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.CoroutineStart -import kotlinx.coroutines.Deferred -import kotlinx.coroutines.ExperimentalCoroutinesApi - -internal sealed interface TStateImpl<out A> { - val name: String? - val operatorName: String - val changes: TFlowImpl<A> - - suspend fun getCurrentWithEpoch(evalScope: EvalScope): Pair<A, Long> -} - -internal sealed class TStateDerived<A>(override val changes: TFlowImpl<A>) : - TStateImpl<A>, Key<Deferred<Pair<A, Long>>> { - - @Volatile - var invalidatedEpoch = Long.MIN_VALUE - private set - - @Volatile - protected var cache: Any? = EmptyCache - private set - - override suspend fun getCurrentWithEpoch(evalScope: EvalScope): Pair<A, Long> = - evalScope.transactionStore - .getOrPut(this) { evalScope.deferAsync(CoroutineStart.LAZY) { pull(evalScope) } } - .await() - - suspend fun pull(evalScope: EvalScope): Pair<A, Long> { - @Suppress("UNCHECKED_CAST") - return recalc(evalScope)?.also { (a, epoch) -> setCache(a, epoch) } - ?: ((cache as A) to invalidatedEpoch) - } - - fun setCache(value: A, epoch: Long) { - if (epoch > invalidatedEpoch) { - cache = value - invalidatedEpoch = epoch - } - } - - fun getCachedUnsafe(): Maybe<A> { - @Suppress("UNCHECKED_CAST") - return if (cache == EmptyCache) none else just(cache as A) - } - - protected abstract suspend fun recalc(evalScope: EvalScope): Pair<A, Long>? - - private data object EmptyCache -} - -internal class TStateSource<A>( - override val name: String?, - override val operatorName: String, - init: Deferred<A>, - override val changes: TFlowImpl<A>, -) : TStateImpl<A> { - constructor( - name: String?, - operatorName: String, - init: A, - changes: TFlowImpl<A>, - ) : this(name, operatorName, CompletableDeferred(init), changes) - - lateinit var upstreamConnection: NodeConnection<A> - - // Note: Don't need to synchronize; we will never interleave reads and writes, since all writes - // are performed at the end of a network step, after any reads would have taken place. - - @Volatile private var _current: Deferred<A> = init - @Volatile - var writeEpoch = 0L - private set - - override suspend fun getCurrentWithEpoch(evalScope: EvalScope): Pair<A, Long> = - _current.await() to writeEpoch - - /** called by network after eval phase has completed */ - suspend fun updateState(evalScope: EvalScope) { - // write the latch - val eventResult = upstreamConnection.getPushEvent(evalScope) - if (eventResult is Just) { - _current = CompletableDeferred(eventResult.value) - writeEpoch = evalScope.epoch - } - } - - override fun toString(): String = "TStateImpl(changes=$changes, current=$_current)" - - @OptIn(ExperimentalCoroutinesApi::class) - fun getStorageUnsafe(): Maybe<A> = - if (_current.isCompleted) just(_current.getCompleted()) else none -} - -internal fun <A> constS(name: String?, operatorName: String, init: A): TStateImpl<A> = - TStateSource(name, operatorName, init, neverImpl) - -internal inline fun <A> mkState( - name: String?, - operatorName: String, - evalScope: EvalScope, - crossinline getChanges: suspend EvalScope.() -> TFlowImpl<A>, - init: Deferred<A>, -): TStateImpl<A> { - lateinit var state: TStateSource<A> - val calm: TFlowImpl<A> = - filterNode(getChanges) { new -> new != state.getCurrentWithEpoch(evalScope = this).first } - .cached() - return TStateSource(name, operatorName, init, calm).also { - state = it - evalScope.scheduleOutput( - OneShot { - calm.activate(evalScope = this, downstream = Schedulable.S(state))?.let { - (connection, needsEval) -> - state.upstreamConnection = connection - if (needsEval) { - schedule(state) - } - } - } - ) - } -} - -private inline fun <A> TFlowImpl<A>.calm( - crossinline getState: () -> TStateDerived<A> -): TFlowImpl<A> = - filterNode({ this@calm }) { new -> - val state = getState() - val (current, _) = state.getCurrentWithEpoch(evalScope = this) - if (new != current) { - state.setCache(new, epoch) - true - } else { - false - } - } - .cached() - -internal fun <A, B> TStateImpl<A>.mapCheap( - name: String?, - operatorName: String, - transform: suspend EvalScope.(A) -> B, -): TStateImpl<B> = - DerivedMapCheap(name, operatorName, this, mapImpl({ changes }) { transform(it) }, transform) - -internal class DerivedMapCheap<A, B>( - override val name: String?, - override val operatorName: String, - val upstream: TStateImpl<A>, - override val changes: TFlowImpl<B>, - private val transform: suspend EvalScope.(A) -> B, -) : TStateImpl<B> { - - override suspend fun getCurrentWithEpoch(evalScope: EvalScope): Pair<B, Long> { - val (a, epoch) = upstream.getCurrentWithEpoch(evalScope) - return evalScope.transform(a) to epoch - } - - override fun toString(): String = "${this::class.simpleName}@$hashString" -} - -internal fun <A, B> TStateImpl<A>.map( - name: String?, - operatorName: String, - transform: suspend EvalScope.(A) -> B, -): TStateImpl<B> { - lateinit var state: TStateDerived<B> - val mappedChanges = mapImpl({ changes }) { transform(it) }.cached().calm { state } - state = DerivedMap(name, operatorName, transform, this, mappedChanges) - return state -} - -internal class DerivedMap<A, B>( - override val name: String?, - override val operatorName: String, - private val transform: suspend EvalScope.(A) -> B, - val upstream: TStateImpl<A>, - changes: TFlowImpl<B>, -) : TStateDerived<B>(changes) { - override fun toString(): String = "${this::class.simpleName}@$hashString" - - override suspend fun recalc(evalScope: EvalScope): Pair<B, Long>? { - val (a, epoch) = upstream.getCurrentWithEpoch(evalScope) - return if (epoch > invalidatedEpoch) { - evalScope.transform(a) to epoch - } else { - null - } - } -} - -internal fun <A> TStateImpl<TStateImpl<A>>.flatten(name: String?, operator: String): TStateImpl<A> { - // emits the current value of the new inner state, when that state is emitted - val switchEvents = mapImpl({ changes }) { newInner -> newInner.getCurrentWithEpoch(this).first } - // emits the new value of the new inner state when that state is emitted, or - // falls back to the current value if a new state is *not* being emitted this - // transaction - val innerChanges = - mapImpl({ changes }) { newInner -> - mergeNodes({ switchEvents }, { newInner.changes }) { _, new -> new } - } - val switchedChanges: TFlowImpl<A> = - mapImpl({ - switchPromptImpl( - getStorage = { - mapOf(Unit to this@flatten.getCurrentWithEpoch(evalScope = this).first.changes) - }, - getPatches = { mapImpl({ innerChanges }) { new -> mapOf(Unit to just(new)) } }, - ) - }) { map -> - map.getValue(Unit) - } - lateinit var state: DerivedFlatten<A> - state = DerivedFlatten(name, operator, this, switchedChanges.calm { state }) - return state -} - -internal class DerivedFlatten<A>( - override val name: String?, - override val operatorName: String, - val upstream: TStateImpl<TStateImpl<A>>, - changes: TFlowImpl<A>, -) : TStateDerived<A>(changes) { - override suspend fun recalc(evalScope: EvalScope): Pair<A, Long> { - val (inner, epoch0) = upstream.getCurrentWithEpoch(evalScope) - val (a, epoch1) = inner.getCurrentWithEpoch(evalScope) - return a to maxOf(epoch0, epoch1) - } - - override fun toString(): String = "${this::class.simpleName}@$hashString" -} - -@Suppress("NOTHING_TO_INLINE") -internal inline fun <A, B> TStateImpl<A>.flatMap( - name: String?, - operatorName: String, - noinline transform: suspend EvalScope.(A) -> TStateImpl<B>, -): TStateImpl<B> = map(null, operatorName, transform).flatten(name, operatorName) - -internal fun <A, B, Z> zipStates( - name: String?, - operatorName: String, - l1: TStateImpl<A>, - l2: TStateImpl<B>, - transform: suspend EvalScope.(A, B) -> Z, -): TStateImpl<Z> = - zipStates(null, operatorName, mapOf(0 to l1, 1 to l2)).map(name, operatorName) { - val a = it.getValue(0) - val b = it.getValue(1) - @Suppress("UNCHECKED_CAST") transform(a as A, b as B) - } - -internal fun <A, B, C, Z> zipStates( - name: String?, - operatorName: String, - l1: TStateImpl<A>, - l2: TStateImpl<B>, - l3: TStateImpl<C>, - transform: suspend EvalScope.(A, B, C) -> Z, -): TStateImpl<Z> = - zipStates(null, operatorName, mapOf(0 to l1, 1 to l2, 2 to l3)).map(name, operatorName) { - val a = it.getValue(0) - val b = it.getValue(1) - val c = it.getValue(2) - @Suppress("UNCHECKED_CAST") transform(a as A, b as B, c as C) - } - -internal fun <A, B, C, D, Z> zipStates( - name: String?, - operatorName: String, - l1: TStateImpl<A>, - l2: TStateImpl<B>, - l3: TStateImpl<C>, - l4: TStateImpl<D>, - transform: suspend EvalScope.(A, B, C, D) -> Z, -): TStateImpl<Z> = - zipStates(null, operatorName, mapOf(0 to l1, 1 to l2, 2 to l3, 3 to l4)).map( - name, - operatorName, - ) { - val a = it.getValue(0) - val b = it.getValue(1) - val c = it.getValue(2) - val d = it.getValue(3) - @Suppress("UNCHECKED_CAST") transform(a as A, b as B, c as C, d as D) - } - -internal fun <A, B, C, D, E, Z> zipStates( - name: String?, - operatorName: String, - l1: TStateImpl<A>, - l2: TStateImpl<B>, - l3: TStateImpl<C>, - l4: TStateImpl<D>, - l5: TStateImpl<E>, - transform: suspend EvalScope.(A, B, C, D, E) -> Z, -): TStateImpl<Z> = - zipStates(null, operatorName, mapOf(0 to l1, 1 to l2, 2 to l3, 3 to l4, 4 to l5)).map( - name, - operatorName, - ) { - val a = it.getValue(0) - val b = it.getValue(1) - val c = it.getValue(2) - val d = it.getValue(3) - val e = it.getValue(4) - @Suppress("UNCHECKED_CAST") transform(a as A, b as B, c as C, d as D, e as E) - } - -internal fun <K : Any, A> zipStates( - name: String?, - operatorName: String, - states: Map<K, TStateImpl<A>>, -): TStateImpl<Map<K, A>> { - if (states.isEmpty()) return constS(name, operatorName, emptyMap()) - val stateChanges: Map<K, TFlowImpl<A>> = states.mapValues { it.value.changes } - lateinit var state: DerivedZipped<K, A> - // No need for calm; invariant ensures that changes will only emit when there's a difference - val changes: TFlowImpl<Map<K, A>> = - mapImpl({ - switchDeferredImpl(getStorage = { stateChanges }, getPatches = { neverImpl }) - }) { patch -> - states - .mapValues { (k, v) -> - if (k in patch) { - patch.getValue(k) - } else { - v.getCurrentWithEpoch(evalScope = this).first - } - } - .also { state.setCache(it, epoch) } - } - state = DerivedZipped(name, operatorName, states, changes) - return state -} - -internal class DerivedZipped<K : Any, A>( - override val name: String?, - override val operatorName: String, - val upstream: Map<K, TStateImpl<A>>, - changes: TFlowImpl<Map<K, A>>, -) : TStateDerived<Map<K, A>>(changes) { - override suspend fun recalc(evalScope: EvalScope): Pair<Map<K, A>, Long> { - val newEpoch = AtomicLong() - return upstream.mapValuesParallel { - val (a, epoch) = it.value.getCurrentWithEpoch(evalScope) - newEpoch.accumulateAndGet(epoch, ::maxOf) - a - } to newEpoch.get() - } - - override fun toString(): String = "${this::class.simpleName}@$hashString" -} - -@Suppress("NOTHING_TO_INLINE") -internal inline fun <A> zipStates( - name: String?, - operatorName: String, - states: List<TStateImpl<A>>, -): TStateImpl<List<A>> = - if (states.isEmpty()) { - constS(name, operatorName, emptyList()) - } else { - zipStates(null, operatorName, states.asIterable().associateByIndex()).mapCheap( - name, - operatorName, - ) { - it.values.toList() - } - } diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/TransactionalImpl.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/TransactionalImpl.kt index 8647bdd5b7b1..13bd3b005871 100644 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/TransactionalImpl.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/TransactionalImpl.kt @@ -16,31 +16,25 @@ package com.android.systemui.kairos.internal -import com.android.systemui.kairos.internal.util.Key import com.android.systemui.kairos.internal.util.hashString -import kotlinx.coroutines.CoroutineStart -import kotlinx.coroutines.Deferred internal sealed class TransactionalImpl<out A> { - data class Const<out A>(val value: Deferred<A>) : TransactionalImpl<A>() + data class Const<out A>(val value: Lazy<A>) : TransactionalImpl<A>() + + class Impl<A>(val block: EvalScope.() -> A) : TransactionalImpl<A>() { + val cache = TransactionCache<Lazy<A>>() - class Impl<A>(val block: suspend EvalScope.() -> A) : TransactionalImpl<A>(), Key<Deferred<A>> { override fun toString(): String = "${this::class.simpleName}@$hashString" } } @Suppress("NOTHING_TO_INLINE") -internal inline fun <A> transactionalImpl( - noinline block: suspend EvalScope.() -> A -): TransactionalImpl<A> = TransactionalImpl.Impl(block) +internal inline fun <A> transactionalImpl(noinline block: EvalScope.() -> A): TransactionalImpl<A> = + TransactionalImpl.Impl(block) -internal fun <A> TransactionalImpl<A>.sample(evalScope: EvalScope): Deferred<A> = +internal fun <A> TransactionalImpl<A>.sample(evalScope: EvalScope): Lazy<A> = when (this) { is TransactionalImpl.Const -> value is TransactionalImpl.Impl -> - evalScope.transactionStore - .getOrPut(this) { - evalScope.deferAsync(start = CoroutineStart.LAZY) { evalScope.block() } - } - .also { it.start() } + cache.getOrPut(evalScope) { evalScope.deferAsync { evalScope.block() } } } diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/store/ArrayMapK.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/store/ArrayMapK.kt new file mode 100644 index 000000000000..f0c2f346e9b7 --- /dev/null +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/store/ArrayMapK.kt @@ -0,0 +1,129 @@ +/* + * 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.kairos.internal.store + +import java.util.concurrent.atomic.AtomicReferenceArray + +/** A [Map] backed by a flat array. */ +internal class ArrayMapK<V>( + val unwrapped: List<MutableMap.MutableEntry<Int, V>>, + val originalCapacity: Int, +) : MapK<ArrayMapK.W, Int, V>, AbstractMap<Int, V>() { + object W + + override val entries: Set<Map.Entry<Int, V>> = + object : AbstractSet<Map.Entry<Int, V>>() { + override val size: Int + get() = unwrapped.size + + override fun iterator(): Iterator<Map.Entry<Int, V>> = unwrapped.iterator() + } +} + +@Suppress("NOTHING_TO_INLINE") +internal inline fun <V> MapK<ArrayMapK.W, Int, V>.asArrayHolder(): ArrayMapK<V> = + this as ArrayMapK<V> + +internal class MutableArrayMapK<V> +private constructor(private val storage: AtomicReferenceArray<MutableMap.MutableEntry<Int, V>?>) : + MutableMapK<ArrayMapK.W, Int, V>, AbstractMutableMap<Int, V>() { + + constructor(length: Int) : this(AtomicReferenceArray<MutableMap.MutableEntry<Int, V>?>(length)) + + override fun readOnlyCopy(): ArrayMapK<V> { + val size1 = storage.length() + return ArrayMapK( + buildList { + for (i in 0 until size1) { + storage.get(i)?.let { entry -> add(StoreEntry(entry.key, entry.value)) } + } + }, + size1, + ) + } + + override fun asReadOnly(): MapK<ArrayMapK.W, Int, V> = readOnlyCopy() + + private fun getNumEntries(): Int { + val capacity = storage.length() + var total = 0 + for (i in 0 until capacity) { + storage.get(i)?.let { total++ } + } + return total + } + + override fun put(key: Int, value: V): V? = + storage.get(key)?.value.also { storage.set(key, StoreEntry(key, value)) } + + override val entries: MutableSet<MutableMap.MutableEntry<Int, V>> = + object : AbstractMutableSet<MutableMap.MutableEntry<Int, V>>() { + override val size: Int + get() = getNumEntries() + + override fun add(element: MutableMap.MutableEntry<Int, V>): Boolean = + (storage.get(element.key) is MutableMap.MutableEntry<*, *>).also { + storage.set(element.key, element) + } + + override fun iterator(): MutableIterator<MutableMap.MutableEntry<Int, V>> = + object : MutableIterator<MutableMap.MutableEntry<Int, V>> { + + var cursor = -1 + var nextIndex = -1 + + override fun hasNext(): Boolean { + val capacity = storage.length() + if (nextIndex >= capacity) return false + if (nextIndex != cursor) return true + while (++nextIndex < capacity) { + if (storage.get(nextIndex) != null) { + return true + } + } + return false + } + + override fun next(): MutableMap.MutableEntry<Int, V> { + if (!hasNext()) throw NoSuchElementException() + cursor = nextIndex + return storage.get(cursor)!! + } + + override fun remove() { + check( + cursor >= 0 && + cursor < storage.length() && + storage.getAndSet(cursor, null) != null + ) + } + } + } + + class Factory : MutableMapK.Factory<ArrayMapK.W, Int> { + override fun <V> create(capacity: Int?) = + MutableArrayMapK<V>(checkNotNull(capacity) { "Cannot use ArrayMapK with null capacity." }) + + override fun <V> create(input: MapK<ArrayMapK.W, Int, V>): MutableArrayMapK<V> { + val holder = input.asArrayHolder() + return MutableArrayMapK( + AtomicReferenceArray<MutableMap.MutableEntry<Int, V>?>(holder.originalCapacity) + .apply { holder.unwrapped.forEach { set(it.key, it) } } + ) + } + } +} diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/store/MapHolder.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/store/MapHolder.kt new file mode 100644 index 000000000000..db2dde00f17a --- /dev/null +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/store/MapHolder.kt @@ -0,0 +1,52 @@ +/* + * 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.kairos.internal.store + +import com.android.systemui.kairos.internal.util.ConcurrentNullableHashMap + +@JvmInline +internal value class MapHolder<K, V>(val unwrapped: Map<K, V>) : + MapK<MapHolder.W, K, V>, Map<K, V> by unwrapped { + object W +} + +@Suppress("NOTHING_TO_INLINE") +internal inline fun <K, V> MapK<MapHolder.W, K, V>.asMapHolder(): MapHolder<K, V> = + this as MapHolder<K, V> + +// TODO: preserve insertion order? +internal class ConcurrentHashMapK<K, V>(private val storage: ConcurrentNullableHashMap<K, V>) : + MutableMapK<MapHolder.W, K, V>, MutableMap<K, V> by storage { + + override fun readOnlyCopy() = MapHolder(storage.toMap()) + + override fun asReadOnly(): MapK<MapHolder.W, K, V> = MapHolder(storage) + + class Factory<K> : MutableMapK.Factory<MapHolder.W, K> { + override fun <V> create(capacity: Int?) = + ConcurrentHashMapK<K, V>( + capacity?.let { ConcurrentNullableHashMap(capacity) } ?: ConcurrentNullableHashMap() + ) + + override fun <V> create(input: MapK<MapHolder.W, K, V>) = + ConcurrentHashMapK( + ConcurrentNullableHashMap<K, V>().apply { + input.asMapHolder().unwrapped.forEach { (k, v) -> set(k, v) } + } + ) + } +} diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/store/MapK.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/store/MapK.kt new file mode 100644 index 000000000000..e193a4957bd0 --- /dev/null +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/store/MapK.kt @@ -0,0 +1,76 @@ +/* + * 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.kairos.internal.store + +/** + * Higher-kinded encoding for [Map]. + * + * Let's say you want to write a class that is generic over both a map, and the type of data within + * the map: + * ``` kotlin + * class Foo<TMap, TKey, TValue> { + * val container: TMap<TKey, TElement> // disallowed! + * } + * ``` + * + * You can use `MapK` to represent the "higher-kinded" type variable `TMap`: + * ``` kotlin + * class Foo<TMap, TKey, TValue> { + * val container: MapK<TMap, TKey, TValue> // OK! + * } + * ``` + * + * Note that Kotlin will not let you use the generic type without parameters as `TMap`: + * ``` kotlin + * val fooHk: MapK<HashMap, Int, String> // not allowed: HashMap requires two type parameters + * ``` + * + * To work around this, you need to declare a special type-witness object. This object is only used + * at compile time and can be stripped out by a minifier because it's never used at runtime. + * + * ``` kotlin + * class Foo<A, B> : MapK<FooWitness, A, B> { ... } + * object FooWitness + * + * // safe, as long as Foo is the only implementor of MapK<FooWitness, *, *> + * fun <A, B> MapK<FooWitness, A, B>.asFoo(): Foo<A, B> = this as Foo<A, B> + * + * val fooStore: MapK<FooWitness, Int, String> = Foo() + * val foo: Foo<Int, String> = fooStore.asFoo() + * ``` + */ +internal interface MapK<W, K, V> : Map<K, V> + +internal interface MutableMapK<W, K, V> : MutableMap<K, V> { + + fun readOnlyCopy(): MapK<W, K, V> + + fun asReadOnly(): MapK<W, K, V> + + interface Factory<W, K> { + fun <V> create(capacity: Int?): MutableMapK<W, K, V> + + fun <V> create(input: MapK<W, K, V>): MutableMapK<W, K, V> + } +} + +internal object NoValue + +internal data class StoreEntry<K, V>(override var key: K, override var value: V) : + MutableMap.MutableEntry<K, V> { + override fun setValue(newValue: V): V = value.also { value = newValue } +} diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/store/Single.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/store/Single.kt new file mode 100644 index 000000000000..2d0894884a4c --- /dev/null +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/store/Single.kt @@ -0,0 +1,93 @@ +/* + * 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.kairos.internal.store + +@Suppress("NOTHING_TO_INLINE") internal inline fun <V> singleOf(value: V) = Single<V>(value) + +/** A [Map] with a single element that has key [Unit]. */ +internal class Single<V>(val unwrapped: Any?) : MapK<Single.W, Unit, V>, AbstractMap<Unit, V>() { + + constructor() : this(NoValue) + + @Suppress("UNCHECKED_CAST") + override val entries: Set<Map.Entry<Unit, V>> = + if (unwrapped === NoValue) emptySet() else setOf(StoreEntry(Unit, unwrapped as V)) + + object W +} + +@Suppress("NOTHING_TO_INLINE") +internal inline fun <V> MapK<Single.W, Unit, V>.asSingle(): Single<V> = this as Single<V> + +internal class SingletonMapK<V>(@Volatile private var value: Any?) : + MutableMapK<Single.W, Unit, V>, AbstractMutableMap<Unit, V>() { + + constructor() : this(NoValue) + + override fun readOnlyCopy() = + Single<V>(if (value === NoValue) value else (value as MutableMap.MutableEntry<*, *>).value) + + override fun asReadOnly(): MapK<Single.W, Unit, V> = readOnlyCopy() + + @Suppress("UNCHECKED_CAST") + override fun put(key: Unit, value: V): V? = + (this.value as? MutableMap.MutableEntry<Unit, V>)?.value.also { + this.value = StoreEntry(Unit, value) + } + + override val entries: MutableSet<MutableMap.MutableEntry<Unit, V>> = + object : AbstractMutableSet<MutableMap.MutableEntry<Unit, V>>() { + override fun add(element: MutableMap.MutableEntry<Unit, V>): Boolean = + (value !== NoValue).also { value = element } + + override val size: Int + get() = if (value === NoValue) 0 else 1 + + override fun iterator(): MutableIterator<MutableMap.MutableEntry<Unit, V>> { + return object : MutableIterator<MutableMap.MutableEntry<Unit, V>> { + + var done = false + + override fun hasNext(): Boolean = value !== NoValue && !done + + override fun next(): MutableMap.MutableEntry<Unit, V> { + if (!hasNext()) throw NoSuchElementException() + done = true + @Suppress("UNCHECKED_CAST") + return value as MutableMap.MutableEntry<Unit, V> + } + + override fun remove() { + if (!done || value === NoValue) throw IllegalStateException() + value = NoValue + } + } + } + } + + internal class Factory : MutableMapK.Factory<Single.W, Unit> { + override fun <V> create(capacity: Int?): SingletonMapK<V> { + check(capacity == null || capacity == 0 || capacity == 1) { + "Can't use singleton store with capacity > 1. Got: $capacity" + } + return SingletonMapK() + } + + override fun <V> create(input: MapK<Single.W, Unit, V>): SingletonMapK<V> = + SingletonMapK(input.asSingle().unwrapped) + } +} diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/util/ConcurrentNullableHashMap.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/util/ConcurrentNullableHashMap.kt index 6c8ae7cf6436..afeb0679fe12 100644 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/util/ConcurrentNullableHashMap.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/util/ConcurrentNullableHashMap.kt @@ -16,31 +16,114 @@ package com.android.systemui.kairos.internal.util +import com.android.systemui.kairos.internal.store.NoValue import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.ConcurrentMap + +internal class ConcurrentNullableHashMap<K, V> +private constructor(private val inner: ConcurrentHashMap<Any, Any>) : + ConcurrentMap<K, V>, AbstractMutableMap<K, V>() { -internal class ConcurrentNullableHashMap<K : Any, V> -private constructor(private val inner: ConcurrentHashMap<K, Any>) { constructor() : this(ConcurrentHashMap()) - @Suppress("UNCHECKED_CAST") - operator fun get(key: K): V? = inner[key]?.takeIf { it !== NullValue } as V? + constructor(capacity: Int) : this(ConcurrentHashMap(capacity)) + + override fun get(key: K): V? = inner[key ?: NullValue]?.let { toNullable<V>(it) } + + fun getValue(key: K): V = toNullable(inner.getValue(key ?: NullValue)) @Suppress("UNCHECKED_CAST") - fun put(key: K, value: V?): V? = - inner.put(key, value ?: NullValue)?.takeIf { it !== NullValue } as V? + override fun put(key: K, value: V): V? = + inner.put(key ?: NullValue, value ?: NullValue)?.takeIf { it !== NullValue } as V? - operator fun set(key: K, value: V?) { + operator fun set(key: K, value: V) { put(key, value) } - @Suppress("UNCHECKED_CAST") - fun toMap(): Map<K, V> = inner.mapValues { (_, v) -> v.takeIf { it !== NullValue } as V } + fun toMap(): Map<K, V> = + inner.asSequence().associate { (k, v) -> toNullable<K>(k) to toNullable(v) } - fun clear() { + override fun clear() { inner.clear() } + override fun remove(key: K, value: V): Boolean = inner.remove(key ?: NoValue, value ?: NoValue) + + override val entries: MutableSet<MutableMap.MutableEntry<K, V>> = + object : AbstractMutableSet<MutableMap.MutableEntry<K, V>>() { + val wrapped = inner.entries + + override fun add(element: MutableMap.MutableEntry<K, V>): Boolean { + val e = + object : MutableMap.MutableEntry<Any, Any> { + override val key: Any + get() = element.key ?: NullValue + + override val value: Any + get() = element.value ?: NullValue + + override fun setValue(newValue: Any): Any = + element.setValue(toNullable(newValue)) ?: NullValue + } + return wrapped.add(e) + } + + override val size: Int + get() = wrapped.size + + override fun iterator(): MutableIterator<MutableMap.MutableEntry<K, V>> { + val iter = wrapped.iterator() + return object : MutableIterator<MutableMap.MutableEntry<K, V>> { + override fun hasNext(): Boolean = iter.hasNext() + + override fun next(): MutableMap.MutableEntry<K, V> { + val element = iter.next() + return object : MutableMap.MutableEntry<K, V> { + override val key: K + get() = toNullable(element.key) + + override val value: V + get() = toNullable(element.value) + + override fun setValue(newValue: V): V = + toNullable(element.setValue(newValue ?: NullValue)) + } + } + + override fun remove() { + iter.remove() + } + } + } + } + + override fun replace(key: K, oldValue: V, newValue: V): Boolean = + inner.replace(key ?: NullValue, oldValue ?: NullValue, newValue ?: NullValue) + + override fun replace(key: K, value: V): V? = + inner.replace(key ?: NullValue, value ?: NullValue)?.let { toNullable<V>(it) } + + override fun putIfAbsent(key: K, value: V): V? = + inner.putIfAbsent(key ?: NullValue, value ?: NullValue)?.let { toNullable<V>(it) } + + @Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE") + private inline fun <T> toNullable(value: Any): T = value.takeIf { it !== NullValue } as T + fun isNotEmpty(): Boolean = inner.isNotEmpty() + + @Suppress("UNCHECKED_CAST") + override fun remove(key: K): V? = + inner.remove(key ?: NullValue)?.takeIf { it !== NullValue } as V? + + fun asSequence(): Sequence<Pair<K, V>> = + inner.asSequence().map { (key, value) -> toNullable<K>(key) to toNullable(value) } + + override fun isEmpty(): Boolean = inner.isEmpty() + + override fun containsKey(key: K): Boolean = inner.containsKey(key ?: NullValue) + + fun getOrPut(key: K, defaultValue: () -> V): V = + toNullable(inner.getOrPut(key) { defaultValue() ?: NullValue }) } private object NullValue diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/util/HeteroMap.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/util/HeteroMap.kt index 5cee2dd5880a..9b6940d03270 100644 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/util/HeteroMap.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/util/HeteroMap.kt @@ -17,17 +17,18 @@ package com.android.systemui.kairos.internal.util import com.android.systemui.kairos.util.Maybe -import com.android.systemui.kairos.util.None +import com.android.systemui.kairos.util.Maybe.None import com.android.systemui.kairos.util.just import java.util.concurrent.ConcurrentHashMap -internal interface Key<A> - private object NULL -internal class HeteroMap { +internal class HeteroMap private constructor(private val store: ConcurrentHashMap<Key<*>, Any>) { + interface Key<A> {} + + constructor() : this(ConcurrentHashMap()) - private val store = ConcurrentHashMap<Key<*>, Any>() + constructor(capacity: Int) : this(ConcurrentHashMap(capacity)) @Suppress("UNCHECKED_CAST") operator fun <A> get(key: Key<A>): Maybe<A> = @@ -37,6 +38,17 @@ internal class HeteroMap { store[key] = value ?: NULL } + @Suppress("UNCHECKED_CAST") + fun <A : Any> getOrNull(key: Key<A>): A? = + store[key]?.let { (if (it === NULL) null else it) as A } + + @Suppress("UNCHECKED_CAST") + fun <A> getOrError(key: Key<A>, block: () -> String): A { + store[key]?.let { + return (if (it === NULL) null else it) as A + } ?: error(block()) + } + operator fun contains(key: Key<*>): Boolean = store.containsKey(key) fun clear() { diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/util/MapUtils.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/util/MapUtils.kt index ebf9a66be0ae..67862593b80a 100644 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/util/MapUtils.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/util/MapUtils.kt @@ -16,8 +16,6 @@ package com.android.systemui.kairos.internal.util -import kotlinx.coroutines.CoroutineStart -import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.yield @@ -32,7 +30,7 @@ internal suspend inline fun <K, A, B : Any, M : MutableMap<K, B>> Map<K, A> destination.also { coroutineScope { mapValues { - async { + asyncImmediate { yield() block(it) } @@ -41,7 +39,7 @@ internal suspend inline fun <K, A, B : Any, M : MutableMap<K, B>> Map<K, A> .mapValuesNotNullTo(it) { (_, deferred) -> deferred.await() } } -internal inline fun <K, A, B : Any, M : MutableMap<K, B>> Map<K, A>.mapValuesNotNullTo( +internal inline fun <K, A, B, M : MutableMap<K, B>> Map<K, A>.mapValuesNotNullTo( destination: M, block: (Map.Entry<K, A>) -> B?, ): M = @@ -51,9 +49,13 @@ internal inline fun <K, A, B : Any, M : MutableMap<K, B>> Map<K, A>.mapValuesNot } } +internal inline fun <K, A, B> Map<K, A>.mapValuesNotNull( + block: (Map.Entry<K, A>) -> B? +): Map<K, B> = mapValuesNotNullTo(mutableMapOf(), block) + internal suspend fun <A, B> Iterable<A>.mapParallel(transform: suspend (A) -> B): List<B> = coroutineScope { - map { async(start = CoroutineStart.LAZY) { transform(it) } }.awaitAll() + map { asyncImmediate { transform(it) } }.awaitAll() } internal suspend fun <K, A, B, M : MutableMap<K, B>> Map<K, A>.mapValuesParallelTo( diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/util/Util.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/util/Util.kt index 6bb7f9f593aa..466a9f83b91f 100644 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/util/Util.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/internal/util/Util.kt @@ -18,8 +18,13 @@ package com.android.systemui.kairos.internal.util +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext +import kotlin.time.DurationUnit +import kotlin.time.measureTimedValue import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.Deferred @@ -31,6 +36,62 @@ import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.launch import kotlinx.coroutines.newCoroutineContext +private const val LogEnabled = false + +@Suppress("NOTHING_TO_INLINE") +internal inline fun logLn(indent: Int = 0, message: Any?) { + if (!LogEnabled) return + log(indent, message) + println() +} + +@Suppress("NOTHING_TO_INLINE") +internal inline fun log(indent: Int = 0, message: Any?) { + if (!LogEnabled) return + printIndent(indent) + print(message) +} + +@JvmInline +internal value class LogIndent(val currentLogIndent: Int) { + @OptIn(ExperimentalContracts::class) + inline fun <R> logDuration(prefix: String, start: Boolean = true, block: LogIndent.() -> R): R { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + return logDuration(currentLogIndent, prefix, start, block) + } + + @Suppress("NOTHING_TO_INLINE") + inline fun logLn(message: Any?) = logLn(currentLogIndent, message) +} + +@OptIn(ExperimentalContracts::class) +internal inline fun <R> logDuration( + indent: Int, + prefix: String, + start: Boolean = true, + block: LogIndent.() -> R, +): R { + contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } + if (!LogEnabled) return LogIndent(0).block() + if (start) { + logLn(indent, prefix) + } + val (result, duration) = measureTimedValue { LogIndent(indent + 1).block() } + + printIndent(indent) + print(prefix) + print(": ") + println(duration.toString(DurationUnit.MICROSECONDS)) + return result +} + +@Suppress("NOTHING_TO_INLINE") +private inline fun printIndent(indent: Int) { + for (i in 0 until indent) { + print(" ") + } +} + internal fun <A> CoroutineScope.asyncImmediate( start: CoroutineStart = CoroutineStart.UNDISPATCHED, context: CoroutineContext = EmptyCoroutineContext, diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/util/Either.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/util/Either.kt index ad9f7d715156..957d46ff1ecd 100644 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/util/Either.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/util/Either.kt @@ -18,6 +18,9 @@ package com.android.systemui.kairos.util +import com.android.systemui.kairos.util.Either.Left +import com.android.systemui.kairos.util.Either.Right + /** * Contains a value of two possibilities: `Left<A>` or `Right<B>` * @@ -25,13 +28,13 @@ package com.android.systemui.kairos.util * [Pair] is effectively an anonymous grouping of two instances, then an [Either] is an anonymous * set of two options. */ -sealed class Either<out A, out B> - -/** An [Either] that contains a [Left] value. */ -data class Left<out A>(val value: A) : Either<A, Nothing>() +sealed interface Either<out A, out B> { + /** An [Either] that contains a [Left] value. */ + @JvmInline value class Left<out A>(val value: A) : Either<A, Nothing> -/** An [Either] that contains a [Right] value. */ -data class Right<out B>(val value: B) : Either<Nothing, B>() + /** An [Either] that contains a [Right] value. */ + @JvmInline value class Right<out B>(val value: B) : Either<Nothing, B> +} /** * Returns an [Either] containing the result of applying [transform] to the [Left] value, or the @@ -57,7 +60,7 @@ inline fun <A, B, C> Either<A, B>.mapRight(transform: (B) -> C): Either<A, C> = inline fun <A> Either<A, *>.leftMaybe(): Maybe<A> = when (this) { is Left -> just(value) - else -> None + else -> none } /** Returns the [Left] value held by this [Either], or `null` if this is a [Right] value. */ @@ -71,7 +74,7 @@ inline fun <A> Either<A, *>.leftOrNull(): A? = inline fun <B> Either<*, B>.rightMaybe(): Maybe<B> = when (this) { is Right -> just(value) - else -> None + else -> none } /** Returns the [Right] value held by this [Either], or `null` if this is a [Left] value. */ diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/util/MapPatch.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/util/MapPatch.kt new file mode 100644 index 000000000000..f368cbf8f124 --- /dev/null +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/util/MapPatch.kt @@ -0,0 +1,98 @@ +/* + * 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.kairos.util + +import com.android.systemui.kairos.util.Either.Left +import com.android.systemui.kairos.util.Either.Right +import com.android.systemui.kairos.util.Maybe.Just + +/** A "patch" that can be used to batch-update a [Map], via [applyPatch]. */ +typealias MapPatch<K, V> = Map<K, Maybe<V>> + +/** + * Returns a new [Map] that has [patch] applied to the original map. + * + * For each entry in [patch]: + * * a [Just] value will be included in the new map, replacing the entry in the original map with + * the same key, if present. + * * a [Maybe.None] value will be omitted from the new map, excluding the entry in the original map + * with the same key, if present. + */ +fun <K, V> Map<K, V>.applyPatch(patch: MapPatch<K, V>): Map<K, V> { + val (adds: List<Pair<K, V>>, removes: List<K>) = + patch + .asSequence() + .map { (k, v) -> if (v is Just) Left(k to v.value) else Right(k) } + .partitionEithers() + val removed: Map<K, V> = this - removes.toSet() + val updated: Map<K, V> = removed + adds + return updated +} + +/** + * Returns a [MapPatch] that, when applied, includes all of the values from the original [Map]. + * + * Shorthand for: + * ```kotlin + * mapValues { just(it.value) } + * ``` + */ +fun <K, V> Map<K, V>.toMapPatch(): MapPatch<K, V> = mapValues { just(it.value) } + +/** + * Returns a [MapPatch] that, when applied, includes all of the entries from [new] whose keys are + * not present in [old], and excludes all entries with keys present in [old] that are not also + * present in [new]. + * + * Note that, unlike [mapPatchFromFullDiff], only keys are taken into account. If the same key is + * present in both [old] and [new], but the associated values are not equal, then the returned + * [MapPatch] will *not* include any update to that key. + */ +fun <K, V> mapPatchFromKeyDiff(old: Map<K, V>, new: Map<K, V>): MapPatch<K, V> { + val removes = old.keys - new.keys + val adds = new - old.keys + return buildMap { + for (removed in removes) { + put(removed, none) + } + for ((newKey, newValue) in adds) { + put(newKey, just(newValue)) + } + } +} + +/** + * Returns a [MapPatch] that, when applied, includes all of the entries from [new] that are not + * present in [old], and excludes all entries with keys present in [old] that are not also present + * in [new]. + * + * Note that, unlike [mapPatchFromKeyDiff], both keys and values are taken into account. If the same + * key is present in both [old] and [new], but the associated values are not equal, then the + * returned [MapPatch] will include the entry from [new]. + */ +fun <K, V> mapPatchFromFullDiff(old: Map<K, V>, new: Map<K, V>): MapPatch<K, V> { + val removes = old.keys - new.keys + val adds = new.mapMaybeValues { (k, v) -> if (k in old && v == old[k]) none else just(v) } + return hashMapOf<K, Maybe<V>>().apply { + for (removed in removes) { + put(removed, none) + } + for ((newKey, newValue) in adds) { + put(newKey, just(newValue)) + } + } +} diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/util/Maybe.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/util/Maybe.kt index c3cae3885bd3..681218399d93 100644 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/util/Maybe.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/util/Maybe.kt @@ -18,6 +18,8 @@ package com.android.systemui.kairos.util +import com.android.systemui.kairos.util.Maybe.Just +import com.android.systemui.kairos.util.Maybe.None import kotlin.coroutines.Continuation import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext @@ -27,13 +29,13 @@ import kotlin.coroutines.startCoroutine import kotlin.coroutines.suspendCoroutine /** Represents a value that may or may not be present. */ -sealed class Maybe<out A> +sealed interface Maybe<out A> { + /** A [Maybe] value that is present. */ + @JvmInline value class Just<out A> internal constructor(val value: A) : Maybe<A> -/** A [Maybe] value that is present. */ -data class Just<out A> internal constructor(val value: A) : Maybe<A>() - -/** A [Maybe] value that is not present. */ -data object None : Maybe<Nothing>() + /** A [Maybe] value that is not present. */ + data object None : Maybe<Nothing> +} /** Utilities to query [Maybe] instances from within a [maybe] block. */ @RestrictsSuspension @@ -230,8 +232,14 @@ fun <A> Maybe<A>.mergeWith(other: Maybe<A>, transform: (A, A) -> A): Maybe<A> = * Returns a list containing only the present results of applying [transform] to each element in the * original iterable. */ -fun <A, B> Iterable<A>.mapMaybe(transform: (A) -> Maybe<B>): List<B> = - asSequence().mapMaybe(transform).toList() +inline fun <A, B> Iterable<A>.mapMaybe(transform: (A) -> Maybe<B>): List<B> = buildList { + for (a in this@mapMaybe) { + val result = transform(a) + if (result is Just) { + add(result.value) + } + } +} /** * Returns a sequence containing only the present results of applying [transform] to each element in @@ -244,9 +252,15 @@ fun <A, B> Sequence<A>.mapMaybe(transform: (A) -> Maybe<B>): Sequence<B> = * Returns a map with values of only the present results of applying [transform] to each entry in * the original map. */ -inline fun <K, A, B> Map<K, A>.mapMaybeValues( - crossinline p: (Map.Entry<K, A>) -> Maybe<B> -): Map<K, B> = asSequence().mapMaybe { entry -> p(entry).map { entry.key to it } }.toMap() +inline fun <K, A, B> Map<K, A>.mapMaybeValues(transform: (Map.Entry<K, A>) -> Maybe<B>): Map<K, B> = + buildMap { + for (entry in this@mapMaybeValues) { + val result = transform(entry) + if (result is Just) { + put(entry.key, result.value) + } + } + } /** Returns a map with all non-present values filtered out. */ fun <K, A> Map<K, Maybe<A>>.filterJustValues(): Map<K, A> = diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/util/These.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/util/These.kt index aa95e0d2dc1b..092dca4d2f1d 100644 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/util/These.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/util/These.kt @@ -16,8 +16,10 @@ package com.android.systemui.kairos.util +import com.android.systemui.kairos.util.Maybe.Just + /** Contains at least one of two potential values. */ -sealed class These<A, B> { +sealed class These<out A, out B> { /** Contains a single potential value. */ class This<A, B> internal constructor(val thiz: A) : These<A, B>() @@ -29,10 +31,10 @@ sealed class These<A, B> { companion object { /** Constructs a [These] containing only [thiz]. */ - fun <A, B> thiz(thiz: A): These<A, B> = This(thiz) + fun <A> thiz(thiz: A): These<A, Nothing> = This(thiz) /** Constructs a [These] containing only [that]. */ - fun <A, B> that(that: B): These<A, B> = That(that) + fun <B> that(that: B): These<Nothing, B> = That(that) /** Constructs a [These] containing both [thiz] and [that]. */ fun <A, B> both(thiz: A, that: B): These<A, B> = Both(thiz, that) @@ -54,7 +56,7 @@ inline fun <A> These<A, A>.merge(f: (A, A) -> A): A = fun <A> These<A, *>.maybeThis(): Maybe<A> = when (this) { is These.Both -> just(thiz) - is These.That -> None + is These.That -> none is These.This -> just(thiz) } @@ -74,7 +76,7 @@ fun <A> These<*, A>.maybeThat(): Maybe<A> = when (this) { is These.Both -> just(that) is These.That -> just(that) - is These.This -> None + is These.This -> none } /** @@ -92,7 +94,7 @@ fun <A : Any> These<*, A>.thatOrNull(): A? = fun <A, B> These<A, B>.maybeBoth(): Maybe<Pair<A, B>> = when (this) { is These.Both -> just(thiz to that) - else -> None + else -> none } /** Returns a [These] containing [thiz] and/or [that] if they are present. */ diff --git a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/util/WithPrev.kt b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/util/WithPrev.kt index 5cfaa3ea2801..1bb97acc165d 100644 --- a/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/util/WithPrev.kt +++ b/packages/SystemUI/utils/kairos/src/com/android/systemui/kairos/util/WithPrev.kt @@ -16,5 +16,5 @@ package com.android.systemui.kairos.util -/** Holds a [newValue] emitted from a `TFlow`, along with the [previousValue] emitted value. */ +/** Holds a [newValue] emitted from a `Events`, along with the [previousValue] emitted value. */ data class WithPrev<out S, out T : S>(val previousValue: S, val newValue: T) diff --git a/packages/SystemUI/utils/kairos/test/com/android/systemui/kairos/KairosTests.kt b/packages/SystemUI/utils/kairos/test/com/android/systemui/kairos/KairosTests.kt index 688adae8fcae..150b462df655 100644 --- a/packages/SystemUI/utils/kairos/test/com/android/systemui/kairos/KairosTests.kt +++ b/packages/SystemUI/utils/kairos/test/com/android/systemui/kairos/KairosTests.kt @@ -1,28 +1,10 @@ -/* - * 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. - */ - -@file:OptIn(ExperimentalCoroutinesApi::class, ExperimentalFrpApi::class) - package com.android.systemui.kairos import com.android.systemui.kairos.util.Either -import com.android.systemui.kairos.util.Left +import com.android.systemui.kairos.util.Either.Left +import com.android.systemui.kairos.util.Either.Right import com.android.systemui.kairos.util.Maybe -import com.android.systemui.kairos.util.None -import com.android.systemui.kairos.util.Right +import com.android.systemui.kairos.util.Maybe.None import com.android.systemui.kairos.util.just import com.android.systemui.kairos.util.map import com.android.systemui.kairos.util.maybe @@ -53,13 +35,15 @@ import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Assert.assertNull import org.junit.Assert.assertTrue +import org.junit.Assert.fail import org.junit.Test +@OptIn(ExperimentalCoroutinesApi::class) class KairosTests { @Test fun basic() = runFrpTest { network -> - val emitter = network.mutableTFlow<Int>() + val emitter = network.mutableEvents<Int>() var result: Int? = null activateSpec(network) { emitter.observe { result = it } } runCurrent() @@ -70,8 +54,8 @@ class KairosTests { } @Test - fun basicTFlow() = runFrpTest { network -> - val emitter = network.mutableTFlow<Int>() + fun basicEvents() = runFrpTest { network -> + val emitter = network.mutableEvents<Int>() println("starting network") val result = activateSpecWithResult(network) { emitter.nextDeferred() } runCurrent() @@ -84,9 +68,9 @@ class KairosTests { } @Test - fun basicTState() = runFrpTest { network -> - val emitter = network.mutableTFlow<Int>() - val result = activateSpecWithResult(network) { emitter.hold(0).stateChanges.nextDeferred() } + fun basicState() = runFrpTest { network -> + val emitter = network.mutableEvents<Int>() + val result = activateSpecWithResult(network) { emitter.holdState(0).changes.nextDeferred() } runCurrent() emitter.emit(3) @@ -110,7 +94,7 @@ class KairosTests { fun basicTransactional() = runFrpTest { network -> var value: Int? = null var bSource = 1 - val emitter = network.mutableTFlow<Unit>() + val emitter = network.mutableEvents<Unit>() // Sampling this transactional will increment the source count. val transactional = transactionally { bSource++ } measureTime { @@ -149,24 +133,26 @@ class KairosTests { @Test fun diamondGraph() = runFrpTest { network -> - val flow = network.mutableTFlow<Int>() - val outFlow = + val flow = network.mutableEvents<Int>() + val ouevents = activateSpecWithResult(network) { - // map TFlow like we map Flow + // map Events like we map Flow val left = flow.map { "left" to it }.onEach { println("left: $it") } val right = flow.map { "right" to it }.onEach { println("right: $it") } - // convert TFlows to TStates so that they can be combined + // convert Eventss to States so that they can be combined val combined = - left.hold("left" to 0).combineWith(right.hold("right" to 0)) { l, r -> l to r } - combined.stateChanges // get TState changes + left.holdState("left" to 0).combineWith(right.holdState("right" to 0)) { l, r -> + l to r + } + combined.changes // get State changes .onEach { println("merged: $it") } .toSharedFlow() // convert back to Flow } runCurrent() val results = mutableListOf<Pair<Pair<String, Int>, Pair<String, Int>>>() - backgroundScope.launch { outFlow.toCollection(results) } + backgroundScope.launch { ouevents.toCollection(results) } runCurrent() flow.emit(1) @@ -185,19 +171,19 @@ class KairosTests { fun staticNetwork() = runFrpTest { network -> var finalSum: Int? = null - val intEmitter = network.mutableTFlow<Int>() - val sampleEmitter = network.mutableTFlow<Unit>() + val intEmitter = network.mutableEvents<Int>() + val sampleEmitter = network.mutableEvents<Unit>() activateSpecWithResult(network) { val updates = intEmitter.map { a -> { b: Int -> a + b } } val sumD = - TStateLoop<Int>().apply { + StateLoop<Int>().apply { loopback = updates .sample(this) { f, sum -> f(sum) } .onEach { println("sum update: $it") } - .hold(0) + .holdState(0) } sampleEmitter .onEach { println("sampleEmitter emitted") } @@ -227,10 +213,10 @@ class KairosTests { var wasSold = false var currentAmt: Int? = null - val coin = network.mutableTFlow<Unit>() + val coin = network.mutableEvents<Unit>() val price = 50 - val frpSpec = frpSpec { - val eSold = TFlowLoop<Unit>() + val buildSpec = buildSpec { + val eSold = EventsLoop<Unit>() val eInsert = coin.map { @@ -250,10 +236,10 @@ class KairosTests { val eUpdate = eInsert.mergeWith(eReset) { f, g -> { a -> g(f(a)) } } - val dTotal = TStateLoop<Int>() - dTotal.loopback = eUpdate.sample(dTotal) { f, total -> f(total) }.hold(price) + val dTotal = StateLoop<Int>() + dTotal.loopback = eUpdate.sample(dTotal) { f, total -> f(total) }.holdState(price) - val eAmt = dTotal.stateChanges + val eAmt = dTotal.changes val bAmt = transactionally { dTotal.sample() } eSold.loopback = coin @@ -268,7 +254,7 @@ class KairosTests { eSold.nextDeferred() } - activateSpec(network) { frpSpec.applySpec() } + activateSpec(network) { buildSpec.applySpec() } runCurrent() @@ -312,8 +298,8 @@ class KairosTests { @Test fun promptCleanup() = runFrpTest { network -> - val emitter = network.mutableTFlow<Int>() - val stopper = network.mutableTFlow<Unit>() + val emitter = network.mutableEvents<Int>() + val stopper = network.mutableEvents<Unit>() var result: Int? = null @@ -331,19 +317,19 @@ class KairosTests { } @Test - fun switchTFlow() = runFrpTest { network -> + fun switchEvents() = runFrpTest { network -> var currentSum: Int? = null - val switchHandler = network.mutableTFlow<Pair<TFlow<Int>, String>>() - val aHandler = network.mutableTFlow<Int>() - val stopHandler = network.mutableTFlow<Unit>() - val bHandler = network.mutableTFlow<Int>() + val switchHandler = network.mutableEvents<Pair<Events<Int>, String>>() + val aHandler = network.mutableEvents<Int>() + val stopHandler = network.mutableEvents<Unit>() + val bHandler = network.mutableEvents<Int>() val sumFlow = activateSpecWithResult(network) { - val switchE = TFlowLoop<TFlow<Int>>() + val switchE = EventsLoop<Events<Int>>() switchE.loopback = - switchHandler.mapStateful { (intFlow, name) -> + switchHandler.mapStateful { (inevents, name) -> println("[onEach] Switching to: $name") val nextSwitch = switchE.skipNext().onEach { println("[onEach] switched-out") } @@ -351,11 +337,11 @@ class KairosTests { stopHandler .onEach { println("[onEach] stopped") } .mergeWith(nextSwitch) { _, b -> b } - intFlow.takeUntil(stopEvent) + inevents.takeUntil(stopEvent) } - val adderE: TFlow<(Int) -> Int> = - switchE.hold(emptyTFlow).switch().map { a -> + val adderE: Events<(Int) -> Int> = + switchE.holdState(emptyEvents).switchEvents().map { a -> println("[onEach] new number $a") ({ sum: Int -> println("$a+$sum=${a + sum}") @@ -363,13 +349,13 @@ class KairosTests { }) } - val sumD = TStateLoop<Int>() + val sumD = StateLoop<Int>() sumD.loopback = adderE .sample(sumD) { f, sum -> f(sum) } .onEach { println("[onEach] writing sum: $it") } - .hold(0) - val sumE = sumD.stateChanges + .holdState(0) + val sumE = sumD.changes sumE.toSharedFlow() } @@ -493,16 +479,16 @@ class KairosTests { @Test fun switchIndirect() = runFrpTest { network -> - val emitter = network.mutableTFlow<Unit>() + val emitter = network.mutableEvents<Unit>() activateSpec(network) { - emptyTFlow.map { emitter.map { 1 } }.flatten().map { "$it" }.observe() + emptyEvents.map { emitter.map { 1 } }.flatten().map { "$it" }.observe() } runCurrent() } @Test fun switchInWithResult() = runFrpTest { network -> - val emitter = network.mutableTFlow<Unit>() + val emitter = network.mutableEvents<Unit>() val out = activateSpecWithResult(network) { emitter.map { emitter.map { 1 } }.flatten().toSharedFlow() @@ -518,11 +504,11 @@ class KairosTests { fun switchInCompleted() = runFrpTest { network -> val outputs = mutableListOf<Int>() - val switchAH = network.mutableTFlow<Unit>() - val intAH = network.mutableTFlow<Int>() - val stopEmitter = network.mutableTFlow<Unit>() + val switchAH = network.mutableEvents<Unit>() + val intAH = network.mutableEvents<Int>() + val stopEmitter = network.mutableEvents<Unit>() - val top = frpSpec { + val top = buildSpec { val intS = intAH.takeUntil(stopEmitter) val switched = switchAH.map { intS }.flatten() switched.toSharedFlow() @@ -554,13 +540,13 @@ class KairosTests { } @Test - fun switchTFlow_outerCompletesFirst() = runFrpTest { network -> + fun switchEvents_outerCompletesFirst() = runFrpTest { network -> var stepResult: Int? = null - val switchAH = network.mutableTFlow<Unit>() - val switchStopEmitter = network.mutableTFlow<Unit>() - val intStopEmitter = network.mutableTFlow<Unit>() - val intAH = network.mutableTFlow<Int>() + val switchAH = network.mutableEvents<Unit>() + val switchStopEmitter = network.mutableEvents<Unit>() + val intStopEmitter = network.mutableEvents<Unit>() + val intAH = network.mutableEvents<Int>() val flow = activateSpecWithResult(network) { val intS = intAH.takeUntil(intStopEmitter) @@ -608,8 +594,8 @@ class KairosTests { } @Test - fun mapTFlow() = runFrpTest { network -> - val emitter = network.mutableTFlow<Int>() + fun mapEvents() = runFrpTest { network -> + val emitter = network.mutableEvents<Int>() var stepResult: Int? = null val flow = @@ -643,7 +629,7 @@ class KairosTests { var pullValue = 0 val a = transactionally { pullValue } val b = transactionally { a.sample() * 2 } - val emitter = network.mutableTFlow<Unit>() + val emitter = network.mutableEvents<Unit>() val flow = activateSpecWithResult(network) { val sampleB = emitter.sample(b) { _, b -> b } @@ -667,14 +653,14 @@ class KairosTests { } @Test - fun mapTState() = runFrpTest { network -> - val emitter = network.mutableTFlow<Int>() + fun mapState() = runFrpTest { network -> + val emitter = network.mutableEvents<Int>() var stepResult: Int? = null val flow = activateSpecWithResult(network) { - val state = emitter.hold(0).map { it + 2 } + val state = emitter.holdState(0).map { it + 2 } val stateCurrent = transactionally { state.sample() } - val stateChanges = state.stateChanges + val stateChanges = state.changes val sampleState = emitter.sample(stateCurrent) { _, b -> b } val merge = stateChanges.mergeWith(sampleState) { a, b -> a + b } merge.toSharedFlow() @@ -695,14 +681,14 @@ class KairosTests { @Test fun partitionEither() = runFrpTest { network -> - val emitter = network.mutableTFlow<Either<Int, Int>>() + val emitter = network.mutableEvents<Either<Int, Int>>() val result = activateSpecWithResult(network) { val (l, r) = emitter.partitionEither() val pDiamond = l.map { it * 2 } .mergeWith(r.map { it * -1 }) { _, _ -> error("unexpected coincidence") } - pDiamond.hold(null).toStateFlow() + pDiamond.holdState(null).toStateFlow() } runCurrent() @@ -718,15 +704,16 @@ class KairosTests { } @Test - fun accumTState() = runFrpTest { network -> - val emitter = network.mutableTFlow<Int>() - val sampler = network.mutableTFlow<Unit>() + fun accumState() = runFrpTest { network -> + val emitter = network.mutableEvents<Int>() + val sampler = network.mutableEvents<Unit>() var stepResult: Int? = null val flow = activateSpecWithResult(network) { - val sumState = emitter.map { a -> { b: Int -> a + b } }.fold(0) { f, a -> f(a) } + val sumState = + emitter.map { a -> { b: Int -> a + b } }.foldState(0) { f, a -> f(a) } - sumState.stateChanges + sumState.changes .mergeWith(sampler.sample(sumState) { _, sum -> sum }) { _, _ -> error("Unexpected coincidence") } @@ -750,11 +737,11 @@ class KairosTests { } @Test - fun mergeTFlows() = runFrpTest { network -> - val first = network.mutableTFlow<Int>() - val stopFirst = network.mutableTFlow<Unit>() - val second = network.mutableTFlow<Int>() - val stopSecond = network.mutableTFlow<Unit>() + fun mergeEventss() = runFrpTest { network -> + val first = network.mutableEvents<Int>() + val stopFirst = network.mutableEvents<Unit>() + val second = network.mutableEvents<Int>() + val stopSecond = network.mutableEvents<Unit>() var stepResult: Int? = null val flow: SharedFlow<Int> @@ -831,19 +818,19 @@ class KairosTests { secondEmitDuration: ${secondEmitDuration.toString(DurationUnit.MILLISECONDS, 2)} stopFirstDuration: ${stopFirstDuration.toString(DurationUnit.MILLISECONDS, 2)} testDeadEmitFirstDuration: ${ - testDeadEmitFirstDuration.toString( - DurationUnit.MILLISECONDS, - 2, - ) - } + testDeadEmitFirstDuration.toString( + DurationUnit.MILLISECONDS, + 2, + ) + } secondEmitDuration2: ${secondEmitDuration2.toString(DurationUnit.MILLISECONDS, 2)} stopSecondDuration: ${stopSecondDuration.toString(DurationUnit.MILLISECONDS, 2)} testDeadEmitSecondDuration: ${ - testDeadEmitSecondDuration.toString( - DurationUnit.MILLISECONDS, - 2, - ) - } + testDeadEmitSecondDuration.toString( + DurationUnit.MILLISECONDS, + 2, + ) + } """ .trimIndent() ) @@ -851,10 +838,10 @@ class KairosTests { @Test fun sampleCancel() = runFrpTest { network -> - val updater = network.mutableTFlow<Int>() - val stopUpdater = network.mutableTFlow<Unit>() - val sampler = network.mutableTFlow<Unit>() - val stopSampler = network.mutableTFlow<Unit>() + val updater = network.mutableEvents<Int>() + val stopUpdater = network.mutableEvents<Unit>() + val sampler = network.mutableEvents<Unit>() + val stopSampler = network.mutableEvents<Unit>() var stepResult: Int? = null val flow = activateSpecWithResult(network) { @@ -862,7 +849,7 @@ class KairosTests { val samplerS = sampler.takeUntil(stopSamplerFirst) val stopUpdaterFirst = stopUpdater val updaterS = updater.takeUntil(stopUpdaterFirst) - val sampledS = samplerS.sample(updaterS.hold(0)) { _, b -> b } + val sampledS = samplerS.sample(updaterS.holdState(0)) { _, b -> b } sampledS.toSharedFlow() } @@ -893,35 +880,35 @@ class KairosTests { @Test fun combineStates_differentUpstreams() = runFrpTest { network -> - val a = network.mutableTFlow<Int>() - val b = network.mutableTFlow<Int>() + val a = network.mutableEvents<Int>() + val b = network.mutableEvents<Int>() var observed: Pair<Int, Int>? = null - val tState = + val state = activateSpecWithResult(network) { - val state = combine(a.hold(0), b.hold(0)) { a, b -> Pair(a, b) } - state.stateChanges.observe { observed = it } + val state = combine(a.holdState(0), b.holdState(0)) { a, b -> Pair(a, b) } + state.changes.observe { observed = it } state } - assertEquals(0 to 0, network.transact { tState.sample() }) + assertEquals(0 to 0, network.transact { state.sample() }) assertEquals(null, observed) a.emit(5) assertEquals(5 to 0, observed) - assertEquals(5 to 0, network.transact { tState.sample() }) + assertEquals(5 to 0, network.transact { state.sample() }) b.emit(3) assertEquals(5 to 3, observed) - assertEquals(5 to 3, network.transact { tState.sample() }) + assertEquals(5 to 3, network.transact { state.sample() }) } @Test fun sampleCombinedStates() = runFrpTest { network -> - val updater = network.mutableTFlow<Int>() - val emitter = network.mutableTFlow<Unit>() + val updater = network.mutableEvents<Int>() + val emitter = network.mutableEvents<Unit>() val result = activateSpecWithResult(network) { - val bA = updater.map { it * 2 }.hold(0) - val bB = updater.hold(0) - val combineD: TState<Pair<Int, Int>> = bA.combineWith(bB) { a, b -> a to b } + val bA = updater.map { it * 2 }.holdState(0) + val bB = updater.holdState(0) + val combineD: State<Pair<Int, Int>> = bA.combineWith(bB) { a, b -> a to b } val sampleS = emitter.sample(combineD) { _, b -> b } sampleS.nextDeferred() } @@ -942,13 +929,13 @@ class KairosTests { @Test fun switchMapPromptly() = runFrpTest { network -> - val emitter = network.mutableTFlow<Unit>() + val emitter = network.mutableEvents<Unit>() val result = activateSpecWithResult(network) { emitter .map { emitter.map { 1 }.map { it + 1 }.map { it * 2 } } - .hold(emptyTFlow) - .switchPromptly() + .holdState(emptyEvents) + .switchEventsPromptly() .nextDeferred() } runCurrent() @@ -962,8 +949,8 @@ class KairosTests { @Test fun switchDeeper() = runFrpTest { network -> - val emitter = network.mutableTFlow<Unit>() - val e2 = network.mutableTFlow<Unit>() + val emitter = network.mutableEvents<Unit>() + val e2 = network.mutableEvents<Unit>() val result = activateSpecWithResult(network) { val tres = @@ -988,14 +975,14 @@ class KairosTests { @Test fun recursionBasic() = runFrpTest { network -> - val add1 = network.mutableTFlow<Unit>() - val sub1 = network.mutableTFlow<Unit>() + val add1 = network.mutableEvents<Unit>() + val sub1 = network.mutableEvents<Unit>() val stepResult: StateFlow<Int> = activateSpecWithResult(network) { - val dSum = TStateLoop<Int>() + val dSum = StateLoop<Int>() val sAdd1 = add1.sample(dSum) { _, sum -> sum + 1 } val sMinus1 = sub1.sample(dSum) { _, sum -> sum - 1 } - dSum.loopback = sAdd1.mergeWith(sMinus1) { a, _ -> a }.hold(0) + dSum.loopback = sAdd1.mergeWith(sMinus1) { a, _ -> a }.holdState(0) dSum.toStateFlow() } runCurrent() @@ -1017,16 +1004,17 @@ class KairosTests { } @Test - fun recursiveTState() = runFrpTest { network -> - val e = network.mutableTFlow<Unit>() + fun recursiveState() = runFrpTest { network -> + val e = network.mutableEvents<Unit>() var changes = 0 val state = activateSpecWithResult(network) { - val s = TFlowLoop<Unit>() - val deferred = s.map { tStateOf(null) } - val e3 = e.map { tStateOf(Unit) } - val flattened = e3.mergeWith(deferred) { a, _ -> a }.hold(tStateOf(null)).flatten() - s.loopback = emptyTFlow + val s = EventsLoop<Unit>() + val deferred = s.map { stateOf(null) } + val e3 = e.map { stateOf(Unit) } + val flattened = + e3.mergeWith(deferred) { a, _ -> a }.holdState(stateOf(null)).flatten() + s.loopback = emptyEvents flattened.toStateFlow() } @@ -1036,7 +1024,7 @@ class KairosTests { @Test fun fanOut() = runFrpTest { network -> - val e = network.mutableTFlow<Map<String, Int>>() + val e = network.mutableEvents<Map<String, Int>>() val (fooFlow, barFlow) = activateSpecWithResult(network) { val selector = e.groupByKey() @@ -1057,16 +1045,30 @@ class KairosTests { } @Test + fun propagateError() { + try { + runFrpTest { network -> + runCurrent() + try { + network.transact<Unit> { error("message") } + fail("caller did not throw exception") + } catch (_: IllegalStateException) {} + } + fail("scheduler did not throw exception") + } catch (_: IllegalStateException) {} + } + + @Test fun fanOutLateSubscribe() = runFrpTest { network -> - val e = network.mutableTFlow<Map<String, Int>>() + val e = network.mutableEvents<Map<String, Int>>() val barFlow = activateSpecWithResult(network) { val selector = e.groupByKey() selector .eventsForKey("foo") .map { selector.eventsForKey("bar") } - .hold(emptyTFlow) - .switchPromptly() + .holdState(emptyEvents) + .switchEventsPromptly() .toSharedFlow() } val stateFlow = barFlow.stateIn(backgroundScope, SharingStarted.Eagerly, null) @@ -1081,9 +1083,9 @@ class KairosTests { } @Test - fun inputFlowCompleted() = runFrpTest { network -> + fun inputEventsCompleted() = runFrpTest { network -> val results = mutableListOf<Int>() - val e = network.mutableTFlow<Int>() + val e = network.mutableEvents<Int>() activateSpec(network) { e.nextOnly().observe { results.add(it) } } runCurrent() @@ -1099,49 +1101,59 @@ class KairosTests { @Test fun fanOutThenMergeIncrementally() = runFrpTest { network -> - // A tflow of group updates, where a group is a tflow of child updates, where a child is a + // A events of group updates, where a group is a events of child updates, where a child is a // stateflow - val e = network.mutableTFlow<Map<Int, Maybe<TFlow<Map<Int, Maybe<StateFlow<String>>>>>>>() + val e = network.mutableEvents<Map<Int, Maybe<Events<Map<Int, Maybe<StateFlow<String>>>>>>>() println("fanOutMergeInc START") val state = activateSpecWithResult(network) { - // Convert nested Flows to nested TFlow/TState - val emitter: TFlow<Map<Int, Maybe<TFlow<Map<Int, Maybe<TState<String>>>>>>> = + // Convert nested Flows to nested Events/State + val emitter: Events<Map<Int, Maybe<Events<Map<Int, Maybe<State<String>>>>>>> = e.mapBuild { m -> m.mapValues { (_, mFlow) -> mFlow.map { it.mapBuild { m2 -> + println("m2: $m2") m2.mapValues { (_, mState) -> - mState.map { stateFlow -> stateFlow.toTState() } + mState.map { stateFlow -> stateFlow.toState() } } } } } } - // Accumulate all of our updates into a single TState - val accState: TState<Map<Int, Map<Int, String>>> = + // Accumulate all of our updates into a single State + val accState: State<Map<Int, Map<Int, String>>> = emitter .mapStateful { - changeMap: Map<Int, Maybe<TFlow<Map<Int, Maybe<TState<String>>>>>> -> + changeMap: Map<Int, Maybe<Events<Map<Int, Maybe<State<String>>>>>> -> changeMap.mapValues { (groupId, mGroupChanges) -> mGroupChanges.map { - groupChanges: TFlow<Map<Int, Maybe<TState<String>>>> -> + groupChanges: Events<Map<Int, Maybe<State<String>>>> -> // New group val childChangeById = groupChanges.groupByKey() - val map: TFlow<Map<Int, Maybe<TFlow<Maybe<TState<String>>>>>> = + val map: Events<Map<Int, Maybe<Events<Maybe<State<String>>>>>> = groupChanges.mapStateful { - gChangeMap: Map<Int, Maybe<TState<String>>> -> + gChangeMap: Map<Int, Maybe<State<String>>> -> + println("gChangeMap: $gChangeMap") gChangeMap.mapValues { (childId, mChild) -> - mChild.map { child: TState<String> -> + mChild.map { child: State<String> -> println("new child $childId in the house") // New child val eRemoved = childChangeById .eventsForKey(childId) .filter { it === None } - .nextOnly() + .onEach { + println( + "removing? (groupId=$groupId, childId=$childId)" + ) + } + .nextOnly( + name = + "eRemoved(groupId=$groupId, childId=$childId)" + ) - val addChild: TFlow<Maybe<TState<String>>> = + val addChild: Events<Maybe<State<String>>> = now.map { mChild } .onEach { println( @@ -1149,7 +1161,7 @@ class KairosTests { ) } - val removeChild: TFlow<Maybe<TState<String>>> = + val removeChild: Events<Maybe<State<String>>> = eRemoved .onEach { println( @@ -1158,23 +1170,28 @@ class KairosTests { } .map { none() } - addChild.mergeWith(removeChild) { _, _ -> + addChild.mergeWith( + removeChild, + name = + "childUpdatesMerged(groupId=$groupId, childId=$childId)", + ) { _, _ -> error("unexpected coincidence") } } } } - val mergeIncrementally: TFlow<Map<Int, Maybe<TState<String>>>> = + val mergeIncrementally: Events<Map<Int, Maybe<State<String>>>> = map.onEach { println("merge patch: $it") } - .mergeIncrementallyPromptly() + .mergeIncrementallyPromptly(name = "mergeIncrementally") mergeIncrementally - .onEach { println("patch: $it") } - .foldMapIncrementally() + .onEach { println("foldmap patch: $it") } + .foldStateMapIncrementally() .flatMap { it.combine() } } } } - .foldMapIncrementally() + .onEach { println("fold patch: $it") } + .foldStateMapIncrementally() .flatMap { it.combine() } accState.toStateFlow() @@ -1183,7 +1200,7 @@ class KairosTests { assertEquals(emptyMap(), state.value) - val emitter2 = network.mutableTFlow<Map<Int, Maybe<StateFlow<String>>>>() + val emitter2 = network.mutableEvents<Map<Int, Maybe<StateFlow<String>>>>() println() println("init outer 0") e.emit(mapOf(0 to just(emitter2.onEach { println("emitter2 emit: $it") }))) @@ -1218,6 +1235,10 @@ class KairosTests { assertEquals(mapOf(0 to mapOf(10 to "(2, 10)")), state.value) + // LogEnabled = true + + println("batch update") + // batch update emitter2.emit( mapOf( @@ -1233,13 +1254,13 @@ class KairosTests { @Test fun applyLatestNetworkChanges() = runFrpTest { network -> - val newCount = network.mutableTFlow<FrpSpec<Flow<Int>>>() + val newCount = network.mutableEvents<BuildSpec<Flow<Int>>>() val flowOfFlows: Flow<Flow<Int>> = activateSpecWithResult(network) { newCount.applyLatestSpec().toSharedFlow() } runCurrent() - val incCount = network.mutableTFlow<Unit>() - fun newFlow(): FrpSpec<SharedFlow<Int>> = frpSpec { + val incCount = network.mutableEvents<Unit>() + fun newFlow(): BuildSpec<SharedFlow<Int>> = buildSpec { launchEffect { try { println("new flow!") @@ -1248,16 +1269,16 @@ class KairosTests { println("cancelling old flow") } } - lateinit var count: TState<Int> + lateinit var count: State<Int> count = incCount .onEach { println("incrementing ${count.sample()}") } - .fold(0) { _, c -> c + 1 } - count.stateChanges.toSharedFlow() + .foldState(0) { _, c -> c + 1 } + count.changes.toSharedFlow() } var outerCount = 0 - val lastFlows: StateFlow<Pair<StateFlow<Int?>, StateFlow<Int?>>> = + val laseventss: StateFlow<Pair<StateFlow<Int?>, StateFlow<Int?>>> = flowOfFlows .map { it.stateIn(backgroundScope, SharingStarted.Eagerly, null) } .pairwise(MutableStateFlow(null)) @@ -1275,18 +1296,18 @@ class KairosTests { assertEquals(1, outerCount) // assertEquals(1, incCount.subscriptionCount) - assertNull(lastFlows.value.second.value) + assertNull(laseventss.value.second.value) incCount.emit(Unit) runCurrent() println("checking") - assertEquals(1, lastFlows.value.second.value) + assertEquals(1, laseventss.value.second.value) incCount.emit(Unit) runCurrent() - assertEquals(2, lastFlows.value.second.value) + assertEquals(2, laseventss.value.second.value) newCount.emit(newFlow()) runCurrent() @@ -1294,17 +1315,17 @@ class KairosTests { runCurrent() // verify old flow is not getting updates - assertEquals(2, lastFlows.value.first.value) + assertEquals(2, laseventss.value.first.value) // but the new one is - assertEquals(1, lastFlows.value.second.value) + assertEquals(1, laseventss.value.second.value) } @Test fun buildScope_stateAccumulation() = runFrpTest { network -> - val input = network.mutableTFlow<Unit>() + val input = network.mutableEvents<Unit>() var observedCount: Int? = null activateSpec(network) { - val (c, j) = asyncScope { input.fold(0) { _, x -> x + 1 } } + val (c, j) = asyncScope { input.foldState(0) { _, x -> x + 1 } } deferredBuildScopeAction { c.get().observe { observedCount = it } } } runCurrent() @@ -1321,7 +1342,7 @@ class KairosTests { @Test fun effect() = runFrpTest { network -> - val input = network.mutableTFlow<Unit>() + val input = network.mutableEvents<Unit>() var effectRunning = false var count = 0 activateSpec(network) { @@ -1333,7 +1354,7 @@ class KairosTests { effectRunning = false } } - merge(emptyTFlow, input.nextOnly()).observe { + merge(emptyEvents, input.nextOnly()).observe { count++ j.cancel() } @@ -1355,23 +1376,93 @@ class KairosTests { assertEquals(1, count) } + @Test + fun observeEffect_disposeHandle() = runFrpTest { network -> + val input = network.mutableEvents<Unit>() + val stopper = network.mutableEvents<Unit>() + var runningCount = 0 + val specJob = + activateSpec(network) { + val handle = + input.observe { + effectCoroutineScope.launch { + runningCount++ + awaitClose { runningCount-- } + } + } + stopper.nextOnly().observe { handle.dispose() } + } + runCurrent() + assertEquals(0, runningCount) + + input.emit(Unit) + assertEquals(1, runningCount) + + input.emit(Unit) + assertEquals(2, runningCount) + + stopper.emit(Unit) + assertEquals(2, runningCount) + + input.emit(Unit) + assertEquals(2, runningCount) + + specJob.cancel() + runCurrent() + assertEquals(0, runningCount) + } + + @Test + fun observeEffect_takeUntil() = runFrpTest { network -> + val input = network.mutableEvents<Unit>() + val stopper = network.mutableEvents<Unit>() + var runningCount = 0 + val specJob = + activateSpec(network) { + input.takeUntil(stopper).observe { + effectCoroutineScope.launch { + runningCount++ + awaitClose { runningCount-- } + } + } + } + runCurrent() + assertEquals(0, runningCount) + + input.emit(Unit) + assertEquals(1, runningCount) + + input.emit(Unit) + assertEquals(2, runningCount) + + stopper.emit(Unit) + assertEquals(2, runningCount) + + input.emit(Unit) + assertEquals(2, runningCount) + + specJob.cancel() + runCurrent() + assertEquals(0, runningCount) + } + private fun runFrpTest( timeout: Duration = 3.seconds, - block: suspend TestScope.(FrpNetwork) -> Unit, + block: suspend TestScope.(KairosNetwork) -> Unit, ) { runTest(timeout = timeout) { - val network = backgroundScope.newFrpNetwork() + val network = backgroundScope.launchKairosNetwork() runCurrent() block(network) } } - private fun TestScope.activateSpec(network: FrpNetwork, spec: FrpSpec<*>) = + private fun TestScope.activateSpec(network: KairosNetwork, spec: BuildSpec<*>) = backgroundScope.launch { network.activateSpec(spec) } private suspend fun <R> TestScope.activateSpecWithResult( - network: FrpNetwork, - spec: FrpSpec<R>, + network: KairosNetwork, + spec: BuildSpec<R>, ): R = CompletableDeferred<R>() .apply { activateSpec(network) { complete(spec.applySpec()) } } diff --git a/services/accessibility/java/com/android/server/accessibility/AutoclickController.java b/services/accessibility/java/com/android/server/accessibility/AutoclickController.java index 50c754008234..a69ececd5373 100644 --- a/services/accessibility/java/com/android/server/accessibility/AutoclickController.java +++ b/services/accessibility/java/com/android/server/accessibility/AutoclickController.java @@ -16,11 +16,14 @@ package com.android.server.accessibility; +import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; + import android.accessibilityservice.AccessibilityTrace; import android.annotation.NonNull; import android.content.ContentResolver; import android.content.Context; import android.database.ContentObserver; +import android.graphics.PixelFormat; import android.net.Uri; import android.os.Handler; import android.os.SystemClock; @@ -30,6 +33,7 @@ import android.view.KeyEvent; import android.view.MotionEvent; import android.view.MotionEvent.PointerCoords; import android.view.MotionEvent.PointerProperties; +import android.view.WindowManager; import android.view.accessibility.AccessibilityManager; /** @@ -64,6 +68,9 @@ public class AutoclickController extends BaseEventStreamTransformation { // Lazily created on the first mouse motion event. private ClickScheduler mClickScheduler; private ClickDelayObserver mClickDelayObserver; + private AutoclickIndicatorScheduler mAutoclickIndicatorScheduler; + private AutoclickIndicatorView mAutoclickIndicatorView; + private WindowManager mWindowManager; public AutoclickController(Context context, int userId, AccessibilityTraceManager trace) { mTrace = trace; @@ -84,6 +91,10 @@ public class AutoclickController extends BaseEventStreamTransformation { new ClickScheduler(handler, AccessibilityManager.AUTOCLICK_DELAY_DEFAULT); mClickDelayObserver = new ClickDelayObserver(mUserId, handler); mClickDelayObserver.start(mContext.getContentResolver(), mClickScheduler); + + if (Flags.enableAutoclickIndicator()) { + initiateAutoclickIndicator(handler); + } } handleMouseMotion(event, policyFlags); @@ -94,6 +105,27 @@ public class AutoclickController extends BaseEventStreamTransformation { super.onMotionEvent(event, rawEvent, policyFlags); } + private void initiateAutoclickIndicator(Handler handler) { + mAutoclickIndicatorScheduler = new AutoclickIndicatorScheduler(handler); + mAutoclickIndicatorView = new AutoclickIndicatorView(mContext); + + final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(); + layoutParams.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY; + layoutParams.flags = + WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE + | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE + | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; + layoutParams.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS; + layoutParams.setFitInsetsTypes(0); + layoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; + layoutParams.format = PixelFormat.TRANSLUCENT; + layoutParams.setTitle(AutoclickIndicatorView.class.getSimpleName()); + layoutParams.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL; + + mWindowManager = mContext.getSystemService(WindowManager.class); + mWindowManager.addView(mAutoclickIndicatorView, layoutParams); + } + @Override public void onKeyEvent(KeyEvent event, int policyFlags) { if (mTrace.isA11yTracingEnabledForTypes(AccessibilityTrace.FLAGS_INPUT_FILTER)) { @@ -130,6 +162,12 @@ public class AutoclickController extends BaseEventStreamTransformation { mClickScheduler.cancel(); mClickScheduler = null; } + + if (mAutoclickIndicatorScheduler != null) { + mAutoclickIndicatorScheduler.cancel(); + mAutoclickIndicatorScheduler = null; + mWindowManager.removeView(mAutoclickIndicatorView); + } } private void handleMouseMotion(MotionEvent event, int policyFlags) { @@ -225,6 +263,62 @@ public class AutoclickController extends BaseEventStreamTransformation { } } + private final class AutoclickIndicatorScheduler implements Runnable { + private final Handler mHandler; + private long mScheduledShowIndicatorTime; + private boolean mIndicatorCallbackActive = false; + + public AutoclickIndicatorScheduler(Handler handler) { + mHandler = handler; + } + + @Override + public void run() { + long now = SystemClock.uptimeMillis(); + // Indicator was rescheduled after task was posted. Post new run task at updated time. + if (now < mScheduledShowIndicatorTime) { + mHandler.postDelayed(this, mScheduledShowIndicatorTime - now); + return; + } + + mAutoclickIndicatorView.redrawIndicator(); + mIndicatorCallbackActive = false; + } + + public void update() { + // TODO(b/383901288): update delay time once determined by UX. + long SHOW_INDICATOR_DELAY_TIME = 150; + long scheduledShowIndicatorTime = + SystemClock.uptimeMillis() + SHOW_INDICATOR_DELAY_TIME; + // If there already is a scheduled show indicator at time before the updated time, just + // update scheduled time. + if (mIndicatorCallbackActive + && scheduledShowIndicatorTime > mScheduledShowIndicatorTime) { + mScheduledShowIndicatorTime = scheduledShowIndicatorTime; + return; + } + + if (mIndicatorCallbackActive) { + mHandler.removeCallbacks(this); + } + + mIndicatorCallbackActive = true; + mScheduledShowIndicatorTime = scheduledShowIndicatorTime; + + mHandler.postDelayed(this, SHOW_INDICATOR_DELAY_TIME); + } + + public void cancel() { + if (!mIndicatorCallbackActive) { + return; + } + + mIndicatorCallbackActive = false; + mScheduledShowIndicatorTime = -1; + mHandler.removeCallbacks(this); + } + } + /** * Schedules and performs click event sequence that should be initiated when mouse pointer stops * moving. The click is first scheduled when a mouse movement is detected, and then further @@ -305,6 +399,13 @@ public class AutoclickController extends BaseEventStreamTransformation { if (moved) { rescheduleClick(mDelay); + + if (Flags.enableAutoclickIndicator()) { + final int pointerIndex = event.getActionIndex(); + mAutoclickIndicatorView.setCoordination( + event.getX(pointerIndex), event.getY(pointerIndex)); + mAutoclickIndicatorScheduler.update(); + } } } @@ -385,6 +486,10 @@ public class AutoclickController extends BaseEventStreamTransformation { mLastMotionEvent = null; } mScheduledClickTime = -1; + + if (Flags.enableAutoclickIndicator() && mAutoclickIndicatorView != null) { + mAutoclickIndicatorView.clearIndicator(); + } } /** diff --git a/services/accessibility/java/com/android/server/accessibility/AutoclickIndicatorView.java b/services/accessibility/java/com/android/server/accessibility/AutoclickIndicatorView.java new file mode 100644 index 000000000000..54c31e5bca79 --- /dev/null +++ b/services/accessibility/java/com/android/server/accessibility/AutoclickIndicatorView.java @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2025 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.server.accessibility; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.util.DisplayMetrics; +import android.view.View; + +// A visual indicator for the autoclick feature. +public class AutoclickIndicatorView extends View { + private static final String TAG = AutoclickIndicatorView.class.getSimpleName(); + + // TODO(b/383901288): allow users to customize the indicator area. + static final float RADIUS = 50; + + private final Paint mPaint; + + // x and y coordinates of the visual indicator. + private float mX; + private float mY; + + // Status of whether the visual indicator should display or not. + private boolean showIndicator = false; + + public AutoclickIndicatorView(Context context) { + super(context); + + mPaint = new Paint(); + // TODO(b/383901288): update styling once determined by UX. + mPaint.setARGB(255, 52, 103, 235); + mPaint.setStyle(Paint.Style.STROKE); + mPaint.setStrokeWidth(10); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + if (showIndicator) { + canvas.drawCircle(mX, mY, RADIUS, mPaint); + } + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + // Get the screen dimensions. + DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); + int screenWidth = displayMetrics.widthPixels; + int screenHeight = displayMetrics.heightPixels; + + setMeasuredDimension(screenWidth, screenHeight); + } + + public void setCoordination(float x, float y) { + mX = x; + mY = y; + } + + public void redrawIndicator() { + showIndicator = true; + invalidate(); + } + + public void clearIndicator() { + showIndicator = false; + invalidate(); + } +} diff --git a/services/autofill/bugfixes.aconfig b/services/autofill/bugfixes.aconfig index ec6c3b7ebf7a..68bb224ad166 100644 --- a/services/autofill/bugfixes.aconfig +++ b/services/autofill/bugfixes.aconfig @@ -64,6 +64,16 @@ flag { } flag { + name: "fix_get_autofill_component" + namespace: "autofill" + description: "Fix getAutofillComponent returning null, even when user has selected provider" + bug: "319503432" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { name: "test_flag" namespace: "autofill" description: "Test flag " diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java index cba8c66cd5e3..c68e54956c99 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java @@ -18,6 +18,7 @@ package com.android.server.autofill; import static android.Manifest.permission.MANAGE_AUTO_FILL; import static android.content.Context.AUTOFILL_MANAGER_SERVICE; +import static android.service.autofill.Flags.fixGetAutofillComponent; import static android.view.autofill.AutofillManager.MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS; import static android.view.autofill.AutofillManager.getSmartSuggestionModeToString; @@ -1920,8 +1921,12 @@ public final class AutofillManagerService try { synchronized (mLock) { - final AutofillManagerServiceImpl service = - peekServiceForUserWithLocalBinderIdentityLocked(userId); + final AutofillManagerServiceImpl service; + if (fixGetAutofillComponent()) { + service = getServiceForUserWithLocalBinderIdentityLocked(userId); + } else { + service = peekServiceForUserWithLocalBinderIdentityLocked(userId); + } if (service != null) { componentName = service.getServiceComponentName(); } else if (sVerbose) { diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java index c1c03ff9ec11..dce9760b3971 100644 --- a/services/core/java/com/android/server/GestureLauncherService.java +++ b/services/core/java/com/android/server/GestureLauncherService.java @@ -17,6 +17,7 @@ package com.android.server; import static android.service.quickaccesswallet.Flags.launchWalletOptionOnPowerDoubleTap; +import static android.service.quickaccesswallet.Flags.launchWalletViaSysuiCallbacks; import static com.android.hardware.input.Flags.overridePowerKeyBehaviorInFocusedWindow; import static com.android.internal.R.integer.config_defaultMinEmergencyGestureTapDurationMillis; @@ -759,7 +760,8 @@ public class GestureLauncherService extends SystemService { } else if (launchWallet) { Slog.i(TAG, "Power button double tap gesture detected, launching wallet. Interval=" + powerTapInterval + "ms"); - launchWallet = sendGestureTargetActivityPendingIntent(); + launchWallet = launchWalletViaSysuiCallbacks() ? + handleWalletGesture() : sendGestureTargetActivityPendingIntent(); } else if (launchEmergencyGesture) { Slog.i(TAG, "Emergency gesture detected, launching."); launchEmergencyGesture = handleEmergencyGesture(); @@ -879,6 +881,31 @@ public class GestureLauncherService extends SystemService { } } + @VisibleForTesting + boolean handleWalletGesture() { + Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, + "GestureLauncher:handleWalletGesture"); + try { + boolean userSetupComplete = isUserSetupComplete(); + if (!userSetupComplete) { + if (DBG) { + Slog.d(TAG, "userSetupComplete = false, ignoring wallet gesture."); + } + return false; + } + if (DBG) { + Slog.d(TAG, "userSetupComplete = true, performing wallet gesture."); + } + + StatusBarManagerInternal service = LocalServices.getService( + StatusBarManagerInternal.class); + service.onWalletLaunchGestureDetected(); + return true; + } finally { + Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); + } + } + /** * @return true if emergency gesture UI was launched, false otherwise. */ diff --git a/services/core/java/com/android/server/am/UidObserverController.java b/services/core/java/com/android/server/am/UidObserverController.java index 7eeec32cf24a..f58e3f85bb26 100644 --- a/services/core/java/com/android/server/am/UidObserverController.java +++ b/services/core/java/com/android/server/am/UidObserverController.java @@ -31,6 +31,7 @@ import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.os.Message; +import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.SystemClock; @@ -90,10 +91,12 @@ public class UidObserverController { + UUID.randomUUID().toString()); synchronized (mLock) { + final boolean canInteractAcrossUsers = ActivityManager.checkComponentPermission( + INTERACT_ACROSS_USERS_FULL, callingUid, Process.INVALID_UID, true) + == PackageManager.PERMISSION_GRANTED; mUidObservers.register(observer, new UidObserverRegistration(callingUid, callingPackage, which, cutpoint, - ActivityManager.checkUidPermission(INTERACT_ACROSS_USERS_FULL, callingUid) - == PackageManager.PERMISSION_GRANTED, uids, token)); + canInteractAcrossUsers, uids, token)); } return token; diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java index 805357e79565..88f5c81231b8 100644 --- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java +++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java @@ -57,6 +57,7 @@ import com.android.internal.display.BrightnessSynchronizer; import com.android.internal.os.BackgroundThread; import com.android.server.EventLogTags; import com.android.server.display.brightness.BrightnessEvent; +import com.android.server.display.brightness.clamper.BrightnessClamperController; import com.android.server.display.config.HysteresisLevels; import com.android.server.display.feature.DisplayManagerFlags; @@ -265,7 +266,7 @@ public class AutomaticBrightnessController { private final BrightnessRangeController mBrightnessRangeController; // Throttles (caps) maximum allowed brightness - private final BrightnessThrottler mBrightnessThrottler; + private final BrightnessClamperController mBrightnessClamperController; private boolean mIsBrightnessThrottled; // Context-sensitive brightness configurations require keeping track of the foreground app's @@ -299,7 +300,7 @@ public class AutomaticBrightnessController { HysteresisLevels ambientBrightnessThresholdsIdle, HysteresisLevels screenBrightnessThresholdsIdle, Context context, BrightnessRangeController brightnessModeController, - BrightnessThrottler brightnessThrottler, int ambientLightHorizonShort, + BrightnessClamperController clamperController, int ambientLightHorizonShort, int ambientLightHorizonLong, float userLux, float userNits, DisplayManagerFlags displayManagerFlags) { this(new Injector(), callbacks, looper, sensorManager, lightSensor, @@ -310,7 +311,7 @@ public class AutomaticBrightnessController { resetAmbientLuxAfterWarmUpConfig, ambientBrightnessThresholds, screenBrightnessThresholds, ambientBrightnessThresholdsIdle, screenBrightnessThresholdsIdle, context, brightnessModeController, - brightnessThrottler, ambientLightHorizonShort, ambientLightHorizonLong, userLux, + clamperController, ambientLightHorizonShort, ambientLightHorizonLong, userLux, userNits, displayManagerFlags ); } @@ -328,7 +329,7 @@ public class AutomaticBrightnessController { HysteresisLevels ambientBrightnessThresholdsIdle, HysteresisLevels screenBrightnessThresholdsIdle, Context context, BrightnessRangeController brightnessRangeController, - BrightnessThrottler brightnessThrottler, int ambientLightHorizonShort, + BrightnessClamperController clamperController, int ambientLightHorizonShort, int ambientLightHorizonLong, float userLux, float userNits, DisplayManagerFlags displayManagerFlags) { mInjector = injector; @@ -374,7 +375,7 @@ public class AutomaticBrightnessController { mForegroundAppCategory = ApplicationInfo.CATEGORY_UNDEFINED; mPendingForegroundAppCategory = ApplicationInfo.CATEGORY_UNDEFINED; mBrightnessRangeController = brightnessRangeController; - mBrightnessThrottler = brightnessThrottler; + mBrightnessClamperController = clamperController; mBrightnessMappingStrategyMap = brightnessMappingStrategyMap; mDisplayManagerFlags = displayManagerFlags; @@ -472,9 +473,10 @@ public class AutomaticBrightnessController { } changed |= setLightSensorEnabled(enable); - if (mIsBrightnessThrottled != mBrightnessThrottler.isThrottled()) { + boolean isBrightnessThrottled = mBrightnessClamperController.isThrottled(); + if (mIsBrightnessThrottled != isBrightnessThrottled) { // Maximum brightness has changed, so recalculate display brightness. - mIsBrightnessThrottled = mBrightnessThrottler.isThrottled(); + mIsBrightnessThrottled = isBrightnessThrottled; changed = true; } @@ -1038,10 +1040,9 @@ public class AutomaticBrightnessController { // Clamps values with float range [0.0-1.0] private float clampScreenBrightness(float value) { - final float minBrightness = Math.min(mBrightnessRangeController.getCurrentBrightnessMin(), - mBrightnessThrottler.getBrightnessCap()); + final float minBrightness = mBrightnessRangeController.getCurrentBrightnessMin(); final float maxBrightness = Math.min(mBrightnessRangeController.getCurrentBrightnessMax(), - mBrightnessThrottler.getBrightnessCap()); + mBrightnessClamperController.getMaxBrightness()); return MathUtils.constrain(value, minBrightness, maxBrightness); } diff --git a/services/core/java/com/android/server/display/BrightnessThrottler.java b/services/core/java/com/android/server/display/BrightnessThrottler.java deleted file mode 100644 index b56a23416693..000000000000 --- a/services/core/java/com/android/server/display/BrightnessThrottler.java +++ /dev/null @@ -1,476 +0,0 @@ -/* - * Copyright (C) 2022 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.server.display; - -import static com.android.server.display.DisplayDeviceConfig.DEFAULT_ID; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.Context; -import android.hardware.display.BrightnessInfo; -import android.os.Handler; -import android.os.HandlerExecutor; -import android.os.IThermalEventListener; -import android.os.IThermalService; -import android.os.PowerManager; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.os.Temperature; -import android.provider.DeviceConfig; -import android.provider.DeviceConfigInterface; -import android.util.Slog; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData; -import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData.ThrottlingLevel; -import com.android.server.display.config.SensorData; -import com.android.server.display.feature.DeviceConfigParameterProvider; -import com.android.server.display.utils.DebugUtils; -import com.android.server.display.utils.DeviceConfigParsingUtils; -import com.android.server.display.utils.SensorUtils; - -import java.io.PrintWriter; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Executor; -import java.util.function.BiFunction; -import java.util.function.Function; - -/** - * This class monitors various conditions, such as skin temperature throttling status, and limits - * the allowed brightness range accordingly. - * - * @deprecated will be replaced by - * {@link com.android.server.display.brightness.clamper.BrightnessThermalClamper} - */ -@Deprecated -class BrightnessThrottler { - private static final String TAG = "BrightnessThrottler"; - - // To enable these logs, run: - // 'adb shell setprop persist.log.tag.BrightnessThrottler DEBUG && adb reboot' - private static final boolean DEBUG = DebugUtils.isDebuggable(TAG); - private static final int THROTTLING_INVALID = -1; - - private final Injector mInjector; - private final Handler mHandler; - // We need a separate handler for unit testing. These two handlers are the same throughout the - // non-test code. - private final Handler mDeviceConfigHandler; - private final Runnable mThrottlingChangeCallback; - private final SkinThermalStatusObserver mSkinThermalStatusObserver; - private final DeviceConfigListener mDeviceConfigListener; - private final DeviceConfigParameterProvider mConfigParameterProvider; - - private int mThrottlingStatus; - - // Maps the throttling ID to the data. Sourced from DisplayDeviceConfig. - @NonNull - private Map<String, ThermalBrightnessThrottlingData> mDdcThermalThrottlingDataMap; - - // Current throttling data being used. - // Null if we do not support throttling. - @Nullable - private ThermalBrightnessThrottlingData mThermalThrottlingData; - - private float mBrightnessCap = PowerManager.BRIGHTNESS_MAX; - private @BrightnessInfo.BrightnessMaxReason int mBrightnessMaxReason = - BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE; - private String mUniqueDisplayId; - - // The most recent string that has been set from DeviceConfig - private String mThermalBrightnessThrottlingDataString; - - // The brightness throttling configuration that should be used. - private String mThermalBrightnessThrottlingDataId; - - // Temperature Sensor to be monitored for throttling. - @NonNull - private SensorData mTempSensor; - - // This is a collection of brightness throttling data that has been written as overrides from - // the DeviceConfig. This will always take priority over the display device config data. - // We need to store the data for every display device, so we do not need to update this each - // time the underlying display device changes. - // This map is indexed by uniqueDisplayId, to provide maps for throttlingId -> throttlingData. - // HashMap< uniqueDisplayId, HashMap< throttlingDataId, ThermalBrightnessThrottlingData >> - private final Map<String, Map<String, ThermalBrightnessThrottlingData>> - mThermalBrightnessThrottlingDataOverride = new HashMap<>(); - - private final BiFunction<String, String, ThrottlingLevel> mDataPointMapper = (key, value) -> { - try { - int status = DeviceConfigParsingUtils.parseThermalStatus(key); - float brightnessPoint = DeviceConfigParsingUtils.parseBrightness(value); - return new ThrottlingLevel(status, brightnessPoint); - } catch (IllegalArgumentException iae) { - return null; - } - }; - - private final Function<List<ThrottlingLevel>, ThermalBrightnessThrottlingData> - mDataSetMapper = ThermalBrightnessThrottlingData::create; - - BrightnessThrottler(Handler handler, Runnable throttlingChangeCallback, String uniqueDisplayId, - String throttlingDataId, - @NonNull DisplayDeviceConfig displayDeviceConfig) { - this(new Injector(), handler, handler, throttlingChangeCallback, uniqueDisplayId, - throttlingDataId, - displayDeviceConfig.getThermalBrightnessThrottlingDataMapByThrottlingId(), - displayDeviceConfig.getTempSensor()); - } - - @VisibleForTesting - BrightnessThrottler(Injector injector, Handler handler, Handler deviceConfigHandler, - Runnable throttlingChangeCallback, String uniqueDisplayId, String throttlingDataId, - @NonNull Map<String, ThermalBrightnessThrottlingData> - thermalBrightnessThrottlingDataMap, - @NonNull SensorData tempSensor) { - mInjector = injector; - - mHandler = handler; - mDeviceConfigHandler = deviceConfigHandler; - mDdcThermalThrottlingDataMap = thermalBrightnessThrottlingDataMap; - mThrottlingChangeCallback = throttlingChangeCallback; - mSkinThermalStatusObserver = new SkinThermalStatusObserver(mInjector, mHandler); - - mUniqueDisplayId = uniqueDisplayId; - mConfigParameterProvider = new DeviceConfigParameterProvider(injector.getDeviceConfig()); - mDeviceConfigListener = new DeviceConfigListener(); - mThermalBrightnessThrottlingDataId = throttlingDataId; - mDdcThermalThrottlingDataMap = thermalBrightnessThrottlingDataMap; - loadThermalBrightnessThrottlingDataFromDeviceConfig(); - loadThermalBrightnessThrottlingDataFromDisplayDeviceConfig(mDdcThermalThrottlingDataMap, - tempSensor, mThermalBrightnessThrottlingDataId, mUniqueDisplayId); - } - - boolean deviceSupportsThrottling() { - return mThermalThrottlingData != null; - } - - float getBrightnessCap() { - return mBrightnessCap; - } - - int getBrightnessMaxReason() { - return mBrightnessMaxReason; - } - - boolean isThrottled() { - return mBrightnessMaxReason != BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE; - } - - void stop() { - mSkinThermalStatusObserver.stopObserving(); - mConfigParameterProvider.removeOnPropertiesChangedListener(mDeviceConfigListener); - // We're asked to stop throttling, so reset brightness restrictions. - mBrightnessCap = PowerManager.BRIGHTNESS_MAX; - mBrightnessMaxReason = BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE; - - // We set throttling status to an invalid value here so that we act on the first throttling - // value received from the thermal service after registration, even if that throttling value - // is THROTTLING_NONE. - mThrottlingStatus = THROTTLING_INVALID; - } - - void loadThermalBrightnessThrottlingDataFromDisplayDeviceConfig( - Map<String, ThermalBrightnessThrottlingData> ddcThrottlingDataMap, - SensorData tempSensor, - String brightnessThrottlingDataId, - String uniqueDisplayId) { - mDdcThermalThrottlingDataMap = ddcThrottlingDataMap; - mThermalBrightnessThrottlingDataId = brightnessThrottlingDataId; - mUniqueDisplayId = uniqueDisplayId; - mTempSensor = tempSensor; - resetThermalThrottlingData(); - } - - private float verifyAndConstrainBrightnessCap(float brightness) { - if (brightness < PowerManager.BRIGHTNESS_MIN) { - Slog.e(TAG, "brightness " + brightness + " is lower than the minimum possible " - + "brightness " + PowerManager.BRIGHTNESS_MIN); - brightness = PowerManager.BRIGHTNESS_MIN; - } - - if (brightness > PowerManager.BRIGHTNESS_MAX) { - Slog.e(TAG, "brightness " + brightness + " is higher than the maximum possible " - + "brightness " + PowerManager.BRIGHTNESS_MAX); - brightness = PowerManager.BRIGHTNESS_MAX; - } - - return brightness; - } - - private void thermalStatusChanged(@Temperature.ThrottlingStatus int newStatus) { - if (mThrottlingStatus != newStatus) { - mThrottlingStatus = newStatus; - updateThermalThrottling(); - } - } - - private void updateThermalThrottling() { - if (!deviceSupportsThrottling()) { - return; - } - - float brightnessCap = PowerManager.BRIGHTNESS_MAX; - int brightnessMaxReason = BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE; - - if (mThrottlingStatus != THROTTLING_INVALID && mThermalThrottlingData != null) { - // Throttling levels are sorted by increasing severity - for (ThrottlingLevel level : mThermalThrottlingData.throttlingLevels) { - if (level.thermalStatus <= mThrottlingStatus) { - brightnessCap = level.brightness; - brightnessMaxReason = BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL; - } else { - // Throttling levels that are greater than the current status are irrelevant - break; - } - } - } - - if (mBrightnessCap != brightnessCap || mBrightnessMaxReason != brightnessMaxReason) { - mBrightnessCap = verifyAndConstrainBrightnessCap(brightnessCap); - mBrightnessMaxReason = brightnessMaxReason; - - if (DEBUG) { - Slog.d(TAG, "State changed: mBrightnessCap = " + mBrightnessCap - + ", mBrightnessMaxReason = " - + BrightnessInfo.briMaxReasonToString(mBrightnessMaxReason)); - } - - if (mThrottlingChangeCallback != null) { - mThrottlingChangeCallback.run(); - } - } - } - - void dump(PrintWriter pw) { - mHandler.runWithScissors(() -> dumpLocal(pw), 1000); - } - - private void dumpLocal(PrintWriter pw) { - pw.println("BrightnessThrottler:"); - pw.println("--------------------"); - pw.println(" mThermalBrightnessThrottlingDataId=" + mThermalBrightnessThrottlingDataId); - pw.println(" mThermalThrottlingData=" + mThermalThrottlingData); - pw.println(" mUniqueDisplayId=" + mUniqueDisplayId); - pw.println(" mThrottlingStatus=" + mThrottlingStatus); - pw.println(" mBrightnessCap=" + mBrightnessCap); - pw.println(" mBrightnessMaxReason=" + - BrightnessInfo.briMaxReasonToString(mBrightnessMaxReason)); - pw.println(" mDdcThermalThrottlingDataMap=" + mDdcThermalThrottlingDataMap); - pw.println(" mThermalBrightnessThrottlingDataOverride=" - + mThermalBrightnessThrottlingDataOverride); - pw.println(" mThermalBrightnessThrottlingDataString=" - + mThermalBrightnessThrottlingDataString); - - mSkinThermalStatusObserver.dump(pw); - } - - // The brightness throttling data id may or may not be specified in the string that is passed - // in, if there is none specified, we assume it is for the default case. Each string passed in - // here must be for one display and one throttling id. - // 123,1,critical,0.8 - // 456,2,moderate,0.9,critical,0.7 - // 456,2,moderate,0.9,critical,0.7,default - // 456,2,moderate,0.9,critical,0.7,id_2 - // displayId, number, <state, val> * number - // displayId, <number, <state, val> * number>, throttlingId - private void loadThermalBrightnessThrottlingDataFromDeviceConfig() { - mThermalBrightnessThrottlingDataString = - mConfigParameterProvider.getBrightnessThrottlingData(); - mThermalBrightnessThrottlingDataOverride.clear(); - if (mThermalBrightnessThrottlingDataString != null) { - Map<String, Map<String, ThermalBrightnessThrottlingData>> tempThrottlingData = - DeviceConfigParsingUtils.parseDeviceConfigMap( - mThermalBrightnessThrottlingDataString, mDataPointMapper, mDataSetMapper); - mThermalBrightnessThrottlingDataOverride.putAll(tempThrottlingData); - } else { - Slog.w(TAG, "DeviceConfig ThermalBrightnessThrottlingData is null"); - } - } - - private void resetThermalThrottlingData() { - stop(); - - mDeviceConfigListener.startListening(); - - // Get throttling data for this id, if it exists - mThermalThrottlingData = getConfigFromId(mThermalBrightnessThrottlingDataId); - - // Fallback to default id otherwise. - if (!DEFAULT_ID.equals(mThermalBrightnessThrottlingDataId) - && mThermalThrottlingData == null) { - mThermalThrottlingData = getConfigFromId(DEFAULT_ID); - Slog.d(TAG, "Falling back to default throttling Id"); - } - - if (deviceSupportsThrottling()) { - mSkinThermalStatusObserver.startObserving(mTempSensor); - } - } - - private ThermalBrightnessThrottlingData getConfigFromId(String id) { - ThermalBrightnessThrottlingData returnValue; - - // Fallback pattern for fetching correct throttling data for this display and id. - // 1) throttling data from device config for this throttling data id - returnValue = mThermalBrightnessThrottlingDataOverride.get(mUniqueDisplayId) == null - ? null - : mThermalBrightnessThrottlingDataOverride.get(mUniqueDisplayId).get(id); - // 2) throttling data from ddc for this throttling data id - returnValue = returnValue == null - ? mDdcThermalThrottlingDataMap.get(id) - : returnValue; - - return returnValue; - } - - /** - * Listens to config data change and updates the brightness throttling data using - * DisplayManager#KEY_BRIGHTNESS_THROTTLING_DATA. - * The format should be a string similar to: "local:4619827677550801152,2,moderate,0.5,severe, - * 0.379518072;local:4619827677550801151,1,moderate,0.75" - * In this order: - * <displayId>,<no of throttling levels>,[<severity as string>,<brightness cap>][,throttlingId]? - * Where [<severity as string>,<brightness cap>] is repeated for each throttling level, and the - * entirety is repeated for each display & throttling data id, separated by a semicolon. - */ - public class DeviceConfigListener implements DeviceConfig.OnPropertiesChangedListener { - public Executor mExecutor = new HandlerExecutor(mDeviceConfigHandler); - - public void startListening() { - mConfigParameterProvider.addOnPropertiesChangedListener(mExecutor, this); - } - - @Override - public void onPropertiesChanged(DeviceConfig.Properties properties) { - loadThermalBrightnessThrottlingDataFromDeviceConfig(); - resetThermalThrottlingData(); - } - } - - private final class SkinThermalStatusObserver extends IThermalEventListener.Stub { - private final Injector mInjector; - private final Handler mHandler; - private SensorData mObserverTempSensor; - - private IThermalService mThermalService; - private boolean mStarted; - - SkinThermalStatusObserver(Injector injector, Handler handler) { - mInjector = injector; - mHandler = handler; - } - - @Override - public void notifyThrottling(Temperature temp) { - if (DEBUG) { - Slog.d(TAG, "New thermal throttling status = " + temp.getStatus()); - } - - if (mObserverTempSensor.name != null - && !mObserverTempSensor.name.equals(temp.getName())) { - Slog.i(TAG, "Skipping thermal throttling notification as monitored sensor: " - + mObserverTempSensor.name - + " != notified sensor: " - + temp.getName()); - return; - } - mHandler.post(() -> { - final @Temperature.ThrottlingStatus int status = temp.getStatus(); - thermalStatusChanged(status); - }); - } - - void startObserving(SensorData tempSensor) { - if (!mStarted || mObserverTempSensor == null) { - mObserverTempSensor = tempSensor; - registerThermalListener(); - return; - } - - String curType = mObserverTempSensor.type; - mObserverTempSensor = tempSensor; - if (curType.equals(tempSensor.type)) { - if (DEBUG) { - Slog.d(TAG, "Thermal status observer already started"); - } - return; - } - stopObserving(); - registerThermalListener(); - } - - void registerThermalListener() { - mThermalService = mInjector.getThermalService(); - if (mThermalService == null) { - Slog.e(TAG, "Could not observe thermal status. Service not available"); - return; - } - int temperatureType = SensorUtils.getSensorTemperatureType(mObserverTempSensor); - try { - // We get a callback immediately upon registering so there's no need to query - // for the current value. - mThermalService.registerThermalEventListenerWithType(this, temperatureType); - mStarted = true; - } catch (RemoteException e) { - Slog.e(TAG, "Failed to register thermal status listener", e); - } - } - - void stopObserving() { - if (!mStarted) { - if (DEBUG) { - Slog.d(TAG, "Stop skipped because thermal status observer not started"); - } - return; - } - try { - mThermalService.unregisterThermalEventListener(this); - mStarted = false; - } catch (RemoteException e) { - Slog.e(TAG, "Failed to unregister thermal status listener", e); - } - mThermalService = null; - } - - void dump(PrintWriter writer) { - writer.println(" SkinThermalStatusObserver:"); - writer.println(" mStarted: " + mStarted); - writer.println(" mObserverTempSensor: " + mObserverTempSensor); - if (mThermalService != null) { - writer.println(" ThermalService available"); - } else { - writer.println(" ThermalService not available"); - } - } - } - - public static class Injector { - public IThermalService getThermalService() { - return IThermalService.Stub.asInterface( - ServiceManager.getService(Context.THERMAL_SERVICE)); - } - - @NonNull - public DeviceConfigInterface getDeviceConfig() { - return DeviceConfigInterface.REAL; - } - } -} diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index 92f5cab10c2a..49aedf5f3797 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -104,7 +104,6 @@ import com.android.server.display.whitebalance.DisplayWhiteBalanceSettings; import com.android.server.policy.WindowManagerPolicy; import java.io.PrintWriter; -import java.util.Objects; /** * Controls the power state of the display. @@ -416,8 +415,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call private final BrightnessRangeController mBrightnessRangeController; - private final BrightnessThrottler mBrightnessThrottler; - private final BrightnessClamperController mBrightnessClamperController; private final Runnable mOnBrightnessChangeRunnable; @@ -482,9 +479,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call private boolean mIsInTransition; private boolean mIsDisplayInternal; - // The id of the thermal brightness throttling policy that should be used. - private String mThermalBrightnessThrottlingDataId; - // DPCs following the brightness of this DPC. This is used in concurrent displays mode - there // is one lead display, the additional displays follow the brightness value of the lead display. @GuardedBy("mLock") @@ -546,8 +540,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mDisplayPowerProximityStateController, resources.getBoolean(R.bool.config_skipScreenOffTransition)); mTag = TAG + "[" + mDisplayId + "]"; - mThermalBrightnessThrottlingDataId = - logicalDisplay.getDisplayInfoLocked().thermalBrightnessThrottlingDataId; mUniqueDisplayId = mDisplayDevice.getUniqueId(); mDisplayStatsId = mUniqueDisplayId.hashCode(); @@ -598,7 +590,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call HighBrightnessModeController hbmController = createHbmControllerLocked(hbmMetadata, modeChangeCallback); - mBrightnessThrottler = createBrightnessThrottlerLocked(); mBrightnessRangeController = mInjector.getBrightnessRangeController(hbmController, modeChangeCallback, mDisplayDeviceConfig, mHandler, flags, @@ -610,11 +601,13 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call brightnessSetting, () -> postBrightnessChangeRunnable(), new HandlerExecutor(mHandler), flags); + String thermalBrightnessThrottlingDataId = + logicalDisplay.getDisplayInfoLocked().thermalBrightnessThrottlingDataId; mBrightnessClamperController = mInjector.getBrightnessClamperController( mHandler, modeChangeCallback::run, new BrightnessClamperController.DisplayDeviceData( mUniqueDisplayId, - mThermalBrightnessThrottlingDataId, + thermalBrightnessThrottlingDataId, logicalDisplay.getPowerThrottlingDataIdLocked(), mDisplayDeviceConfig, displayDeviceInfo.width, displayDeviceInfo.height, displayToken, mDisplayId), mContext, flags, mSensorManager, @@ -928,7 +921,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mDisplayStatsId = mUniqueDisplayId.hashCode(); mDisplayDeviceConfig = config; mIdleStylusTimeoutMillisConfig = mDisplayDeviceConfig.getIdleStylusTimeoutMillis(); - mThermalBrightnessThrottlingDataId = thermalBrightnessThrottlingDataId; loadFromDisplayDeviceConfig(token, info, hbmMetadata); mDisplayPowerProximityStateController.notifyDisplayDeviceChanged(config); @@ -936,22 +928,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // last command that was sent to change it's state. Let's assume it is unknown so // that we trigger a change immediately. mPowerState.resetScreenState(); - } else if (!Objects.equals(mThermalBrightnessThrottlingDataId, - thermalBrightnessThrottlingDataId)) { - changed = true; - mThermalBrightnessThrottlingDataId = thermalBrightnessThrottlingDataId; - mBrightnessThrottler.loadThermalBrightnessThrottlingDataFromDisplayDeviceConfig( - config.getThermalBrightnessThrottlingDataMapByThrottlingId(), - config.getTempSensor(), - mThermalBrightnessThrottlingDataId, - mUniqueDisplayId); } mIsDisplayInternal = isDisplayInternal; - // using local variables here, when mBrightnessThrottler is removed, - // mThermalBrightnessThrottlingDataId could be removed as well - // changed = true will be not needed - clampers are maintaining their state and - // will call updatePowerState if needed. + mBrightnessClamperController.onDisplayChanged( new BrightnessClamperController.DisplayDeviceData(uniqueId, thermalBrightnessThrottlingDataId, powerThrottlingDataId, @@ -1000,10 +980,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call setAnimatorRampSpeeds(/* isIdleMode= */ false); mBrightnessRangeController.loadFromConfig(hbmMetadata, token, info, mDisplayDeviceConfig); - mBrightnessThrottler.loadThermalBrightnessThrottlingDataFromDisplayDeviceConfig( - mDisplayDeviceConfig.getThermalBrightnessThrottlingDataMapByThrottlingId(), - mDisplayDeviceConfig.getTempSensor(), - mThermalBrightnessThrottlingDataId, mUniqueDisplayId); } private void sendUpdatePowerState() { @@ -1188,7 +1164,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call autoBrightnessResetAmbientLuxAfterWarmUp, ambientBrightnessThresholds, screenBrightnessThresholds, ambientBrightnessThresholdsIdle, screenBrightnessThresholdsIdle, mContext, mBrightnessRangeController, - mBrightnessThrottler, mDisplayDeviceConfig.getAmbientHorizonShort(), + mBrightnessClamperController, mDisplayDeviceConfig.getAmbientHorizonShort(), mDisplayDeviceConfig.getAmbientHorizonLong(), userLux, userNits, mFlags); mDisplayBrightnessController.setUpAutoBrightness( mAutomaticBrightnessController, mSensorManager, mDisplayDeviceConfig, mHandler, @@ -1309,7 +1285,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call private void cleanupHandlerThreadAfterStop() { mDisplayPowerProximityStateController.cleanup(); mBrightnessRangeController.stop(); - mBrightnessThrottler.stop(); mBrightnessClamperController.stop(); mHandler.removeCallbacksAndMessages(null); @@ -2104,18 +2079,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call maxDesiredHdrSdrRatio), modeChangeCallback, hbmMetadata, mContext); } - private BrightnessThrottler createBrightnessThrottlerLocked() { - final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked(); - final DisplayDeviceConfig ddConfig = device.getDisplayDeviceConfig(); - return new BrightnessThrottler(mHandler, - () -> { - sendUpdatePowerState(); - postBrightnessChangeRunnable(); - }, mUniqueDisplayId, - mLogicalDisplay.getDisplayInfoLocked().thermalBrightnessThrottlingDataId, - ddConfig); - } - private void blockScreenOn() { if (mPendingScreenOnUnblocker == null) { Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0); @@ -2780,11 +2743,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } pw.println(); - if (mBrightnessThrottler != null) { - mBrightnessThrottler.dump(pw); - } - - pw.println(); if (mDisplayWhiteBalanceController != null) { mDisplayWhiteBalanceController.dump(pw); mDisplayWhiteBalanceSettings.dump(pw); @@ -3330,7 +3288,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call HysteresisLevels ambientBrightnessThresholdsIdle, HysteresisLevels screenBrightnessThresholdsIdle, Context context, BrightnessRangeController brightnessModeController, - BrightnessThrottler brightnessThrottler, int ambientLightHorizonShort, + BrightnessClamperController clamperController, int ambientLightHorizonShort, int ambientLightHorizonLong, float userLux, float userNits, DisplayManagerFlags displayManagerFlags) { @@ -3342,7 +3300,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call resetAmbientLuxAfterWarmUpConfig, ambientBrightnessThresholds, screenBrightnessThresholds, ambientBrightnessThresholdsIdle, screenBrightnessThresholdsIdle, context, brightnessModeController, - brightnessThrottler, ambientLightHorizonShort, ambientLightHorizonLong, userLux, + clamperController, ambientLightHorizonShort, ambientLightHorizonLong, userLux, userNits, displayManagerFlags); } diff --git a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java index 860be2028eb3..204d74d377fa 100644 --- a/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java +++ b/services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java @@ -195,6 +195,19 @@ public class BrightnessClamperController { mModifiers.forEach(BrightnessStateModifier::stop); } + /** + * returns max allowed brightness. + * TODO(b/387452517): introduce constrainBrightness method + */ + public float getMaxBrightness() { + return mModifiersAggregatedState.mMaxBrightness; + } + + public boolean isThrottled() { + return mModifiersAggregatedState.mMaxBrightnessReason + != BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE; + } + // Called in DisplayControllerHandler private void recalculateModifiersState() { @@ -306,7 +319,7 @@ public class BrightnessClamperController { BrightnessWearBedtimeModeModifier.WearBedtimeModeData { @NonNull private final String mUniqueDisplayId; - @NonNull + @Nullable private final String mThermalThrottlingDataId; @NonNull private final String mPowerThrottlingDataId; @@ -322,7 +335,7 @@ public class BrightnessClamperController { final int mDisplayId; public DisplayDeviceData(@NonNull String uniqueDisplayId, - @NonNull String thermalThrottlingDataId, + @Nullable String thermalThrottlingDataId, @NonNull String powerThrottlingDataId, @NonNull DisplayDeviceConfig displayDeviceConfig, int width, @@ -345,7 +358,7 @@ public class BrightnessClamperController { return mUniqueDisplayId; } - @NonNull + @Nullable @Override public String getThermalThrottlingDataId() { return mThermalThrottlingDataId; @@ -354,6 +367,9 @@ public class BrightnessClamperController { @Nullable @Override public ThermalBrightnessThrottlingData getThermalBrightnessThrottlingData() { + if (mThermalThrottlingDataId == null) { + return null; + } return mDisplayDeviceConfig.getThermalBrightnessThrottlingDataMapByThrottlingId().get( mThermalThrottlingDataId); } diff --git a/services/core/java/com/android/server/display/brightness/clamper/BrightnessThermalModifier.java b/services/core/java/com/android/server/display/brightness/clamper/BrightnessThermalModifier.java index 21ef309fb327..593bba2c841e 100644 --- a/services/core/java/com/android/server/display/brightness/clamper/BrightnessThermalModifier.java +++ b/services/core/java/com/android/server/display/brightness/clamper/BrightnessThermalModifier.java @@ -347,7 +347,7 @@ class BrightnessThermalModifier implements BrightnessStateModifier, @NonNull String getUniqueDisplayId(); - @NonNull + @Nullable String getThermalThrottlingDataId(); @Nullable diff --git a/services/core/java/com/android/server/input/debug/TouchpadDebugViewController.java b/services/core/java/com/android/server/input/debug/TouchpadDebugViewController.java index 9cfbfa649e1c..2c1d68e3dbda 100644 --- a/services/core/java/com/android/server/input/debug/TouchpadDebugViewController.java +++ b/services/core/java/com/android/server/input/debug/TouchpadDebugViewController.java @@ -163,9 +163,15 @@ public class TouchpadDebugViewController implements InputManager.InputDeviceList int deviceId) { mHandler.post(() -> { if (mTouchpadDebugView != null) { - mTouchpadDebugView.post( - () -> mTouchpadDebugView.updateHardwareState(touchpadHardwareState, - deviceId)); + mTouchpadDebugView.post(() -> { + // hideDebugView might have been called since we posted the action (e.g. if the + // developer option toggle is clicked using the same touchpad currently being + // visualized, b/376018148), so we need to check for null again. + if (mTouchpadDebugView != null) { + mTouchpadDebugView.updateHardwareState(touchpadHardwareState, + deviceId); + } + }); } }); } @@ -177,8 +183,14 @@ public class TouchpadDebugViewController implements InputManager.InputDeviceList public void updateTouchpadGestureInfo(int gestureType, int deviceId) { mHandler.post(() -> { if (mTouchpadDebugView != null) { - mTouchpadDebugView.post( - () -> mTouchpadDebugView.updateGestureInfo(gestureType, deviceId)); + mTouchpadDebugView.post(() -> { + // hideDebugView might have been called since we posted the action (e.g. if the + // developer option toggle is clicked using the same touchpad currently being + // visualized, b/376018148), so we need to check for null again. + if (mTouchpadDebugView != null) { + mTouchpadDebugView.updateGestureInfo(gestureType, deviceId); + } + }); } }); } diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubEndpointBroker.java b/services/core/java/com/android/server/location/contexthub/ContextHubEndpointBroker.java index 2c072d0ed8fe..87d809b5e850 100644 --- a/services/core/java/com/android/server/location/contexthub/ContextHubEndpointBroker.java +++ b/services/core/java/com/android/server/location/contexthub/ContextHubEndpointBroker.java @@ -16,6 +16,7 @@ package com.android.server.location.contexthub; +import android.app.AppOpsManager; import android.content.Context; import android.hardware.contexthub.EndpointInfo; import android.hardware.contexthub.ErrorCode; @@ -23,18 +24,21 @@ import android.hardware.contexthub.HubEndpointInfo; import android.hardware.contexthub.HubMessage; import android.hardware.contexthub.IContextHubEndpoint; import android.hardware.contexthub.IContextHubEndpointCallback; +import android.hardware.contexthub.IEndpointCommunication; import android.hardware.contexthub.Message; import android.hardware.contexthub.MessageDeliveryStatus; +import android.hardware.contexthub.Reason; import android.hardware.location.ContextHubTransaction; import android.hardware.location.IContextHubTransactionCallback; +import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; +import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; -import java.util.HashSet; -import java.util.Set; +import java.util.Collection; import java.util.concurrent.atomic.AtomicBoolean; /** @@ -44,18 +48,24 @@ import java.util.concurrent.atomic.AtomicBoolean; * @hide */ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub - implements IBinder.DeathRecipient { + implements IBinder.DeathRecipient, AppOpsManager.OnOpChangedListener { private static final String TAG = "ContextHubEndpointBroker"; + /** Message used by noteOp when this client receives a message from an endpoint. */ + private static final String RECEIVE_MSG_NOTE = "ContextHubEndpointMessageDelivery"; + /** The context of the service. */ private final Context mContext; - /** The proxy to talk to the Context Hub HAL. */ - private final IContextHubWrapper mContextHubProxy; + /** The proxy to talk to the Context Hub HAL for endpoint communication. */ + private final IEndpointCommunication mHubInterface; /** The manager that registered this endpoint. */ private final ContextHubEndpointManager mEndpointManager; + /** Manager used for noting permissions usage of this broker. */ + private final AppOpsManager mAppOpsManager; + /** Metadata about this endpoint (app-facing container). */ private final HubEndpointInfo mEndpointInfo; @@ -70,40 +80,84 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub private final Object mOpenSessionLock = new Object(); - /** The set of session IDs that are pending remote acceptance */ - @GuardedBy("mOpenSessionLock") - private final Set<Integer> mPendingSessionIds = new HashSet<>(); + static class SessionInfo { + enum SessionState { + /* The session is pending acceptance from the remote endpoint. */ + PENDING, + /* The session is active and can transport messages. */ + ACTIVE, + }; - /** The set of session IDs that are actively enabled by this endpoint */ - @GuardedBy("mOpenSessionLock") - private final Set<Integer> mActiveSessionIds = new HashSet<>(); + private final HubEndpointInfo mRemoteEndpointInfo; + + private SessionState mSessionState = SessionState.PENDING; + + private final boolean mRemoteInitiated; - /** The set of session IDs that are actively enabled by the remote endpoint */ + SessionInfo(HubEndpointInfo remoteEndpointInfo, boolean remoteInitiated) { + mRemoteEndpointInfo = remoteEndpointInfo; + mRemoteInitiated = remoteInitiated; + } + + public boolean isRemoteInitiated() { + return mRemoteInitiated; + } + + public HubEndpointInfo getRemoteEndpointInfo() { + return mRemoteEndpointInfo; + } + + public void setSessionState(SessionState state) { + mSessionState = state; + } + + public boolean isActive() { + return mSessionState == SessionState.ACTIVE; + } + } + + /** A map between a session ID which maps to its current state. */ @GuardedBy("mOpenSessionLock") - private final Set<Integer> mActiveRemoteSessionIds = new HashSet<>(); + private final SparseArray<SessionInfo> mSessionInfoMap = new SparseArray<>(); /** The package name of the app that created the endpoint */ private final String mPackageName; - /* Transaction manager used for sending reliable messages */ + /** The attribution tag of the module that created the endpoint */ + private final String mAttributionTag; + + /** Transaction manager used for sending reliable messages */ private final ContextHubTransactionManager mTransactionManager; + /** The PID/UID of the endpoint package providing IContextHubEndpointCallback */ + private final int mPid; + + private final int mUid; + /* package */ ContextHubEndpointBroker( Context context, - IContextHubWrapper contextHubProxy, + IEndpointCommunication hubInterface, ContextHubEndpointManager endpointManager, EndpointInfo halEndpointInfo, IContextHubEndpointCallback callback, String packageName, + String attributionTag, ContextHubTransactionManager transactionManager) { mContext = context; - mContextHubProxy = contextHubProxy; + mHubInterface = hubInterface; mEndpointManager = endpointManager; mEndpointInfo = new HubEndpointInfo(halEndpointInfo); mHalEndpointInfo = halEndpointInfo; mContextHubEndpointCallback = callback; mPackageName = packageName; + mAttributionTag = attributionTag; mTransactionManager = transactionManager; + + mPid = Binder.getCallingPid(); + mUid = Binder.getCallingUid(); + + mAppOpsManager = context.getSystemService(AppOpsManager.class); + mAppOpsManager.startWatchingMode(AppOpsManager.OP_NONE, mPackageName, this); } @Override @@ -117,21 +171,25 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub throws RemoteException { super.openSession_enforcePermission(); if (!mIsRegistered.get()) throw new IllegalStateException("Endpoint is not registered"); + if (!hasEndpointPermissions(destination)) { + throw new SecurityException( + "Insufficient permission to open a session with endpoint: " + destination); + } + int sessionId = mEndpointManager.reserveSessionId(); EndpointInfo halEndpointInfo = ContextHubServiceUtil.convertHalEndpointInfo(destination); synchronized (mOpenSessionLock) { try { - mPendingSessionIds.add(sessionId); - mContextHubProxy.openEndpointSession( + mSessionInfoMap.put(sessionId, new SessionInfo(destination, false)); + mHubInterface.openEndpointSession( sessionId, halEndpointInfo.id, mHalEndpointInfo.id, serviceDescriptor); } catch (RemoteException | IllegalArgumentException | UnsupportedOperationException e) { Log.e(TAG, "Exception while calling HAL openEndpointSession", e); - mPendingSessionIds.remove(sessionId); - mEndpointManager.returnSessionId(sessionId); + cleanupSessionResources(sessionId); throw e; } @@ -144,13 +202,11 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub public void closeSession(int sessionId, int reason) throws RemoteException { super.closeSession_enforcePermission(); if (!mIsRegistered.get()) throw new IllegalStateException("Endpoint is not registered"); - try { - mContextHubProxy.closeEndpointSession( - sessionId, ContextHubServiceUtil.toHalReason(reason)); - } catch (RemoteException | IllegalArgumentException | UnsupportedOperationException e) { - Log.e(TAG, "Exception while calling HAL closeEndpointSession", e); - throw e; + if (!cleanupSessionResources(sessionId)) { + throw new IllegalArgumentException( + "Unknown session ID in closeSession: id=" + sessionId); } + halCloseEndpointSession(sessionId, ContextHubServiceUtil.toHalReason(reason)); } @Override @@ -159,20 +215,16 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub super.unregister_enforcePermission(); mIsRegistered.set(false); try { - mContextHubProxy.unregisterEndpoint(mHalEndpointInfo); + mHubInterface.unregisterEndpoint(mHalEndpointInfo); } catch (RemoteException e) { Log.e(TAG, "RemoteException while calling HAL unregisterEndpoint", e); } synchronized (mOpenSessionLock) { - for (int id : mPendingSessionIds) { - mEndpointManager.returnSessionId(id); + // Iterate in reverse since cleanupSessionResources will remove the entry + for (int i = mSessionInfoMap.size() - 1; i >= 0; i--) { + int id = mSessionInfoMap.keyAt(i); + cleanupSessionResources(id); } - for (int id : mActiveSessionIds) { - mEndpointManager.returnSessionId(id); - } - mPendingSessionIds.clear(); - mActiveSessionIds.clear(); - mActiveRemoteSessionIds.clear(); } mEndpointManager.unregisterEndpoint(mEndpointInfo.getIdentifier().getEndpoint()); } @@ -182,9 +234,14 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub public void openSessionRequestComplete(int sessionId) { super.openSessionRequestComplete_enforcePermission(); synchronized (mOpenSessionLock) { + SessionInfo info = mSessionInfoMap.get(sessionId); + if (info == null) { + throw new IllegalArgumentException( + "openSessionRequestComplete for invalid session id=" + sessionId); + } try { - mContextHubProxy.endpointSessionOpenComplete(sessionId); - mActiveRemoteSessionIds.add(sessionId); + mHubInterface.endpointSessionOpenComplete(sessionId); + info.setSessionState(SessionInfo.SessionState.ACTIVE); } catch (RemoteException | IllegalArgumentException | UnsupportedOperationException e) { Log.e(TAG, "Exception while calling endpointSessionOpenComplete", e); } @@ -197,25 +254,21 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub int sessionId, HubMessage message, IContextHubTransactionCallback callback) { super.sendMessage_enforcePermission(); Message halMessage = ContextHubServiceUtil.createHalMessage(message); - synchronized (mOpenSessionLock) { - if (!mActiveSessionIds.contains(sessionId) - && !mActiveRemoteSessionIds.contains(sessionId)) { - throw new SecurityException( - "sendMessage called on inactive session (id= " + sessionId + ")"); - } + if (!isSessionActive(sessionId)) { + throw new SecurityException( + "sendMessage called on inactive session (id= " + sessionId + ")"); } - // TODO(b/381102453): Handle permissions if (callback == null) { try { - mContextHubProxy.sendMessageToEndpoint(sessionId, halMessage); + mHubInterface.sendMessageToEndpoint(sessionId, halMessage); } catch (RemoteException e) { Log.w(TAG, "Exception while sending message on session " + sessionId, e); } } else { ContextHubServiceTransaction transaction = mTransactionManager.createSessionMessageTransaction( - sessionId, halMessage, mPackageName, callback); + mHubInterface, sessionId, halMessage, mPackageName, callback); try { mTransactionManager.addTransaction(transaction); } catch (IllegalStateException e) { @@ -240,7 +293,7 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub status.messageSequenceNumber = messageSeqNumber; status.errorCode = errorCode; try { - mContextHubProxy.sendMessageDeliveryStatusToEndpoint(sessionId, status); + mHubInterface.sendMessageDeliveryStatusToEndpoint(sessionId, status); } catch (RemoteException e) { Log.w( TAG, @@ -257,6 +310,31 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub } } + @Override + public void onOpChanged(String op, String packageName) { + if (!packageName.equals(mPackageName)) { + Log.w( + TAG, + "onOpChanged called with invalid package " + + packageName + + " expected " + + mPackageName); + } else { + synchronized (mOpenSessionLock) { + // Iterate in reverse since cleanupSessionResources will remove the entry + for (int i = mSessionInfoMap.size() - 1; i >= 0; i--) { + int id = mSessionInfoMap.keyAt(i); + HubEndpointInfo target = mSessionInfoMap.get(id).getRemoteEndpointInfo(); + if (!hasEndpointPermissions(target)) { + halCloseEndpointSessionNoThrow(id, Reason.PERMISSION_DENIED); + onCloseEndpointSession(id, Reason.PERMISSION_DENIED); + // Resource cleanup is done in onCloseEndpointSession + } + } + } + } + } + /* package */ void attachDeathRecipient() throws RemoteException { if (mContextHubEndpointCallback != null) { mContextHubEndpointCallback.asBinder().linkToDeath(this, 0 /* flags */); @@ -265,21 +343,36 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub /* package */ void onEndpointSessionOpenRequest( int sessionId, HubEndpointInfo initiator, String serviceDescriptor) { + if (!hasEndpointPermissions(initiator)) { + halCloseEndpointSessionNoThrow(sessionId, Reason.PERMISSION_DENIED); + return; + } + + synchronized (mOpenSessionLock) { + if (hasSessionId(sessionId)) { + Log.e(TAG, "Existing session in onEndpointSessionOpenRequest: id=" + sessionId); + halCloseEndpointSessionNoThrow(sessionId, Reason.UNSPECIFIED); + return; + } + mSessionInfoMap.put(sessionId, new SessionInfo(initiator, true)); + } + if (mContextHubEndpointCallback != null) { try { mContextHubEndpointCallback.onSessionOpenRequest( sessionId, initiator, serviceDescriptor); } catch (RemoteException e) { Log.e(TAG, "RemoteException while calling onSessionOpenRequest", e); + cleanupSessionResources(sessionId); + return; } } } /* package */ void onCloseEndpointSession(int sessionId, byte reason) { - synchronized (mOpenSessionLock) { - mPendingSessionIds.remove(sessionId); - mActiveSessionIds.remove(sessionId); - mActiveRemoteSessionIds.remove(sessionId); + if (!cleanupSessionResources(sessionId)) { + Log.w(TAG, "Unknown session ID in onCloseEndpointSession: id=" + sessionId); + return; } if (mContextHubEndpointCallback != null) { try { @@ -293,8 +386,11 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub /* package */ void onEndpointSessionOpenComplete(int sessionId) { synchronized (mOpenSessionLock) { - mPendingSessionIds.remove(sessionId); - mActiveSessionIds.add(sessionId); + if (!hasSessionId(sessionId)) { + Log.w(TAG, "Unknown session ID in onEndpointSessionOpenComplete: id=" + sessionId); + return; + } + mSessionInfoMap.get(sessionId).setSessionState(SessionInfo.SessionState.ACTIVE); } if (mContextHubEndpointCallback != null) { try { @@ -306,11 +402,51 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub } /* package */ void onMessageReceived(int sessionId, HubMessage message) { + HubEndpointInfo remote; + synchronized (mOpenSessionLock) { + if (!isSessionActive(sessionId)) { + Log.e( + TAG, + "Dropping message for inactive session (id=" + + sessionId + + ") with message: " + + message); + sendMessageDeliveryStatus( + sessionId, message.getMessageSequenceNumber(), ErrorCode.PERMANENT_ERROR); + return; + } + remote = mSessionInfoMap.get(sessionId).getRemoteEndpointInfo(); + } + if (!ContextHubServiceUtil.notePermissions( + mAppOpsManager, + mUid, + mPackageName, + mAttributionTag, + remote.getRequiredPermissions(), + RECEIVE_MSG_NOTE + + "-0x" + + Long.toHexString(remote.getIdentifier().getHub()) + + "-0x" + + Long.toHexString(remote.getIdentifier().getEndpoint()))) { + Log.e( + TAG, + "Dropping message from " + + remote + + ". " + + mPackageName + + " doesn't have permission"); + sendMessageDeliveryStatus( + sessionId, message.getMessageSequenceNumber(), ErrorCode.PERMISSION_DENIED); + return; + } + if (mContextHubEndpointCallback != null) { try { mContextHubEndpointCallback.onMessageReceived(sessionId, message); } catch (RemoteException e) { Log.e(TAG, "RemoteException while calling onMessageReceived", e); + sendMessageDeliveryStatus( + sessionId, message.getMessageSequenceNumber(), ErrorCode.TRANSIENT_ERROR); } } } @@ -322,9 +458,66 @@ public class ContextHubEndpointBroker extends IContextHubEndpoint.Stub /* package */ boolean hasSessionId(int sessionId) { synchronized (mOpenSessionLock) { - return mPendingSessionIds.contains(sessionId) - || mActiveSessionIds.contains(sessionId) - || mActiveRemoteSessionIds.contains(sessionId); + return mSessionInfoMap.contains(sessionId); } } + + /** + * Calls the HAL closeEndpointSession API. + * + * @param sessionId The session ID to close + * @param halReason The HAL reason + */ + private void halCloseEndpointSession(int sessionId, byte halReason) throws RemoteException { + try { + mHubInterface.closeEndpointSession(sessionId, halReason); + } catch (RemoteException | IllegalArgumentException | UnsupportedOperationException e) { + throw e; + } + } + + /** Same as halCloseEndpointSession but does not throw the exception */ + private void halCloseEndpointSessionNoThrow(int sessionId, byte halReason) { + try { + halCloseEndpointSession(sessionId, halReason); + } catch (RemoteException | IllegalArgumentException | UnsupportedOperationException e) { + Log.e(TAG, "Exception while calling HAL closeEndpointSession", e); + } + } + + /** + * Cleans up resources related to a session with the provided ID. + * + * @param sessionId The session ID to clean up resources for + * @return false if the session ID was invalid + */ + private boolean cleanupSessionResources(int sessionId) { + synchronized (mOpenSessionLock) { + SessionInfo info = mSessionInfoMap.get(sessionId); + if (info != null && !info.isRemoteInitiated()) { + mEndpointManager.returnSessionId(sessionId); + mSessionInfoMap.remove(sessionId); + } + return info != null; + } + } + + /** + * @param sessionId The ID of the session to check + * @return true if the session with the given ID is currently active + */ + private boolean isSessionActive(int sessionId) { + synchronized (mOpenSessionLock) { + return hasSessionId(sessionId) && mSessionInfoMap.get(sessionId).isActive(); + } + } + + /** + * @param targetEndpointInfo The target endpoint to check permissions for + * @return true if this endpoint has sufficient permission to the provided target endpoint + */ + private boolean hasEndpointPermissions(HubEndpointInfo targetEndpointInfo) { + Collection<String> requiredPermissions = targetEndpointInfo.getRequiredPermissions(); + return ContextHubServiceUtil.hasPermissions(mContext, mPid, mUid, requiredPermissions); + } } diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubEndpointManager.java b/services/core/java/com/android/server/location/contexthub/ContextHubEndpointManager.java index 07df7f994b24..7698a87f80c9 100644 --- a/services/core/java/com/android/server/location/contexthub/ContextHubEndpointManager.java +++ b/services/core/java/com/android/server/location/contexthub/ContextHubEndpointManager.java @@ -17,11 +17,14 @@ package com.android.server.location.contexthub; import android.content.Context; +import android.hardware.contexthub.ContextHubInfo; import android.hardware.contexthub.EndpointInfo; import android.hardware.contexthub.HubEndpointInfo; +import android.hardware.contexthub.HubInfo; import android.hardware.contexthub.HubMessage; import android.hardware.contexthub.IContextHubEndpoint; import android.hardware.contexthub.IContextHubEndpointCallback; +import android.hardware.contexthub.IEndpointCommunication; import android.os.RemoteException; import android.os.ServiceSpecificException; import android.util.Log; @@ -75,11 +78,11 @@ import java.util.concurrent.ConcurrentHashMap; @GuardedBy("mEndpointLock") private long mNextEndpointId = -2; - /** The minimum session ID reservable by endpoints (retrieved from HAL) */ - private final int mMinSessionId; + /** The minimum session ID reservable by endpoints (retrieved from HAL in init()) */ + private int mMinSessionId = -1; - /** The minimum session ID reservable by endpoints (retrieved from HAL) */ - private final int mMaxSessionId; + /** The minimum session ID reservable by endpoints (retrieved from HAL in init()) */ + private int mMaxSessionId = -1; /** Variables for managing session ID creation */ private final Object mSessionIdLock = new Object(); @@ -92,8 +95,11 @@ import java.util.concurrent.ConcurrentHashMap; @GuardedBy("mSessionIdLock") private int mNextSessionId = 0; - /** Initialized to true if all initialization in the constructor succeeds. */ - private final boolean mSessionIdsValid; + /** Set true if init() succeeds */ + private boolean mSessionIdsValid = false; + + /** The interface for endpoint communication (retrieved from HAL in init()) */ + private IEndpointCommunication mHubInterface = null; /* package */ ContextHubEndpointManager( Context context, @@ -104,34 +110,73 @@ import java.util.concurrent.ConcurrentHashMap; mContextHubProxy = contextHubProxy; mHubInfoRegistry = hubInfoRegistry; mTransactionManager = transactionManager; + } + + /** + * Initializes this class. + * + * This is separate from the constructor so that this may be passed into the callback registered + * with the HAL. + * + * @throws InstantiationException on any failure + */ + /* package */ void init() throws InstantiationException { + if (mSessionIdsValid) { + throw new IllegalStateException("Already initialized"); + } + try { + HubInfo info = new HubInfo(); + info.hubId = SERVICE_HUB_ID; + // TODO(b/387291125): Populate the ContextHubInfo with real values. + ContextHubInfo contextHubInfo = new ContextHubInfo(); + contextHubInfo.name = ""; + contextHubInfo.vendor = ""; + contextHubInfo.toolchain = ""; + contextHubInfo.supportedPermissions = new String[0]; + info.hubDetails = HubInfo.HubDetails.contextHubInfo(contextHubInfo); + mHubInterface = mContextHubProxy.registerEndpointHub( + new ContextHubHalEndpointCallback(mHubInfoRegistry, this), + info); + if (mHubInterface == null) { + throw new IllegalStateException("Received null IEndpointCommunication"); + } + } catch (RemoteException | IllegalStateException | ServiceSpecificException + | UnsupportedOperationException e) { + String error = "Failed to register ContextHubService as message hub"; + Log.e(TAG, error, e); + throw new InstantiationException(error); + } + int[] range = null; try { - range = mContextHubProxy.requestSessionIdRange(SERVICE_SESSION_RANGE); + range = mHubInterface.requestSessionIdRange(SERVICE_SESSION_RANGE); if (range != null && range.length < SERVICE_SESSION_RANGE_LENGTH) { - Log.e(TAG, "Invalid session ID range: range array size = " + range.length); - range = null; + String error = "Invalid session ID range: range array size = " + range.length; + Log.e(TAG, error); + unregisterHub(); + throw new InstantiationException(error); } } catch (RemoteException | IllegalArgumentException | ServiceSpecificException e) { - Log.e(TAG, "Exception while calling HAL requestSessionIdRange", e); + String error = "Exception while calling HAL requestSessionIdRange"; + Log.e(TAG, error, e); + unregisterHub(); + throw new InstantiationException(error); } - if (range == null) { - mMinSessionId = -1; - mMaxSessionId = -1; - mSessionIdsValid = false; - } else { - mMinSessionId = range[0]; - mMaxSessionId = range[1]; - if (!isSessionIdRangeValid(mMinSessionId, mMaxSessionId)) { - Log.e( - TAG, - "Invalid session ID range: max=" + mMaxSessionId + " min=" + mMinSessionId); - mSessionIdsValid = false; - } else { - mNextSessionId = mMinSessionId; - mSessionIdsValid = true; - } + mMinSessionId = range[0]; + mMaxSessionId = range[1]; + if (!isSessionIdRangeValid(mMinSessionId, mMaxSessionId)) { + String error = + "Invalid session ID range: max=" + mMaxSessionId + " min=" + mMinSessionId; + Log.e(TAG, error); + unregisterHub(); + throw new InstantiationException(error); + } + + synchronized (mSessionIdLock) { + mNextSessionId = mMinSessionId; } + mSessionIdsValid = true; } /** @@ -146,7 +191,8 @@ import java.util.concurrent.ConcurrentHashMap; /* package */ IContextHubEndpoint registerEndpoint( HubEndpointInfo pendingEndpointInfo, IContextHubEndpointCallback callback, - String packageName) + String packageName, + String attributionTag) throws RemoteException { if (!mSessionIdsValid) { throw new IllegalStateException("ContextHubEndpointManager failed to initialize"); @@ -157,7 +203,7 @@ import java.util.concurrent.ConcurrentHashMap; ContextHubServiceUtil.createHalEndpointInfo( pendingEndpointInfo, endpointId, SERVICE_HUB_ID); try { - mContextHubProxy.registerEndpoint(halEndpointInfo); + mHubInterface.registerEndpoint(halEndpointInfo); } catch (RemoteException e) { Log.e(TAG, "RemoteException while calling HAL registerEndpoint", e); throw e; @@ -165,11 +211,12 @@ import java.util.concurrent.ConcurrentHashMap; broker = new ContextHubEndpointBroker( mContext, - mContextHubProxy, + mHubInterface, this /* endpointManager */, halEndpointInfo, callback, packageName, + attributionTag, mTransactionManager); mEndpointMap.put(endpointId, broker); @@ -327,6 +374,15 @@ import java.util.concurrent.ConcurrentHashMap; } } + /** Unregister the hub (called during init() failure). Silence errors. */ + private void unregisterHub() { + try { + mHubInterface.unregister(); + } catch (RemoteException | IllegalStateException e) { + Log.e(TAG, "Failed to unregister from HAL on init failure", e); + } + } + /** @return an available endpoint ID */ private long getNewEndpointId() { synchronized (mEndpointLock) { diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubHalEndpointCallback.java b/services/core/java/com/android/server/location/contexthub/ContextHubHalEndpointCallback.java index f1f2217fc3c4..88764b6601ff 100644 --- a/services/core/java/com/android/server/location/contexthub/ContextHubHalEndpointCallback.java +++ b/services/core/java/com/android/server/location/contexthub/ContextHubHalEndpointCallback.java @@ -21,6 +21,9 @@ import android.hardware.contexthub.HubMessage; import android.hardware.contexthub.IEndpointCallback; import android.hardware.contexthub.Message; import android.hardware.contexthub.MessageDeliveryStatus; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Process; import android.os.RemoteException; /** IEndpointCallback implementation. */ @@ -29,6 +32,11 @@ public class ContextHubHalEndpointCallback private final IEndpointLifecycleCallback mEndpointLifecycleCallback; private final IEndpointSessionCallback mEndpointSessionCallback; + // Use this thread in case where the execution requires to be on an async service thread. + private final HandlerThread mHandlerThread = + new HandlerThread("Context Hub endpoint callback", Process.THREAD_PRIORITY_BACKGROUND); + private Handler mHandler; + /** Interface for listening for endpoint start and stop events. */ public interface IEndpointLifecycleCallback { /** Called when a batch of endpoints started. */ @@ -65,6 +73,9 @@ public class ContextHubHalEndpointCallback IEndpointSessionCallback endpointSessionCallback) { mEndpointLifecycleCallback = endpointLifecycleCallback; mEndpointSessionCallback = endpointSessionCallback; + + mHandlerThread.start(); + mHandler = new Handler(mHandlerThread.getLooper()); } @Override @@ -77,7 +88,7 @@ public class ContextHubHalEndpointCallback for (int i = 0; i < halEndpointInfos.length; i++) { endpointInfos[i] = new HubEndpointInfo(halEndpointInfos[i]); } - mEndpointLifecycleCallback.onEndpointStarted(endpointInfos); + mHandler.post(() -> mEndpointLifecycleCallback.onEndpointStarted(endpointInfos)); } @Override @@ -87,40 +98,48 @@ public class ContextHubHalEndpointCallback for (int i = 0; i < halEndpointIds.length; i++) { endpointIds[i] = new HubEndpointInfo.HubEndpointIdentifier(halEndpointIds[i]); } - mEndpointLifecycleCallback.onEndpointStopped(endpointIds, reason); + mHandler.post(() -> mEndpointLifecycleCallback.onEndpointStopped(endpointIds, reason)); } @Override public void onEndpointSessionOpenRequest( - int i, EndpointId destination, EndpointId initiator, String s) throws RemoteException { + int sessionId, EndpointId destination, EndpointId initiator, String serviceDescriptor) + throws RemoteException { HubEndpointInfo.HubEndpointIdentifier destinationId = new HubEndpointInfo.HubEndpointIdentifier(destination.hubId, destination.id); HubEndpointInfo.HubEndpointIdentifier initiatorId = new HubEndpointInfo.HubEndpointIdentifier(initiator.hubId, initiator.id); - mEndpointSessionCallback.onEndpointSessionOpenRequest(i, destinationId, initiatorId, s); + mHandler.post( + () -> + mEndpointSessionCallback.onEndpointSessionOpenRequest( + sessionId, destinationId, initiatorId, serviceDescriptor)); } @Override - public void onCloseEndpointSession(int i, byte b) throws RemoteException { - mEndpointSessionCallback.onCloseEndpointSession(i, b); + public void onCloseEndpointSession(int sessionId, byte reason) throws RemoteException { + mHandler.post(() -> mEndpointSessionCallback.onCloseEndpointSession(sessionId, reason)); } @Override - public void onEndpointSessionOpenComplete(int i) throws RemoteException { - mEndpointSessionCallback.onEndpointSessionOpenComplete(i); + public void onEndpointSessionOpenComplete(int sessionId) throws RemoteException { + mHandler.post(() -> mEndpointSessionCallback.onEndpointSessionOpenComplete(sessionId)); } @Override - public void onMessageReceived(int i, Message message) throws RemoteException { + public void onMessageReceived(int sessionId, Message message) throws RemoteException { HubMessage hubMessage = ContextHubServiceUtil.createHubMessage(message); - mEndpointSessionCallback.onMessageReceived(i, hubMessage); + mHandler.post(() -> mEndpointSessionCallback.onMessageReceived(sessionId, hubMessage)); } @Override - public void onMessageDeliveryStatusReceived(int i, MessageDeliveryStatus messageDeliveryStatus) - throws RemoteException { - mEndpointSessionCallback.onMessageDeliveryStatusReceived( - i, messageDeliveryStatus.messageSequenceNumber, messageDeliveryStatus.errorCode); + public void onMessageDeliveryStatusReceived( + int sessionId, MessageDeliveryStatus messageDeliveryStatus) throws RemoteException { + mHandler.post( + () -> + mEndpointSessionCallback.onMessageDeliveryStatusReceived( + sessionId, + messageDeliveryStatus.messageSequenceNumber, + messageDeliveryStatus.errorCode)); } @Override diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubService.java b/services/core/java/com/android/server/location/contexthub/ContextHubService.java index f91b030dd1ba..54ed5a9711b3 100644 --- a/services/core/java/com/android/server/location/contexthub/ContextHubService.java +++ b/services/core/java/com/android/server/location/contexthub/ContextHubService.java @@ -338,8 +338,9 @@ public class ContextHubService extends IContextHubService.Stub { mEndpointManager = new ContextHubEndpointManager( mContext, mContextHubWrapper, registry, mTransactionManager); + mEndpointManager.init(); Log.i(TAG, "Enabling generic offload API"); - } catch (UnsupportedOperationException e) { + } catch (InstantiationException e) { mEndpointManager = null; registry = null; Log.w(TAG, "Generic offload API not supported, disabling"); @@ -352,7 +353,6 @@ public class ContextHubService extends IContextHubService.Stub { } initDefaultClientMap(); - initEndpointCallback(); initLocationSettingNotifications(); initWifiSettingNotifications(); @@ -531,18 +531,6 @@ public class ContextHubService extends IContextHubService.Stub { mDefaultClientMap = Collections.unmodifiableMap(defaultClientMap); } - private void initEndpointCallback() { - if (mHubInfoRegistry == null) { - return; - } - try { - mContextHubWrapper.registerEndpointCallback( - new ContextHubHalEndpointCallback(mHubInfoRegistry, mEndpointManager)); - } catch (RemoteException | UnsupportedOperationException e) { - Log.e(TAG, "Exception while registering IEndpointCallback", e); - } - } - /** * Initializes existing callbacks with the mContextHubWrapper for every context hub */ @@ -799,14 +787,16 @@ public class ContextHubService extends IContextHubService.Stub { public IContextHubEndpoint registerEndpoint( HubEndpointInfo pendingHubEndpointInfo, IContextHubEndpointCallback callback, - String packageName) + String packageName, + String attributionTag) throws RemoteException { super.registerEndpoint_enforcePermission(); if (mEndpointManager == null) { Log.e(TAG, "Endpoint manager failed to initialize"); throw new UnsupportedOperationException("Endpoint registration is not supported"); } - return mEndpointManager.registerEndpoint(pendingHubEndpointInfo, callback, packageName); + return mEndpointManager.registerEndpoint( + pendingHubEndpointInfo, callback, packageName, attributionTag); } @android.annotation.EnforcePermission(android.Manifest.permission.ACCESS_CONTEXT_HUB) diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubServiceUtil.java b/services/core/java/com/android/server/location/contexthub/ContextHubServiceUtil.java index 7b59d6f1301e..a41194b898ac 100644 --- a/services/core/java/com/android/server/location/contexthub/ContextHubServiceUtil.java +++ b/services/core/java/com/android/server/location/contexthub/ContextHubServiceUtil.java @@ -601,7 +601,7 @@ import java.util.List; int uid, String packageName, String attributionTag, - List<String> permissions, + Collection<String> permissions, String noteMessage) { for (String permission : permissions) { int opCode = AppOpsManager.permissionToOpCode(permission); diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubTransactionManager.java b/services/core/java/com/android/server/location/contexthub/ContextHubTransactionManager.java index 5dd40ea97a64..a430a82fc13b 100644 --- a/services/core/java/com/android/server/location/contexthub/ContextHubTransactionManager.java +++ b/services/core/java/com/android/server/location/contexthub/ContextHubTransactionManager.java @@ -17,6 +17,7 @@ package com.android.server.location.contexthub; import android.chre.flags.Flags; +import android.hardware.contexthub.IEndpointCommunication; import android.hardware.contexthub.Message; import android.hardware.location.ContextHubTransaction; import android.hardware.location.IContextHubTransactionCallback; @@ -402,12 +403,14 @@ import java.util.concurrent.atomic.AtomicInteger; /** * Creates a transaction to send a message through a session. * + * @param hubInterface Interface for interacting with other endpoint hubs. * @param sessionId The ID of the endpoint session the message should be sent through. * @param message The message to send. * @param transactionCallback The callback of the transactions. * @return The generated transaction. */ /* package */ ContextHubServiceTransaction createSessionMessageTransaction( + IEndpointCommunication hubInterface, int sessionId, Message message, String packageName, @@ -422,7 +425,7 @@ import java.util.concurrent.atomic.AtomicInteger; /* package */ int onTransact() { try { message.sequenceNumber = getMessageSequenceNumber(); - mContextHubProxy.sendMessageToEndpoint(sessionId, message); + hubInterface.sendMessageToEndpoint(sessionId, message); return ContextHubTransaction.RESULT_SUCCESS; } catch (RemoteException e) { Log.e(TAG, "RemoteException while trying to send a session message", e); diff --git a/services/core/java/com/android/server/location/contexthub/HubInfoRegistry.java b/services/core/java/com/android/server/location/contexthub/HubInfoRegistry.java index 503f1aca64d9..6e650c207358 100644 --- a/services/core/java/com/android/server/location/contexthub/HubInfoRegistry.java +++ b/services/core/java/com/android/server/location/contexthub/HubInfoRegistry.java @@ -98,10 +98,16 @@ class HubInfoRegistry implements ContextHubHalEndpointCallback.IEndpointLifecycl private final Object mCallbackLock = new Object(); - HubInfoRegistry(IContextHubWrapper contextHubWrapper) { + HubInfoRegistry(IContextHubWrapper contextHubWrapper) throws InstantiationException { mContextHubWrapper = contextHubWrapper; - refreshCachedHubs(); - refreshCachedEndpoints(); + try { + refreshCachedHubs(); + refreshCachedEndpoints(); + } catch (UnsupportedOperationException e) { + String error = "Failed to update hub and endpoint cache"; + Log.e(TAG, error, e); + throw new InstantiationException(error); + } } /** Retrieve the list of hubs available. */ diff --git a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java index e1df503eccdb..a9bd38f6daf9 100644 --- a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java +++ b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java @@ -18,10 +18,8 @@ package com.android.server.location.contexthub; import android.annotation.NonNull; import android.annotation.Nullable; import android.chre.flags.Flags; -import android.hardware.contexthub.EndpointId; import android.hardware.contexthub.HostEndpointInfo; import android.hardware.contexthub.HubEndpointInfo; -import android.hardware.contexthub.Message; import android.hardware.contexthub.MessageDeliveryStatus; import android.hardware.contexthub.NanSessionRequest; import android.hardware.contexthub.V1_0.ContextHub; @@ -238,40 +236,13 @@ public abstract class IContextHubWrapper { } /** Calls the appropriate registerEndpointCallback function depending on the HAL version. */ - public void registerEndpointCallback(android.hardware.contexthub.IEndpointCallback cb) - throws RemoteException {} - - /** Registers the endpoint with the ContextHub HAL */ - public void registerEndpoint(android.hardware.contexthub.EndpointInfo info) - throws RemoteException {} - - /** Unregisters a previously registered endpoint */ - public int[] requestSessionIdRange(int size) throws RemoteException { - return null; + public android.hardware.contexthub.IEndpointCommunication registerEndpointHub( + android.hardware.contexthub.IEndpointCallback cb, + android.hardware.contexthub.HubInfo hubInfo) + throws RemoteException { + throw new UnsupportedOperationException(); } - /** Opens an endpoint session between two endpoints */ - public void openEndpointSession( - int sessionId, EndpointId destination, EndpointId initiator, String serviceDescriptor) - throws RemoteException {} - - /** Closes a previously opened endpoint */ - public void closeEndpointSession(int sessionId, byte reason) throws RemoteException {} - - /** Unregisters a previously registered endpoint */ - public void unregisterEndpoint(android.hardware.contexthub.EndpointInfo info) - throws RemoteException {} - - /** Notifies the completion of a session opened by the HAL */ - public void endpointSessionOpenComplete(int sessionId) throws RemoteException {} - - /** Sends a message to a remote endpoint */ - public void sendMessageToEndpoint(int sessionId, Message msg) throws RemoteException {} - - /** Sends a message delivery status to a remote endpoint */ - public void sendMessageDeliveryStatusToEndpoint(int sessionId, MessageDeliveryStatus msgStatus) - throws RemoteException {} - /** * @return True if this version of the Contexthub HAL supports Location setting notifications. */ @@ -691,97 +662,19 @@ public abstract class IContextHubWrapper { } @Override - public void registerEndpointCallback(android.hardware.contexthub.IEndpointCallback cb) - throws RemoteException { - android.hardware.contexthub.IContextHub hub = getHub(); - if (hub == null) { - return; - } - - if (DEBUG) { - Log.i(TAG, "registerEndpointCallback: cb=" + cb); - } - hub.registerEndpointCallback(cb); - } - - @Override - public void registerEndpoint(android.hardware.contexthub.EndpointInfo info) - throws RemoteException { - android.hardware.contexthub.IContextHub hub = getHub(); - if (hub == null) { - return; - } - hub.registerEndpoint(info); - } - - @Override - public int[] requestSessionIdRange(int size) throws RemoteException { + public android.hardware.contexthub.IEndpointCommunication registerEndpointHub( + android.hardware.contexthub.IEndpointCallback cb, + android.hardware.contexthub.HubInfo hubInfo) + throws RemoteException { android.hardware.contexthub.IContextHub hub = getHub(); if (hub == null) { return null; } - return hub.requestSessionIdRange(size); - } - - @Override - public void openEndpointSession( - int sessionId, - EndpointId destination, - EndpointId initiator, - String serviceDescriptor) - throws RemoteException { - android.hardware.contexthub.IContextHub hub = getHub(); - if (hub == null) { - return; - } - hub.openEndpointSession(sessionId, destination, initiator, serviceDescriptor); - } - - @Override - public void closeEndpointSession(int sessionId, byte reason) throws RemoteException { - android.hardware.contexthub.IContextHub hub = getHub(); - if (hub == null) { - return; - } - hub.closeEndpointSession(sessionId, reason); - } - - @Override - public void unregisterEndpoint(android.hardware.contexthub.EndpointInfo info) - throws RemoteException { - android.hardware.contexthub.IContextHub hub = getHub(); - if (hub == null) { - return; - } - hub.unregisterEndpoint(info); - } - @Override - public void endpointSessionOpenComplete(int sessionId) throws RemoteException { - android.hardware.contexthub.IContextHub hub = getHub(); - if (hub == null) { - return; - } - hub.endpointSessionOpenComplete(sessionId); - } - - @Override - public void sendMessageToEndpoint(int sessionId, Message msg) throws RemoteException { - android.hardware.contexthub.IContextHub hub = getHub(); - if (hub == null) { - return; - } - hub.sendMessageToEndpoint(sessionId, msg); - } - - @Override - public void sendMessageDeliveryStatusToEndpoint( - int sessionId, MessageDeliveryStatus msgStatus) throws RemoteException { - android.hardware.contexthub.IContextHub hub = getHub(); - if (hub == null) { - return; + if (DEBUG) { + Log.i(TAG, "registerEndpointHub: cb=" + cb); } - hub.sendMessageDeliveryStatusToEndpoint(sessionId, msgStatus); + return hub.registerEndpointHub(cb, hubInfo); } public boolean supportsLocationSettingNotifications() { diff --git a/services/core/java/com/android/server/media/quality/MediaQualityService.java b/services/core/java/com/android/server/media/quality/MediaQualityService.java index c81023144c0f..34bb4155c943 100644 --- a/services/core/java/com/android/server/media/quality/MediaQualityService.java +++ b/services/core/java/com/android/server/media/quality/MediaQualityService.java @@ -26,12 +26,14 @@ import android.media.quality.IMediaQualityManager; import android.media.quality.IPictureProfileCallback; import android.media.quality.ISoundProfileCallback; import android.media.quality.MediaQualityContract.BaseParameters; -import android.media.quality.ParamCapability; +import android.media.quality.MediaQualityManager; +import android.media.quality.ParameterCapability; import android.media.quality.PictureProfile; import android.media.quality.PictureProfileHandle; import android.media.quality.SoundProfile; import android.media.quality.SoundProfileHandle; import android.os.Binder; +import android.os.Bundle; import android.os.PersistableBundle; import android.os.UserHandle; import android.util.Log; @@ -130,8 +132,10 @@ public class MediaQualityService extends SystemService { } @Override - public PictureProfile getPictureProfile(int type, String name, boolean includeParams, + public PictureProfile getPictureProfile(int type, String name, Bundle options, UserHandle user) { + boolean includeParams = + options.getBoolean(MediaQualityManager.OPTION_INCLUDE_PARAMETERS, false); String selection = BaseParameters.PARAMETER_TYPE + " = ? AND " + BaseParameters.PARAMETER_NAME + " = ?"; String[] selectionArguments = {Integer.toString(type), name}; @@ -158,7 +162,9 @@ public class MediaQualityService extends SystemService { @Override public List<PictureProfile> getPictureProfilesByPackage( - String packageName, boolean includeParams, UserHandle user) { + String packageName, Bundle options, UserHandle user) { + boolean includeParams = + options.getBoolean(MediaQualityManager.OPTION_INCLUDE_PARAMETERS, false); String selection = BaseParameters.PARAMETER_PACKAGE + " = ?"; String[] selectionArguments = {packageName}; return getPictureProfilesBasedOnConditions(getMediaProfileColumns(includeParams), @@ -166,12 +172,11 @@ public class MediaQualityService extends SystemService { } @Override - public List<PictureProfile> getAvailablePictureProfiles( - boolean includeParams, UserHandle user) { + public List<PictureProfile> getAvailablePictureProfiles(Bundle options, UserHandle user) { String[] packageNames = mContext.getPackageManager().getPackagesForUid( Binder.getCallingUid()); if (packageNames != null && packageNames.length == 1 && !packageNames[0].isEmpty()) { - return getPictureProfilesByPackage(packageNames[0], includeParams, user); + return getPictureProfilesByPackage(packageNames[0], options, user); } return new ArrayList<>(); } @@ -251,8 +256,10 @@ public class MediaQualityService extends SystemService { } @Override - public SoundProfile getSoundProfile(int type, String id, boolean includeParams, + public SoundProfile getSoundProfile(int type, String id, Bundle options, UserHandle user) { + boolean includeParams = + options.getBoolean(MediaQualityManager.OPTION_INCLUDE_PARAMETERS, false); String selection = BaseParameters.PARAMETER_TYPE + " = ? AND " + BaseParameters.PARAMETER_ID + " = ?"; String[] selectionArguments = {String.valueOf(type), id}; @@ -279,7 +286,9 @@ public class MediaQualityService extends SystemService { @Override public List<SoundProfile> getSoundProfilesByPackage( - String packageName, boolean includeParams, UserHandle user) { + String packageName, Bundle options, UserHandle user) { + boolean includeParams = + options.getBoolean(MediaQualityManager.OPTION_INCLUDE_PARAMETERS, false); String selection = BaseParameters.PARAMETER_PACKAGE + " = ?"; String[] selectionArguments = {packageName}; return getSoundProfilesBasedOnConditions(getMediaProfileColumns(includeParams), @@ -288,11 +297,11 @@ public class MediaQualityService extends SystemService { @Override public List<SoundProfile> getAvailableSoundProfiles( - boolean includeParams, UserHandle user) { + Bundle options, UserHandle user) { String[] packageNames = mContext.getPackageManager().getPackagesForUid( Binder.getCallingUid()); if (packageNames != null && packageNames.length == 1 && !packageNames[0].isEmpty()) { - return getSoundProfilesByPackage(packageNames[0], includeParams, user); + return getSoundProfilesByPackage(packageNames[0], options, user); } return new ArrayList<>(); } @@ -535,7 +544,8 @@ public class MediaQualityService extends SystemService { } @Override - public List<ParamCapability> getParamCapabilities(List<String> names, UserHandle user) { + public List<ParameterCapability> getParameterCapabilities( + List<String> names, UserHandle user) { return new ArrayList<>(); } diff --git a/services/core/java/com/android/server/om/OverlayReferenceMapper.java b/services/core/java/com/android/server/om/OverlayReferenceMapper.java index f8ae99aa2e3e..fdceabe74dd8 100644 --- a/services/core/java/com/android/server/om/OverlayReferenceMapper.java +++ b/services/core/java/com/android/server/om/OverlayReferenceMapper.java @@ -26,10 +26,13 @@ import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.CollectionUtils; import com.android.server.SystemConfig; import com.android.server.pm.pkg.AndroidPackage; import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -118,16 +121,20 @@ public class OverlayReferenceMapper { return actorPair.first; } - @Nullable + @NonNull @Override - public Pair<String, String> getTargetToOverlayables(@NonNull AndroidPackage pkg) { + public Map<String, Set<String>> getTargetToOverlayables(@NonNull AndroidPackage pkg) { String target = pkg.getOverlayTarget(); if (TextUtils.isEmpty(target)) { - return null; + return Collections.emptyMap(); } String overlayable = pkg.getOverlayTargetOverlayableName(); - return Pair.create(target, overlayable); + Map<String, Set<String>> targetToOverlayables = new HashMap<>(); + Set<String> overlayables = new HashSet<>(); + overlayables.add(overlayable); + targetToOverlayables.put(target, overlayables); + return targetToOverlayables; } }; } @@ -167,7 +174,7 @@ public class OverlayReferenceMapper { } // TODO(b/135203078): Replace with isOverlay boolean flag check; fix test mocks - if (mProvider.getTargetToOverlayables(pkg) != null) { + if (!mProvider.getTargetToOverlayables(pkg).isEmpty()) { addOverlay(pkg, otherPkgs, changed); } @@ -238,17 +245,20 @@ public class OverlayReferenceMapper { String target = targetPkg.getPackageName(); removeTarget(target, changedPackages); - final Map<String, String> overlayablesToActors = targetPkg.getOverlayables(); - for (final var entry : overlayablesToActors.entrySet()) { - final String overlayable = entry.getKey(); - final String actor = entry.getValue(); + Map<String, String> overlayablesToActors = targetPkg.getOverlayables(); + for (String overlayable : overlayablesToActors.keySet()) { + String actor = overlayablesToActors.get(overlayable); addTargetToMap(actor, target, changedPackages); for (AndroidPackage overlayPkg : otherPkgs.values()) { - var targetToOverlayables = + Map<String, Set<String>> targetToOverlayables = mProvider.getTargetToOverlayables(overlayPkg); - if (targetToOverlayables != null && targetToOverlayables.first.equals(target) - && targetToOverlayables.second.equals(overlayable)) { + Set<String> overlayables = targetToOverlayables.get(target); + if (CollectionUtils.isEmpty(overlayables)) { + continue; + } + + if (overlayables.contains(overlayable)) { String overlay = overlayPkg.getPackageName(); addOverlayToMap(actor, target, overlay, changedPackages); } @@ -300,22 +310,25 @@ public class OverlayReferenceMapper { String overlay = overlayPkg.getPackageName(); removeOverlay(overlay, changedPackages); - Pair<String, String> targetToOverlayables = + Map<String, Set<String>> targetToOverlayables = mProvider.getTargetToOverlayables(overlayPkg); - if (targetToOverlayables != null) { - String target = targetToOverlayables.first; + for (Map.Entry<String, Set<String>> entry : targetToOverlayables.entrySet()) { + String target = entry.getKey(); + Set<String> overlayables = entry.getValue(); AndroidPackage targetPkg = otherPkgs.get(target); if (targetPkg == null) { - return; + continue; } + String targetPkgName = targetPkg.getPackageName(); Map<String, String> overlayableToActor = targetPkg.getOverlayables(); - String overlayable = targetToOverlayables.second; - String actor = overlayableToActor.get(overlayable); - if (TextUtils.isEmpty(actor)) { - return; + for (String overlayable : overlayables) { + String actor = overlayableToActor.get(overlayable); + if (TextUtils.isEmpty(actor)) { + continue; + } + addOverlayToMap(actor, targetPkgName, overlay, changedPackages); } - addOverlayToMap(actor, targetPkgName, overlay, changedPackages); } } } @@ -417,11 +430,11 @@ public class OverlayReferenceMapper { String getActorPkg(@NonNull String actor); /** - * Mock response of overlay tags. + * Mock response of multiple overlay tags. * * TODO(b/119899133): Replace with actual implementation; fix OverlayReferenceMapperTests */ - @Nullable - Pair<String, String> getTargetToOverlayables(@NonNull AndroidPackage pkg); + @NonNull + Map<String, Set<String>> getTargetToOverlayables(@NonNull AndroidPackage pkg); } } diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java index 38617621bf89..b441e9dd561d 100644 --- a/services/core/java/com/android/server/pm/ComputerEngine.java +++ b/services/core/java/com/android/server/pm/ComputerEngine.java @@ -5386,7 +5386,7 @@ public class ComputerEngine implements Computer { + ", uid:" + callingUid); throw new IllegalArgumentException("Unknown package: " + packageName); } - if (pkg.getUid() != callingUid + if (!UserHandle.isSameApp(callingUid, pkg.getUid()) && Process.SYSTEM_UID != callingUid) { throw new SecurityException("May not access signing KeySet of other apps."); } diff --git a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java index 24d857b0fc1f..caaf5a2b16d0 100644 --- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java +++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java @@ -12746,20 +12746,24 @@ public class BatteryStatsImpl extends BatteryStats { // Distribute the remaining Tx power appropriately between all apps that transmitted // packets. - for (int i = 0; i < txPackets.size(); i++) { - final int uid = txPackets.keyAt(i); - final long myTxTimeMs = (txPackets.valueAt(i) * leftOverTxTimeMs) - / totalTxPackets; - txTimesMs.incrementValue(uid, myTxTimeMs); + if (totalTxPackets != 0 && leftOverTxTimeMs != 0) { + for (int i = 0; i < txPackets.size(); i++) { + final int uid = txPackets.keyAt(i); + final long myTxTimeMs = (txPackets.valueAt(i) * leftOverTxTimeMs) + / totalTxPackets; + txTimesMs.incrementValue(uid, myTxTimeMs); + } } // Distribute the remaining Rx power appropriately between all apps that received // packets. - for (int i = 0; i < rxPackets.size(); i++) { - final int uid = rxPackets.keyAt(i); - final long myRxTimeMs = (rxPackets.valueAt(i) * leftOverRxTimeMs) - / totalRxPackets; - rxTimesMs.incrementValue(uid, myRxTimeMs); + if (totalRxPackets != 0 && leftOverRxTimeMs != 0) { + for (int i = 0; i < rxPackets.size(); i++) { + final int uid = rxPackets.keyAt(i); + final long myRxTimeMs = (rxPackets.valueAt(i) * leftOverRxTimeMs) + / totalRxPackets; + rxTimesMs.incrementValue(uid, myRxTimeMs); + } } for (int i = 0; i < txTimesMs.size(); i++) { diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java index 83cb72e1df1f..1f162a26fa95 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java @@ -113,6 +113,11 @@ public interface StatusBarManagerInternal { void startAssist(Bundle args); void onCameraLaunchGestureDetected(int source); + + /** + * Notifies SysUI that the wallet launch gesture has been detected. + */ + void onWalletLaunchGestureDetected(); void setDisableFlags(int displayId, int flags, String cause); void toggleSplitScreen(); void appTransitionFinished(int displayId); diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index c18918fd9f8b..4ed5f90f2852 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -419,6 +419,17 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D } } + @Override + public void onWalletLaunchGestureDetected() { + IStatusBar bar = mBar; + if (bar != null) { + try { + bar.onWalletLaunchGestureDetected(); + } catch (RemoteException e) { + } + } + } + /** * Notifies the status bar that a Emergency Action launch gesture has been detected. * diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index e4ad56fdc074..093df8c5075c 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -2668,11 +2668,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } // Only do transfer after transaction has done when starting window exist. if (mStartingData != null) { - final boolean isWaitingForSyncTransactionCommit = - Flags.removeStartingWindowWaitForMultiTransitions() - ? getSyncTransactionCommitCallbackDepth() > 0 - : mStartingData.mWaitForSyncTransactionCommit; - if (isWaitingForSyncTransactionCommit) { + if (getSyncTransactionCommitCallbackDepth() > 0) { mStartingData.mRemoveAfterTransaction = AFTER_TRANSACTION_COPY_TO_CLIENT; return true; } @@ -2835,21 +2831,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } @Override - void waitForSyncTransactionCommit(ArraySet<WindowContainer> wcAwaitingCommit) { - super.waitForSyncTransactionCommit(wcAwaitingCommit); - if (mStartingData != null) { - mStartingData.mWaitForSyncTransactionCommit = true; - } - } - - @Override void onSyncTransactionCommitted(SurfaceControl.Transaction t) { super.onSyncTransactionCommitted(t); if (mStartingData == null) { return; } final StartingData lastData = mStartingData; - lastData.mWaitForSyncTransactionCommit = false; if (lastData.mRemoveAfterTransaction == AFTER_TRANSACTION_REMOVE_DIRECTLY) { removeStartingWindowAnimation(lastData.mPrepareRemoveAnimation); } else if (lastData.mRemoveAfterTransaction == AFTER_TRANSACTION_COPY_TO_CLIENT) { @@ -2879,12 +2866,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A final boolean animate; final boolean hasImeSurface; if (mStartingData != null) { - final boolean isWaitingForSyncTransactionCommit = - Flags.removeStartingWindowWaitForMultiTransitions() - ? getSyncTransactionCommitCallbackDepth() > 0 - : mStartingData.mWaitForSyncTransactionCommit; - if (isWaitingForSyncTransactionCommit - || mSyncState != SYNC_STATE_NONE) { + if (getSyncTransactionCommitCallbackDepth() > 0 || mSyncState != SYNC_STATE_NONE) { mStartingData.mRemoveAfterTransaction = AFTER_TRANSACTION_REMOVE_DIRECTLY; mStartingData.mPrepareRemoveAnimation = prepareAnimation; return; diff --git a/services/core/java/com/android/server/wm/BLASTSyncEngine.java b/services/core/java/com/android/server/wm/BLASTSyncEngine.java index 94830fa11134..6eda3cf48eb4 100644 --- a/services/core/java/com/android/server/wm/BLASTSyncEngine.java +++ b/services/core/java/com/android/server/wm/BLASTSyncEngine.java @@ -95,6 +95,7 @@ class BLASTSyncEngine { interface TransactionReadyListener { void onTransactionReady(int mSyncId, SurfaceControl.Transaction transaction); + default void onTransactionCommitted() {} default void onTransactionCommitTimeout() {} default void onReadyTimeout() {} @@ -224,20 +225,19 @@ class BLASTSyncEngine { if (mOrphanTransaction != null) { merged.merge(mOrphanTransaction); } - for (WindowContainer wc : mRootMembers) { - wc.finishSync(merged, this, false /* cancel */); - } - - final ArraySet<WindowContainer> wcAwaitingCommit = new ArraySet<>(); - for (WindowContainer wc : mRootMembers) { - wc.waitForSyncTransactionCommit(wcAwaitingCommit); - } final long mergedTxId = merged.getId(); class CommitCallback implements Runnable { + final ArraySet<WindowContainer> mWcAwaitingCommit = new ArraySet<>(); + // Can run a second time if the action completes after the timeout. boolean ran = false; public void onCommitted(SurfaceControl.Transaction t) { + mListener.onTransactionCommitted(); + if (mTraceName != null) { + Trace.instant(TRACE_TAG_WINDOW_MANAGER, + mSyncName + "#" + mSyncId + "-committed"); + } // Don't wait to hold the global lock to remove the timeout runnable mHandler.removeCallbacks(this); synchronized (mWm.mGlobalLock) { @@ -245,11 +245,11 @@ class BLASTSyncEngine { return; } ran = true; - for (WindowContainer wc : wcAwaitingCommit) { - wc.onSyncTransactionCommitted(t); + for (int i = mWcAwaitingCommit.size() - 1; i >= 0; --i) { + mWcAwaitingCommit.valueAt(i).onSyncTransactionCommitted(t); } t.apply(); - wcAwaitingCommit.clear(); + mWcAwaitingCommit.clear(); } } @@ -272,6 +272,12 @@ class BLASTSyncEngine { } }; CommitCallback callback = new CommitCallback(); + for (int i = mRootMembers.size() - 1; i >= 0; --i) { + final WindowContainer<?> wc = mRootMembers.valueAt(i); + wc.finishSync(merged, this, false /* cancel */); + wc.waitForSyncTransactionCommit(callback.mWcAwaitingCommit); + } + merged.addTransactionCommittedListener(Runnable::run, () -> callback.onCommitted(new SurfaceControl.Transaction())); mHandler.postDelayed(callback, BLAST_TIMEOUT_DURATION); diff --git a/services/core/java/com/android/server/wm/StartingData.java b/services/core/java/com/android/server/wm/StartingData.java index 896612d3d27a..7349224ddcd8 100644 --- a/services/core/java/com/android/server/wm/StartingData.java +++ b/services/core/java/com/android/server/wm/StartingData.java @@ -63,18 +63,6 @@ public abstract class StartingData { /** * For Shell transition. - * There will be a transition happen on attached activity, do not remove starting window during - * this period, because the transaction to show app window may not apply before remove starting - * window. - * Note this isn't equal to transition playing, the period should be - * Sync finishNow -> Start transaction apply. - * @deprecated TODO(b/362347290): cleanup after fix ramp up - */ - @Deprecated - boolean mWaitForSyncTransactionCommit; - - /** - * For Shell transition. * This starting window should be removed after applying the start transaction of transition, * which ensures the app window has shown. */ @@ -114,7 +102,6 @@ public abstract class StartingData { public String toString() { return getClass().getSimpleName() + "{" + Integer.toHexString(System.identityHashCode(this)) - + " waitForSyncTransactionCommit=" + mWaitForSyncTransactionCommit + " removeAfterTransaction= " + mRemoveAfterTransaction + "}"; } diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index e7ed61ae57fb..f0faa8e4691f 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -1977,7 +1977,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { } else { // No player registered or it's not enabled, so just finish/apply immediately if (!mIsPlayerEnabled) { - mLogger.mSendTimeNs = SystemClock.uptimeNanos(); + mLogger.mSendTimeNs = SystemClock.elapsedRealtimeNanos(); ProtoLog.v(WmProtoLogGroups.WM_DEBUG_WINDOW_TRANSITIONS, "Apply and finish immediately because player is disabled " + "for transition #%d .", mSyncId); @@ -2080,6 +2080,12 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { } } + // Note that this method is not called in WM lock. + @Override + public void onTransactionCommitted() { + mLogger.mTransactionCommitTimeNs = SystemClock.elapsedRealtimeNanos(); + } + @Override public void onTransactionCommitTimeout() { if (mCleanupTransaction == null) return; @@ -3991,7 +3997,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { /** @return true if all tracked subtrees are ready. */ boolean allReady() { ProtoLog.v(WmProtoLogGroups.WM_DEBUG_WINDOW_TRANSITIONS, - " allReady query: used=%b " + "override=%b defer=%d states=[%s]", mUsed, + " allReady query: used=%b override=%b defer=%d states=[%s]", mUsed, mReadyOverride, mDeferReadyDepth, groupsToString()); // If the readiness has never been touched, mUsed will be false. We never want to // consider a transition ready if nothing has been reported on it. diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java index f3c03cbfb3b4..ff9e5a2aad99 100644 --- a/services/core/java/com/android/server/wm/TransitionController.java +++ b/services/core/java/com/android/server/wm/TransitionController.java @@ -774,7 +774,7 @@ class TransitionController { "Disabling player for transition #%d because display isn't enabled yet", transition.getSyncId()); transition.mIsPlayerEnabled = false; - transition.mLogger.mRequestTimeNs = SystemClock.uptimeNanos(); + transition.mLogger.mRequestTimeNs = SystemClock.elapsedRealtimeNanos(); mAtm.mH.post(() -> mAtm.mWindowOrganizerController.startTransition( transition.getToken(), null)); return transition; @@ -1694,6 +1694,7 @@ class TransitionController { long mStartTimeNs; long mReadyTimeNs; long mSendTimeNs; + long mTransactionCommitTimeNs; long mFinishTimeNs; long mAbortTimeNs; TransitionRequestInfo mRequest; @@ -1746,6 +1747,9 @@ class TransitionController { sb.append(" started=").append(toMsString(mStartTimeNs - mCreateTimeNs)); sb.append(" ready=").append(toMsString(mReadyTimeNs - mCreateTimeNs)); sb.append(" sent=").append(toMsString(mSendTimeNs - mCreateTimeNs)); + if (mTransactionCommitTimeNs != 0) { + sb.append(" commit=").append(toMsString(mTransactionCommitTimeNs - mSendTimeNs)); + } sb.append(" finished=").append(toMsString(mFinishTimeNs - mCreateTimeNs)); return sb.toString(); } diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/AppsFilterImplTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/AppsFilterImplTest.java index 66aaa562b873..7277fd79fdd5 100644 --- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/AppsFilterImplTest.java +++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/AppsFilterImplTest.java @@ -45,7 +45,6 @@ import android.os.UserHandle; import android.platform.test.annotations.Presubmit; import android.util.ArrayMap; import android.util.ArraySet; -import android.util.Pair; import android.util.SparseArray; import androidx.annotation.NonNull; @@ -79,7 +78,10 @@ import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.Set; @Presubmit @RunWith(JUnit4.class) @@ -883,15 +885,18 @@ public class AppsFilterImplTest { return null; } - @Nullable + @NonNull @Override - public Pair<String, String> getTargetToOverlayables( + public Map<String, Set<String>> getTargetToOverlayables( @NonNull AndroidPackage pkg) { if (overlay.getPackageName().equals(pkg.getPackageName())) { - return Pair.create(overlay.getOverlayTarget(), - overlay.getOverlayTargetOverlayableName()); + Map<String, Set<String>> map = new ArrayMap<>(); + Set<String> set = new ArraySet<>(); + set.add(overlay.getOverlayTargetOverlayableName()); + map.put(overlay.getOverlayTarget(), set); + return map; } - return null; + return Collections.emptyMap(); } }, mMockHandler); @@ -972,15 +977,18 @@ public class AppsFilterImplTest { return null; } - @Nullable + @NonNull @Override - public Pair<String, String> getTargetToOverlayables( + public Map<String, Set<String>> getTargetToOverlayables( @NonNull AndroidPackage pkg) { if (overlay.getPackageName().equals(pkg.getPackageName())) { - return Pair.create(overlay.getOverlayTarget(), - overlay.getOverlayTargetOverlayableName()); + Map<String, Set<String>> map = new ArrayMap<>(); + Set<String> set = new ArraySet<>(); + set.add(overlay.getOverlayTargetOverlayableName()); + map.put(overlay.getOverlayTarget(), set); + return map; } - return null; + return Collections.emptyMap(); } }, mMockHandler); diff --git a/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java index 0e9dfedac0c9..7d25acd7f5e7 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/AutomaticBrightnessControllerTest.java @@ -52,6 +52,7 @@ import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import com.android.server.display.brightness.clamper.BrightnessClamperController; import com.android.server.display.config.HysteresisLevels; import com.android.server.display.feature.DisplayManagerFlags; import com.android.server.testutils.OffsettableClock; @@ -102,7 +103,8 @@ public class AutomaticBrightnessControllerTest { @Mock BrightnessRangeController mBrightnessRangeController; @Mock DisplayManagerFlags mDisplayManagerFlags; - @Mock BrightnessThrottler mBrightnessThrottler; + @Mock + BrightnessClamperController mBrightnessClamperController; @Before public void setUp() throws Exception { @@ -175,7 +177,7 @@ public class AutomaticBrightnessControllerTest { RESET_AMBIENT_LUX_AFTER_WARMUP_CONFIG, mAmbientBrightnessThresholds, mScreenBrightnessThresholds, mAmbientBrightnessThresholdsIdle, mScreenBrightnessThresholdsIdle, - mContext, mBrightnessRangeController, mBrightnessThrottler, + mContext, mBrightnessRangeController, mBrightnessClamperController, useHorizon ? AMBIENT_LIGHT_HORIZON_SHORT : 1, useHorizon ? AMBIENT_LIGHT_HORIZON_LONG : 10000, userLux, userNits, mDisplayManagerFlags @@ -186,8 +188,8 @@ public class AutomaticBrightnessControllerTest { when(mBrightnessRangeController.getCurrentBrightnessMin()).thenReturn( BRIGHTNESS_MIN_FLOAT); // Disable brightness throttling by default. Individual tests can enable it as needed. - when(mBrightnessThrottler.getBrightnessCap()).thenReturn(BRIGHTNESS_MAX_FLOAT); - when(mBrightnessThrottler.isThrottled()).thenReturn(false); + when(mBrightnessClamperController.getMaxBrightness()).thenReturn(BRIGHTNESS_MAX_FLOAT); + when(mBrightnessClamperController.isThrottled()).thenReturn(false); // Configure the brightness controller and grab an instance of the sensor listener, // through which we can deliver fake (for test) sensor values. @@ -754,8 +756,8 @@ public class AutomaticBrightnessControllerTest { // Apply throttling and notify ABC (simulates DisplayPowerController#updatePowerState()) final float throttledBrightness = 0.123f; - when(mBrightnessThrottler.getBrightnessCap()).thenReturn(throttledBrightness); - when(mBrightnessThrottler.isThrottled()).thenReturn(true); + when(mBrightnessClamperController.getMaxBrightness()).thenReturn(throttledBrightness); + when(mBrightnessClamperController.isThrottled()).thenReturn(true); mController.configure(AUTO_BRIGHTNESS_ENABLED, null /* configuration= */, BRIGHTNESS_MAX_FLOAT /* brightness= */, false /* userChangedBrightness= */, 0 /* adjustment= */, false /* userChanged= */, DisplayPowerRequest.POLICY_BRIGHT, @@ -766,8 +768,8 @@ public class AutomaticBrightnessControllerTest { assertEquals(BRIGHTNESS_MAX_FLOAT, mController.getRawAutomaticScreenBrightness(), 0.0f); // Remove throttling and notify ABC again - when(mBrightnessThrottler.getBrightnessCap()).thenReturn(BRIGHTNESS_MAX_FLOAT); - when(mBrightnessThrottler.isThrottled()).thenReturn(false); + when(mBrightnessClamperController.getMaxBrightness()).thenReturn(BRIGHTNESS_MAX_FLOAT); + when(mBrightnessClamperController.isThrottled()).thenReturn(false); mController.configure(AUTO_BRIGHTNESS_ENABLED, null /* configuration= */, BRIGHTNESS_MAX_FLOAT /* brightness= */, false /* userChangedBrightness= */, 0 /* adjustment= */, false /* userChanged= */, DisplayPowerRequest.POLICY_BRIGHT, @@ -1098,7 +1100,7 @@ public class AutomaticBrightnessControllerTest { when(mAmbientBrightnessThresholds.getDarkeningThreshold(lux)).thenReturn(lux); when(mBrightnessMappingStrategy.getBrightness(eq(lux), /* packageName= */ eq(null), /* category= */ anyInt())).thenReturn(normalizedBrightness); - when(mBrightnessThrottler.getBrightnessCap()).thenReturn(BRIGHTNESS_MAX_FLOAT); + when(mBrightnessClamperController.getMaxBrightness()).thenReturn(BRIGHTNESS_MAX_FLOAT); // Set policy to DOZE mController.configure(AUTO_BRIGHTNESS_ENABLED, /* configuration= */ null, @@ -1135,7 +1137,7 @@ public class AutomaticBrightnessControllerTest { when(mAmbientBrightnessThresholds.getDarkeningThreshold(lux)).thenReturn(lux); when(mBrightnessMappingStrategy.getBrightness(eq(lux), /* packageName= */ eq(null), /* category= */ anyInt())).thenReturn(normalizedBrightness); - when(mBrightnessThrottler.getBrightnessCap()).thenReturn(BRIGHTNESS_MAX_FLOAT); + when(mBrightnessClamperController.getMaxBrightness()).thenReturn(BRIGHTNESS_MAX_FLOAT); // Set policy to DOZE mController.configure(AUTO_BRIGHTNESS_ENABLED, /* configuration= */ null, @@ -1172,7 +1174,7 @@ public class AutomaticBrightnessControllerTest { when(mAmbientBrightnessThresholds.getDarkeningThreshold(lux)).thenReturn(lux); when(mBrightnessMappingStrategy.getBrightness(eq(lux), /* packageName= */ eq(null), /* category= */ anyInt())).thenReturn(normalizedBrightness); - when(mBrightnessThrottler.getBrightnessCap()).thenReturn(BRIGHTNESS_MAX_FLOAT); + when(mBrightnessClamperController.getMaxBrightness()).thenReturn(BRIGHTNESS_MAX_FLOAT); // Set policy to DOZE mController.configure(AUTO_BRIGHTNESS_ENABLED, /* configuration= */ null, @@ -1204,7 +1206,7 @@ public class AutomaticBrightnessControllerTest { when(mAmbientBrightnessThresholds.getDarkeningThreshold(lux)).thenReturn(lux); when(mDozeBrightnessMappingStrategy.getBrightness(eq(lux), /* packageName= */ eq(null), /* category= */ anyInt())).thenReturn(normalizedBrightness); - when(mBrightnessThrottler.getBrightnessCap()).thenReturn(BRIGHTNESS_MAX_FLOAT); + when(mBrightnessClamperController.getMaxBrightness()).thenReturn(BRIGHTNESS_MAX_FLOAT); // Switch mode to DOZE mController.switchMode(AUTO_BRIGHTNESS_MODE_DOZE, /* sendUpdate= */ false); @@ -1239,7 +1241,7 @@ public class AutomaticBrightnessControllerTest { when(mAmbientBrightnessThresholds.getDarkeningThreshold(lux)).thenReturn(lux); when(mDozeBrightnessMappingStrategy.getBrightness(eq(lux), /* packageName= */ eq(null), /* category= */ anyInt())).thenReturn(normalizedBrightness); - when(mBrightnessThrottler.getBrightnessCap()).thenReturn(BRIGHTNESS_MAX_FLOAT); + when(mBrightnessClamperController.getMaxBrightness()).thenReturn(BRIGHTNESS_MAX_FLOAT); // Send a new sensor value listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, (int) lux)); @@ -1267,7 +1269,7 @@ public class AutomaticBrightnessControllerTest { when(mAmbientBrightnessThresholds.getDarkeningThreshold(lux)).thenReturn(lux); when(mDozeBrightnessMappingStrategy.getBrightness(eq(lux), /* packageName= */ eq(null), /* category= */ anyInt())).thenReturn(normalizedBrightness); - when(mBrightnessThrottler.getBrightnessCap()).thenReturn(BRIGHTNESS_MAX_FLOAT); + when(mBrightnessClamperController.getMaxBrightness()).thenReturn(BRIGHTNESS_MAX_FLOAT); // Send a new sensor value listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, (int) lux)); diff --git a/services/tests/displayservicetests/src/com/android/server/display/BrightnessThrottlerTest.java b/services/tests/displayservicetests/src/com/android/server/display/BrightnessThrottlerTest.java deleted file mode 100644 index 36baacc529d5..000000000000 --- a/services/tests/displayservicetests/src/com/android/server/display/BrightnessThrottlerTest.java +++ /dev/null @@ -1,556 +0,0 @@ -/* - * Copyright (C) 2022 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.server.display; - -import static com.android.server.display.config.DisplayDeviceConfigTestUtilsKt.createSensorData; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.hardware.display.BrightnessInfo; -import android.os.Handler; -import android.os.IThermalEventListener; -import android.os.IThermalService; -import android.os.Message; -import android.os.PowerManager; -import android.os.Temperature; -import android.os.Temperature.ThrottlingStatus; -import android.os.test.TestLooper; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.internal.os.BackgroundThread; -import com.android.server.display.BrightnessThrottler.Injector; -import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData; -import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData.ThrottlingLevel; -import com.android.server.display.config.SensorData; -import com.android.server.display.mode.DisplayModeDirectorTest; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -@SmallTest -@RunWith(AndroidJUnit4.class) -public class BrightnessThrottlerTest { - private static final float EPSILON = 0.000001f; - - private Handler mHandler; - private TestLooper mTestLooper; - - @Mock IThermalService mThermalServiceMock; - @Mock Injector mInjectorMock; - - DisplayModeDirectorTest.FakeDeviceConfig mDeviceConfigFake; - - @Captor ArgumentCaptor<IThermalEventListener> mThermalEventListenerCaptor; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - when(mInjectorMock.getThermalService()).thenReturn(mThermalServiceMock); - mTestLooper = new TestLooper(); - mHandler = new Handler(mTestLooper.getLooper(), new Handler.Callback() { - @Override - public boolean handleMessage(Message msg) { - return true; - } - }); - mDeviceConfigFake = new DisplayModeDirectorTest.FakeDeviceConfig(); - when(mInjectorMock.getDeviceConfig()).thenReturn(mDeviceConfigFake); - - } - - ///////////////// - // Test Methods - ///////////////// - - @Test - public void testThermalBrightnessThrottlingData() { - List<ThrottlingLevel> singleLevel = new ArrayList<>(); - singleLevel.add(new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.25f)); - - List<ThrottlingLevel> validLevels = new ArrayList<>(); - validLevels.add(new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, 0.62f)); - validLevels.add(new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.25f)); - - List<ThrottlingLevel> unsortedThermalLevels = new ArrayList<>(); - unsortedThermalLevels.add(new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.62f)); - unsortedThermalLevels.add(new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, 0.25f)); - - List<ThrottlingLevel> unsortedBrightnessLevels = new ArrayList<>(); - unsortedBrightnessLevels.add( - new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, 0.25f)); - unsortedBrightnessLevels.add( - new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.62f)); - - List<ThrottlingLevel> unsortedLevels = new ArrayList<>(); - unsortedLevels.add(new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.25f)); - unsortedLevels.add(new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, 0.62f)); - - List<ThrottlingLevel> invalidLevel = new ArrayList<>(); - invalidLevel.add(new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, - PowerManager.BRIGHTNESS_MAX + EPSILON)); - - // Test invalid data - ThermalBrightnessThrottlingData data; - data = ThermalBrightnessThrottlingData.create((List<ThrottlingLevel>) null); - assertEquals(data, null); - data = ThermalBrightnessThrottlingData.create(new ArrayList<ThrottlingLevel>()); - assertEquals(data, null); - data = ThermalBrightnessThrottlingData.create(unsortedThermalLevels); - assertEquals(data, null); - data = ThermalBrightnessThrottlingData.create(unsortedBrightnessLevels); - assertEquals(data, null); - data = ThermalBrightnessThrottlingData.create(unsortedLevels); - assertEquals(data, null); - data = ThermalBrightnessThrottlingData.create(invalidLevel); - assertEquals(data, null); - - // Test valid data - data = ThermalBrightnessThrottlingData.create(singleLevel); - assertNotEquals(data, null); - assertThrottlingLevelsEquals(singleLevel, data.throttlingLevels); - - data = ThermalBrightnessThrottlingData.create(validLevels); - assertNotEquals(data, null); - assertThrottlingLevelsEquals(validLevels, data.throttlingLevels); - } - - @Test - public void testThermalThrottlingUnsupported() { - final BrightnessThrottler throttler = createThrottlerUnsupported(); - assertFalse(throttler.deviceSupportsThrottling()); - - // Thermal listener shouldn't be registered if throttling is unsupported - verify(mInjectorMock, never()).getThermalService(); - - // Ensure that brightness is uncapped when the device doesn't support throttling - assertEquals(PowerManager.BRIGHTNESS_MAX, throttler.getBrightnessCap(), 0f); - } - - @Test - public void testThermalThrottlingSingleLevel() throws Exception { - final ThrottlingLevel level = new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, - 0.25f); - - List<ThrottlingLevel> levels = new ArrayList<>(); - levels.add(level); - final ThermalBrightnessThrottlingData data = ThermalBrightnessThrottlingData.create(levels); - final BrightnessThrottler throttler = createThrottlerSupported(data); - assertTrue(throttler.deviceSupportsThrottling()); - - verify(mThermalServiceMock).registerThermalEventListenerWithType( - mThermalEventListenerCaptor.capture(), eq(Temperature.TYPE_SKIN)); - final IThermalEventListener listener = mThermalEventListenerCaptor.getValue(); - - // Set status too low to trigger throttling - listener.notifyThrottling(getSkinTemp(level.thermalStatus - 1)); - mTestLooper.dispatchAll(); - assertEquals(PowerManager.BRIGHTNESS_MAX, throttler.getBrightnessCap(), 0f); - assertFalse(throttler.isThrottled()); - assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE, throttler.getBrightnessMaxReason()); - - // Set status just high enough to trigger throttling - listener.notifyThrottling(getSkinTemp(level.thermalStatus)); - mTestLooper.dispatchAll(); - assertEquals(level.brightness, throttler.getBrightnessCap(), 0f); - assertTrue(throttler.isThrottled()); - assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL, - throttler.getBrightnessMaxReason()); - - // Set status more than high enough to trigger throttling - listener.notifyThrottling(getSkinTemp(level.thermalStatus + 1)); - mTestLooper.dispatchAll(); - assertEquals(level.brightness, throttler.getBrightnessCap(), 0f); - assertTrue(throttler.isThrottled()); - assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL, - throttler.getBrightnessMaxReason()); - - // Return to the lower throttling level - listener.notifyThrottling(getSkinTemp(level.thermalStatus)); - mTestLooper.dispatchAll(); - assertEquals(level.brightness, throttler.getBrightnessCap(), 0f); - assertTrue(throttler.isThrottled()); - assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL, - throttler.getBrightnessMaxReason()); - - // Cool down - listener.notifyThrottling(getSkinTemp(level.thermalStatus - 1)); - mTestLooper.dispatchAll(); - assertEquals(PowerManager.BRIGHTNESS_MAX, throttler.getBrightnessCap(), 0f); - assertFalse(throttler.isThrottled()); - assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE, - throttler.getBrightnessMaxReason()); - } - - @Test - public void testThermalThrottlingMultiLevel() throws Exception { - final ThrottlingLevel levelLo = new ThrottlingLevel(PowerManager.THERMAL_STATUS_MODERATE, - 0.62f); - final ThrottlingLevel levelHi = new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, - 0.25f); - - List<ThrottlingLevel> levels = new ArrayList<>(); - levels.add(levelLo); - levels.add(levelHi); - final ThermalBrightnessThrottlingData data = ThermalBrightnessThrottlingData.create(levels); - final BrightnessThrottler throttler = createThrottlerSupported(data); - assertTrue(throttler.deviceSupportsThrottling()); - - verify(mThermalServiceMock).registerThermalEventListenerWithType( - mThermalEventListenerCaptor.capture(), eq(Temperature.TYPE_SKIN)); - final IThermalEventListener listener = mThermalEventListenerCaptor.getValue(); - - // Set status too low to trigger throttling - listener.notifyThrottling(getSkinTemp(levelLo.thermalStatus - 1)); - mTestLooper.dispatchAll(); - assertEquals(PowerManager.BRIGHTNESS_MAX, throttler.getBrightnessCap(), 0f); - assertFalse(throttler.isThrottled()); - assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE, throttler.getBrightnessMaxReason()); - - // Set status just high enough to trigger throttling - listener.notifyThrottling(getSkinTemp(levelLo.thermalStatus)); - mTestLooper.dispatchAll(); - assertEquals(levelLo.brightness, throttler.getBrightnessCap(), 0f); - assertTrue(throttler.isThrottled()); - assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL, - throttler.getBrightnessMaxReason()); - - // Set status to an intermediate throttling level - listener.notifyThrottling(getSkinTemp(levelLo.thermalStatus + 1)); - mTestLooper.dispatchAll(); - assertEquals(levelLo.brightness, throttler.getBrightnessCap(), 0f); - assertTrue(throttler.isThrottled()); - assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL, - throttler.getBrightnessMaxReason()); - - // Set status to the highest configured throttling level - listener.notifyThrottling(getSkinTemp(levelHi.thermalStatus)); - mTestLooper.dispatchAll(); - assertEquals(levelHi.brightness, throttler.getBrightnessCap(), 0f); - assertTrue(throttler.isThrottled()); - assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL, - throttler.getBrightnessMaxReason()); - - // Set status to exceed the highest configured throttling level - listener.notifyThrottling(getSkinTemp(levelHi.thermalStatus + 1)); - mTestLooper.dispatchAll(); - assertEquals(levelHi.brightness, throttler.getBrightnessCap(), 0f); - assertTrue(throttler.isThrottled()); - assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL, - throttler.getBrightnessMaxReason()); - - // Return to an intermediate throttling level - listener.notifyThrottling(getSkinTemp(levelLo.thermalStatus + 1)); - mTestLooper.dispatchAll(); - assertEquals(levelLo.brightness, throttler.getBrightnessCap(), 0f); - assertTrue(throttler.isThrottled()); - assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL, - throttler.getBrightnessMaxReason()); - - // Return to the lowest configured throttling level - listener.notifyThrottling(getSkinTemp(levelLo.thermalStatus)); - mTestLooper.dispatchAll(); - assertEquals(levelLo.brightness, throttler.getBrightnessCap(), 0f); - assertTrue(throttler.isThrottled()); - assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL, - throttler.getBrightnessMaxReason()); - - // Cool down - listener.notifyThrottling(getSkinTemp(levelLo.thermalStatus - 1)); - mTestLooper.dispatchAll(); - assertEquals(PowerManager.BRIGHTNESS_MAX, throttler.getBrightnessCap(), 0f); - assertFalse(throttler.isThrottled()); - assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE, throttler.getBrightnessMaxReason()); - } - - - @Test - public void testThermalThrottlingWithDisplaySensor() throws Exception { - final ThrottlingLevel level = - new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.25f); - List<ThrottlingLevel> levels = new ArrayList<>(List.of(level)); - final ThermalBrightnessThrottlingData data = ThermalBrightnessThrottlingData.create(levels); - final SensorData tempSensor = createSensorData("DISPLAY", "VIRTUAL-SKIN-DISPLAY"); - final BrightnessThrottler throttler = - createThrottlerSupportedWithTempSensor(data, tempSensor); - assertTrue(throttler.deviceSupportsThrottling()); - - verify(mThermalServiceMock) - .registerThermalEventListenerWithType( - mThermalEventListenerCaptor.capture(), eq(Temperature.TYPE_DISPLAY)); - final IThermalEventListener listener = mThermalEventListenerCaptor.getValue(); - - // Set VIRTUAL-SKIN-DISPLAY tatus too low to verify no throttling. - listener.notifyThrottling(getDisplayTempWithName(tempSensor.name, level.thermalStatus - 1)); - mTestLooper.dispatchAll(); - assertEquals(PowerManager.BRIGHTNESS_MAX, throttler.getBrightnessCap(), 0f); - assertFalse(throttler.isThrottled()); - assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE, throttler.getBrightnessMaxReason()); - - // Verify when skin sensor throttled, no brightness throttling triggered. - listener.notifyThrottling(getSkinTemp(level.thermalStatus + 1)); - mTestLooper.dispatchAll(); - assertEquals(PowerManager.BRIGHTNESS_MAX, throttler.getBrightnessCap(), 0f); - assertFalse(throttler.isThrottled()); - assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE, throttler.getBrightnessMaxReason()); - - // Verify when display sensor of another name throttled, no brightness throttling triggered. - listener.notifyThrottling(getDisplayTempWithName("ANOTHER-NAME", level.thermalStatus + 1)); - mTestLooper.dispatchAll(); - assertEquals(PowerManager.BRIGHTNESS_MAX, throttler.getBrightnessCap(), 0f); - assertFalse(throttler.isThrottled()); - assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE, throttler.getBrightnessMaxReason()); - - // Verify when display sensor of current name throttled, brightness throttling triggered. - listener.notifyThrottling(getDisplayTempWithName(tempSensor.name, level.thermalStatus + 1)); - mTestLooper.dispatchAll(); - assertEquals(level.brightness, throttler.getBrightnessCap(), 0f); - assertTrue(throttler.isThrottled()); - assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL, - throttler.getBrightnessMaxReason()); - } - - @Test public void testUpdateThermalThrottlingData() throws Exception { - // Initialise brightness throttling levels - // Ensure that they are overridden by setting the data through device config. - final ThrottlingLevel level = new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, - 0.25f); - List<ThrottlingLevel> levels = new ArrayList<>(); - levels.add(level); - final ThermalBrightnessThrottlingData data = ThermalBrightnessThrottlingData.create(levels); - mDeviceConfigFake.setThermalBrightnessThrottlingData("123,1,critical,0.4"); - final BrightnessThrottler throttler = createThrottlerSupported(data); - - verify(mThermalServiceMock).registerThermalEventListenerWithType( - mThermalEventListenerCaptor.capture(), eq(Temperature.TYPE_SKIN)); - final IThermalEventListener listener = mThermalEventListenerCaptor.getValue(); - testThermalThrottling(throttler, listener, PowerManager.BRIGHTNESS_MAX, 0.4f); - - // Set new (valid) data from device config - mDeviceConfigFake.setThermalBrightnessThrottlingData("123,1,critical,0.8"); - testThermalThrottling(throttler, listener, PowerManager.BRIGHTNESS_MAX, 0.8f); - - mDeviceConfigFake.setThermalBrightnessThrottlingData( - "123,1,critical,0.75;123,1,critical,0.99,id_2"); - testThermalThrottling(throttler, listener, PowerManager.BRIGHTNESS_MAX, 0.75f); - mDeviceConfigFake.setThermalBrightnessThrottlingData( - "123,1,critical,0.8,default;123,1,critical,0.99,id_2"); - testThermalThrottling(throttler, listener, PowerManager.BRIGHTNESS_MAX, 0.8f); - } - - @Test public void testInvalidThrottlingStrings() throws Exception { - // Initialise brightness throttling levels - // Ensure that they are not overridden by invalid data through device config. - final ThrottlingLevel level = new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, - 0.25f); - List<ThrottlingLevel> levels = new ArrayList<>(); - levels.add(level); - final ThermalBrightnessThrottlingData data = ThermalBrightnessThrottlingData.create(levels); - final BrightnessThrottler throttler = createThrottlerSupported(data); - verify(mThermalServiceMock).registerThermalEventListenerWithType( - mThermalEventListenerCaptor.capture(), eq(Temperature.TYPE_SKIN)); - final IThermalEventListener listener = mThermalEventListenerCaptor.getValue(); - - // None of these are valid so shouldn't override the original data - - // Not the current id - mDeviceConfigFake.setThermalBrightnessThrottlingData("321,1,critical,0.4"); - testThermalThrottling(throttler, listener, PowerManager.BRIGHTNESS_MAX, 0.25f); - // Incorrect number - mDeviceConfigFake.setThermalBrightnessThrottlingData("123,0,critical,0.4"); - testThermalThrottling(throttler, listener, PowerManager.BRIGHTNESS_MAX, 0.25f); - // Incorrect number - mDeviceConfigFake.setThermalBrightnessThrottlingData("123,2,critical,0.4"); - testThermalThrottling(throttler, listener, PowerManager.BRIGHTNESS_MAX, 0.25f); - // Invalid level - mDeviceConfigFake.setThermalBrightnessThrottlingData("123,1,invalid,0.4"); - testThermalThrottling(throttler, listener, PowerManager.BRIGHTNESS_MAX, 0.25f); - // Invalid brightness - mDeviceConfigFake.setThermalBrightnessThrottlingData("123,1,critical,none"); - testThermalThrottling(throttler, listener, PowerManager.BRIGHTNESS_MAX, 0.25f); - // Invalid brightness - mDeviceConfigFake.setThermalBrightnessThrottlingData("123,1,critical,-3"); - testThermalThrottling(throttler, listener, PowerManager.BRIGHTNESS_MAX, 0.25f); - // Invalid format - mDeviceConfigFake.setThermalBrightnessThrottlingData("invalid string"); - testThermalThrottling(throttler, listener, PowerManager.BRIGHTNESS_MAX, 0.25f); - // Invalid format - mDeviceConfigFake.setThermalBrightnessThrottlingData(""); - testThermalThrottling(throttler, listener, PowerManager.BRIGHTNESS_MAX, 0.25f); - // Invalid string format - mDeviceConfigFake.setThermalBrightnessThrottlingData( - "123,default,1,critical,0.75,1,critical,0.99"); - testThermalThrottling(throttler, listener, PowerManager.BRIGHTNESS_MAX, 0.25f); - // Invalid level string and number string - mDeviceConfigFake.setThermalBrightnessThrottlingData( - "123,1,1,critical,0.75,id_2,1,critical,0.99"); - testThermalThrottling(throttler, listener, PowerManager.BRIGHTNESS_MAX, 0.25f); - // Invalid format - (two default ids for same display) - mDeviceConfigFake.setThermalBrightnessThrottlingData( - "123,1,critical,0.75,default;123,1,critical,0.99"); - testThermalThrottling(throttler, listener, PowerManager.BRIGHTNESS_MAX, 0.25f); - } - - private void testThermalThrottling(BrightnessThrottler throttler, - IThermalEventListener listener, float tooLowCap, float tooHighCap) throws Exception { - final ThrottlingLevel level = new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, - tooHighCap); - - // Set status too low to trigger throttling - listener.notifyThrottling(getSkinTemp(level.thermalStatus - 1)); - mTestLooper.dispatchAll(); - assertEquals(tooLowCap, throttler.getBrightnessCap(), 0f); - assertFalse(throttler.isThrottled()); - - // Set status high enough to trigger throttling - listener.notifyThrottling(getSkinTemp(level.thermalStatus)); - mTestLooper.dispatchAll(); - assertEquals(tooHighCap, throttler.getBrightnessCap(), 0f); - assertTrue(throttler.isThrottled()); - } - - @Test public void testMultipleConfigPoints() throws Exception { - // Initialise brightness throttling levels - final ThrottlingLevel level = new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, - 0.25f); - List<ThrottlingLevel> levels = new ArrayList<>(); - levels.add(level); - final ThermalBrightnessThrottlingData data = ThermalBrightnessThrottlingData.create(levels); - - // These are identical to the string set below - final ThrottlingLevel levelSevere = new ThrottlingLevel(PowerManager.THERMAL_STATUS_SEVERE, - 0.9f); - final ThrottlingLevel levelCritical = new ThrottlingLevel( - PowerManager.THERMAL_STATUS_CRITICAL, 0.5f); - final ThrottlingLevel levelEmergency = new ThrottlingLevel( - PowerManager.THERMAL_STATUS_EMERGENCY, 0.1f); - - mDeviceConfigFake.setThermalBrightnessThrottlingData( - "123,3,severe,0.9,critical,0.5,emergency,0.1"); - final BrightnessThrottler throttler = createThrottlerSupported(data); - - verify(mThermalServiceMock).registerThermalEventListenerWithType( - mThermalEventListenerCaptor.capture(), eq(Temperature.TYPE_SKIN)); - final IThermalEventListener listener = mThermalEventListenerCaptor.getValue(); - - // Ensure that the multiple levels set via the string through the device config correctly - // override the original display device config ones. - - // levelSevere - // Set status too low to trigger throttling - listener.notifyThrottling(getSkinTemp(levelSevere.thermalStatus - 1)); - mTestLooper.dispatchAll(); - assertEquals(PowerManager.BRIGHTNESS_MAX, throttler.getBrightnessCap(), 0f); - assertFalse(throttler.isThrottled()); - - // Set status high enough to trigger throttling - listener.notifyThrottling(getSkinTemp(levelSevere.thermalStatus)); - mTestLooper.dispatchAll(); - assertEquals(0.9f, throttler.getBrightnessCap(), 0f); - assertTrue(throttler.isThrottled()); - - // levelCritical - // Set status too low to trigger throttling - listener.notifyThrottling(getSkinTemp(levelCritical.thermalStatus - 1)); - mTestLooper.dispatchAll(); - assertEquals(0.9f, throttler.getBrightnessCap(), 0f); - assertTrue(throttler.isThrottled()); - - // Set status high enough to trigger throttling - listener.notifyThrottling(getSkinTemp(levelCritical.thermalStatus)); - mTestLooper.dispatchAll(); - assertEquals(0.5f, throttler.getBrightnessCap(), 0f); - assertTrue(throttler.isThrottled()); - - //levelEmergency - // Set status too low to trigger throttling - listener.notifyThrottling(getSkinTemp(levelEmergency.thermalStatus - 1)); - mTestLooper.dispatchAll(); - assertEquals(0.5f, throttler.getBrightnessCap(), 0f); - assertTrue(throttler.isThrottled()); - - // Set status high enough to trigger throttling - listener.notifyThrottling(getSkinTemp(levelEmergency.thermalStatus)); - mTestLooper.dispatchAll(); - assertEquals(0.1f, throttler.getBrightnessCap(), 0f); - assertTrue(throttler.isThrottled()); - } - - private void assertThrottlingLevelsEquals( - List<ThrottlingLevel> expected, - List<ThrottlingLevel> actual) { - assertEquals(expected.size(), actual.size()); - - for (int i = 0; i < expected.size(); i++) { - ThrottlingLevel expectedLevel = expected.get(i); - ThrottlingLevel actualLevel = actual.get(i); - - assertEquals(expectedLevel.thermalStatus, actualLevel.thermalStatus); - assertEquals(expectedLevel.brightness, actualLevel.brightness, 0.0f); - } - } - - private BrightnessThrottler createThrottlerUnsupported() { - return new BrightnessThrottler(mInjectorMock, mHandler, mHandler, - /* throttlingChangeCallback= */ () -> {}, /* uniqueDisplayId= */ null, - /* thermalThrottlingDataId= */ null, - /* thermalThrottlingDataMap= */ new HashMap<>(1), - /* tempSensor= */ null); - } - - private BrightnessThrottler createThrottlerSupported(ThermalBrightnessThrottlingData data) { - SensorData tempSensor = SensorData.loadTempSensorUnspecifiedConfig(); - return createThrottlerSupportedWithTempSensor(data, tempSensor); - } - private BrightnessThrottler createThrottlerSupportedWithTempSensor( - ThermalBrightnessThrottlingData data, SensorData tempSensor) { - assertNotNull(data); - Map<String, ThermalBrightnessThrottlingData> throttlingDataMap = new HashMap<>(1); - throttlingDataMap.put("default", data); - return new BrightnessThrottler(mInjectorMock, mHandler, BackgroundThread.getHandler(), - () -> {}, "123", "default", throttlingDataMap, tempSensor); - } - - private Temperature getSkinTemp(@ThrottlingStatus int status) { - return new Temperature(30.0f, Temperature.TYPE_SKIN, "test_skin_temp", status); - } - - private Temperature getDisplayTempWithName( - String sensorName, @ThrottlingStatus int status) { - assertNotNull(sensorName); - return new Temperature(30.0f, Temperature.TYPE_DISPLAY, sensorName, status); - } -} diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java index 7f12e9cf145a..aed1f9858660 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java @@ -85,6 +85,7 @@ import com.android.server.display.RampAnimator.DualRampAnimator; import com.android.server.display.brightness.BrightnessEvent; import com.android.server.display.brightness.BrightnessReason; import com.android.server.display.brightness.clamper.BrightnessClamperController; +import com.android.server.display.brightness.clamper.BrightnessClamperController.DisplayDeviceData; import com.android.server.display.brightness.clamper.HdrClamper; import com.android.server.display.color.ColorDisplayService; import com.android.server.display.config.HighBrightnessModeData; @@ -1288,7 +1289,7 @@ public final class DisplayPowerControllerTest { any(HysteresisLevels.class), eq(mContext), any(BrightnessRangeController.class), - any(BrightnessThrottler.class), + any(BrightnessClamperController.class), /* ambientLightHorizonShort= */ anyInt(), /* ambientLightHorizonLong= */ anyInt(), eq(lux), @@ -1299,8 +1300,9 @@ public final class DisplayPowerControllerTest { @Test public void testUpdateBrightnessThrottlingDataId() { + String throttlingDataId = "throttling-data-id"; mHolder.display.getDisplayInfoLocked().thermalBrightnessThrottlingDataId = - "throttling-data-id"; + throttlingDataId; clearInvocations(mHolder.display.getPrimaryDisplayDeviceLocked().getDisplayDeviceConfig()); mHolder.dpc.onDisplayChanged(mHolder.hbmMetadata, Layout.NO_LEAD_DISPLAY); @@ -1308,8 +1310,10 @@ public final class DisplayPowerControllerTest { mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false); advanceTime(1); // Run updatePowerState - verify(mHolder.display.getPrimaryDisplayDeviceLocked().getDisplayDeviceConfig()) - .getThermalBrightnessThrottlingDataMapByThrottlingId(); + ArgumentCaptor<DisplayDeviceData> argumentCaptor = ArgumentCaptor.forClass( + DisplayDeviceData.class); + verify(mHolder.clamperController).onDisplayChanged(argumentCaptor.capture()); + assertEquals(throttlingDataId, argumentCaptor.getValue().getThermalThrottlingDataId()); } @Test @@ -2798,7 +2802,7 @@ public final class DisplayPowerControllerTest { HysteresisLevels ambientBrightnessThresholdsIdle, HysteresisLevels screenBrightnessThresholdsIdle, Context context, BrightnessRangeController brightnessRangeController, - BrightnessThrottler brightnessThrottler, int ambientLightHorizonShort, + BrightnessClamperController clamperController, int ambientLightHorizonShort, int ambientLightHorizonLong, float userLux, float userNits, DisplayManagerFlags displayManagerFlags) { return mAutomaticBrightnessController; @@ -2842,7 +2846,7 @@ public final class DisplayPowerControllerTest { @Override BrightnessClamperController getBrightnessClamperController(Handler handler, BrightnessClamperController.ClamperChangeListener clamperChangeListener, - BrightnessClamperController.DisplayDeviceData data, Context context, + DisplayDeviceData data, Context context, DisplayManagerFlags flags, SensorManager sensorManager, float currentBrightness) { return mClamperController; } diff --git a/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java b/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java index 45761b696877..82efae45e1a4 100644 --- a/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java @@ -17,7 +17,9 @@ package com.android.server; import static android.service.quickaccesswallet.Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP; +import static android.service.quickaccesswallet.Flags.FLAG_LAUNCH_WALLET_VIA_SYSUI_CALLBACKS; import static android.service.quickaccesswallet.Flags.launchWalletOptionOnPowerDoubleTap; +import static android.service.quickaccesswallet.Flags.launchWalletViaSysuiCallbacks; import static com.android.server.GestureLauncherService.LAUNCH_CAMERA_ON_DOUBLE_TAP_POWER; import static com.android.server.GestureLauncherService.LAUNCH_WALLET_ON_DOUBLE_TAP_POWER; @@ -45,6 +47,7 @@ import android.content.res.Resources; import android.os.Looper; import android.os.UserHandle; import android.platform.test.annotations.Presubmit; +import android.platform.test.annotations.RequiresFlagsDisabled; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; @@ -653,7 +656,11 @@ public class GestureLauncherServiceTest { eventTime += interval; sendPowerKeyDownToGestureLauncherServiceAndAssertValues(eventTime, true, true); - assertTrue(receiver.waitUntilShown()); + if (launchWalletViaSysuiCallbacks()) { + verify(mStatusBarManagerInternal).onWalletLaunchGestureDetected(); + } else { + assertTrue(receiver.waitUntilShown()); + } // Presses 3 and 4 should not trigger any gesture for (int i = 0; i < 2; i++) { @@ -683,11 +690,17 @@ public class GestureLauncherServiceTest { final long interval = POWER_DOUBLE_TAP_MAX_TIME_MS - 1; eventTime += interval; sendPowerKeyDownToGestureLauncherServiceAndAssertValues(eventTime, true, true); - assertTrue(receiver.waitUntilShown()); + + if (launchWalletViaSysuiCallbacks()) { + verify(mStatusBarManagerInternal).onWalletLaunchGestureDetected(); + } else { + assertTrue(receiver.waitUntilShown()); + } } @Test @RequiresFlagsEnabled(FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) + @RequiresFlagsDisabled(FLAG_LAUNCH_WALLET_VIA_SYSUI_CALLBACKS) public void testInterceptPowerKeyDown_walletGestureOn_quickAccessWalletServiceUnavailable() { when(mQuickAccessWalletClient.isWalletServiceAvailable()).thenReturn(false); WalletLaunchedReceiver receiver = registerWalletLaunchedReceiver(LAUNCH_TEST_WALLET_ACTION); @@ -720,11 +733,16 @@ public class GestureLauncherServiceTest { eventTime += interval; sendPowerKeyDownToGestureLauncherServiceAndAssertValues(eventTime, false, false); - assertFalse(receiver.waitUntilShown()); + if (launchWalletViaSysuiCallbacks()) { + verify(mStatusBarManagerInternal, never()).onWalletLaunchGestureDetected(); + } else { + assertFalse(receiver.waitUntilShown()); + } } @Test @RequiresFlagsEnabled(FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) + @RequiresFlagsDisabled(FLAG_LAUNCH_WALLET_VIA_SYSUI_CALLBACKS) public void testInterceptPowerKeyDown_walletPowerGesture_nullPendingIntent() { WalletLaunchedReceiver gestureReceiver = registerWalletLaunchedReceiver(LAUNCH_TEST_WALLET_ACTION); @@ -767,8 +785,12 @@ public class GestureLauncherServiceTest { eventTime += interval; sendPowerKeyDownToGestureLauncherServiceAndAssertValues(eventTime, false, false); - assertFalse(gestureReceiver.waitUntilShown()); - assertFalse(fallbackReceiver.waitUntilShown()); + if (launchWalletViaSysuiCallbacks()) { + verify(mStatusBarManagerInternal, never()).onWalletLaunchGestureDetected(); + } else { + assertFalse(gestureReceiver.waitUntilShown()); + assertFalse(fallbackReceiver.waitUntilShown()); + } } @Test diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayReferenceMapperTests.kt b/services/tests/servicestests/src/com/android/server/om/OverlayReferenceMapperTests.kt index bc10cd6bf1c9..1352adef783f 100644 --- a/services/tests/servicestests/src/com/android/server/om/OverlayReferenceMapperTests.kt +++ b/services/tests/servicestests/src/com/android/server/om/OverlayReferenceMapperTests.kt @@ -76,10 +76,12 @@ class OverlayReferenceMapperTests { val overlay1 = mockOverlay(1) mapper = mapper( overlayToTargetToOverlayables = mapOf( - overlay0.packageName to android.util.Pair(target.packageName, - target.overlayables.keys.first()), - overlay1.packageName to android.util.Pair(target.packageName, - target.overlayables.keys.first()) + overlay0.packageName to mapOf( + target.packageName to target.overlayables.keys + ), + overlay1.packageName to mapOf( + target.packageName to target.overlayables.keys + ) ) ) val existing = mapper.addInOrder(overlay0, overlay1) { @@ -132,6 +134,33 @@ class OverlayReferenceMapperTests { } @Test + fun overlayWithMultipleTargets() { + val target0 = mockTarget(0) + val target1 = mockTarget(1) + val overlay = mockOverlay() + mapper = mapper( + overlayToTargetToOverlayables = mapOf( + overlay.packageName to mapOf( + target0.packageName to target0.overlayables.keys, + target1.packageName to target1.overlayables.keys + ) + ) + ) + mapper.addInOrder(target0, target1, overlay) { + assertThat(it).containsExactly(ACTOR_PACKAGE_NAME) + } + assertMapping(ACTOR_PACKAGE_NAME to setOf(target0, target1, overlay)) + mapper.remove(target0) { + assertThat(it).containsExactly(ACTOR_PACKAGE_NAME) + } + assertMapping(ACTOR_PACKAGE_NAME to setOf(target1, overlay)) + mapper.remove(target1) { + assertThat(it).containsExactly(ACTOR_PACKAGE_NAME) + } + assertEmpty() + } + + @Test fun overlayWithoutTarget() { val overlay = mockOverlay() mapper.addInOrder(overlay) { @@ -190,15 +219,17 @@ class OverlayReferenceMapperTests { namedActors: Map<String, Map<String, String>> = Uri.parse(ACTOR_NAME).run { mapOf(authority!! to mapOf(pathSegments.first() to ACTOR_PACKAGE_NAME)) }, - overlayToTargetToOverlayables: Map<String, android.util.Pair<String, String>> = mapOf( - mockOverlay().packageName to mockTarget().run { android.util.Pair(packageName!!, - overlayables.keys.first()) }) + overlayToTargetToOverlayables: Map<String, Map<String, Set<String>>> = mapOf( + mockOverlay().packageName to mapOf( + mockTarget().run { packageName to overlayables.keys } + ) + ) ) = OverlayReferenceMapper(deferRebuild, object : OverlayReferenceMapper.Provider { override fun getActorPkg(actor: String) = OverlayActorEnforcer.getPackageNameForActor(actor, namedActors).first override fun getTargetToOverlayables(pkg: AndroidPackage) = - overlayToTargetToOverlayables[pkg.packageName] + overlayToTargetToOverlayables[pkg.packageName] ?: emptyMap() }) private fun mockTarget(increment: Int = 0) = mockThrowOnUnmocked<AndroidPackage> { diff --git a/services/tests/servicestests/src/com/android/server/security/advancedprotection/AdvancedProtectionServiceTest.java b/services/tests/servicestests/src/com/android/server/security/advancedprotection/AdvancedProtectionServiceTest.java index b1df0f1e9cce..c7a06b8eec7b 100644 --- a/services/tests/servicestests/src/com/android/server/security/advancedprotection/AdvancedProtectionServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/security/advancedprotection/AdvancedProtectionServiceTest.java @@ -31,6 +31,7 @@ import android.os.test.FakePermissionEnforcer; import android.os.test.TestLooper; import android.provider.Settings; import android.security.advancedprotection.AdvancedProtectionFeature; +import android.security.advancedprotection.AdvancedProtectionManager; import android.security.advancedprotection.IAdvancedProtectionCallback; import androidx.annotation.NonNull; @@ -54,7 +55,8 @@ public class AdvancedProtectionServiceTest { private Context mContext; private AdvancedProtectionService.AdvancedProtectionStore mStore; private TestLooper mLooper; - AdvancedProtectionFeature mFeature = new AdvancedProtectionFeature("test-id"); + AdvancedProtectionFeature mTestFeature2g = new AdvancedProtectionFeature( + AdvancedProtectionManager.FEATURE_ID_DISALLOW_CELLULAR_2G); @Before public void setup() throws Settings.SettingNotFoundException { @@ -105,7 +107,7 @@ public class AdvancedProtectionServiceTest { @NonNull @Override public AdvancedProtectionFeature getFeature() { - return mFeature; + return mTestFeature2g; } @Override @@ -135,7 +137,7 @@ public class AdvancedProtectionServiceTest { @NonNull @Override public AdvancedProtectionFeature getFeature() { - return mFeature; + return mTestFeature2g; } @Override @@ -165,7 +167,7 @@ public class AdvancedProtectionServiceTest { @NonNull @Override public AdvancedProtectionFeature getFeature() { - return mFeature; + return mTestFeature2g; } @Override @@ -238,8 +240,10 @@ public class AdvancedProtectionServiceTest { @Test public void testGetFeatures() { - AdvancedProtectionFeature feature1 = new AdvancedProtectionFeature("id-1"); - AdvancedProtectionFeature feature2 = new AdvancedProtectionFeature("id-2"); + AdvancedProtectionFeature feature1 = new AdvancedProtectionFeature( + AdvancedProtectionManager.FEATURE_ID_DISALLOW_CELLULAR_2G); + AdvancedProtectionFeature feature2 = new AdvancedProtectionFeature( + AdvancedProtectionManager.FEATURE_ID_DISALLOW_INSTALL_UNKNOWN_SOURCES); AdvancedProtectionHook hook = new AdvancedProtectionHook(mContext, true) { @NonNull @Override @@ -268,8 +272,10 @@ public class AdvancedProtectionServiceTest { @Test public void testGetFeatures_featureNotAvailable() { - AdvancedProtectionFeature feature1 = new AdvancedProtectionFeature("id-1"); - AdvancedProtectionFeature feature2 = new AdvancedProtectionFeature("id-2"); + AdvancedProtectionFeature feature1 = new AdvancedProtectionFeature( + AdvancedProtectionManager.FEATURE_ID_DISALLOW_CELLULAR_2G); + AdvancedProtectionFeature feature2 = new AdvancedProtectionFeature( + AdvancedProtectionManager.FEATURE_ID_DISALLOW_INSTALL_UNKNOWN_SOURCES); AdvancedProtectionHook hook = new AdvancedProtectionHook(mContext, true) { @NonNull @Override diff --git a/telecomm/java/android/telecom/StatusHints.java b/telecomm/java/android/telecom/StatusHints.java index 5f0c8d729e74..31b84ff04b85 100644 --- a/telecomm/java/android/telecom/StatusHints.java +++ b/telecomm/java/android/telecom/StatusHints.java @@ -27,6 +27,7 @@ import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.os.UserHandle; +import android.util.Log; import com.android.internal.annotations.VisibleForTesting; @@ -40,6 +41,7 @@ public final class StatusHints implements Parcelable { private final CharSequence mLabel; private Icon mIcon; private final Bundle mExtras; + private static final String TAG = StatusHints.class.getSimpleName(); /** * @hide @@ -150,17 +152,37 @@ public final class StatusHints implements Parcelable { // incompatible types. if (icon != null && (icon.getType() == Icon.TYPE_URI || icon.getType() == Icon.TYPE_URI_ADAPTIVE_BITMAP)) { - String encodedUser = icon.getUri().getEncodedUserInfo(); - // If there is no encoded user, the URI is calling into the calling user space - if (encodedUser != null) { - int userId = Integer.parseInt(encodedUser); - // Do not try to save the icon if the user id isn't in the calling user space. - if (userId != callingUserHandle.getIdentifier()) return null; + int callingUserId = callingUserHandle.getIdentifier(); + int requestingUserId = getUserIdFromAuthority( + icon.getUri().getAuthority(), callingUserId); + if (callingUserId != requestingUserId) { + return null; } + } return icon; } + /** + * Derives the user id from the authority or the default user id if none could be found. + * @param auth + * @param defaultUserId + * @return The user id from the given authority. + * @hide + */ + public static int getUserIdFromAuthority(String auth, int defaultUserId) { + if (auth == null) return defaultUserId; + int end = auth.lastIndexOf('@'); + if (end == -1) return defaultUserId; + String userIdString = auth.substring(0, end); + try { + return Integer.parseInt(userIdString); + } catch (NumberFormatException e) { + Log.w(TAG, "Error parsing userId." + e); + return UserHandle.USER_NULL; + } + } + @Override public void writeToParcel(Parcel out, int flags) { out.writeCharSequence(mLabel); diff --git a/telephony/java/android/telephony/satellite/ISatelliteCommunicationAllowedStateCallback.aidl b/telephony/java/android/telephony/satellite/ISatelliteCommunicationAccessStateCallback.aidl index 2730f90c4e5e..a3c66a03fd7f 100644 --- a/telephony/java/android/telephony/satellite/ISatelliteCommunicationAllowedStateCallback.aidl +++ b/telephony/java/android/telephony/satellite/ISatelliteCommunicationAccessStateCallback.aidl @@ -19,18 +19,18 @@ package android.telephony.satellite; import android.telephony.satellite.SatelliteAccessConfiguration; /** - * Interface for satellite communication allowed state callback. + * Interface for satellite communication access state callback. * @hide */ -oneway interface ISatelliteCommunicationAllowedStateCallback { +oneway interface ISatelliteCommunicationAccessStateCallback { /** * Telephony does not guarantee that whenever there is a change in communication allowed * state, this API will be called. Telephony does its best to detect the changes and notify - * its listners accordingly. + * its listeners accordingly. * * @param allowed whether satellite communication state or not */ - void onSatelliteCommunicationAllowedStateChanged(in boolean isAllowed); + void onAccessAllowedStateChanged(in boolean isAllowed); /** * Callback method invoked when the satellite access configuration changes @@ -39,6 +39,6 @@ oneway interface ISatelliteCommunicationAllowedStateCallback { * When satellite is not allowed at the current location, * {@code satelliteRegionalConfiguration} will be null. */ - void onSatelliteAccessConfigurationChanged(in SatelliteAccessConfiguration + void onAccessConfigurationChanged(in SatelliteAccessConfiguration satelliteAccessConfiguration); } diff --git a/telephony/java/android/telephony/satellite/SatelliteCommunicationAllowedStateCallback.java b/telephony/java/android/telephony/satellite/SatelliteCommunicationAccessStateCallback.java index 6291102cd6e3..7fb8a968a6e3 100644 --- a/telephony/java/android/telephony/satellite/SatelliteCommunicationAllowedStateCallback.java +++ b/telephony/java/android/telephony/satellite/SatelliteCommunicationAccessStateCallback.java @@ -25,24 +25,24 @@ import com.android.internal.telephony.flags.Flags; /** - * A callback class for monitoring satellite communication allowed state changed events. + * A callback class for monitoring satellite communication access state changed events. * * @hide */ @SystemApi @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) -public interface SatelliteCommunicationAllowedStateCallback { +public interface SatelliteCommunicationAccessStateCallback { /** * Telephony does not guarantee that whenever there is a change in communication allowed state, * this API will be called. Telephony does its best to detect the changes and notify its - * listeners accordingly. Satellite communication is allowed at a location when it is legally - * allowed by the local authority and satellite signal coverage is available. + * listeners accordingly. Satellite communication access is allowed at a location when it is + * legally allowed by the local authority and satellite signal coverage is available. * * @param isAllowed {@code true} means satellite is allowed, * {@code false} satellite is not allowed. */ - void onSatelliteCommunicationAllowedStateChanged(boolean isAllowed); + void onAccessAllowedStateChanged(boolean isAllowed); /** * Callback method invoked when the satellite access configuration changes @@ -52,6 +52,6 @@ public interface SatelliteCommunicationAllowedStateCallback { * the current location, * {@code satelliteRegionalConfiguration} will be null. */ - default void onSatelliteAccessConfigurationChanged( + default void onAccessConfigurationChanged( @Nullable SatelliteAccessConfiguration satelliteAccessConfiguration) {}; } diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java index b885b30d17d7..63a12816f783 100644 --- a/telephony/java/android/telephony/satellite/SatelliteManager.java +++ b/telephony/java/android/telephony/satellite/SatelliteManager.java @@ -100,9 +100,9 @@ public final class SatelliteManager { private static final ConcurrentHashMap<Consumer<Boolean>, IBooleanConsumer> sSatelliteSupportedStateCallbackMap = new ConcurrentHashMap<>(); - private static final ConcurrentHashMap<SatelliteCommunicationAllowedStateCallback, - ISatelliteCommunicationAllowedStateCallback> - sSatelliteCommunicationAllowedStateCallbackMap = + private static final ConcurrentHashMap<SatelliteCommunicationAccessStateCallback, + ISatelliteCommunicationAccessStateCallback> + sSatelliteCommunicationAccessStateCallbackMap = new ConcurrentHashMap<>(); private static final ConcurrentHashMap<SatelliteDisallowedReasonsCallback, ISatelliteDisallowedReasonsCallback> @@ -3398,10 +3398,10 @@ public final class SatelliteManager { } /** - * Registers for the satellite communication allowed state changed. + * Registers for the satellite communication access state changed event. * * @param executor The executor on which the callback will be called. - * @param callback The callback to handle satellite communication allowed state changed event. + * @param callback The callback to handle satellite communication access state changed event. * @return The {@link SatelliteResult} result of the operation. * @throws SecurityException if the caller doesn't have required permission. * @throws IllegalStateException if the Telephony process is not currently available. @@ -3411,54 +3411,54 @@ public final class SatelliteManager { @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) @SatelliteResult - public int registerForCommunicationAllowedStateChanged( + public int registerForCommunicationAccessStateChanged( @NonNull @CallbackExecutor Executor executor, - @NonNull SatelliteCommunicationAllowedStateCallback callback) { + @NonNull SatelliteCommunicationAccessStateCallback callback) { Objects.requireNonNull(executor); Objects.requireNonNull(callback); try { ITelephony telephony = getITelephony(); if (telephony != null) { - ISatelliteCommunicationAllowedStateCallback internalCallback = - new ISatelliteCommunicationAllowedStateCallback.Stub() { + ISatelliteCommunicationAccessStateCallback internalCallback = + new ISatelliteCommunicationAccessStateCallback.Stub() { @Override - public void onSatelliteCommunicationAllowedStateChanged( + public void onAccessAllowedStateChanged( boolean isAllowed) { executor.execute(() -> Binder.withCleanCallingIdentity( - () -> callback.onSatelliteCommunicationAllowedStateChanged( + () -> callback.onAccessAllowedStateChanged( isAllowed))); } @Override - public void onSatelliteAccessConfigurationChanged( + public void onAccessConfigurationChanged( @Nullable SatelliteAccessConfiguration satelliteAccessConfiguration) { executor.execute(() -> Binder.withCleanCallingIdentity( - () -> callback.onSatelliteAccessConfigurationChanged( + () -> callback.onAccessConfigurationChanged( satelliteAccessConfiguration))); } }; - sSatelliteCommunicationAllowedStateCallbackMap.put(callback, internalCallback); - return telephony.registerForCommunicationAllowedStateChanged( + sSatelliteCommunicationAccessStateCallbackMap.put(callback, internalCallback); + return telephony.registerForCommunicationAccessStateChanged( mSubId, internalCallback); } else { throw new IllegalStateException("telephony service is null."); } } catch (RemoteException ex) { - loge("registerForCommunicationAllowedStateChanged() RemoteException: " + ex); + loge("registerForCommunicationAccessStateChanged() RemoteException: " + ex); ex.rethrowAsRuntimeException(); } return SATELLITE_RESULT_REQUEST_FAILED; } /** - * Unregisters for the satellite communication allowed state changed. + * Unregisters for the satellite communication access state changed event. * If callback was not registered before, the request will be ignored. * * @param callback The callback that was passed to - * {@link #registerForCommunicationAllowedStateChanged(Executor, - * SatelliteCommunicationAllowedStateCallback)} + * {@link #registerForCommunicationAccessStateChanged(Executor, + * SatelliteCommunicationAccessStateCallback)} * @throws SecurityException if the caller doesn't have required permission. * @throws IllegalStateException if the Telephony process is not currently available. * @hide @@ -3466,26 +3466,26 @@ public final class SatelliteManager { @SystemApi @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION) @FlaggedApi(Flags.FLAG_SATELLITE_SYSTEM_APIS) - public void unregisterForCommunicationAllowedStateChanged( - @NonNull SatelliteCommunicationAllowedStateCallback callback) { + public void unregisterForCommunicationAccessStateChanged( + @NonNull SatelliteCommunicationAccessStateCallback callback) { Objects.requireNonNull(callback); - ISatelliteCommunicationAllowedStateCallback internalCallback = - sSatelliteCommunicationAllowedStateCallbackMap.remove(callback); + ISatelliteCommunicationAccessStateCallback internalCallback = + sSatelliteCommunicationAccessStateCallbackMap.remove(callback); try { ITelephony telephony = getITelephony(); if (telephony != null) { if (internalCallback != null) { - telephony.unregisterForCommunicationAllowedStateChanged(mSubId, + telephony.unregisterForCommunicationAccessStateChanged(mSubId, internalCallback); } else { - loge("unregisterForCommunicationAllowedStateChanged: No internal callback."); + loge("unregisterForCommunicationAccessStateChanged: No internal callback."); } } else { throw new IllegalStateException("telephony service is null."); } } catch (RemoteException ex) { - loge("unregisterForCommunicationAllowedStateChanged() RemoteException: " + ex); + loge("unregisterForCommunicationAccessStateChanged() RemoteException: " + ex); ex.rethrowAsRuntimeException(); } } @@ -3690,6 +3690,11 @@ public final class SatelliteManager { * @param list The list of provisioned satellite subscriber infos. * @param executor The executor on which the callback will be called. * @param callback The callback object to which the result will be delivered. + * If the request is successful, {@link OutcomeReceiver#onResult(Object)} + * will return {@code true}. + * If the request is not successful, + * {@link OutcomeReceiver#onError(Throwable)} will return an error with + * a SatelliteException. * * @throws SecurityException if the caller doesn't have required permission. * @hide @@ -3746,6 +3751,11 @@ public final class SatelliteManager { * @param list The list of deprovisioned satellite subscriber infos. * @param executor The executor on which the callback will be called. * @param callback The callback object to which the result will be delivered. + * If the request is successful, {@link OutcomeReceiver#onResult(Object)} + * will return {@code true}. + * If the request is not successful, + * {@link OutcomeReceiver#onError(Throwable)} will return an error with + * a SatelliteException. * * @throws SecurityException if the caller doesn't have required permission. * @hide diff --git a/telephony/java/android/telephony/satellite/SatellitePosition.java b/telephony/java/android/telephony/satellite/SatellitePosition.java index 46af5c827571..354b729f3854 100644 --- a/telephony/java/android/telephony/satellite/SatellitePosition.java +++ b/telephony/java/android/telephony/satellite/SatellitePosition.java @@ -33,6 +33,7 @@ import java.util.Objects; * Longitude is the angular distance, measured in degrees, east or west of the prime longitude line * ranging from -180 to 180 degrees * Altitude is the distance from the center of the Earth to the satellite, measured in kilometers + * Latitude is not added as only geo stationary satellite are handled for now. * * @hide */ diff --git a/telephony/java/android/telephony/satellite/SatelliteSessionStats.java b/telephony/java/android/telephony/satellite/SatelliteSessionStats.java index 556ec1aa2246..402ac732a01d 100644 --- a/telephony/java/android/telephony/satellite/SatelliteSessionStats.java +++ b/telephony/java/android/telephony/satellite/SatelliteSessionStats.java @@ -252,6 +252,13 @@ public final class SatelliteSessionStats implements Parcelable { } } + public void resetCountOfUserMessagesInQueueToBeSent() { + for (Map.Entry<Integer, SatelliteSessionStats> entry : datagramStats.entrySet()) { + SatelliteSessionStats statsPerDatagramType = entry.getValue(); + statsPerDatagramType.mCountOfUserMessagesInQueueToBeSent = 0; + } + } + public int getCountOfSuccessfulOutgoingDatagram( @SatelliteManager.DatagramType int datagramType) { SatelliteSessionStats data = datagramStats.getOrDefault(datagramType, diff --git a/telephony/java/android/telephony/satellite/SatelliteSubscriberInfo.java b/telephony/java/android/telephony/satellite/SatelliteSubscriberInfo.java index 6e33995f1a3c..9d9cac9702bb 100644 --- a/telephony/java/android/telephony/satellite/SatelliteSubscriberInfo.java +++ b/telephony/java/android/telephony/satellite/SatelliteSubscriberInfo.java @@ -47,7 +47,7 @@ public final class SatelliteSubscriberInfo implements Parcelable { /** apn */ private String mNiddApn; - private int mSubId; + private int mSubscriptionId; /** SubscriberId format is the ICCID. */ public static final int SUBSCRIBER_ID_TYPE_ICCID = 0; @@ -75,7 +75,7 @@ public final class SatelliteSubscriberInfo implements Parcelable { this.mSubscriberId = builder.mSubscriberId; this.mCarrierId = builder.mCarrierId; this.mNiddApn = builder.mNiddApn; - this.mSubId = builder.mSubId; + this.mSubscriptionId = builder.mSubscriptionId; this.mSubscriberIdType = builder.mSubscriberIdType; } @@ -87,7 +87,7 @@ public final class SatelliteSubscriberInfo implements Parcelable { private int mCarrierId; @NonNull private String mNiddApn; - private int mSubId; + private int mSubscriptionId; @SubscriberIdType private int mSubscriberIdType; @@ -125,8 +125,8 @@ public final class SatelliteSubscriberInfo implements Parcelable { * Set the subId and returns the Builder class. */ @NonNull - public Builder setSubId(int subId) { - mSubId = subId; + public Builder setSubscriptionId(int subId) { + mSubscriptionId = subId; return this; } @@ -153,7 +153,7 @@ public final class SatelliteSubscriberInfo implements Parcelable { out.writeString(mSubscriberId); out.writeInt(mCarrierId); out.writeString(mNiddApn); - out.writeInt(mSubId); + out.writeInt(mSubscriptionId); out.writeInt(mSubscriberIdType); } @@ -203,8 +203,8 @@ public final class SatelliteSubscriberInfo implements Parcelable { /** * Return the subscriptionId of the subscription which is used for satellite attachment. */ - public int getSubId() { - return mSubId; + public int getSubscriptionId() { + return mSubscriptionId; } /** @@ -231,8 +231,8 @@ public final class SatelliteSubscriberInfo implements Parcelable { sb.append(mNiddApn); sb.append(","); - sb.append("SubId:"); - sb.append(mSubId); + sb.append("SubscriptionId:"); + sb.append(mSubscriptionId); sb.append(","); sb.append("SubscriberIdType:"); @@ -242,7 +242,8 @@ public final class SatelliteSubscriberInfo implements Parcelable { @Override public int hashCode() { - return Objects.hash(mSubscriberId, mCarrierId, mNiddApn, mSubId, mSubscriberIdType); + return Objects.hash( + mSubscriberId, mCarrierId, mNiddApn, mSubscriptionId, mSubscriberIdType); } @Override @@ -251,7 +252,8 @@ public final class SatelliteSubscriberInfo implements Parcelable { if (!(o instanceof SatelliteSubscriberInfo)) return false; SatelliteSubscriberInfo that = (SatelliteSubscriberInfo) o; return Objects.equals(mSubscriberId, that.mSubscriberId) && mCarrierId == that.mCarrierId - && Objects.equals(mNiddApn, that.mNiddApn) && mSubId == that.mSubId + && Objects.equals(mNiddApn, that.mNiddApn) + && mSubscriptionId == that.mSubscriptionId && mSubscriberIdType == that.mSubscriberIdType; } @@ -259,7 +261,7 @@ public final class SatelliteSubscriberInfo implements Parcelable { mSubscriberId = in.readString(); mCarrierId = in.readInt(); mNiddApn = in.readString(); - mSubId = in.readInt(); + mSubscriptionId = in.readInt(); mSubscriberIdType = in.readInt(); } } diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index aa577304c564..08c003027c5b 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -69,7 +69,7 @@ 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.ISatelliteCommunicationAllowedStateCallback; +import android.telephony.satellite.ISatelliteCommunicationAccessStateCallback; import android.telephony.satellite.ISatelliteDatagramCallback; import android.telephony.satellite.ISatelliteDisallowedReasonsCallback; import android.telephony.satellite.ISatelliteTransmissionUpdateCallback; @@ -3446,20 +3446,20 @@ interface ITelephony { */ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(" + "android.Manifest.permission.SATELLITE_COMMUNICATION)") - int registerForCommunicationAllowedStateChanged(int subId, - in ISatelliteCommunicationAllowedStateCallback callback); + int registerForCommunicationAccessStateChanged(int subId, + in ISatelliteCommunicationAccessStateCallback callback); /** * Unregisters for satellite communication allowed state. * If callback was not registered before, the request will be ignored. * * @param subId The subId of the subscription to unregister for supported state changed. - * @param callback The callback that was passed to registerForCommunicationAllowedStateChanged. + * @param callback The callback that was passed to registerForCommunicationAccessStateChanged. */ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(" + "android.Manifest.permission.SATELLITE_COMMUNICATION)") - void unregisterForCommunicationAllowedStateChanged(int subId, - in ISatelliteCommunicationAllowedStateCallback callback); + void unregisterForCommunicationAccessStateChanged(int subId, + in ISatelliteCommunicationAccessStateCallback callback); /** * This API can be used by only CTS to override the boolean configs used by the diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/BottomHalfPipAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/BottomHalfPipAppHelper.kt index 6573c2c83f20..ed2cff4a9515 100644 --- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/BottomHalfPipAppHelper.kt +++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/BottomHalfPipAppHelper.kt @@ -19,6 +19,7 @@ package com.android.server.wm.flicker.helpers import android.app.Instrumentation import android.content.Intent import android.tools.traces.parsers.toFlickerComponent +import android.tools.traces.parsers.WindowManagerStateHelper import com.android.server.wm.flicker.testapp.ActivityOptions class BottomHalfPipAppHelper( @@ -38,4 +39,14 @@ class BottomHalfPipAppHelper( ActivityOptions.BottomHalfPip.COMPONENT } } + + override fun exitPipToOriginalTaskViaIntent(wmHelper: WindowManagerStateHelper) { + launchViaIntent( + wmHelper, + Intent().apply { + component = ActivityOptions.BottomHalfPip.COMPONENT + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + } + ) + } }
\ No newline at end of file diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt index de17bf422c0c..344cac1ac7e5 100644 --- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt +++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt @@ -75,8 +75,9 @@ open class PipAppHelper( .waitForAndVerify() } - /** Expand the PIP window back to full screen via intent and wait until the app is visible */ - fun exitPipToFullScreenViaIntent(wmHelper: WindowManagerStateHelper) = launchViaIntent(wmHelper) + /** Expand the PIP window back to original task via intent and wait until the app is visible */ + open fun exitPipToOriginalTaskViaIntent(wmHelper: WindowManagerStateHelper) = + launchViaIntent(wmHelper) fun changeAspectRatio(wmHelper: WindowManagerStateHelper) { val intent = Intent("com.android.wm.shell.flicker.testapp.ASPECT_RATIO") diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/BottomHalfPipLaunchingActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/BottomHalfPipLaunchingActivity.java index d9d4361411bb..209f71e4f307 100644 --- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/BottomHalfPipLaunchingActivity.java +++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/BottomHalfPipLaunchingActivity.java @@ -24,8 +24,12 @@ public class BottomHalfPipLaunchingActivity extends SimpleActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - final Intent intent = new Intent(this, BottomHalfPipActivity.class); + // Pass extras to BottomHalfPipActivity. + final Bundle extras = getIntent().getExtras(); + if (extras != null) { + intent.putExtras(extras); + } startActivity(intent); } } |