diff options
311 files changed, 7097 insertions, 3521 deletions
diff --git a/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java b/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java index ecd149989ce6..1be68f5d53a4 100644 --- a/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java +++ b/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java @@ -135,7 +135,6 @@ public class RelayoutPerfTest extends WindowManagerPerfTestBase final int mHeight; final Point mOutSurfaceSize = new Point(); final SurfaceControl mOutSurfaceControl; - final SurfaceControl mOutBlastSurfaceControl = new SurfaceControl(); final IntSupplier mViewVisibility; @@ -158,7 +157,7 @@ public class RelayoutPerfTest extends WindowManagerPerfTestBase session.relayout(mWindow, mParams, mWidth, mHeight, mViewVisibility.getAsInt(), mFlags, mFrameNumber, mOutFrames, mOutMergedConfiguration, mOutSurfaceControl, mOutInsetsState, mOutControls, - mOutSurfaceSize, mOutBlastSurfaceControl); + mOutSurfaceSize); } } } diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java index 1a81587990f2..81f22fe36ea1 100644 --- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java +++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java @@ -2179,7 +2179,7 @@ public class DeviceIdleController extends SystemService if (getContext().getResources().getBoolean( com.android.internal.R.bool.config_autoPowerModePrefetchLocation)) { mLocationRequest = new LocationRequest.Builder(/*intervalMillis=*/ 0) - .setQuality(LocationRequest.ACCURACY_FINE) + .setQuality(LocationRequest.QUALITY_HIGH_ACCURACY) .setMaxUpdates(1) .build(); } diff --git a/api/current.txt b/api/current.txt index a550bf879717..c8419c58c4ae 100644 --- a/api/current.txt +++ b/api/current.txt @@ -10667,12 +10667,15 @@ package android.content { field public static final String ACTION_PACKAGE_CHANGED = "android.intent.action.PACKAGE_CHANGED"; field public static final String ACTION_PACKAGE_DATA_CLEARED = "android.intent.action.PACKAGE_DATA_CLEARED"; field public static final String ACTION_PACKAGE_FIRST_LAUNCH = "android.intent.action.PACKAGE_FIRST_LAUNCH"; + field public static final String ACTION_PACKAGE_FULLY_LOADED = "android.intent.action.PACKAGE_FULLY_LOADED"; field public static final String ACTION_PACKAGE_FULLY_REMOVED = "android.intent.action.PACKAGE_FULLY_REMOVED"; field @Deprecated public static final String ACTION_PACKAGE_INSTALL = "android.intent.action.PACKAGE_INSTALL"; field public static final String ACTION_PACKAGE_NEEDS_VERIFICATION = "android.intent.action.PACKAGE_NEEDS_VERIFICATION"; field public static final String ACTION_PACKAGE_REMOVED = "android.intent.action.PACKAGE_REMOVED"; field public static final String ACTION_PACKAGE_REPLACED = "android.intent.action.PACKAGE_REPLACED"; field public static final String ACTION_PACKAGE_RESTARTED = "android.intent.action.PACKAGE_RESTARTED"; + field public static final String ACTION_PACKAGE_STARTABLE = "android.intent.action.PACKAGE_STARTABLE"; + field public static final String ACTION_PACKAGE_UNSTARTABLE = "android.intent.action.PACKAGE_UNSTARTABLE"; field public static final String ACTION_PACKAGE_VERIFIED = "android.intent.action.PACKAGE_VERIFIED"; field public static final String ACTION_PASTE = "android.intent.action.PASTE"; field public static final String ACTION_PICK = "android.intent.action.PICK"; @@ -10837,6 +10840,7 @@ package android.content { field public static final String EXTRA_TIMEZONE = "time-zone"; field public static final String EXTRA_TITLE = "android.intent.extra.TITLE"; field public static final String EXTRA_UID = "android.intent.extra.UID"; + field public static final String EXTRA_UNSTARTABLE_REASON = "android.intent.extra.UNSTARTABLE_REASON"; field public static final String EXTRA_USER = "android.intent.extra.USER"; field public static final int FILL_IN_ACTION = 1; // 0x1 field public static final int FILL_IN_CATEGORIES = 4; // 0x4 @@ -11710,7 +11714,10 @@ package android.content.pm { method public android.graphics.drawable.Drawable getIcon(int); method public CharSequence getLabel(); method public String getName(); + method public float getProgress(); method public android.os.UserHandle getUser(); + method public boolean isLoading(); + method public boolean isStartable(); } public class LauncherApps { @@ -11750,6 +11757,7 @@ package android.content.pm { ctor public LauncherApps.Callback(); method public abstract void onPackageAdded(String, android.os.UserHandle); method public abstract void onPackageChanged(String, android.os.UserHandle); + method public void onPackageProgressChanged(@NonNull String, @NonNull android.os.UserHandle, float); method public abstract void onPackageRemoved(String, android.os.UserHandle); method public abstract void onPackagesAvailable(String[], android.os.UserHandle, boolean); method public void onPackagesSuspended(String[], android.os.UserHandle); @@ -12296,6 +12304,9 @@ package android.content.pm { field public static final int SYNCHRONOUS = 2; // 0x2 field @Nullable public static final java.util.List<java.security.cert.Certificate> TRUST_ALL; field @NonNull public static final java.util.List<java.security.cert.Certificate> TRUST_NONE; + field public static final int UNSTARTABLE_REASON_CONNECTION_ERROR = 1; // 0x1 + field public static final int UNSTARTABLE_REASON_INSUFFICIENT_STORAGE = 2; // 0x2 + field public static final int UNSTARTABLE_REASON_UNKNOWN = 0; // 0x0 field public static final int VERIFICATION_ALLOW = 1; // 0x1 field public static final int VERIFICATION_REJECT = -1; // 0xffffffff field public static final int VERSION_CODE_HIGHEST = -1; // 0xffffffff @@ -24092,9 +24103,13 @@ package android.location { method @IntRange(from=1, to=java.lang.Integer.MAX_VALUE) public int getMaxUpdates(); method @FloatRange(from=0, to=java.lang.Float.MAX_VALUE) public float getMinUpdateDistanceMeters(); method @IntRange(from=0) public long getMinUpdateIntervalMillis(); + method public int getQuality(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.location.LocationRequest> CREATOR; field public static final long PASSIVE_INTERVAL = 9223372036854775807L; // 0x7fffffffffffffffL + field public static final int QUALITY_BALANCED_POWER_ACCURACY = 102; // 0x66 + field public static final int QUALITY_HIGH_ACCURACY = 100; // 0x64 + field public static final int QUALITY_LOW_POWER = 104; // 0x68 } public static final class LocationRequest.Builder { @@ -24107,6 +24122,7 @@ package android.location { method @NonNull public android.location.LocationRequest.Builder setMaxUpdates(@IntRange(from=1, to=java.lang.Integer.MAX_VALUE) int); method @NonNull public android.location.LocationRequest.Builder setMinUpdateDistanceMeters(@FloatRange(from=0, to=java.lang.Float.MAX_VALUE) float); method @NonNull public android.location.LocationRequest.Builder setMinUpdateIntervalMillis(@IntRange(from=0) long); + method @NonNull public android.location.LocationRequest.Builder setQuality(int); } public interface OnNmeaMessageListener { @@ -32094,13 +32110,13 @@ package android.net.wifi.hotspot2.pps { method public String getFriendlyName(); method @Nullable public long[] getMatchAllOis(); method @Nullable public long[] getMatchAnyOis(); - method @Nullable public String[] getOtherHomePartners(); + method @NonNull public java.util.Collection<java.lang.String> getOtherHomePartnersList(); method public long[] getRoamingConsortiumOis(); method public void setFqdn(String); method public void setFriendlyName(String); method public void setMatchAllOis(@Nullable long[]); method public void setMatchAnyOis(@Nullable long[]); - method public void setOtherHomePartners(@Nullable String[]); + method public void setOtherHomePartnersList(@NonNull java.util.Collection<java.lang.String>); method public void setRoamingConsortiumOis(long[]); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.HomeSp> CREATOR; @@ -53728,11 +53744,12 @@ package android.view { method @Nullable public android.net.Uri getLinkUri(); method public int getSource(); field public static final int FLAG_CONVERT_TO_PLAIN_TEXT = 1; // 0x1 - field public static final int SOURCE_AUTOFILL = 3; // 0x3 - field public static final int SOURCE_CLIPBOARD = 0; // 0x0 - field public static final int SOURCE_DRAG_AND_DROP = 2; // 0x2 - field public static final int SOURCE_INPUT_METHOD = 1; // 0x1 - field public static final int SOURCE_PROCESS_TEXT = 4; // 0x4 + field public static final int SOURCE_APP = 0; // 0x0 + field public static final int SOURCE_AUTOFILL = 4; // 0x4 + field public static final int SOURCE_CLIPBOARD = 1; // 0x1 + field public static final int SOURCE_DRAG_AND_DROP = 3; // 0x3 + field public static final int SOURCE_INPUT_METHOD = 2; // 0x2 + field public static final int SOURCE_PROCESS_TEXT = 5; // 0x5 } public static final class OnReceiveContentCallback.Payload.Builder { diff --git a/api/module-lib-current.txt b/api/module-lib-current.txt index b8b66879dbae..e825b62fdcdb 100644 --- a/api/module-lib-current.txt +++ b/api/module-lib-current.txt @@ -188,6 +188,18 @@ package android.provider { } +package android.telephony { + + public abstract class CellSignalStrength { + method public static int getNumSignalStrengthLevels(); + } + + public class TelephonyManager { + method @NonNull public static int[] getAllNetworkTypes(); + } + +} + package android.util { public class AtomicFile { diff --git a/api/system-current.txt b/api/system-current.txt index 648be0d74bae..bcea591f869d 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -122,6 +122,7 @@ package android { field public static final String MANAGE_FACTORY_RESET_PROTECTION = "android.permission.MANAGE_FACTORY_RESET_PROTECTION"; field public static final String MANAGE_IPSEC_TUNNELS = "android.permission.MANAGE_IPSEC_TUNNELS"; field public static final String MANAGE_MUSIC_RECOGNITION = "android.permission.MANAGE_MUSIC_RECOGNITION"; + field public static final String MANAGE_NOTIFICATION_LISTENERS = "android.permission.MANAGE_NOTIFICATION_LISTENERS"; field public static final String MANAGE_ONE_TIME_PERMISSION_SESSIONS = "android.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS"; field public static final String MANAGE_ROLE_HOLDERS = "android.permission.MANAGE_ROLE_HOLDERS"; field public static final String MANAGE_ROLLBACKS = "android.permission.MANAGE_ROLLBACKS"; @@ -674,8 +675,10 @@ package android.app { public class NotificationManager { method @NonNull public java.util.List<java.lang.String> getAllowedAssistantAdjustments(); method @Nullable public android.content.ComponentName getAllowedNotificationAssistant(); + method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS) public java.util.List<android.content.ComponentName> getEnabledNotificationListeners(); method public boolean isNotificationAssistantAccessGranted(@NonNull android.content.ComponentName); method public void setNotificationAssistantAccessGranted(@Nullable android.content.ComponentName, boolean); + method @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS) public void setNotificationListenerAccessGranted(@NonNull android.content.ComponentName, boolean); field @RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE) public static final String ACTION_CLOSE_NOTIFICATION_HANDLER_PANEL = "android.app.action.CLOSE_NOTIFICATION_HANDLER_PANEL"; field @RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE) public static final String ACTION_OPEN_NOTIFICATION_HANDLER_PANEL = "android.app.action.OPEN_NOTIFICATION_HANDLER_PANEL"; field @RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE) public static final String ACTION_TOGGLE_NOTIFICATION_HANDLER_PANEL = "android.app.action.TOGGLE_NOTIFICATION_HANDLER_PANEL"; @@ -1448,20 +1451,20 @@ package android.app.time { package android.app.usage { public final class CacheQuotaHint implements android.os.Parcelable { - ctor public CacheQuotaHint(android.app.usage.CacheQuotaHint.Builder); + ctor public CacheQuotaHint(@NonNull android.app.usage.CacheQuotaHint.Builder); method public int describeContents(); method public long getQuota(); method public int getUid(); - method public android.app.usage.UsageStats getUsageStats(); - method public String getVolumeUuid(); - method public void writeToParcel(android.os.Parcel, int); + method @Nullable public android.app.usage.UsageStats getUsageStats(); + method @Nullable public String getVolumeUuid(); + method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.app.usage.CacheQuotaHint> CREATOR; field public static final long QUOTA_NOT_SET = -1L; // 0xffffffffffffffffL } public static final class CacheQuotaHint.Builder { ctor public CacheQuotaHint.Builder(); - ctor public CacheQuotaHint.Builder(android.app.usage.CacheQuotaHint); + ctor public CacheQuotaHint.Builder(@NonNull android.app.usage.CacheQuotaHint); method @NonNull public android.app.usage.CacheQuotaHint build(); method @NonNull public android.app.usage.CacheQuotaHint.Builder setQuota(long); method @NonNull public android.app.usage.CacheQuotaHint.Builder setUid(int); @@ -4171,7 +4174,6 @@ package android.location { method @Deprecated public long getInterval(); method @Deprecated public int getNumUpdates(); method @Deprecated @NonNull public String getProvider(); - method public int getQuality(); method @Deprecated public float getSmallestDisplacement(); method @NonNull public android.os.WorkSource getWorkSource(); method public boolean isHiddenFromAppOps(); @@ -4190,11 +4192,11 @@ package android.location { method @Deprecated @NonNull public android.location.LocationRequest setQuality(int); method @Deprecated @NonNull public android.location.LocationRequest setSmallestDisplacement(float); method @Deprecated public void setWorkSource(@Nullable android.os.WorkSource); - field public static final int ACCURACY_BLOCK = 102; // 0x66 - field public static final int ACCURACY_CITY = 104; // 0x68 - field public static final int ACCURACY_FINE = 100; // 0x64 - field public static final int POWER_HIGH = 203; // 0xcb - field public static final int POWER_LOW = 201; // 0xc9 + field @Deprecated public static final int ACCURACY_BLOCK = 102; // 0x66 + field @Deprecated public static final int ACCURACY_CITY = 104; // 0x68 + field @Deprecated public static final int ACCURACY_FINE = 100; // 0x64 + field @Deprecated public static final int POWER_HIGH = 203; // 0xcb + field @Deprecated public static final int POWER_LOW = 201; // 0xc9 field @Deprecated public static final int POWER_NONE = 200; // 0xc8 } @@ -4202,7 +4204,6 @@ package android.location { method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS) public android.location.LocationRequest.Builder setHiddenFromAppOps(boolean); method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public android.location.LocationRequest.Builder setLocationSettingsIgnored(boolean); method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.location.LocationRequest.Builder setLowPower(boolean); - method @NonNull public android.location.LocationRequest.Builder setQuality(int); method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.location.LocationRequest.Builder setWorkSource(@Nullable android.os.WorkSource); } @@ -4769,6 +4770,22 @@ package android.media.tv { field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.DvbDeviceInfo> CREATOR; } + public final class TunedInfo implements android.os.Parcelable { + method public int describeContents(); + method public int getAppTag(); + method public int getAppType(); + method @Nullable public android.net.Uri getChannelUri(); + method @NonNull public String getInputId(); + method public boolean isForeground(); + method public boolean isRecordingSession(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field public static final int APP_TAG_SELF = 0; // 0x0 + field public static final int APP_TYPE_NON_SYSTEM = 3; // 0x3 + field public static final int APP_TYPE_SELF = 1; // 0x1 + field public static final int APP_TYPE_SYSTEM = 2; // 0x2 + field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.TunedInfo> CREATOR; + } + public final class TvContentRatingSystemInfo implements android.os.Parcelable { method public static android.media.tv.TvContentRatingSystemInfo createTvContentRatingSystemInfo(int, android.content.pm.ApplicationInfo); method public int describeContents(); @@ -4884,6 +4901,7 @@ package android.media.tv { method @RequiresPermission(android.Manifest.permission.MODIFY_PARENTAL_CONTROLS) public void addBlockedRating(@NonNull android.media.tv.TvContentRating); method @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT) public boolean captureFrame(String, android.view.Surface, android.media.tv.TvStreamConfig); method @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT) public java.util.List<android.media.tv.TvStreamConfig> getAvailableTvStreamConfigList(String); + method @NonNull @RequiresPermission("com.android.providers.tv.permission.ACCESS_WATCHED_PROGRAMS") public java.util.List<android.media.tv.TunedInfo> getCurrentTunedInfos(); method @NonNull @RequiresPermission("android.permission.DVB_DEVICE") public java.util.List<android.media.tv.DvbDeviceInfo> getDvbDeviceList(); method @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE) public java.util.List<android.media.tv.TvInputHardwareInfo> getHardwareList(); method @RequiresPermission(android.Manifest.permission.READ_CONTENT_RATING_SYSTEMS) public java.util.List<android.media.tv.TvContentRatingSystemInfo> getTvContentRatingSystemList(); @@ -4909,6 +4927,10 @@ package android.media.tv { method public abstract void onStreamConfigChanged(android.media.tv.TvStreamConfig[]); } + public abstract static class TvInputManager.TvInputCallback { + method public void onCurrentTunedInfosUpdated(@NonNull java.util.List<android.media.tv.TunedInfo>); + } + public abstract class TvInputService extends android.app.Service { method @Nullable public android.media.tv.TvInputInfo onHardwareAdded(android.media.tv.TvInputHardwareInfo); method @Nullable public String onHardwareRemoved(android.media.tv.TvInputHardwareInfo); @@ -5055,6 +5077,7 @@ package android.media.tv.tuner { field public static final int INVALID_AV_SYNC_ID = -1; // 0xffffffff field public static final int INVALID_FILTER_ID = -1; // 0xffffffff field public static final long INVALID_FILTER_ID_64BIT = -1L; // 0xffffffffffffffffL + field public static final int INVALID_FRONTEND_SETTING_FREQUENCY = -1; // 0xffffffff field public static final int INVALID_LTS_ID = -1; // 0xffffffff field public static final int INVALID_MMTP_RECORD_EVENT_MPT_SEQUENCE_NUM = -1; // 0xffffffff field public static final int INVALID_STREAM_ID = 65535; // 0xffff @@ -5088,10 +5111,10 @@ package android.media.tv.tuner { package android.media.tv.tuner.dvr { public class DvrPlayback implements java.lang.AutoCloseable { - method public int attachFilter(@NonNull android.media.tv.tuner.filter.Filter); + method @Deprecated public int attachFilter(@NonNull android.media.tv.tuner.filter.Filter); method public void close(); method public int configure(@NonNull android.media.tv.tuner.dvr.DvrSettings); - method public int detachFilter(@NonNull android.media.tv.tuner.filter.Filter); + method @Deprecated public int detachFilter(@NonNull android.media.tv.tuner.filter.Filter); method public int flush(); method public long read(long); method public long read(@NonNull byte[], long, long); @@ -5268,16 +5291,19 @@ package android.media.tv.tuner.filter { method @NonNull public static android.media.tv.tuner.filter.IpFilterConfiguration.Builder builder(); method @NonNull @Size(min=4, max=16) public byte[] getDstIpAddress(); method public int getDstPort(); + method public int getIpFilterContextId(); method @NonNull @Size(min=4, max=16) public byte[] getSrcIpAddress(); method public int getSrcPort(); method public int getType(); method public boolean isPassthrough(); + field public static final int INVALID_IP_FILTER_CONTEXT_ID = -1; // 0xffffffff } public static final class IpFilterConfiguration.Builder { method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration build(); method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration.Builder setDstIpAddress(@NonNull byte[]); method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration.Builder setDstPort(int); + method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration.Builder setIpFilterContextId(int); method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration.Builder setPassthrough(boolean); method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration.Builder setSettings(@Nullable android.media.tv.tuner.filter.Settings); method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration.Builder setSrcIpAddress(@NonNull byte[]); @@ -5497,9 +5523,13 @@ package android.media.tv.tuner.frontend { public class AnalogFrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings { method @NonNull public static android.media.tv.tuner.frontend.AnalogFrontendSettings.Builder builder(); + method public int getAftFlag(); method public int getSifStandard(); method public int getSignalType(); method public int getType(); + field public static final int AFT_FLAG_FALSE = 2; // 0x2 + field public static final int AFT_FLAG_TRUE = 1; // 0x1 + field public static final int AFT_FLAG_UNDEFINED = 0; // 0x0 field public static final int SIF_AUTO = 1; // 0x1 field public static final int SIF_BG = 2; // 0x2 field public static final int SIF_BG_A2 = 4; // 0x4 @@ -5532,6 +5562,7 @@ package android.media.tv.tuner.frontend { public static class AnalogFrontendSettings.Builder { method @NonNull public android.media.tv.tuner.frontend.AnalogFrontendSettings build(); + method @NonNull public android.media.tv.tuner.frontend.AnalogFrontendSettings.Builder setAftFlag(int); method @IntRange(from=1) @NonNull public android.media.tv.tuner.frontend.AnalogFrontendSettings.Builder setFrequency(int); method @NonNull public android.media.tv.tuner.frontend.AnalogFrontendSettings.Builder setSifStandard(int); method @NonNull public android.media.tv.tuner.frontend.AnalogFrontendSettings.Builder setSignalType(int); @@ -5647,6 +5678,69 @@ package android.media.tv.tuner.frontend { method @NonNull public android.media.tv.tuner.frontend.AtscFrontendSettings.Builder setModulation(int); } + public class DtmbFrontendCapabilities extends android.media.tv.tuner.frontend.FrontendCapabilities { + method public int getBandwidthCapability(); + method public int getCodeRateCapability(); + method public int getGuardIntervalCapability(); + method public int getModulationCapability(); + method public int getTimeInterleaveModeCapability(); + method public int getTransmissionModeCapability(); + } + + public class DtmbFrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings { + method @NonNull public static android.media.tv.tuner.frontend.DtmbFrontendSettings.Builder builder(); + method public int getBandwidth(); + method public int getCodeRate(); + method public int getGuardInterval(); + method public int getModulation(); + method public int getTimeInterleaveMode(); + method public int getTransmissionMode(); + method public int getType(); + field public static final int BANDWIDTH_6MHZ = 4; // 0x4 + field public static final int BANDWIDTH_8MHZ = 2; // 0x2 + field public static final int BANDWIDTH_AUTO = 1; // 0x1 + field public static final int BANDWIDTH_UNDEFINED = 0; // 0x0 + field public static final int CODERATE_2_5 = 2; // 0x2 + field public static final int CODERATE_3_5 = 4; // 0x4 + field public static final int CODERATE_4_5 = 8; // 0x8 + field public static final int CODERATE_AUTO = 1; // 0x1 + field public static final int CODERATE_UNDEFINED = 0; // 0x0 + field public static final int GUARD_INTERVAL_AUTO = 1; // 0x1 + field public static final int GUARD_INTERVAL_PN_420_CONST = 16; // 0x10 + field public static final int GUARD_INTERVAL_PN_420_VARIOUS = 2; // 0x2 + field public static final int GUARD_INTERVAL_PN_595_CONST = 4; // 0x4 + field public static final int GUARD_INTERVAL_PN_945_CONST = 32; // 0x20 + field public static final int GUARD_INTERVAL_PN_945_VARIOUS = 8; // 0x8 + field public static final int GUARD_INTERVAL_PN_RESERVED = 64; // 0x40 + field public static final int GUARD_INTERVAL_UNDEFINED = 0; // 0x0 + field public static final int MODULATION_CONSTELLATION_16QAM = 8; // 0x8 + field public static final int MODULATION_CONSTELLATION_32QAM = 16; // 0x10 + field public static final int MODULATION_CONSTELLATION_4QAM = 2; // 0x2 + field public static final int MODULATION_CONSTELLATION_4QAM_NR = 4; // 0x4 + field public static final int MODULATION_CONSTELLATION_64QAM = 32; // 0x20 + field public static final int MODULATION_CONSTELLATION_AUTO = 1; // 0x1 + field public static final int MODULATION_CONSTELLATION_UNDEFINED = 0; // 0x0 + field public static final int TIME_INTERLEAVE_MODE_AUTO = 1; // 0x1 + field public static final int TIME_INTERLEAVE_MODE_TIMER_INT_240 = 2; // 0x2 + field public static final int TIME_INTERLEAVE_MODE_TIMER_INT_720 = 4; // 0x4 + field public static final int TIME_INTERLEAVE_MODE_UNDEFINED = 0; // 0x0 + field public static final int TRANSMISSION_MODE_AUTO = 1; // 0x1 + field public static final int TRANSMISSION_MODE_C1 = 2; // 0x2 + field public static final int TRANSMISSION_MODE_C3780 = 4; // 0x4 + field public static final int TRANSMISSION_MODE_UNDEFINED = 0; // 0x0 + } + + public static final class DtmbFrontendSettings.Builder { + method @NonNull public android.media.tv.tuner.frontend.DtmbFrontendSettings build(); + method @NonNull public android.media.tv.tuner.frontend.DtmbFrontendSettings.Builder setBandwidth(int); + method @NonNull public android.media.tv.tuner.frontend.DtmbFrontendSettings.Builder setCodeRate(int); + method @IntRange(from=1) @NonNull public android.media.tv.tuner.frontend.DtmbFrontendSettings.Builder setFrequency(int); + method @NonNull public android.media.tv.tuner.frontend.DtmbFrontendSettings.Builder setGuardInterval(int); + method @NonNull public android.media.tv.tuner.frontend.DtmbFrontendSettings.Builder setModulation(int); + method @NonNull public android.media.tv.tuner.frontend.DtmbFrontendSettings.Builder setTimeInterleaveMode(int); + method @NonNull public android.media.tv.tuner.frontend.DtmbFrontendSettings.Builder setTransmissionMode(int); + } + public class DvbcFrontendCapabilities extends android.media.tv.tuner.frontend.FrontendCapabilities { method public int getAnnexCapability(); method public int getFecCapability(); @@ -5661,6 +5755,7 @@ package android.media.tv.tuner.frontend { method public int getOuterFec(); method public int getSpectralInversion(); method public int getSymbolRate(); + method public int getTimeInterleaveMode(); method public int getType(); field public static final int ANNEX_A = 1; // 0x1 field public static final int ANNEX_B = 2; // 0x2 @@ -5676,9 +5771,20 @@ package android.media.tv.tuner.frontend { field public static final int OUTER_FEC_OUTER_FEC_NONE = 1; // 0x1 field public static final int OUTER_FEC_OUTER_FEC_RS = 2; // 0x2 field public static final int OUTER_FEC_UNDEFINED = 0; // 0x0 - field public static final int SPECTRAL_INVERSION_INVERTED = 2; // 0x2 - field public static final int SPECTRAL_INVERSION_NORMAL = 1; // 0x1 - field public static final int SPECTRAL_INVERSION_UNDEFINED = 0; // 0x0 + field @Deprecated public static final int SPECTRAL_INVERSION_INVERTED = 2; // 0x2 + field @Deprecated public static final int SPECTRAL_INVERSION_NORMAL = 1; // 0x1 + field @Deprecated public static final int SPECTRAL_INVERSION_UNDEFINED = 0; // 0x0 + field public static final int TIME_INTERLEAVE_MODE_128_1_0 = 2; // 0x2 + field public static final int TIME_INTERLEAVE_MODE_128_1_1 = 4; // 0x4 + field public static final int TIME_INTERLEAVE_MODE_128_2 = 128; // 0x80 + field public static final int TIME_INTERLEAVE_MODE_128_3 = 256; // 0x100 + field public static final int TIME_INTERLEAVE_MODE_128_4 = 512; // 0x200 + field public static final int TIME_INTERLEAVE_MODE_16_8 = 32; // 0x20 + field public static final int TIME_INTERLEAVE_MODE_32_4 = 16; // 0x10 + field public static final int TIME_INTERLEAVE_MODE_64_2 = 8; // 0x8 + field public static final int TIME_INTERLEAVE_MODE_8_16 = 64; // 0x40 + field public static final int TIME_INTERLEAVE_MODE_AUTO = 1; // 0x1 + field public static final int TIME_INTERLEAVE_MODE_UNDEFINED = 0; // 0x0 } public static class DvbcFrontendSettings.Builder { @@ -5690,6 +5796,7 @@ package android.media.tv.tuner.frontend { method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder setOuterFec(int); method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder setSpectralInversion(int); method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder setSymbolRate(int); + method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder setTimeInterleaveMode(int); } public class DvbsCodeRate { @@ -5721,6 +5828,7 @@ package android.media.tv.tuner.frontend { method public int getModulation(); method public int getPilot(); method public int getRolloff(); + method public int getScanType(); method public int getStandard(); method public int getSymbolRate(); method public int getType(); @@ -5751,6 +5859,11 @@ package android.media.tv.tuner.frontend { field public static final int ROLLOFF_0_35 = 1; // 0x1 field public static final int ROLLOFF_0_5 = 6; // 0x6 field public static final int ROLLOFF_UNDEFINED = 0; // 0x0 + field public static final int SCAN_TYPE_DIRECT = 1; // 0x1 + field public static final int SCAN_TYPE_DISEQC = 2; // 0x2 + field public static final int SCAN_TYPE_JESS = 4; // 0x4 + field public static final int SCAN_TYPE_UNDEFINED = 0; // 0x0 + field public static final int SCAN_TYPE_UNICABLE = 3; // 0x3 field public static final int STANDARD_AUTO = 1; // 0x1 field public static final int STANDARD_S = 2; // 0x2 field public static final int STANDARD_S2 = 4; // 0x4 @@ -5768,6 +5881,7 @@ package android.media.tv.tuner.frontend { method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setModulation(int); method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setPilot(int); method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setRolloff(int); + method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setScanType(int); method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setStandard(int); method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setSymbolRate(int); method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setVcmMode(int); @@ -5820,10 +5934,14 @@ package android.media.tv.tuner.frontend { field public static final int CODERATE_AUTO = 1; // 0x1 field public static final int CODERATE_UNDEFINED = 0; // 0x0 field public static final int CONSTELLATION_16QAM = 4; // 0x4 + field public static final int CONSTELLATION_16QAM_R = 64; // 0x40 field public static final int CONSTELLATION_256QAM = 16; // 0x10 + field public static final int CONSTELLATION_256QAM_R = 256; // 0x100 field public static final int CONSTELLATION_64QAM = 8; // 0x8 + field public static final int CONSTELLATION_64QAM_R = 128; // 0x80 field public static final int CONSTELLATION_AUTO = 1; // 0x1 field public static final int CONSTELLATION_QPSK = 2; // 0x2 + field public static final int CONSTELLATION_QPSK_R = 32; // 0x20 field public static final int CONSTELLATION_UNDEFINED = 0; // 0x0 field public static final int GUARD_INTERVAL_19_128 = 64; // 0x40 field public static final int GUARD_INTERVAL_19_256 = 128; // 0x80 @@ -5857,6 +5975,9 @@ package android.media.tv.tuner.frontend { field public static final int TRANSMISSION_MODE_4K = 8; // 0x8 field public static final int TRANSMISSION_MODE_8K = 4; // 0x4 field public static final int TRANSMISSION_MODE_AUTO = 1; // 0x1 + field public static final int TRANSMISSION_MODE_EXTENDED_16K = 256; // 0x100 + field public static final int TRANSMISSION_MODE_EXTENDED_32K = 512; // 0x200 + field public static final int TRANSMISSION_MODE_EXTENDED_8K = 128; // 0x80 field public static final int TRANSMISSION_MODE_UNDEFINED = 0; // 0x0 } @@ -5894,8 +6015,12 @@ package android.media.tv.tuner.frontend { } public abstract class FrontendSettings { + method public int getEndFrequency(); method public int getFrequency(); + method public int getFrontendSpectralInversion(); method public abstract int getType(); + method @IntRange(from=1) public void setEndFrequency(int); + method public void setSpectralInversion(int); field public static final long FEC_11_15 = 4194304L; // 0x400000L field public static final long FEC_11_20 = 8388608L; // 0x800000L field public static final long FEC_11_45 = 16777216L; // 0x1000000L @@ -5933,9 +6058,13 @@ package android.media.tv.tuner.frontend { field public static final long FEC_9_20 = 2097152L; // 0x200000L field public static final long FEC_AUTO = 1L; // 0x1L field public static final long FEC_UNDEFINED = 0L; // 0x0L + field public static final int FRONTEND_SPECTRAL_INVERSION_INVERTED = 2; // 0x2 + field public static final int FRONTEND_SPECTRAL_INVERSION_NORMAL = 1; // 0x1 + field public static final int FRONTEND_SPECTRAL_INVERSION_UNDEFINED = 0; // 0x0 field public static final int TYPE_ANALOG = 1; // 0x1 field public static final int TYPE_ATSC = 2; // 0x2 field public static final int TYPE_ATSC3 = 3; // 0x3 + field public static final int TYPE_DTMB = 10; // 0xa field public static final int TYPE_DVBC = 4; // 0x4 field public static final int TYPE_DVBS = 5; // 0x5 field public static final int TYPE_DVBT = 6; // 0x6 @@ -11043,6 +11172,25 @@ package android.telephony { field public static final String MBMS_STREAMING_SERVICE_ACTION = "android.telephony.action.EmbmsStreaming"; } + public final class ModemActivityInfo implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public android.telephony.ModemActivityInfo getDelta(@NonNull android.telephony.ModemActivityInfo); + method public long getIdleTimeMillis(); + method public static int getNumTxPowerLevels(); + method public long getReceiveTimeMillis(); + method public long getSleepTimeMillis(); + method public long getTimestampMillis(); + method public long getTransmitDurationMillisAtPowerLevel(int); + method @NonNull public android.util.Range<java.lang.Integer> getTransmitPowerRange(int); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ModemActivityInfo> CREATOR; + field public static final int TX_POWER_LEVEL_0 = 0; // 0x0 + field public static final int TX_POWER_LEVEL_1 = 1; // 0x1 + field public static final int TX_POWER_LEVEL_2 = 2; // 0x2 + field public static final int TX_POWER_LEVEL_3 = 3; // 0x3 + field public static final int TX_POWER_LEVEL_4 = 4; // 0x4 + } + public final class NetworkRegistrationInfo implements android.os.Parcelable { method @Nullable public android.telephony.DataSpecificRegistrationInfo getDataSpecificInfo(); method public int getRegistrationState(); diff --git a/api/system-lint-baseline.txt b/api/system-lint-baseline.txt index 7195144f28e5..773ecd034a8e 100644 --- a/api/system-lint-baseline.txt +++ b/api/system-lint-baseline.txt @@ -159,8 +159,6 @@ MissingNullability: android.telephony.ModemActivityInfo#toString(): MissingNullability: android.telephony.ModemActivityInfo#writeToParcel(android.os.Parcel, int) parameter #0: -MissingNullability: android.telephony.ModemActivityInfo.TransmitPower#toString(): - MissingNullability: android.telephony.NetworkService#onUnbind(android.content.Intent) parameter #0: MissingNullability: android.telephony.SmsCbCmasInfo#toString(): diff --git a/api/test-current.txt b/api/test-current.txt index dd0723697182..d61526a93e8a 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -14,6 +14,7 @@ package android { field public static final String FORCE_STOP_PACKAGES = "android.permission.FORCE_STOP_PACKAGES"; field public static final String MANAGE_ACTIVITY_STACKS = "android.permission.MANAGE_ACTIVITY_STACKS"; field public static final String MANAGE_CRATES = "android.permission.MANAGE_CRATES"; + field public static final String MANAGE_NOTIFICATION_LISTENERS = "android.permission.MANAGE_NOTIFICATION_LISTENERS"; field public static final String MANAGE_ROLLBACKS = "android.permission.MANAGE_ROLLBACKS"; field public static final String NETWORK_SETTINGS = "android.permission.NETWORK_SETTINGS"; field public static final String NETWORK_STACK = "android.permission.NETWORK_STACK"; @@ -494,9 +495,11 @@ package android.app { method @NonNull public java.util.List<java.lang.String> getAllowedAssistantAdjustments(); method @Nullable public android.content.ComponentName getAllowedNotificationAssistant(); method public android.content.ComponentName getEffectsSuppressor(); + method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS) public java.util.List<android.content.ComponentName> getEnabledNotificationListeners(); method public boolean isNotificationAssistantAccessGranted(@NonNull android.content.ComponentName); method public boolean matchesCallFilter(android.os.Bundle); method public void setNotificationAssistantAccessGranted(@Nullable android.content.ComponentName, boolean); + method @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS) public void setNotificationListenerAccessGranted(@NonNull android.content.ComponentName, boolean); method public void updateNotificationChannel(@NonNull String, int, @NonNull android.app.NotificationChannel); } @@ -790,6 +793,28 @@ package android.app.role { package android.app.usage { + public final class CacheQuotaHint implements android.os.Parcelable { + ctor public CacheQuotaHint(@NonNull android.app.usage.CacheQuotaHint.Builder); + method public int describeContents(); + method public long getQuota(); + method public int getUid(); + method @Nullable public android.app.usage.UsageStats getUsageStats(); + method @Nullable public String getVolumeUuid(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.app.usage.CacheQuotaHint> CREATOR; + field public static final long QUOTA_NOT_SET = -1L; // 0xffffffffffffffffL + } + + public static final class CacheQuotaHint.Builder { + ctor public CacheQuotaHint.Builder(); + ctor public CacheQuotaHint.Builder(@NonNull android.app.usage.CacheQuotaHint); + method @NonNull public android.app.usage.CacheQuotaHint build(); + method @NonNull public android.app.usage.CacheQuotaHint.Builder setQuota(long); + method @NonNull public android.app.usage.CacheQuotaHint.Builder setUid(int); + method @NonNull public android.app.usage.CacheQuotaHint.Builder setUsageStats(@Nullable android.app.usage.UsageStats); + method @NonNull public android.app.usage.CacheQuotaHint.Builder setVolumeUuid(@Nullable String); + } + public class NetworkStatsManager { method public void setPollForce(boolean); } @@ -802,6 +827,10 @@ package android.app.usage { method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_CRATES) @WorkerThread public java.util.Collection<android.os.storage.CrateInfo> queryCratesForUser(@NonNull java.util.UUID, @NonNull android.os.UserHandle) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException; } + public final class UsageStats implements android.os.Parcelable { + ctor public UsageStats(); + } + public final class UsageStatsManager { method public void forceUsageSourceSettingRead(); } @@ -1234,20 +1263,19 @@ package android.graphics.drawable { package android.hardware.biometrics { public class BiometricManager { - method @NonNull @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public android.hardware.biometrics.BiometricTestSession getTestSession(); + method @NonNull @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public android.hardware.biometrics.BiometricTestSession createTestSession(int); + method @NonNull @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public java.util.List<android.hardware.biometrics.SensorProperties> getSensorProperties(); } public class BiometricTestSession implements java.lang.AutoCloseable { - method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void authenticateReject(int, int); - method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void authenticateSuccess(int, int); + method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void acceptAuthentication(int); + method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void cleanupInternalState(int); method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void close(); - method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void enableTestHal(int, boolean); - method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void enrollFinish(int, int); - method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void enrollStart(int, int); - method @NonNull @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public java.util.List<android.hardware.biometrics.SensorProperties> getSensorProperties(); - method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void internalCleanup(int, int); - method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void notifyAcquired(int, int); - method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void notifyError(int, int); + method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void finishEnroll(int); + method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void notifyAcquired(int); + method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void notifyError(int); + method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void rejectAuthentication(int); + method @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public void startEnroll(int); } public class SensorProperties { @@ -1368,7 +1396,8 @@ package android.hardware.display { package android.hardware.fingerprint { @Deprecated public class FingerprintManager { - method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public android.hardware.biometrics.BiometricTestSession getTestSession(); + method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public android.hardware.biometrics.BiometricTestSession createTestSession(int); + method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.TEST_BIOMETRIC) public java.util.List<android.hardware.biometrics.SensorProperties> getSensorProperties(); } } @@ -1774,11 +1803,11 @@ package android.location { method public boolean isHiddenFromAppOps(); method public boolean isLocationSettingsIgnored(); method public boolean isLowPower(); - field public static final int ACCURACY_BLOCK = 102; // 0x66 - field public static final int ACCURACY_CITY = 104; // 0x68 - field public static final int ACCURACY_FINE = 100; // 0x64 - field public static final int POWER_HIGH = 203; // 0xcb - field public static final int POWER_LOW = 201; // 0xc9 + field @Deprecated public static final int ACCURACY_BLOCK = 102; // 0x66 + field @Deprecated public static final int ACCURACY_CITY = 104; // 0x68 + field @Deprecated public static final int ACCURACY_FINE = 100; // 0x64 + field @Deprecated public static final int POWER_HIGH = 203; // 0xcb + field @Deprecated public static final int POWER_LOW = 201; // 0xc9 } public static final class LocationRequest.Builder { @@ -2396,100 +2425,6 @@ package android.net { method public void teardownTestNetwork(@NonNull android.net.Network); } - public final class TetheredClient implements android.os.Parcelable { - ctor public TetheredClient(@NonNull android.net.MacAddress, @NonNull java.util.Collection<android.net.TetheredClient.AddressInfo>, int); - method public int describeContents(); - method @NonNull public java.util.List<android.net.TetheredClient.AddressInfo> getAddresses(); - method @NonNull public android.net.MacAddress getMacAddress(); - method public int getTetheringType(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.net.TetheredClient> CREATOR; - } - - public static final class TetheredClient.AddressInfo implements android.os.Parcelable { - method public int describeContents(); - method @NonNull public android.net.LinkAddress getAddress(); - method @Nullable public String getHostname(); - method public void writeToParcel(@NonNull android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.net.TetheredClient.AddressInfo> CREATOR; - } - - public class TetheringManager { - method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.TetheringEventCallback); - method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void requestLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.OnTetheringEntitlementResultListener); - method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void startTethering(@NonNull android.net.TetheringManager.TetheringRequest, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback); - method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void stopAllTethering(); - method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void stopTethering(int); - method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.ACCESS_NETWORK_STATE}) public void unregisterTetheringEventCallback(@NonNull android.net.TetheringManager.TetheringEventCallback); - field public static final String ACTION_TETHER_STATE_CHANGED = "android.net.conn.TETHER_STATE_CHANGED"; - field public static final String EXTRA_ACTIVE_LOCAL_ONLY = "android.net.extra.ACTIVE_LOCAL_ONLY"; - field public static final String EXTRA_ACTIVE_TETHER = "tetherArray"; - field public static final String EXTRA_AVAILABLE_TETHER = "availableArray"; - field public static final String EXTRA_ERRORED_TETHER = "erroredArray"; - field public static final int TETHERING_BLUETOOTH = 2; // 0x2 - field public static final int TETHERING_ETHERNET = 5; // 0x5 - field public static final int TETHERING_INVALID = -1; // 0xffffffff - field public static final int TETHERING_NCM = 4; // 0x4 - field public static final int TETHERING_USB = 1; // 0x1 - field public static final int TETHERING_WIFI = 0; // 0x0 - field public static final int TETHERING_WIFI_P2P = 3; // 0x3 - field public static final int TETHER_ERROR_DHCPSERVER_ERROR = 12; // 0xc - field public static final int TETHER_ERROR_DISABLE_FORWARDING_ERROR = 9; // 0x9 - field public static final int TETHER_ERROR_ENABLE_FORWARDING_ERROR = 8; // 0x8 - field public static final int TETHER_ERROR_ENTITLEMENT_UNKNOWN = 13; // 0xd - field public static final int TETHER_ERROR_IFACE_CFG_ERROR = 10; // 0xa - field public static final int TETHER_ERROR_INTERNAL_ERROR = 5; // 0x5 - field public static final int TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION = 15; // 0xf - field public static final int TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION = 14; // 0xe - field public static final int TETHER_ERROR_NO_ERROR = 0; // 0x0 - field public static final int TETHER_ERROR_PROVISIONING_FAILED = 11; // 0xb - field public static final int TETHER_ERROR_SERVICE_UNAVAIL = 2; // 0x2 - field public static final int TETHER_ERROR_TETHER_IFACE_ERROR = 6; // 0x6 - field public static final int TETHER_ERROR_UNAVAIL_IFACE = 4; // 0x4 - field public static final int TETHER_ERROR_UNKNOWN_IFACE = 1; // 0x1 - field public static final int TETHER_ERROR_UNKNOWN_TYPE = 16; // 0x10 - field public static final int TETHER_ERROR_UNSUPPORTED = 3; // 0x3 - field public static final int TETHER_ERROR_UNTETHER_IFACE_ERROR = 7; // 0x7 - field public static final int TETHER_HARDWARE_OFFLOAD_FAILED = 2; // 0x2 - field public static final int TETHER_HARDWARE_OFFLOAD_STARTED = 1; // 0x1 - field public static final int TETHER_HARDWARE_OFFLOAD_STOPPED = 0; // 0x0 - } - - public static interface TetheringManager.OnTetheringEntitlementResultListener { - method public void onTetheringEntitlementResult(int); - } - - public static interface TetheringManager.StartTetheringCallback { - method public default void onTetheringFailed(int); - method public default void onTetheringStarted(); - } - - public static interface TetheringManager.TetheringEventCallback { - method public default void onClientsChanged(@NonNull java.util.Collection<android.net.TetheredClient>); - method public default void onError(@NonNull String, int); - method public default void onOffloadStatusChanged(int); - method public default void onTetherableInterfacesChanged(@NonNull java.util.List<java.lang.String>); - method public default void onTetheredInterfacesChanged(@NonNull java.util.List<java.lang.String>); - method public default void onTetheringSupported(boolean); - method public default void onUpstreamChanged(@Nullable android.net.Network); - } - - public static class TetheringManager.TetheringRequest { - method @Nullable public android.net.LinkAddress getClientStaticIpv4Address(); - method @Nullable public android.net.LinkAddress getLocalIpv4Address(); - method public boolean getShouldShowEntitlementUi(); - method public int getTetheringType(); - method public boolean isExemptFromEntitlementCheck(); - } - - public static class TetheringManager.TetheringRequest.Builder { - ctor public TetheringManager.TetheringRequest.Builder(int); - method @NonNull public android.net.TetheringManager.TetheringRequest build(); - method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setExemptFromEntitlementCheck(boolean); - method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setShouldShowEntitlementUi(boolean); - method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setStaticIpv4Addresses(@NonNull android.net.LinkAddress, @NonNull android.net.LinkAddress); - } - public class TrafficStats { method public static long getLoopbackRxBytes(); method public static long getLoopbackRxPackets(); @@ -3470,12 +3405,6 @@ package android.provider { method @NonNull public static android.net.Uri setManageMode(@NonNull android.net.Uri); } - public final class MediaStore { - method @NonNull @WorkerThread public static android.net.Uri scanFile(@NonNull android.content.ContentResolver, @NonNull java.io.File); - method @WorkerThread public static void scanVolume(@NonNull android.content.ContentResolver, @NonNull String); - method @WorkerThread public static void waitForIdle(@NonNull android.content.ContentResolver); - } - public final class Settings { field public static final String ACTION_ENTERPRISE_PRIVACY_SETTINGS = "android.settings.ENTERPRISE_PRIVACY_SETTINGS"; field public static final String ACTION_MANAGE_APP_OVERLAY_PERMISSION = "android.settings.MANAGE_APP_OVERLAY_PERMISSION"; @@ -4240,6 +4169,27 @@ package android.telephony { field public static final String MBMS_STREAMING_SERVICE_OVERRIDE_METADATA = "mbms-streaming-service-override"; } + public final class ModemActivityInfo implements android.os.Parcelable { + ctor public ModemActivityInfo(long, int, int, @NonNull int[], int); + method public int describeContents(); + method @NonNull public android.telephony.ModemActivityInfo getDelta(@NonNull android.telephony.ModemActivityInfo); + method public long getIdleTimeMillis(); + method public static int getNumTxPowerLevels(); + method public long getReceiveTimeMillis(); + method public long getSleepTimeMillis(); + method public long getTimestampMillis(); + method public long getTransmitDurationMillisAtPowerLevel(int); + method @NonNull public android.util.Range<java.lang.Integer> getTransmitPowerRange(int); + method public boolean isValid(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ModemActivityInfo> CREATOR; + field public static final int TX_POWER_LEVEL_0 = 0; // 0x0 + field public static final int TX_POWER_LEVEL_1 = 1; // 0x1 + field public static final int TX_POWER_LEVEL_2 = 2; // 0x2 + field public static final int TX_POWER_LEVEL_3 = 3; // 0x3 + field public static final int TX_POWER_LEVEL_4 = 4; // 0x4 + } + public final class NetworkRegistrationInfo implements android.os.Parcelable { method @Nullable public android.telephony.DataSpecificRegistrationInfo getDataSpecificInfo(); method public int getRegistrationState(); diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index fe8936654aa4..d442f5f321ec 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -1567,8 +1567,20 @@ public class NotificationManager { } } - /** @hide */ - public void setNotificationListenerAccessGranted(ComponentName listener, boolean granted) { + /** + * Grants/revokes Notification Listener access to the given component for current user. + * To grant access for a particular user, obtain this service by using the {@link Context} + * provided by {@link Context#createPackageContextAsUser} + * + * @param listener Name of component to grant/revoke access + * @param granted Grant/revoke access + * @hide + */ + @SystemApi + @TestApi + @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS) + public void setNotificationListenerAccessGranted( + @NonNull ComponentName listener, boolean granted) { INotificationManager service = getService(); try { service.setNotificationListenerAccessGranted(listener, granted); @@ -1610,6 +1622,21 @@ public class NotificationManager { } } + /** + * Gets the list of enabled notification listener components for current user. + * To query for a particular user, obtain this service by using the {@link Context} + * provided by {@link Context#createPackageContextAsUser} + * + * @return the list of {@link ComponentName}s of the notification listeners + * @hide + */ + @SystemApi + @TestApi + @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS) + public @NonNull List<ComponentName> getEnabledNotificationListeners() { + return getEnabledNotificationListeners(mContext.getUserId()); + } + /** @hide */ public List<ComponentName> getEnabledNotificationListeners(int userId) { INotificationManager service = getService(); diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java index e8937a8da911..8054cdb780eb 100644 --- a/core/java/android/app/PendingIntent.java +++ b/core/java/android/app/PendingIntent.java @@ -363,6 +363,7 @@ public final class PendingIntent implements Parcelable { * parameters. May return null only if {@link #FLAG_NO_CREATE} has been * supplied. */ + @SuppressWarnings("AndroidFrameworkPendingIntentMutability") public static PendingIntent getActivity(Context context, int requestCode, Intent intent, @Flags int flags) { return getActivity(context, requestCode, intent, flags, null); @@ -489,6 +490,7 @@ public final class PendingIntent implements Parcelable { * parameters. May return null only if {@link #FLAG_NO_CREATE} has been * supplied. */ + @SuppressWarnings("AndroidFrameworkPendingIntentMutability") public static PendingIntent getActivities(Context context, int requestCode, @NonNull Intent[] intents, @Flags int flags) { return getActivities(context, requestCode, intents, flags, null); @@ -611,6 +613,7 @@ public final class PendingIntent implements Parcelable { * parameters. May return null only if {@link #FLAG_NO_CREATE} has been * supplied. */ + @SuppressWarnings("AndroidFrameworkPendingIntentMutability") public static PendingIntent getBroadcast(Context context, int requestCode, Intent intent, @Flags int flags) { return getBroadcastAsUser(context, requestCode, intent, flags, context.getUser()); diff --git a/core/java/android/app/Presentation.java b/core/java/android/app/Presentation.java index 7a18b8120d7e..ad903642c908 100644 --- a/core/java/android/app/Presentation.java +++ b/core/java/android/app/Presentation.java @@ -16,30 +16,28 @@ package android.app; -import static android.content.Context.DISPLAY_SERVICE; -import static android.content.Context.WINDOW_SERVICE; +import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE; import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION; import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION; +import android.annotation.NonNull; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.res.Resources; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager.DisplayListener; -import android.os.Binder; +import android.os.Build; import android.os.Handler; -import android.os.IBinder; -import android.os.Message; -import android.util.DisplayMetrics; -import android.util.Log; +import android.os.Looper; import android.util.TypedValue; import android.view.ContextThemeWrapper; import android.view.Display; import android.view.Gravity; import android.view.Window; import android.view.WindowManager; -import android.view.WindowManagerImpl; +import android.view.WindowManager.LayoutParams.WindowType; +import com.android.internal.util.Preconditions; /** * Base class for presentations. * <p> @@ -153,11 +151,10 @@ import android.view.WindowManagerImpl; public class Presentation extends Dialog { private static final String TAG = "Presentation"; - private static final int MSG_CANCEL = 1; - private final Display mDisplay; private final DisplayManager mDisplayManager; - private final IBinder mToken = new Binder(); + private final Handler mHandler = new Handler(Preconditions.checkNotNull(Looper.myLooper(), + "Presentation must be constructed on a looper thread.")); /** * Creates a new presentation that is attached to the specified display @@ -179,6 +176,11 @@ public class Presentation extends Dialog { * @param outerContext The context of the application that is showing the presentation. * The presentation will create its own context (see {@link #getContext()}) based * on this context and information about the associated display. + * From {@link android.os.Build.VERSION_CODES#S}, the presentation will create its own window + * context based on this context, information about the associated display. Customizing window + * type by {@link Window#setType(int) #getWindow#setType(int)} causes the mismatch of the window + * and the created window context, which leads to + * {@link android.view.WindowManager.InvalidDisplayException} when invoking {@link #show()}. * @param display The display to which the presentation should be attached. * @param theme A style resource describing the theme to use for the window. * See <a href="{@docRoot}guide/topics/resources/available-resources.html#stylesandthemes"> @@ -187,24 +189,53 @@ public class Presentation extends Dialog { * <var>outerContext</var>. If 0, the default presentation theme will be used. */ public Presentation(Context outerContext, Display display, int theme) { - super(createPresentationContext(outerContext, display, theme), theme, false); + this(outerContext, display, theme, INVALID_WINDOW_TYPE); + } - mDisplay = display; - mDisplayManager = (DisplayManager)getContext().getSystemService(DISPLAY_SERVICE); + /** + * Creates a new presentation that is attached to the specified display + * using the optionally specified theme, and override the default window type for the + * presentation. + * @param outerContext The context of the application that is showing the presentation. + * The presentation will create its own context (see {@link #getContext()}) based + * on this context and information about the associated display. + * From {@link android.os.Build.VERSION_CODES#S}, the presentation will create its own window + * context based on this context, information about the associated display and the window type. + * If the window type is not specified, the presentation will choose the default type for the + * presentation. + * @param display The display to which the presentation should be attached. + * @param theme A style resource describing the theme to use for the window. + * See <a href="{@docRoot}guide/topics/resources/available-resources.html#stylesandthemes"> + * Style and Theme Resources</a> for more information about defining and using + * styles. This theme is applied on top of the current theme in + * <var>outerContext</var>. If 0, the default presentation theme will be used. + * @param type Window type. + * + * @hide + */ + public Presentation(@NonNull Context outerContext, @NonNull Display display, int theme, + @WindowType int type) { + super(createPresentationContext(outerContext, display, theme, type), theme, false); - final int windowType = - (display.getFlags() & Display.FLAG_PRIVATE) != 0 ? TYPE_PRIVATE_PRESENTATION - : TYPE_PRESENTATION; + mDisplay = display; + mDisplayManager = getContext().getSystemService(DisplayManager.class); final Window w = getWindow(); final WindowManager.LayoutParams attr = w.getAttributes(); - attr.token = mToken; w.setAttributes(attr); w.setGravity(Gravity.FILL); - w.setType(windowType); + w.setType(getWindowType(type, display)); setCanceledOnTouchOutside(false); } + private static @WindowType int getWindowType(@WindowType int type, @NonNull Display display) { + if (type != INVALID_WINDOW_TYPE) { + return type; + } + return (display.getFlags() & Display.FLAG_PRIVATE) != 0 ? TYPE_PRIVATE_PRESENTATION + : TYPE_PRESENTATION; + } + /** * Gets the {@link Display} that this presentation appears on. * @@ -229,16 +260,6 @@ public class Presentation extends Dialog { protected void onStart() { super.onStart(); mDisplayManager.registerDisplayListener(mDisplayListener, mHandler); - - // Since we were not watching for display changes until just now, there is a - // chance that the display metrics have changed. If so, we will need to - // dismiss the presentation immediately. This case is expected - // to be rare but surprising, so we'll write a log message about it. - if (!isConfigurationStillValid()) { - Log.i(TAG, "Presentation is being dismissed because the " - + "display metrics have changed since it was created."); - mHandler.sendEmptyMessage(MSG_CANCEL); - } } @Override @@ -273,10 +294,6 @@ public class Presentation extends Dialog { * Called by the system when the properties of the {@link Display} to which * the presentation is attached have changed. * - * If the display metrics have changed (for example, if the display has been - * resized or rotated), then the system automatically calls - * {@link #cancel} to dismiss the presentation. - * * @see #getDisplay */ public void onDisplayChanged() { @@ -289,28 +306,16 @@ public class Presentation extends Dialog { private void handleDisplayChanged() { onDisplayChanged(); - - // We currently do not support configuration changes for presentations - // (although we could add that feature with a bit more work). - // If the display metrics have changed in any way then the current configuration - // is invalid and the application must recreate the presentation to get - // a new context. - if (!isConfigurationStillValid()) { - Log.i(TAG, "Presentation is being dismissed because the " - + "display metrics have changed since it was created."); - cancel(); - } } - private boolean isConfigurationStillValid() { - DisplayMetrics dm = new DisplayMetrics(); - mDisplay.getMetrics(dm); - return dm.equalsPhysical(getResources().getDisplayMetrics()); + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "{@code N/A}") + private static Context createPresentationContext(Context outerContext, Display display, + int theme) { + return createPresentationContext(outerContext, display, theme, INVALID_WINDOW_TYPE); } - @UnsupportedAppUsage private static Context createPresentationContext( - Context outerContext, Display display, int theme) { + Context outerContext, Display display, int theme, @WindowType int type) { if (outerContext == null) { throw new IllegalArgumentException("outerContext must not be null"); } @@ -318,31 +323,15 @@ public class Presentation extends Dialog { throw new IllegalArgumentException("display must not be null"); } - Context displayContext = outerContext.createDisplayContext(display); + Context windowContext = outerContext.createDisplayContext(display) + .createWindowContext(getWindowType(type, display), null /* options */); if (theme == 0) { TypedValue outValue = new TypedValue(); - displayContext.getTheme().resolveAttribute( + windowContext.getTheme().resolveAttribute( com.android.internal.R.attr.presentationTheme, outValue, true); theme = outValue.resourceId; } - - // Derive the display's window manager from the outer window manager. - // We do this because the outer window manager have some extra information - // such as the parent window, which is important if the presentation uses - // an application window type. - final WindowManagerImpl outerWindowManager = - (WindowManagerImpl)outerContext.getSystemService(WINDOW_SERVICE); - final WindowManagerImpl displayWindowManager = - outerWindowManager.createPresentationWindowManager(displayContext); - return new ContextThemeWrapper(displayContext, theme) { - @Override - public Object getSystemService(String name) { - if (WINDOW_SERVICE.equals(name)) { - return displayWindowManager; - } - return super.getSystemService(name); - } - }; + return new ContextThemeWrapper(windowContext, theme); } private final DisplayListener mDisplayListener = new DisplayListener() { @@ -364,15 +353,4 @@ public class Presentation extends Dialog { } } }; - - private final Handler mHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_CANCEL: - cancel(); - break; - } - } - }; } diff --git a/core/java/android/app/PropertyInvalidatedCache.java b/core/java/android/app/PropertyInvalidatedCache.java index 3e3a956c9788..04a12afb8039 100644 --- a/core/java/android/app/PropertyInvalidatedCache.java +++ b/core/java/android/app/PropertyInvalidatedCache.java @@ -206,6 +206,10 @@ public abstract class PropertyInvalidatedCache<Query, Result> { private static final String TAG = "PropertyInvalidatedCache"; private static final boolean DEBUG = false; private static final boolean VERIFY = false; + // If this is true, dumpsys will dump the cache entries along with cache statistics. + // Most of the time this causes dumpsys to fail because the output stream is too + // large. Only set it to true in development images. + private static final boolean DETAILED = false; // Per-Cache performance counters. As some cache instances are declared static, @GuardedBy("mLock") @@ -912,14 +916,13 @@ public abstract class PropertyInvalidatedCache<Query, Result> { " Current Size: %d, Max Size: %d, HW Mark: %d, Overflows: %d", mCache.size(), mMaxEntries, mHighWaterMark, mMissOverflow)); pw.println(String.format(" Enabled: %s", mDisabled ? "false" : "true")); + pw.println(""); Set<Map.Entry<Query, Result>> cacheEntries = mCache.entrySet(); - if (cacheEntries.size() == 0) { - pw.println(""); + if (!DETAILED || cacheEntries.size() == 0) { return; } - pw.println(""); pw.println(" Contents:"); for (Map.Entry<Query, Result> entry : cacheEntries) { String key = Objects.toString(entry.getKey()); diff --git a/core/java/android/app/TaskStackBuilder.java b/core/java/android/app/TaskStackBuilder.java index b99b32748dcd..e23804668d8d 100644 --- a/core/java/android/app/TaskStackBuilder.java +++ b/core/java/android/app/TaskStackBuilder.java @@ -264,6 +264,7 @@ public class TaskStackBuilder { * * @return The obtained PendingIntent */ + @SuppressWarnings("AndroidFrameworkPendingIntentMutability") public PendingIntent getPendingIntent(int requestCode, @PendingIntent.Flags int flags, Bundle options) { if (mIntents.isEmpty()) { @@ -278,6 +279,7 @@ public class TaskStackBuilder { /** * @hide */ + @SuppressWarnings("AndroidFrameworkPendingIntentMutability") public PendingIntent getPendingIntent(int requestCode, int flags, Bundle options, UserHandle user) { if (mIntents.isEmpty()) { diff --git a/core/java/android/app/usage/CacheQuotaHint.java b/core/java/android/app/usage/CacheQuotaHint.java index b5aed49f211e..d5c72f286a32 100644 --- a/core/java/android/app/usage/CacheQuotaHint.java +++ b/core/java/android/app/usage/CacheQuotaHint.java @@ -19,6 +19,7 @@ package android.app.usage; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; @@ -32,6 +33,7 @@ import java.util.Objects; * allows apps to understand how much cache to use. * {@hide} */ +@TestApi @SystemApi public final class CacheQuotaHint implements Parcelable { public static final long QUOTA_NOT_SET = -1; @@ -44,14 +46,14 @@ public final class CacheQuotaHint implements Parcelable { * Create a new request. * @param builder A builder for this object. */ - public CacheQuotaHint(Builder builder) { + public CacheQuotaHint(@NonNull Builder builder) { this.mUuid = builder.mUuid; this.mUid = builder.mUid; this.mUsageStats = builder.mUsageStats; this.mQuota = builder.mQuota; } - public String getVolumeUuid() { + @Nullable public String getVolumeUuid() { return mUuid; } @@ -63,12 +65,12 @@ public final class CacheQuotaHint implements Parcelable { return mQuota; } - public UsageStats getUsageStats() { + @Nullable public UsageStats getUsageStats() { return mUsageStats; } @Override - public void writeToParcel(Parcel dest, int flags) { + public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeString(mUuid); dest.writeInt(mUid); dest.writeLong(mQuota); @@ -106,7 +108,7 @@ public final class CacheQuotaHint implements Parcelable { public Builder() { } - public Builder(CacheQuotaHint hint) { + public Builder(@NonNull CacheQuotaHint hint) { setVolumeUuid(hint.getVolumeUuid()); setUid(hint.getUid()); setUsageStats(hint.getUsageStats()); diff --git a/core/java/android/app/usage/UsageStats.java b/core/java/android/app/usage/UsageStats.java index f2a054d16ccb..dcecd9070a74 100644 --- a/core/java/android/app/usage/UsageStats.java +++ b/core/java/android/app/usage/UsageStats.java @@ -30,6 +30,7 @@ import static android.app.usage.UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE; import static android.app.usage.UsageEvents.Event.USER_INTERACTION; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; import android.os.Bundle; @@ -155,6 +156,7 @@ public final class UsageStats implements Parcelable { /** * {@hide} */ + @TestApi public UsageStats() { } diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 2f1254f90ccf..a14e21b36c51 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -2744,7 +2744,6 @@ public class Intent implements Parcelable, Cloneable { * </ul> * * <p class="note">This is a protected intent that can only be sent by the system. - * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_PACKAGE_STARTABLE = "android.intent.action.PACKAGE_STARTABLE"; @@ -2755,13 +2754,13 @@ public class Intent implements Parcelable, Cloneable { * <ul> * <li> {@link #EXTRA_UID} containing the integer uid assigned to the package. </li> * <li> {@link #EXTRA_PACKAGE_NAME} containing the package name. </li> - * <li> {@link #EXTRA_REASON} containing the integer indicating the reason for the state change, + * <li> {@link #EXTRA_UNSTARTABLE_REASON} containing the integer indicating the reason for + * the state change, * @see PackageManager.UnstartableReason * </li> * </ul> * * <p class="note">This is a protected intent that can only be sent by the system. - * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_PACKAGE_UNSTARTABLE = @@ -2776,7 +2775,6 @@ public class Intent implements Parcelable, Cloneable { * </ul> * * <p class="note">This is a protected intent that can only be sent by the system. - * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_PACKAGE_FULLY_LOADED = @@ -6015,6 +6013,13 @@ public class Intent implements Parcelable, Cloneable { */ public static final String EXTRA_LOCUS_ID = "android.intent.extra.LOCUS_ID"; + /** + * Intent extra: the reason that the package associated with this intent has become unstartable. + * + * <p>Type: String + */ + public static final String EXTRA_UNSTARTABLE_REASON = "android.intent.extra.UNSTARTABLE_REASON"; + // --------------------------------------------------------------------- // --------------------------------------------------------------------- // Intent flags (see mFlags variable). diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl index 389458b64fc1..d9ecf46069cd 100644 --- a/core/java/android/content/pm/ILauncherApps.aidl +++ b/core/java/android/content/pm/ILauncherApps.aidl @@ -21,9 +21,9 @@ import android.content.ComponentName; import android.content.Intent; import android.content.IntentSender; import android.content.LocusId; -import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.IOnAppsChangedListener; +import android.content.pm.LauncherActivityInfoInternal; import android.content.pm.LauncherApps; import android.content.pm.ShortcutQueryWrapper; import android.content.pm.IPackageInstallerCallback; @@ -47,7 +47,7 @@ interface ILauncherApps { void removeOnAppsChangedListener(in IOnAppsChangedListener listener); ParceledListSlice getLauncherActivities( String callingPackage, String packageName, in UserHandle user); - ActivityInfo resolveActivity( + LauncherActivityInfoInternal resolveLauncherActivityInternal( String callingPackage, in ComponentName component, in UserHandle user); void startSessionDetailsActivityAsUser(in IApplicationThread caller, String callingPackage, String callingFeatureId, in PackageInstaller.SessionInfo sessionInfo, diff --git a/core/java/android/content/pm/IOnAppsChangedListener.aidl b/core/java/android/content/pm/IOnAppsChangedListener.aidl index fcb1de016078..f24ed80983f8 100644 --- a/core/java/android/content/pm/IOnAppsChangedListener.aidl +++ b/core/java/android/content/pm/IOnAppsChangedListener.aidl @@ -33,4 +33,5 @@ oneway interface IOnAppsChangedListener { in Bundle launcherExtras); void onPackagesUnsuspended(in UserHandle user, in String[] packageNames); void onShortcutChanged(in UserHandle user, String packageName, in ParceledListSlice shortcuts); + void onPackageProgressChanged(in UserHandle user, String packageName, float progress); } diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 30f3325cc11c..c32d34457889 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -31,7 +31,6 @@ import android.content.pm.IPackageInstaller; import android.content.pm.IPackageDeleteObserver; import android.content.pm.IPackageDeleteObserver2; import android.content.pm.IPackageDataObserver; -import android.content.pm.IPackageLoadingProgressCallback; import android.content.pm.IPackageMoveObserver; import android.content.pm.IPackageStatsObserver; import android.content.pm.IntentFilterVerificationInfo; diff --git a/core/java/android/content/pm/LauncherActivityInfo.java b/core/java/android/content/pm/LauncherActivityInfo.java index 67deb82f1fbb..ead80d022542 100644 --- a/core/java/android/content/pm/LauncherActivityInfo.java +++ b/core/java/android/content/pm/LauncherActivityInfo.java @@ -16,7 +16,6 @@ package android.content.pm; -import android.compat.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageManager.NameNotFoundException; @@ -35,28 +34,19 @@ public class LauncherActivityInfo { private static final String TAG = "LauncherActivityInfo"; private final PackageManager mPm; - - @UnsupportedAppUsage - private ActivityInfo mActivityInfo; - private ComponentName mComponentName; private UserHandle mUser; + private final LauncherActivityInfoInternal mInternal; /** * Create a launchable activity object for a given ResolveInfo and user. * * @param context The context for fetching resources. - * @param info ResolveInfo from which to create the LauncherActivityInfo. - * @param user The UserHandle of the profile to which this activity belongs. - */ - LauncherActivityInfo(Context context, ActivityInfo info, UserHandle user) { - this(context); - mActivityInfo = info; - mComponentName = new ComponentName(info.packageName, info.name); - mUser = user; - } - LauncherActivityInfo(Context context) { + */ + LauncherActivityInfo(Context context, UserHandle user, LauncherActivityInfoInternal internal) { mPm = context.getPackageManager(); + mUser = user; + mInternal = internal; } /** @@ -65,7 +55,7 @@ public class LauncherActivityInfo { * @return ComponentName of the activity */ public ComponentName getComponentName() { - return mComponentName; + return mInternal.getComponentName(); } /** @@ -90,7 +80,28 @@ public class LauncherActivityInfo { */ public CharSequence getLabel() { // TODO: Go through LauncherAppsService - return mActivityInfo.loadLabel(mPm); + return mInternal.getActivityInfo().loadLabel(mPm); + } + + /** + * @return whether the package is startable. + */ + public boolean isStartable() { + return mInternal.getIncrementalStatesInfo().isStartable(); + } + + /** + * @return whether the package is still loading. + */ + public boolean isLoading() { + return mInternal.getIncrementalStatesInfo().isLoading(); + } + + /** + * @return Package loading progress + */ + public float getProgress() { + return mInternal.getIncrementalStatesInfo().getProgress(); } /** @@ -103,20 +114,20 @@ public class LauncherActivityInfo { */ public Drawable getIcon(int density) { // TODO: Go through LauncherAppsService - final int iconRes = mActivityInfo.getIconResource(); + final int iconRes = mInternal.getActivityInfo().getIconResource(); Drawable icon = null; // Get the preferred density icon from the app's resources if (density != 0 && iconRes != 0) { try { - final Resources resources - = mPm.getResourcesForApplication(mActivityInfo.applicationInfo); + final Resources resources = mPm.getResourcesForApplication( + mInternal.getActivityInfo().applicationInfo); icon = resources.getDrawableForDensity(iconRes, density); } catch (NameNotFoundException | Resources.NotFoundException exc) { } } // Get the default density icon if (icon == null) { - icon = mActivityInfo.loadIcon(mPm); + icon = mInternal.getActivityInfo().loadIcon(mPm); } return icon; } @@ -128,7 +139,7 @@ public class LauncherActivityInfo { * @hide remove before shipping */ public int getApplicationFlags() { - return mActivityInfo.applicationInfo.flags; + return mInternal.getActivityInfo().flags; } /** @@ -136,7 +147,7 @@ public class LauncherActivityInfo { * @return */ public ApplicationInfo getApplicationInfo() { - return mActivityInfo.applicationInfo; + return mInternal.getActivityInfo().applicationInfo; } /** @@ -147,7 +158,7 @@ public class LauncherActivityInfo { public long getFirstInstallTime() { try { // TODO: Go through LauncherAppsService - return mPm.getPackageInfo(mActivityInfo.packageName, + return mPm.getPackageInfo(mInternal.getActivityInfo().packageName, PackageManager.MATCH_UNINSTALLED_PACKAGES).firstInstallTime; } catch (NameNotFoundException nnfe) { // Sorry, can't find package @@ -160,7 +171,7 @@ public class LauncherActivityInfo { * @return the name from android:name for the acitivity. */ public String getName() { - return mActivityInfo.name; + return mInternal.getActivityInfo().name; } /** diff --git a/core/java/android/content/pm/LauncherActivityInfoInternal.aidl b/core/java/android/content/pm/LauncherActivityInfoInternal.aidl new file mode 100644 index 000000000000..5d98d54a27a0 --- /dev/null +++ b/core/java/android/content/pm/LauncherActivityInfoInternal.aidl @@ -0,0 +1,20 @@ +/* +** +** Copyright 2020, 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.content.pm; + +parcelable LauncherActivityInfoInternal;
\ No newline at end of file diff --git a/core/java/android/content/pm/LauncherActivityInfoInternal.java b/core/java/android/content/pm/LauncherActivityInfoInternal.java new file mode 100644 index 000000000000..22e9712ebe3b --- /dev/null +++ b/core/java/android/content/pm/LauncherActivityInfoInternal.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2020 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.content.pm; + +import android.compat.annotation.UnsupportedAppUsage; +import android.content.ComponentName; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * @hide + */ +public class LauncherActivityInfoInternal implements Parcelable { + @UnsupportedAppUsage + private ActivityInfo mActivityInfo; + private ComponentName mComponentName; + private IncrementalStatesInfo mIncrementalStatesInfo; + + /** + * @param info ActivityInfo from which to create the LauncherActivityInfo. + * @param incrementalStatesInfo The package's states. + */ + public LauncherActivityInfoInternal(ActivityInfo info, + IncrementalStatesInfo incrementalStatesInfo) { + mActivityInfo = info; + mComponentName = new ComponentName(info.packageName, info.name); + mIncrementalStatesInfo = incrementalStatesInfo; + } + + public LauncherActivityInfoInternal(Parcel source) { + mActivityInfo = source.readParcelable(ActivityInfo.class.getClassLoader()); + mComponentName = new ComponentName(mActivityInfo.packageName, mActivityInfo.name); + mIncrementalStatesInfo = source.readParcelable( + IncrementalStatesInfo.class.getClassLoader()); + } + + public ComponentName getComponentName() { + return mComponentName; + } + + public ActivityInfo getActivityInfo() { + return mActivityInfo; + } + + public IncrementalStatesInfo getIncrementalStatesInfo() { + return mIncrementalStatesInfo; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeParcelable(mActivityInfo, 0); + dest.writeParcelable(mIncrementalStatesInfo, 0); + } + + public static final @android.annotation.NonNull Creator<LauncherActivityInfoInternal> CREATOR = + new Creator<LauncherActivityInfoInternal>() { + public LauncherActivityInfoInternal createFromParcel(Parcel source) { + return new LauncherActivityInfoInternal(source); + } + public LauncherActivityInfoInternal[] newArray(int size) { + return new LauncherActivityInfoInternal[size]; + } + }; +} diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java index 1a694b34474a..b7af397cd36a 100644 --- a/core/java/android/content/pm/LauncherApps.java +++ b/core/java/android/content/pm/LauncherApps.java @@ -218,6 +218,7 @@ public class LauncherApps { * Indicates that a package was modified in the specified profile. * This can happen, for example, when the package is updated or when * one or more components are enabled or disabled. + * It can also happen if package state has changed, i.e., package becomes unstartable. * * @param packageName The name of the package that has changed. * @param user The UserHandle of the profile that generated the change. @@ -323,6 +324,16 @@ public class LauncherApps { public void onShortcutsChanged(@NonNull String packageName, @NonNull List<ShortcutInfo> shortcuts, @NonNull UserHandle user) { } + + /** + * Indicates that the loading progress of an installed package has changed. + * + * @param packageName The name of the package that has changed. + * @param user The UserHandle of the profile that generated the change. + * @param progress The new progress value, between [0, 1]. + */ + public void onPackageProgressChanged(@NonNull String packageName, + @NonNull UserHandle user, float progress) {} } /** @@ -715,16 +726,15 @@ public class LauncherApps { public LauncherActivityInfo resolveActivity(Intent intent, UserHandle user) { logErrorForInvalidProfileAccess(user); try { - ActivityInfo ai = mService.resolveActivity(mContext.getPackageName(), - intent.getComponent(), user); - if (ai != null) { - LauncherActivityInfo info = new LauncherActivityInfo(mContext, ai, user); - return info; + LauncherActivityInfoInternal ai = mService.resolveLauncherActivityInternal( + mContext.getPackageName(), intent.getComponent(), user); + if (ai == null) { + return null; } + return new LauncherActivityInfo(mContext, user, ai); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } - return null; } /** @@ -813,13 +823,13 @@ public class LauncherApps { } private List<LauncherActivityInfo> convertToActivityList( - @Nullable ParceledListSlice<ResolveInfo> activities, UserHandle user) { - if (activities == null) { + @Nullable ParceledListSlice<LauncherActivityInfoInternal> internals, UserHandle user) { + if (internals == null || internals.getList().isEmpty()) { return Collections.EMPTY_LIST; } ArrayList<LauncherActivityInfo> lais = new ArrayList<>(); - for (ResolveInfo ri : activities.getList()) { - LauncherActivityInfo lai = new LauncherActivityInfo(mContext, ri.activityInfo, user); + for (LauncherActivityInfoInternal internal : internals.getList()) { + LauncherActivityInfo lai = new LauncherActivityInfo(mContext, user, internal); if (DEBUG) { Log.v(TAG, "Returning activity for profile " + user + " : " + lai.getComponentName()); @@ -1667,6 +1677,19 @@ public class LauncherApps { } } } + + public void onPackageProgressChanged(UserHandle user, String packageName, + float progress) { + if (DEBUG) { + Log.d(TAG, "onPackageProgressChanged " + user.getIdentifier() + "," + + packageName + "," + progress); + } + synchronized (LauncherApps.this) { + for (CallbackMessageHandler callback : mCallbacks) { + callback.postOnPackageProgressChanged(user, packageName, progress); + } + } + } }; private static class CallbackMessageHandler extends Handler { @@ -1678,6 +1701,7 @@ public class LauncherApps { private static final int MSG_SUSPENDED = 6; private static final int MSG_UNSUSPENDED = 7; private static final int MSG_SHORTCUT_CHANGED = 8; + private static final int MSG_LOADING_PROGRESS_CHANGED = 9; private LauncherApps.Callback mCallback; @@ -1688,6 +1712,7 @@ public class LauncherApps { boolean replacing; UserHandle user; List<ShortcutInfo> shortcuts; + float mLoadingProgress; } public CallbackMessageHandler(Looper looper, LauncherApps.Callback callback) { @@ -1727,6 +1752,10 @@ public class LauncherApps { case MSG_SHORTCUT_CHANGED: mCallback.onShortcutsChanged(info.packageName, info.shortcuts, info.user); break; + case MSG_LOADING_PROGRESS_CHANGED: + mCallback.onPackageProgressChanged(info.packageName, info.user, + info.mLoadingProgress); + break; } } @@ -1793,6 +1822,15 @@ public class LauncherApps { info.shortcuts = shortcuts; obtainMessage(MSG_SHORTCUT_CHANGED, info).sendToTarget(); } + + public void postOnPackageProgressChanged(UserHandle user, String packageName, + float progress) { + CallbackInfo info = new CallbackInfo(); + info.packageName = packageName; + info.user = user; + info.mLoadingProgress = progress; + obtainMessage(MSG_LOADING_PROGRESS_CHANGED, info).sendToTarget(); + } } /** diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 1a992f519286..32ae105a0ff2 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -3790,8 +3790,8 @@ public abstract class PackageManager { * @hide */ @IntDef({UNSTARTABLE_REASON_UNKNOWN, - UNSTARTABLE_REASON_DATALOADER_TRANSPORT, - UNSTARTABLE_REASON_DATALOADER_STORAGE + UNSTARTABLE_REASON_CONNECTION_ERROR, + UNSTARTABLE_REASON_INSUFFICIENT_STORAGE }) @Retention(RetentionPolicy.SOURCE) public @interface UnstartableReason {} @@ -3800,23 +3800,20 @@ public abstract class PackageManager { * Unstartable state with no root cause specified. E.g., data loader seeing missing pages but * unclear about the cause. This corresponds to a generic alert window shown to the user when * the user attempts to launch the app. - * @hide */ public static final int UNSTARTABLE_REASON_UNKNOWN = 0; /** - * Unstartable state after hint from dataloader of issues with the transport layer. - * This corresponds to an alert window shown to the user indicating network errors. - * @hide + * Unstartable state due to connection issues that interrupt package loading. + * This corresponds to an alert window shown to the user indicating connection errors. */ - public static final int UNSTARTABLE_REASON_DATALOADER_TRANSPORT = 1; + public static final int UNSTARTABLE_REASON_CONNECTION_ERROR = 1; /** * Unstartable state after encountering storage limitations. * This corresponds to an alert window indicating limited storage. - * @hide */ - public static final int UNSTARTABLE_REASON_DATALOADER_STORAGE = 2; + public static final int UNSTARTABLE_REASON_INSUFFICIENT_STORAGE = 2; /** {@hide} */ public int getUserId() { diff --git a/core/java/android/content/pm/parsing/component/ParsedPermission.java b/core/java/android/content/pm/parsing/component/ParsedPermission.java index ced322649c66..f99a0b1dcadb 100644 --- a/core/java/android/content/pm/parsing/component/ParsedPermission.java +++ b/core/java/android/content/pm/parsing/component/ParsedPermission.java @@ -54,22 +54,6 @@ public class ParsedPermission extends ParsedComponent { this.parsedPermissionGroup = other.parsedPermissionGroup; } - public ParsedPermission(ParsedPermission other, PermissionInfo pendingPermissionInfo, - String packageName, String name) { - this(other); - - this.flags = pendingPermissionInfo.flags; - this.descriptionRes = pendingPermissionInfo.descriptionRes; - - this.backgroundPermission = pendingPermissionInfo.backgroundPermission; - this.group = pendingPermissionInfo.group; - this.requestRes = pendingPermissionInfo.requestRes; - this.protectionLevel = pendingPermissionInfo.protectionLevel; - - setName(name); - setPackageName(packageName); - } - public ParsedPermission setGroup(String group) { this.group = TextUtils.safeIntern(group); return this; diff --git a/core/java/android/hardware/biometrics/BiometricManager.java b/core/java/android/hardware/biometrics/BiometricManager.java index 35ef53b52891..25c749b9c14b 100644 --- a/core/java/android/hardware/biometrics/BiometricManager.java +++ b/core/java/android/hardware/biometrics/BiometricManager.java @@ -35,6 +35,8 @@ import android.util.Slog; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; +import java.util.List; /** * A class that contains biometric utilities. For authentication, see {@link BiometricPrompt}. @@ -199,13 +201,24 @@ public class BiometricManager { } /** + * @return A list of {@link SensorProperties} + * @hide + */ + @TestApi + @NonNull + @RequiresPermission(TEST_BIOMETRIC) + public List<SensorProperties> getSensorProperties() { + return new ArrayList<>(); // TODO(169459906) + } + + /** * Retrieves a test session for BiometricManager/BiometricPrompt. * @hide */ @TestApi @NonNull @RequiresPermission(TEST_BIOMETRIC) - public BiometricTestSession getTestSession() { + public BiometricTestSession createTestSession(int sensorId) { return null; // TODO(169459906) } diff --git a/core/java/android/hardware/biometrics/BiometricTestSession.java b/core/java/android/hardware/biometrics/BiometricTestSession.java index 719efa8ce6dd..4c7aa27968fe 100644 --- a/core/java/android/hardware/biometrics/BiometricTestSession.java +++ b/core/java/android/hardware/biometrics/BiometricTestSession.java @@ -23,10 +23,7 @@ import android.annotation.RequiresPermission; import android.annotation.TestApi; import android.content.Context; import android.os.RemoteException; -import android.util.Log; - -import java.util.ArrayList; -import java.util.List; +import android.util.ArraySet; /** * Common set of interfaces to test biometric-related APIs, including {@link BiometricPrompt} and @@ -35,37 +32,20 @@ import java.util.List; */ @TestApi public class BiometricTestSession implements AutoCloseable { - - private static final String TAG = "TestManager"; - private final Context mContext; - private final ITestService mTestService; + private final ITestSession mTestSession; + + // Keep track of users that were tested, which need to be cleaned up when finishing. + private final ArraySet<Integer> mTestedUsers; /** * @hide */ - public BiometricTestSession(@NonNull Context context, @NonNull ITestService testService) { + public BiometricTestSession(@NonNull Context context, @NonNull ITestSession testSession) { mContext = context; - mTestService = testService; - } - - /** - * @return A list of {@link SensorProperties} - */ - @NonNull - @RequiresPermission(TEST_BIOMETRIC) - public List<SensorProperties> getSensorProperties() { - try { - final List<SensorPropertiesInternal> internalProps = - mTestService.getSensorPropertiesInternal(mContext.getOpPackageName()); - final List<SensorProperties> props = new ArrayList<>(); - for (SensorPropertiesInternal internalProp : internalProps) { - props.add(new SensorProperties(internalProp.sensorId, internalProp.sensorStrength)); - } - return props; - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + mTestSession = testSession; + mTestedUsers = new ArraySet<>(); + enableTestHal(true); } /** @@ -75,105 +55,100 @@ public class BiometricTestSession implements AutoCloseable { * secure pathways such as HAT/Keystore are not testable, since they depend on the TEE or its * equivalent for the secret key. * - * @param sensorId Sensor that this command applies to. * @param enableTestHal If true, enable testing with a fake HAL instead of the real HAL. */ @RequiresPermission(TEST_BIOMETRIC) - public void enableTestHal(int sensorId, boolean enableTestHal) { + private void enableTestHal(boolean enableTestHal) { try { - mTestService.enableTestHal(sensorId, enableTestHal); + mTestSession.enableTestHal(enableTestHal); } catch (RemoteException e) { - Log.e(TAG, "Remote exception", e); + throw e.rethrowFromSystemServer(); } } /** * Starts the enrollment process. This should generally be used when the test HAL is enabled. * - * @param sensorId Sensor that this command applies to. * @param userId User that this command applies to. */ @RequiresPermission(TEST_BIOMETRIC) - public void enrollStart(int sensorId, int userId) { + public void startEnroll(int userId) { try { - mTestService.enrollStart(sensorId, userId); + mTestedUsers.add(userId); + mTestSession.startEnroll(userId); } catch (RemoteException e) { - Log.e(TAG, "Remote exception", e); + throw e.rethrowFromSystemServer(); } } /** * Finishes the enrollment process. Simulates the HAL's callback. * - * @param sensorId Sensor that this command applies to. * @param userId User that this command applies to. */ @RequiresPermission(TEST_BIOMETRIC) - public void enrollFinish(int sensorId, int userId) { + public void finishEnroll(int userId) { try { - mTestService.enrollFinish(sensorId, userId); + mTestedUsers.add(userId); + mTestSession.finishEnroll(userId); } catch (RemoteException e) { - Log.e(TAG, "Remote exception", e); + throw e.rethrowFromSystemServer(); } } /** * Simulates a successful authentication, but does not provide a valid HAT. * - * @param sensorId Sensor that this command applies to. * @param userId User that this command applies to. */ @RequiresPermission(TEST_BIOMETRIC) - public void authenticateSuccess(int sensorId, int userId) { + public void acceptAuthentication(int userId) { try { - mTestService.authenticateSuccess(sensorId, userId); + mTestSession.acceptAuthentication(userId); } catch (RemoteException e) { - Log.e(TAG, "Remote exception", e); + throw e.rethrowFromSystemServer(); } } /** * Simulates a rejected attempt. * - * @param sensorId Sensor that this command applies to. * @param userId User that this command applies to. */ @RequiresPermission(TEST_BIOMETRIC) - public void authenticateReject(int sensorId, int userId) { + public void rejectAuthentication(int userId) { try { - mTestService.authenticateReject(sensorId, userId); + mTestSession.rejectAuthentication(userId); } catch (RemoteException e) { - Log.e(TAG, "Remote exception", e); + throw e.rethrowFromSystemServer(); } } /** * Simulates an acquired message from the HAL. * - * @param sensorId Sensor that this command applies to. * @param userId User that this command applies to. */ @RequiresPermission(TEST_BIOMETRIC) - public void notifyAcquired(int sensorId, int userId) { + public void notifyAcquired(int userId) { try { - mTestService.notifyAcquired(sensorId, userId); + mTestSession.notifyAcquired(userId); } catch (RemoteException e) { - Log.e(TAG, "Remote exception", e); + throw e.rethrowFromSystemServer(); } } /** * Simulates an error message from the HAL. * - * @param sensorId Sensor that this command applies to. * @param userId User that this command applies to. */ @RequiresPermission(TEST_BIOMETRIC) - public void notifyError(int sensorId, int userId) { + public void notifyError(int userId) { try { - mTestService.notifyError(sensorId, userId); + mTestSession.notifyError(userId); } catch (RemoteException e) { - Log.e(TAG, "Remote exception", e); + throw e.rethrowFromSystemServer(); } } @@ -182,21 +157,24 @@ public class BiometricTestSession implements AutoCloseable { * that isn't known by both sides are deleted. This should generally be used when the test * HAL is disabled (e.g. to clean up after a test). * - * @param sensorId Sensor that this command applies to. * @param userId User that this command applies to. */ @RequiresPermission(TEST_BIOMETRIC) - public void internalCleanup(int sensorId, int userId) { + public void cleanupInternalState(int userId) { try { - mTestService.internalCleanup(sensorId, userId); + mTestSession.cleanupInternalState(userId); } catch (RemoteException e) { - Log.e(TAG, "Remote exception", e); + throw e.rethrowFromSystemServer(); } } @Override @RequiresPermission(TEST_BIOMETRIC) public void close() { + for (int user : mTestedUsers) { + cleanupInternalState(user); + } + enableTestHal(false); } } diff --git a/core/java/android/hardware/biometrics/ITestService.aidl b/core/java/android/hardware/biometrics/ITestSession.aidl index 637313266022..5677f6517ae5 100644 --- a/core/java/android/hardware/biometrics/ITestService.aidl +++ b/core/java/android/hardware/biometrics/ITestSession.aidl @@ -21,37 +21,34 @@ import android.hardware.biometrics.SensorPropertiesInternal; * A test service for FingerprintManager and BiometricPrompt. * @hide */ -interface ITestService { - // Returns a list of sensor properties supported by the interface. - List<SensorPropertiesInternal> getSensorPropertiesInternal(String opPackageName); - +interface ITestSession { // Switches the specified sensor to use a test HAL. In this mode, the framework will not invoke // any methods on the real HAL implementation. This allows the framework to test a substantial // portion of the framework code that would otherwise require human interaction. Note that // secure pathways such as HAT/Keystore are not testable, since they depend on the TEE or its // equivalent for the secret key. - void enableTestHal(int sensorId, boolean enableTestHal); + void enableTestHal(boolean enableTestHal); // Starts the enrollment process. This should generally be used when the test HAL is enabled. - void enrollStart(int sensorId, int userId); + void startEnroll(int userId); // Finishes the enrollment process. Simulates the HAL's callback. - void enrollFinish(int sensorId, int userId); + void finishEnroll(int userId); // Simulates a successful authentication, but does not provide a valid HAT. - void authenticateSuccess(int sensorId, int userId); + void acceptAuthentication(int userId); // Simulates a rejected attempt. - void authenticateReject(int sensorId, int userId); + void rejectAuthentication(int userId); // Simulates an acquired message from the HAL. - void notifyAcquired(int sensorId, int userId); + void notifyAcquired(int userId); // Simulates an error message from the HAL. - void notifyError(int sensorId, int userId); + void notifyError(int userId); // Matches the framework's cached enrollments against the HAL's enrollments. Any enrollment // that isn't known by both sides are deleted. This should generally be used when the test // HAL is disabled (e.g. to clean up after a test). - void internalCleanup(int sensorId, int userId); + void cleanupInternalState(int userId); } diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java index b35a68f64dc6..c5f8dac24a4e 100644 --- a/core/java/android/hardware/fingerprint/FingerprintManager.java +++ b/core/java/android/hardware/fingerprint/FingerprintManager.java @@ -39,6 +39,7 @@ import android.hardware.biometrics.BiometricFingerprintConstants; import android.hardware.biometrics.BiometricPrompt; import android.hardware.biometrics.BiometricTestSession; import android.hardware.biometrics.IBiometricServiceLockoutResetCallback; +import android.hardware.biometrics.SensorProperties; import android.os.Binder; import android.os.CancellationSignal; import android.os.CancellationSignal.OnCancelListener; @@ -97,6 +98,24 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing private Fingerprint mRemovalFingerprint; private Handler mHandler; + + /** + * Retrieves a list of properties for all fingerprint sensors on the device. + * @hide + */ + @TestApi + @NonNull + @RequiresPermission(TEST_BIOMETRIC) + public List<SensorProperties> getSensorProperties() { + final List<SensorProperties> properties = new ArrayList<>(); + final List<FingerprintSensorPropertiesInternal> internalProperties + = getSensorPropertiesInternal(); + for (FingerprintSensorPropertiesInternal internalProp : internalProperties) { + properties.add(FingerprintSensorProperties.from(internalProp)); + } + return properties; + } + /** * Retrieves a test session for FingerprintManager. * @hide @@ -104,10 +123,10 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing @TestApi @NonNull @RequiresPermission(TEST_BIOMETRIC) - public BiometricTestSession getTestSession() { + public BiometricTestSession createTestSession(int sensorId) { try { return new BiometricTestSession(mContext, - mService.getTestService(mContext.getOpPackageName())); + mService.createTestSession(sensorId, mContext.getOpPackageName())); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -878,21 +897,6 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing } /** - * Retrieves a list of properties for all fingerprint sensors on the device. - * @hide - */ - @NonNull - public List<FingerprintSensorProperties> getSensorProperties() { - final List<FingerprintSensorProperties> properties = new ArrayList<>(); - final List<FingerprintSensorPropertiesInternal> internalProperties - = getSensorPropertiesInternal(); - for (FingerprintSensorPropertiesInternal internalProp : internalProperties) { - properties.add(FingerprintSensorProperties.from(internalProp)); - } - return properties; - } - - /** * Get statically configured sensor properties. * @hide */ diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl index e8ca590ebf1e..cc086cf5656e 100644 --- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl +++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl @@ -17,7 +17,7 @@ package android.hardware.fingerprint; import android.hardware.biometrics.IBiometricSensorReceiver; import android.hardware.biometrics.IBiometricServiceLockoutResetCallback; -import android.hardware.biometrics.ITestService; +import android.hardware.biometrics.ITestSession; import android.hardware.fingerprint.IFingerprintClientActiveCallback; import android.hardware.fingerprint.IFingerprintServiceReceiver; import android.hardware.fingerprint.IUdfpsOverlayController; @@ -32,8 +32,8 @@ import java.util.List; */ interface IFingerprintService { - // Retrieves a test service - ITestService getTestService(String opPackageName); + // Creates a test session with the specified sensorId + ITestSession createTestSession(int sensorId, String opPackageName); // Retrieve static sensor properties for all fingerprint sensors List<FingerprintSensorPropertiesInternal> getSensorPropertiesInternal(String opPackageName); diff --git a/core/java/android/net/TEST_MAPPING b/core/java/android/net/TEST_MAPPING new file mode 100644 index 000000000000..abac81117deb --- /dev/null +++ b/core/java/android/net/TEST_MAPPING @@ -0,0 +1,20 @@ +{ + "imports": [ + { + // Also includes cts/tests/tests/net + "path": "frameworks/base/tests/net" + }, + { + "path": "packages/modules/NetworkStack" + }, + { + "path": "packages/modules/CaptivePortalLogin" + }, + { + "path": "frameworks/base/packages/Tethering" + }, + { + "path": "frameworks/opt/net/wifi" + } + ] +}
\ No newline at end of file diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl index 07363edd3e75..6fe57774f6f3 100644 --- a/core/java/android/os/IUserManager.aidl +++ b/core/java/android/os/IUserManager.aidl @@ -86,6 +86,7 @@ interface IUserManager { Bundle getApplicationRestrictionsForUser(in String packageName, int userId); void setDefaultGuestRestrictions(in Bundle restrictions); Bundle getDefaultGuestRestrictions(); + int removeUserOrSetEphemeral(int userId); boolean markGuestForDeletion(int userId); UserInfo findCurrentGuestUser(); boolean isQuietModeEnabled(int userId); diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index ddc21ab2c8c0..42ae93030f38 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -3978,6 +3978,23 @@ public class UserManager { } /** + * Immediately removes the user or, if the user cannot be removed, such as when the user is + * the current user, then set the user as ephemeral so that it will be removed when it is + * stopped. + * + * @return the {@link com.android.server.pm.UserManagerService.RemoveResult} code + * @hide + */ + @RequiresPermission(android.Manifest.permission.MANAGE_USERS) + public int removeUserOrSetEphemeral(@UserIdInt int userId) { + try { + return mService.removeUserOrSetEphemeral(userId); + } catch (RemoteException re) { + throw re.rethrowFromSystemServer(); + } + } + + /** * Updates the user's name. * * @param userId the user's integer id diff --git a/core/java/android/os/connectivity/CellularBatteryStats.java b/core/java/android/os/connectivity/CellularBatteryStats.java index 121fd333d17f..fc17002ba056 100644 --- a/core/java/android/os/connectivity/CellularBatteryStats.java +++ b/core/java/android/os/connectivity/CellularBatteryStats.java @@ -109,7 +109,7 @@ public final class CellularBatteryStats implements Parcelable { CellSignalStrength.getNumSignalStrengthLevels())); mTxTimeMs = Arrays.copyOfRange( txTimeMs, 0, - Math.min(txTimeMs.length, ModemActivityInfo.TX_POWER_LEVELS)); + Math.min(txTimeMs.length, ModemActivityInfo.getNumTxPowerLevels())); mMonitoredRailChargeConsumedMaMs = monitoredRailChargeConsumedMaMs; } diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java index d80a7e794220..3cfa59be5aa8 100644 --- a/core/java/android/permission/PermissionManager.java +++ b/core/java/android/permission/PermissionManager.java @@ -609,7 +609,7 @@ public final class PermissionManager { /** @hide */ private static final PropertyInvalidatedCache<PermissionQuery, Integer> sPermissionCache = new PropertyInvalidatedCache<PermissionQuery, Integer>( - 16, CACHE_KEY_PACKAGE_INFO, "checkPermission") { + 2048, CACHE_KEY_PACKAGE_INFO, "checkPermission") { @Override protected Integer recompute(PermissionQuery query) { return checkPermissionUncached(query.permission, query.pid, query.uid); diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index b133bcd14218..989efba13649 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -14591,6 +14591,19 @@ public final class Settings { */ public static final String MAXIMUM_OBSCURING_OPACITY_FOR_TOUCH = "maximum_obscuring_opacity_for_touch"; + + /** + * LatencyTracker settings. + * + * The following strings are supported as keys: + * <pre> + * enabled (boolean) + * sampling_interval (int) + * </pre> + * + * @hide + */ + public static final String LATENCY_TRACKER = "latency_tracker"; } /** diff --git a/core/java/android/service/dreams/DreamActivity.java b/core/java/android/service/dreams/DreamActivity.java index 09d1bb9d2b12..96bbf8ebc2cb 100644 --- a/core/java/android/service/dreams/DreamActivity.java +++ b/core/java/android/service/dreams/DreamActivity.java @@ -19,7 +19,6 @@ package android.service.dreams; import android.annotation.Nullable; import android.app.Activity; import android.os.Bundle; -import android.view.WindowInsets; import com.android.internal.R; @@ -63,8 +62,6 @@ public class DreamActivity extends Activity { @Override public void onResume() { super.onResume(); - // Hide all insets (nav bar, status bar, etc) when the dream is showing - getWindow().getInsetsController().hide(WindowInsets.Type.systemBars()); overridePendingTransition(R.anim.dream_activity_open_enter, R.anim.dream_activity_open_exit); } diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java index d2dfb29ba25c..859bb51607b9 100644 --- a/core/java/android/service/dreams/DreamService.java +++ b/core/java/android/service/dreams/DreamService.java @@ -48,6 +48,7 @@ import android.view.SearchEvent; import android.view.View; import android.view.ViewGroup; import android.view.Window; +import android.view.WindowInsets; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; import android.view.accessibility.AccessibilityEvent; @@ -1061,11 +1062,17 @@ public class DreamService extends Service implements Window.Callback { | (mFullscreen ? WindowManager.LayoutParams.FLAG_FULLSCREEN : 0) | (mScreenBright ? WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON : 0) ); + lp.layoutInDisplayCutoutMode = + WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; mWindow.setAttributes(lp); // Workaround: Currently low-profile and in-window system bar backgrounds don't go // along well. Dreams usually don't need such bars anyways, so disable them by default. mWindow.clearFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); + // Hide all insets when the dream is showing + mWindow.getDecorView().getWindowInsetsController().hide(WindowInsets.Type.systemBars()); + mWindow.setDecorFitsSystemWindows(false); + mWindow.getDecorView().addOnAttachStateChangeListener( new View.OnAttachStateChangeListener() { @Override diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index 0f46ffcb2d7f..4d1337b63b19 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -227,9 +227,6 @@ public abstract class WallpaperService extends Service { SurfaceControl mSurfaceControl = new SurfaceControl(); - // Unused relayout out-param - SurfaceControl mTmpSurfaceControl = new SurfaceControl(); - final BaseSurfaceHolder mSurfaceHolder = new BaseSurfaceHolder() { { mRequestedFormat = PixelFormat.RGBX_8888; @@ -905,7 +902,7 @@ public abstract class WallpaperService extends Service { final int relayoutResult = mSession.relayout( mWindow, mLayout, mWidth, mHeight, View.VISIBLE, 0, -1, mWinFrames, mMergedConfiguration, mSurfaceControl, - mInsetsState, mTempControls, mSurfaceSize, mTmpSurfaceControl); + mInsetsState, mTempControls, mSurfaceSize); if (mSurfaceControl.isValid()) { mSurfaceHolder.mSurface.copyFrom(mSurfaceControl); } diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java index 38e3b39f8cfc..4a0bec1300b7 100755 --- a/core/java/android/text/format/DateFormat.java +++ b/core/java/android/text/format/DateFormat.java @@ -17,10 +17,14 @@ package android.text.format; import android.annotation.NonNull; +import android.app.compat.CompatChanges; +import android.compat.annotation.ChangeId; +import android.compat.annotation.EnabledAfter; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.icu.text.DateFormatSymbols; import android.icu.text.DateTimePatternGenerator; +import android.os.Build; import android.provider.Settings; import android.text.SpannableStringBuilder; import android.text.Spanned; @@ -159,6 +163,16 @@ public class DateFormat { private static boolean sIs24Hour; /** + * {@link #getBestDateTimePattern(Locale, String)} does not allow non-consecutive repeated + * symbol in the skeleton. For example, please use a skeleton of {@code "jmm"} or + * {@code "hmma"} instead of {@code "ahmma"} or {@code "jmma"}, because the field 'j' could + * mean using 12-hour in some locales and, in this case, is duplicated as the 'a' field. + */ + @ChangeId + @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.R) + static final long DISALLOW_DUPLICATE_FIELD_IN_SKELETON = 170233598L; + + /** * Returns true if times should be formatted as 24 hour times, false if times should be * formatted as 12 hour (AM/PM) times. Based on the user's chosen locale and other preferences. * @param context the context to use for the content resolver @@ -251,7 +265,9 @@ public class DateFormat { */ public static String getBestDateTimePattern(Locale locale, String skeleton) { DateTimePatternGenerator dtpg = DateTimePatternGenerator.getInstance(locale); - return dtpg.getBestPattern(skeleton); + boolean allowDuplicateFields = !CompatChanges.isChangeEnabled( + DISALLOW_DUPLICATE_FIELD_IN_SKELETON); + return dtpg.getBestPattern(skeleton, allowDuplicateFields); } /** diff --git a/core/java/android/util/Log.java b/core/java/android/util/Log.java index 7a117f14d9b5..12bcd8b0aa97 100644 --- a/core/java/android/util/Log.java +++ b/core/java/android/util/Log.java @@ -44,9 +44,7 @@ import java.net.UnknownHostException; * You can then <a href="{@docRoot}studio/debug/am-logcat.html">view the logs in logcat</a>. * * <p>The order in terms of verbosity, from least to most is - * ERROR, WARN, INFO, DEBUG, VERBOSE. Verbose should never be compiled - * into an application except during development. Debug logs are compiled - * in but stripped at runtime. Error, warning and info logs are always kept. + * ERROR, WARN, INFO, DEBUG, VERBOSE. * * <p><b>Tip:</b> A good convention is to declare a <code>TAG</code> constant * in your class: diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index daab70ae336f..c460f74e7460 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -337,11 +337,16 @@ interface IWindowManager */ boolean isDisplayRotationFrozen(int displayId); - /** + /** * Sets if display rotation is fixed to user specified value for given displayId. */ void setFixedToUserRotation(int displayId, int fixedToUserRotation); + /** + * Sets if all requested fixed orientation should be ignored for given displayId. + */ + void setIgnoreOrientationRequest(int displayId, boolean ignoreOrientationRequest); + /** * Screenshot the current wallpaper layer, including the whole screen. */ diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl index 69a5fafbb0db..910fd905296c 100644 --- a/core/java/android/view/IWindowSession.aidl +++ b/core/java/android/view/IWindowSession.aidl @@ -98,9 +98,6 @@ interface IWindowSession { * @param outSurface Object in which is placed the new display surface. * @param insetsState The current insets state in the system. * @param outSurfaceSize The width and height of the surface control - * @param outBlastSurfaceControl A BLAST SurfaceControl allocated by the WindowManager - * the SurfaceControl willl be managed by the client side, but the WindowManager - * may use it as a deferTransaction barrier. * * @return int Result flags: {@link WindowManagerGlobal#RELAYOUT_SHOW_FOCUS}, * {@link WindowManagerGlobal#RELAYOUT_FIRST_TIME}. @@ -110,7 +107,7 @@ interface IWindowSession { int flags, long frameNumber, out ClientWindowFrames outFrames, out MergedConfiguration outMergedConfiguration, out SurfaceControl outSurfaceControl, out InsetsState insetsState, out InsetsSourceControl[] activeControls, - out Point outSurfaceSize, out SurfaceControl outBlastSurfaceControl); + out Point outSurfaceSize); /* * Notify the window manager that an application is relaunching and diff --git a/core/java/android/view/OnReceiveContentCallback.java b/core/java/android/view/OnReceiveContentCallback.java index 73bcb93d39d0..a217ff642ab7 100644 --- a/core/java/android/view/OnReceiveContentCallback.java +++ b/core/java/android/view/OnReceiveContentCallback.java @@ -134,46 +134,52 @@ public interface OnReceiveContentCallback<T extends View> { final class Payload { /** - * Specifies the UI through which content is being inserted. + * Specifies the UI through which content is being inserted. Future versions of Android may + * support additional values. * * @hide */ - @IntDef(prefix = {"SOURCE_"}, value = {SOURCE_CLIPBOARD, SOURCE_INPUT_METHOD, + @IntDef(prefix = {"SOURCE_"}, value = {SOURCE_APP, SOURCE_CLIPBOARD, SOURCE_INPUT_METHOD, SOURCE_DRAG_AND_DROP, SOURCE_AUTOFILL, SOURCE_PROCESS_TEXT}) @Retention(RetentionPolicy.SOURCE) public @interface Source {} /** + * Specifies that the operation was triggered by the app that contains the target view. + */ + public static final int SOURCE_APP = 0; + + /** * Specifies that the operation was triggered by a paste from the clipboard (e.g. "Paste" or * "Paste as plain text" action in the insertion/selection menu). */ - public static final int SOURCE_CLIPBOARD = 0; + public static final int SOURCE_CLIPBOARD = 1; /** * Specifies that the operation was triggered from the soft keyboard (also known as input * method editor or IME). See https://developer.android.com/guide/topics/text/image-keyboard * for more info. */ - public static final int SOURCE_INPUT_METHOD = 1; + public static final int SOURCE_INPUT_METHOD = 2; /** * Specifies that the operation was triggered by the drag/drop framework. See * https://developer.android.com/guide/topics/ui/drag-drop for more info. */ - public static final int SOURCE_DRAG_AND_DROP = 2; + public static final int SOURCE_DRAG_AND_DROP = 3; /** * Specifies that the operation was triggered by the autofill framework. See * https://developer.android.com/guide/topics/text/autofill for more info. */ - public static final int SOURCE_AUTOFILL = 3; + public static final int SOURCE_AUTOFILL = 4; /** * Specifies that the operation was triggered by a result from a * {@link android.content.Intent#ACTION_PROCESS_TEXT PROCESS_TEXT} action in the selection * menu. */ - public static final int SOURCE_PROCESS_TEXT = 4; + public static final int SOURCE_PROCESS_TEXT = 5; /** * Returns the symbolic name of the given source. @@ -182,6 +188,7 @@ public interface OnReceiveContentCallback<T extends View> { */ static String sourceToString(@Source int source) { switch (source) { + case SOURCE_APP: return "SOURCE_APP"; case SOURCE_CLIPBOARD: return "SOURCE_CLIPBOARD"; case SOURCE_INPUT_METHOD: return "SOURCE_INPUT_METHOD"; case SOURCE_DRAG_AND_DROP: return "SOURCE_DRAG_AND_DROP"; @@ -217,37 +224,11 @@ public interface OnReceiveContentCallback<T extends View> { return String.valueOf(flags); } - /** - * The data to be inserted. - */ @NonNull private final ClipData mClip; - - /** - * The source of the operation. See {@code SOURCE_} constants. - */ private final @Source int mSource; - - /** - * Optional flags that control the insertion behavior. See {@code FLAG_} constants. - */ private final @Flags int mFlags; - - /** - * Optional http/https URI for the content that may be provided by the IME. This is only - * populated if the source is {@link #SOURCE_INPUT_METHOD} and if a non-empty - * {@link android.view.inputmethod.InputContentInfo#getLinkUri linkUri} was passed by the - * IME. - */ - @Nullable - private final Uri mLinkUri; - - /** - * Optional additional metadata. If the source is {@link #SOURCE_INPUT_METHOD}, this will - * include the {@link android.view.inputmethod.InputConnection#commitContent opts} passed by - * the IME. - */ - @Nullable - private final Bundle mExtras; + @Nullable private final Uri mLinkUri; + @Nullable private final Bundle mExtras; private Payload(Builder b) { this.mClip = Objects.requireNonNull(b.mClip); @@ -278,7 +259,8 @@ public interface OnReceiveContentCallback<T extends View> { } /** - * The source of the operation. See {@code SOURCE_} constants. + * The source of the operation. See {@code SOURCE_} constants. Future versions of Android + * may pass additional values. */ public @Source int getSource() { return mSource; diff --git a/core/java/android/view/RemoteAccessibilityController.java b/core/java/android/view/RemoteAccessibilityController.java new file mode 100644 index 000000000000..bc0fab1bcf8d --- /dev/null +++ b/core/java/android/view/RemoteAccessibilityController.java @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2020 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.view; + +import android.graphics.Matrix; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.os.RemoteException; +import android.util.Log; +import android.view.accessibility.IAccessibilityEmbeddedConnection; + +class RemoteAccessibilityController { + private static final String TAG = "RemoteAccessibilityController"; + private int mHostId; + private RemoteAccessibilityEmbeddedConnection mConnectionWrapper; + private Matrix mScreenMatrixForEmbeddedHierarchy = new Matrix(); + private final float[] mMatrixValues = new float[9]; + private View mHostView; + + RemoteAccessibilityController(View v) { + mHostView = v; + } + + private void runOnUiThread(Runnable runnable) { + final Handler h = mHostView.getHandler(); + if (h != null && h.getLooper() != Looper.myLooper()) { + h.post(runnable); + } else { + runnable.run(); + } + } + + void assosciateHierarchy(IAccessibilityEmbeddedConnection connection, + IBinder leashToken, int hostId) { + mHostId = hostId; + + try { + leashToken = connection.associateEmbeddedHierarchy( + leashToken, mHostId); + setRemoteAccessibilityEmbeddedConnection(connection, leashToken); + } catch (RemoteException e) { + Log.d(TAG, "Error in associateEmbeddedHierarchy " + e); + } + } + + void disassosciateHierarchy() { + setRemoteAccessibilityEmbeddedConnection(null, null); + } + + boolean alreadyAssociated(IAccessibilityEmbeddedConnection connection) { + if (mConnectionWrapper == null) { + return false; + } + return mConnectionWrapper.mConnection.equals(connection); + } + + boolean connected() { + return mConnectionWrapper != null; + } + + IBinder getLeashToken() { + return mConnectionWrapper.getLeashToken(); + } + + /** + * Wrapper of accessibility embedded connection for embedded view hierarchy. + */ + private final class RemoteAccessibilityEmbeddedConnection implements IBinder.DeathRecipient { + private final IAccessibilityEmbeddedConnection mConnection; + private final IBinder mLeashToken; + + RemoteAccessibilityEmbeddedConnection(IAccessibilityEmbeddedConnection connection, + IBinder leashToken) { + mConnection = connection; + mLeashToken = leashToken; + } + + IAccessibilityEmbeddedConnection getConnection() { + return mConnection; + } + + IBinder getLeashToken() { + return mLeashToken; + } + + void linkToDeath() throws RemoteException { + mConnection.asBinder().linkToDeath(this, 0); + } + + void unlinkToDeath() { + mConnection.asBinder().unlinkToDeath(this, 0); + } + + @Override + public void binderDied() { + unlinkToDeath(); + runOnUiThread(() -> { + if (mConnectionWrapper == this) { + mConnectionWrapper = null; + } + }); + } + } + + private void setRemoteAccessibilityEmbeddedConnection( + IAccessibilityEmbeddedConnection connection, IBinder leashToken) { + try { + if (mConnectionWrapper != null) { + mConnectionWrapper.getConnection() + .disassociateEmbeddedHierarchy(); + mConnectionWrapper.unlinkToDeath(); + mConnectionWrapper = null; + } + if (connection != null && leashToken != null) { + mConnectionWrapper = + new RemoteAccessibilityEmbeddedConnection(connection, leashToken); + mConnectionWrapper.linkToDeath(); + } + } catch (RemoteException e) { + Log.d(TAG, "Error while setRemoteEmbeddedConnection " + e); + } + } + + private RemoteAccessibilityEmbeddedConnection getRemoteAccessibilityEmbeddedConnection() { + return mConnectionWrapper; + } + + void setScreenMatrix(Matrix m) { + // If the screen matrix is identity or doesn't change, do nothing. + if (m.isIdentity() || m.equals(mScreenMatrixForEmbeddedHierarchy)) { + return; + } + + try { + final RemoteAccessibilityEmbeddedConnection wrapper = + getRemoteAccessibilityEmbeddedConnection(); + if (wrapper == null) { + return; + } + m.getValues(mMatrixValues); + wrapper.getConnection().setScreenMatrix(mMatrixValues); + mScreenMatrixForEmbeddedHierarchy.set(m); + } catch (RemoteException e) { + Log.d(TAG, "Error while setScreenMatrix " + e); + } + } + + + + + + +} diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 78c71b856e2c..7b6a4f877d02 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -41,7 +41,6 @@ import android.os.Build; import android.os.Handler; import android.os.IBinder; import android.os.Looper; -import android.os.RemoteException; import android.os.SystemClock; import android.provider.Settings; import android.util.AttributeSet; @@ -225,13 +224,12 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall private SurfaceControl.Transaction mRtTransaction = new SurfaceControl.Transaction(); private SurfaceControl.Transaction mTmpTransaction = new SurfaceControl.Transaction(); - private int mParentSurfaceGenerationId; + private int mParentSurfaceSequenceId; - private RemoteAccessibilityEmbeddedConnection mRemoteAccessibilityEmbeddedConnection; + private RemoteAccessibilityController mRemoteAccessibilityController = + new RemoteAccessibilityController(this); - private final Matrix mScreenMatrixForEmbeddedHierarchy = new Matrix(); private final Matrix mTmpMatrix = new Matrix(); - private final float[] mMatrixValues = new float[9]; SurfaceControlViewHost.SurfacePackage mSurfacePackage; @@ -467,7 +465,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall Transaction t = new SurfaceControl.Transaction(); t.setAlpha(mSurfaceControl, alpha); t.deferTransactionUntil(mSurfaceControl, - viewRoot.getRenderSurfaceControl(), frame); + viewRoot.getSurfaceControl(), frame); t.apply(); } } @@ -827,7 +825,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall final SurfaceControl.Transaction t = new SurfaceControl.Transaction(); updateRelativeZ(t); t.deferTransactionUntil(mSurfaceControl, - viewRoot.getRenderSurfaceControl(), frame); + viewRoot.getSurfaceControl(), frame); t.apply(); } } @@ -927,6 +925,103 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall } } + private boolean performSurfaceTransaction(ViewRootImpl viewRoot, Translator translator, + boolean creating, boolean sizeChanged, boolean needBLASTSync) { + boolean realSizeChanged = false; + + mSurfaceLock.lock(); + try { + mDrawingStopped = !mVisible; + + if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " + + "Cur surface: " + mSurface); + + // If we are creating the surface control or the parent surface has not + // changed, then set relative z. Otherwise allow the parent + // SurfaceChangedCallback to update the relative z. This is needed so that + // we do not change the relative z before the server is ready to swap the + // parent surface. + if (creating || (mParentSurfaceSequenceId == viewRoot.getSurfaceSequenceId())) { + updateRelativeZ(mTmpTransaction); + } + mParentSurfaceSequenceId = viewRoot.getSurfaceSequenceId(); + + if (mViewVisibility) { + mTmpTransaction.show(mSurfaceControl); + } else { + mTmpTransaction.hide(mSurfaceControl); + } + + if (mSurfacePackage != null) { + reparentSurfacePackage(mTmpTransaction, mSurfacePackage); + } + + updateBackgroundVisibility(mTmpTransaction); + updateBackgroundColor(mTmpTransaction); + if (mUseAlpha) { + float alpha = getFixedAlpha(); + mTmpTransaction.setAlpha(mSurfaceControl, alpha); + mSurfaceAlpha = alpha; + } + + // While creating the surface, we will set it's initial + // geometry. Outside of that though, we should generally + // leave it to the RenderThread. + // + // There is one more case when the buffer size changes we aren't yet + // prepared to sync (as even following the transaction applying + // we still need to latch a buffer). + // b/28866173 + if (sizeChanged || creating || !mRtHandlingPositionUpdates) { + onSetSurfacePositionAndScaleRT(mTmpTransaction, mSurfaceControl, + mScreenRect.left, /*positionLeft*/ + mScreenRect.top /*positionTop*/ , + mScreenRect.width() / (float) mSurfaceWidth /*postScaleX*/, + mScreenRect.height() / (float) mSurfaceHeight /*postScaleY*/); + + // Set a window crop when creating the surface or changing its size to + // crop the buffer to the surface size since the buffer producer may + // use SCALING_MODE_SCALE and submit a larger size than the surface + // size. + if (mClipSurfaceToBounds && mClipBounds != null) { + mTmpTransaction.setWindowCrop(mSurfaceControl, mClipBounds); + } else { + mTmpTransaction.setWindowCrop(mSurfaceControl, mSurfaceWidth, + mSurfaceHeight); + } + } else if (needBLASTSync) { + viewRoot.setUseBLASTSyncTransaction(); + } + mTmpTransaction.setCornerRadius(mSurfaceControl, mCornerRadius); + if (sizeChanged && !creating) { + setBufferSize(mTmpTransaction); + } + + mTmpTransaction.apply(); + updateEmbeddedAccessibilityMatrix(); + + mSurfaceFrame.left = 0; + mSurfaceFrame.top = 0; + if (translator == null) { + mSurfaceFrame.right = mSurfaceWidth; + mSurfaceFrame.bottom = mSurfaceHeight; + } else { + float appInvertedScale = translator.applicationInvertedScale; + mSurfaceFrame.right = (int) (mSurfaceWidth * appInvertedScale + 0.5f); + mSurfaceFrame.bottom = (int) (mSurfaceHeight * appInvertedScale + 0.5f); + } + final int surfaceWidth = mSurfaceFrame.right; + final int surfaceHeight = mSurfaceFrame.bottom; + realSizeChanged = mLastSurfaceWidth != surfaceWidth + || mLastSurfaceHeight != surfaceHeight; + mLastSurfaceWidth = surfaceWidth; + mLastSurfaceHeight = surfaceHeight; + } finally { + mSurfaceLock.unlock(); + } + return realSizeChanged; + } + /** @hide */ protected void updateSurface() { if (!mHaveFrame) { @@ -965,7 +1060,6 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall && mRequestedVisible; final boolean sizeChanged = mSurfaceWidth != myWidth || mSurfaceHeight != myHeight; final boolean windowVisibleChanged = mWindowVisibility != mLastWindowVisibility; - boolean redrawNeeded = false; getLocationInSurface(mLocation); final boolean positionChanged = mWindowSpaceLeft != mLocation[0] || mWindowSpaceTop != mLocation[1]; @@ -988,7 +1082,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall + " top=" + (mWindowSpaceTop != mLocation[1])); try { - final boolean visible = mVisible = mRequestedVisible; + mVisible = mRequestedVisible; mWindowSpaceLeft = mLocation[0]; mWindowSpaceTop = mLocation[1]; mSurfaceWidth = myWidth; @@ -1014,119 +1108,26 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall return; } - boolean realSizeChanged = false; + final boolean needBLASTSync = + (layoutSizeChanged || positionChanged || visibleChanged) && + viewRoot.useBLAST(); + final boolean realSizeChanged = performSurfaceTransaction(viewRoot, + translator, creating, sizeChanged, needBLASTSync); + final boolean redrawNeeded = sizeChanged || creating || + (mVisible && !mDrawFinished); - mSurfaceLock.lock(); try { - mDrawingStopped = !visible; - - if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " " - + "Cur surface: " + mSurface); - - // If we are creating the surface control or the parent surface has not - // changed, then set relative z. Otherwise allow the parent - // SurfaceChangedCallback to update the relative z. This is needed so that - // we do not change the relative z before the server is ready to swap the - // parent surface. - if (creating || (mParentSurfaceGenerationId - == viewRoot.mSurface.getGenerationId())) { - updateRelativeZ(mTmpTransaction); - } - mParentSurfaceGenerationId = viewRoot.mSurface.getGenerationId(); - - if (mViewVisibility) { - mTmpTransaction.show(mSurfaceControl); - } else { - mTmpTransaction.hide(mSurfaceControl); - } - - if (mSurfacePackage != null) { - reparentSurfacePackage(mTmpTransaction, mSurfacePackage); - } - - updateBackgroundVisibility(mTmpTransaction); - updateBackgroundColor(mTmpTransaction); - if (mUseAlpha) { - mTmpTransaction.setAlpha(mSurfaceControl, alpha); - mSurfaceAlpha = alpha; - } - - // While creating the surface, we will set it's initial - // geometry. Outside of that though, we should generally - // leave it to the RenderThread. - // - // There is one more case when the buffer size changes we aren't yet - // prepared to sync (as even following the transaction applying - // we still need to latch a buffer). - // b/28866173 - if (sizeChanged || creating || !mRtHandlingPositionUpdates) { - onSetSurfacePositionAndScaleRT(mTmpTransaction, mSurfaceControl, - mScreenRect.left, /*positionLeft*/ - mScreenRect.top /*positionTop*/ , - mScreenRect.width() / (float) mSurfaceWidth /*postScaleX*/, - mScreenRect.height() / (float) mSurfaceHeight /*postScaleY*/); - - // Set a window crop when creating the surface or changing its size to - // crop the buffer to the surface size since the buffer producer may - // use SCALING_MODE_SCALE and submit a larger size than the surface - // size. - if (mClipSurfaceToBounds && mClipBounds != null) { - mTmpTransaction.setWindowCrop(mSurfaceControl, mClipBounds); - } else { - mTmpTransaction.setWindowCrop(mSurfaceControl, mSurfaceWidth, - mSurfaceHeight); - } - } else if ((layoutSizeChanged || positionChanged || visibleChanged) && - viewRoot.useBLAST()) { - viewRoot.setUseBLASTSyncTransaction(); - } - mTmpTransaction.setCornerRadius(mSurfaceControl, mCornerRadius); - if (sizeChanged && !creating) { - setBufferSize(mTmpTransaction); - } - - mTmpTransaction.apply(); - updateScreenMatrixForEmbeddedHierarchy(); - - if (sizeChanged || creating) { - redrawNeeded = true; - } - - mSurfaceFrame.left = 0; - mSurfaceFrame.top = 0; - if (translator == null) { - mSurfaceFrame.right = mSurfaceWidth; - mSurfaceFrame.bottom = mSurfaceHeight; - } else { - float appInvertedScale = translator.applicationInvertedScale; - mSurfaceFrame.right = (int) (mSurfaceWidth * appInvertedScale + 0.5f); - mSurfaceFrame.bottom = (int) (mSurfaceHeight * appInvertedScale + 0.5f); - } - - final int surfaceWidth = mSurfaceFrame.right; - final int surfaceHeight = mSurfaceFrame.bottom; - realSizeChanged = mLastSurfaceWidth != surfaceWidth - || mLastSurfaceHeight != surfaceHeight; - mLastSurfaceWidth = surfaceWidth; - mLastSurfaceHeight = surfaceHeight; - } finally { - mSurfaceLock.unlock(); - } - - try { - redrawNeeded |= visible && !mDrawFinished; - SurfaceHolder.Callback[] callbacks = null; final boolean surfaceChanged = creating; - if (mSurfaceCreated && (surfaceChanged || (!visible && visibleChanged))) { + if (mSurfaceCreated && (surfaceChanged || (!mVisible && visibleChanged))) { mSurfaceCreated = false; notifySurfaceDestroyed(); } copySurface(creating /* surfaceControlCreated */, sizeChanged); - if (visible && mSurface.isValid()) { + if (mVisible && mSurface.isValid()) { if (!mSurfaceCreated && (surfaceChanged || visibleChanged)) { mSurfaceCreated = true; mIsCreating = true; @@ -1352,7 +1353,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall Rect position, long frameNumber) { final ViewRootImpl viewRoot = getViewRootImpl(); if (frameNumber > 0 && viewRoot != null && !viewRoot.useBLAST()) { - t.deferTransactionUntil(surface, viewRoot.getRenderSurfaceControl(), + t.deferTransactionUntil(surface, viewRoot.getSurfaceControl(), frameNumber); } @@ -1470,7 +1471,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall } else { if (frameNumber > 0 && viewRoot != null && viewRoot.mSurface.isValid()) { mRtTransaction.deferTransactionUntil(mSurfaceControl, - viewRoot.getRenderSurfaceControl(), frameNumber); + viewRoot.getSurfaceControl(), frameNumber); } mRtTransaction.hide(mSurfaceControl); if (mRtReleaseSurfaces) { @@ -1754,7 +1755,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall @Override public void surfaceDestroyed() { setWindowStopped(true); - setRemoteAccessibilityEmbeddedConnection(null, null); + mRemoteAccessibilityController.disassosciateHierarchy(); } /** @@ -1834,14 +1835,12 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall @Override public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfoInternal(info); - final RemoteAccessibilityEmbeddedConnection wrapper = - getRemoteAccessibilityEmbeddedConnection(); - if (wrapper == null) { + if (!mRemoteAccessibilityController.connected()) { return; } // Add a leashed child when this SurfaceView embeds another view hierarchy. Getting this // leashed child would return the root node in the embedded hierarchy - info.addChild(wrapper.getLeashToken()); + info.addChild(mRemoteAccessibilityController.getLeashToken()); } @Override @@ -1850,7 +1849,7 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall // If developers explicitly set the important mode for it, don't change the mode. // Only change the mode to important when this SurfaceView isn't explicitly set and has // an embedded hierarchy. - if (mRemoteAccessibilityEmbeddedConnection == null + if (!mRemoteAccessibilityController.connected() || mode != IMPORTANT_FOR_ACCESSIBILITY_AUTO) { return mode; } @@ -1859,74 +1858,13 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall private void initEmbeddedHierarchyForAccessibility(SurfaceControlViewHost.SurfacePackage p) { final IAccessibilityEmbeddedConnection connection = p.getAccessibilityEmbeddedConnection(); - final RemoteAccessibilityEmbeddedConnection wrapper = - getRemoteAccessibilityEmbeddedConnection(); - - // Do nothing if package is embedding the same view hierarchy. - if (wrapper != null && wrapper.getConnection().equals(connection)) { - return; - } - - // If this SurfaceView embeds a different view hierarchy, unlink the previous one first. - setRemoteAccessibilityEmbeddedConnection(null, null); - - try { - final IBinder leashToken = connection.associateEmbeddedHierarchy( - getViewRootImpl().mLeashToken, getAccessibilityViewId()); - setRemoteAccessibilityEmbeddedConnection(connection, leashToken); - } catch (RemoteException e) { - Log.d(TAG, "Error while associateEmbeddedHierarchy " + e); - } - updateScreenMatrixForEmbeddedHierarchy(); - } - - private void setRemoteAccessibilityEmbeddedConnection( - IAccessibilityEmbeddedConnection connection, IBinder leashToken) { - try { - if (mRemoteAccessibilityEmbeddedConnection != null) { - mRemoteAccessibilityEmbeddedConnection.getConnection() - .disassociateEmbeddedHierarchy(); - mRemoteAccessibilityEmbeddedConnection.unlinkToDeath(); - mRemoteAccessibilityEmbeddedConnection = null; - } - if (connection != null && leashToken != null) { - mRemoteAccessibilityEmbeddedConnection = - new RemoteAccessibilityEmbeddedConnection(connection, leashToken); - mRemoteAccessibilityEmbeddedConnection.linkToDeath(); - } - } catch (RemoteException e) { - Log.d(TAG, "Error while setRemoteEmbeddedConnection " + e); - } - } - - private RemoteAccessibilityEmbeddedConnection getRemoteAccessibilityEmbeddedConnection() { - return mRemoteAccessibilityEmbeddedConnection; - } - - private void updateScreenMatrixForEmbeddedHierarchy() { - getBoundsOnScreen(mTmpRect); - mTmpMatrix.reset(); - mTmpMatrix.setTranslate(mTmpRect.left, mTmpRect.top); - mTmpMatrix.postScale(mScreenRect.width() / (float) mSurfaceWidth, - mScreenRect.height() / (float) mSurfaceHeight); - - // If the screen matrix is identity or doesn't change, do nothing. - if (mTmpMatrix.isIdentity() || mTmpMatrix.equals(mScreenMatrixForEmbeddedHierarchy)) { + if (mRemoteAccessibilityController.alreadyAssociated(connection)) { return; } + mRemoteAccessibilityController.assosciateHierarchy(connection, + getViewRootImpl().mLeashToken, getAccessibilityViewId()); - try { - final RemoteAccessibilityEmbeddedConnection wrapper = - getRemoteAccessibilityEmbeddedConnection(); - if (wrapper == null) { - return; - } - mTmpMatrix.getValues(mMatrixValues); - wrapper.getConnection().setScreenMatrix(mMatrixValues); - mScreenMatrixForEmbeddedHierarchy.set(mTmpMatrix); - } catch (RemoteException e) { - Log.d(TAG, "Error while setScreenMatrix " + e); - } + updateEmbeddedAccessibilityMatrix(); } private void notifySurfaceDestroyed() { @@ -1954,6 +1892,18 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall } } + void updateEmbeddedAccessibilityMatrix() { + if (!mRemoteAccessibilityController.connected()) { + return; + } + getBoundsOnScreen(mTmpRect); + mTmpMatrix.reset(); + mTmpMatrix.setTranslate(mTmpRect.left, mTmpRect.top); + mTmpMatrix.postScale(mScreenRect.width() / (float) mSurfaceWidth, + mScreenRect.height() / (float) mSurfaceHeight); + mRemoteAccessibilityController.setScreenMatrix(mTmpMatrix); + } + @Override protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction, @Nullable Rect previouslyFocusedRect) { @@ -1970,44 +1920,4 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall + "Exception requesting focus on embedded window", e); } } - - /** - * Wrapper of accessibility embedded connection for embedded view hierarchy. - */ - private final class RemoteAccessibilityEmbeddedConnection implements IBinder.DeathRecipient { - private final IAccessibilityEmbeddedConnection mConnection; - private final IBinder mLeashToken; - - RemoteAccessibilityEmbeddedConnection(IAccessibilityEmbeddedConnection connection, - IBinder leashToken) { - mConnection = connection; - mLeashToken = leashToken; - } - - IAccessibilityEmbeddedConnection getConnection() { - return mConnection; - } - - IBinder getLeashToken() { - return mLeashToken; - } - - void linkToDeath() throws RemoteException { - mConnection.asBinder().linkToDeath(this, 0); - } - - void unlinkToDeath() { - mConnection.asBinder().unlinkToDeath(this, 0); - } - - @Override - public void binderDied() { - unlinkToDeath(); - runOnUiThread(() -> { - if (mRemoteAccessibilityEmbeddedConnection == this) { - mRemoteAccessibilityEmbeddedConnection = null; - } - }); - } - } } diff --git a/core/java/android/view/SyncRtSurfaceTransactionApplier.java b/core/java/android/view/SyncRtSurfaceTransactionApplier.java index 062285ff2f5d..bce78b572360 100644 --- a/core/java/android/view/SyncRtSurfaceTransactionApplier.java +++ b/core/java/android/view/SyncRtSurfaceTransactionApplier.java @@ -60,7 +60,7 @@ public class SyncRtSurfaceTransactionApplier { if (mTargetViewRootImpl == null) { return; } - mTargetSc = mTargetViewRootImpl.getRenderSurfaceControl(); + mTargetSc = mTargetViewRootImpl.getSurfaceControl(); mTargetViewRootImpl.registerRtFrameCallback(frame -> { if (mTargetSc == null || !mTargetSc.isValid()) { return; diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index e00ff7e00888..52357402877a 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -105,6 +105,7 @@ import android.graphics.BLASTBufferQueue; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.FrameInfo; +import android.graphics.HardwareRenderer; import android.graphics.HardwareRenderer.FrameDrawingCallback; import android.graphics.Insets; import android.graphics.Matrix; @@ -519,7 +520,6 @@ public final class ViewRootImpl implements ViewParent, @UnsupportedAppUsage public final Surface mSurface = new Surface(); private final SurfaceControl mSurfaceControl = new SurfaceControl(); - private SurfaceControl mBlastSurfaceControl = new SurfaceControl(); private BLASTBufferQueue mBlastBufferQueue; @@ -702,6 +702,11 @@ public final class ViewRootImpl implements ViewParent, private HashSet<ScrollCaptureCallback> mRootScrollCaptureCallbacks; + /** + * Increment this value when the surface has been replaced. + */ + private int mSurfaceSequenceId = 0; + private String mTag = TAG; public ViewRootImpl(Context context, Display display) { @@ -1808,7 +1813,7 @@ public final class ViewRootImpl implements ViewParent, mBoundsLayer = new SurfaceControl.Builder(mSurfaceSession) .setContainerLayer() .setName("Bounds for - " + getTitle().toString()) - .setParent(getRenderSurfaceControl()) + .setParent(getSurfaceControl()) .setCallsite("ViewRootImpl.getBoundsLayer") .build(); setBoundsLayerCrop(mTransaction); @@ -1818,22 +1823,19 @@ public final class ViewRootImpl implements ViewParent, } Surface getOrCreateBLASTSurface(int width, int height) { - if (mSurfaceControl == null - || !mSurfaceControl.isValid() - || mBlastSurfaceControl == null - || !mBlastSurfaceControl.isValid()) { + if (!mSurfaceControl.isValid()) { return null; } Surface ret = null; if (mBlastBufferQueue == null) { mBlastBufferQueue = new BLASTBufferQueue(mTag, - mBlastSurfaceControl, width, height, mEnableTripleBuffering); + mSurfaceControl, width, height, mEnableTripleBuffering); // We only return the Surface the first time, as otherwise // it hasn't changed and there is no need to update. ret = mBlastBufferQueue.createSurface(); } else { - mBlastBufferQueue.update(mBlastSurfaceControl, width, height); + mBlastBufferQueue.update(mSurfaceControl, width, height); } return ret; @@ -1855,7 +1857,7 @@ public final class ViewRootImpl implements ViewParent, private boolean updateBoundsLayer(SurfaceControl.Transaction t) { if (mBoundsLayer != null) { setBoundsLayerCrop(t); - t.deferTransactionUntil(mBoundsLayer, getRenderSurfaceControl(), + t.deferTransactionUntil(mBoundsLayer, getSurfaceControl(), mSurface.getNextFrameNumber()); return true; } @@ -1864,7 +1866,7 @@ public final class ViewRootImpl implements ViewParent, private void prepareSurfaces(boolean sizeChanged) { final SurfaceControl.Transaction t = mTransaction; - final SurfaceControl sc = getRenderSurfaceControl(); + final SurfaceControl sc = getSurfaceControl(); if (!sc.isValid()) return; boolean applyTransaction = updateBoundsLayer(t); @@ -1885,7 +1887,6 @@ public final class ViewRootImpl implements ViewParent, mSurface.release(); mSurfaceControl.release(); - mBlastSurfaceControl.release(); // We should probably add an explicit dispose. mBlastBufferQueue = null; } @@ -2613,7 +2614,7 @@ public final class ViewRootImpl implements ViewParent, boolean surfaceSizeChanged = false; boolean surfaceCreated = false; boolean surfaceDestroyed = false; - /* True if surface generation id changes. */ + // True if surface generation id changes or relayout result is RELAYOUT_RES_SURFACE_CHANGED. boolean surfaceReplaced = false; final boolean windowAttributesChanged = mWindowAttributesChanged; @@ -2708,6 +2709,7 @@ public final class ViewRootImpl implements ViewParent, updateColorModeIfNeeded(lp.getColorMode()); surfaceCreated = !hadSurface && mSurface.isValid(); surfaceDestroyed = hadSurface && !mSurface.isValid(); + // When using Blast, the surface generation id may not change when there's a new // SurfaceControl. In that case, we also check relayout flag // RELAYOUT_RES_SURFACE_CHANGED since it should indicate that WMS created a new @@ -2716,6 +2718,9 @@ public final class ViewRootImpl implements ViewParent, || (relayoutResult & RELAYOUT_RES_SURFACE_CHANGED) == RELAYOUT_RES_SURFACE_CHANGED) && mSurface.isValid(); + if (surfaceReplaced) { + mSurfaceSequenceId++; + } if (cutoutChanged) { mAttachInfo.mDisplayCutout.set(mPendingDisplayCutout); @@ -3815,6 +3820,82 @@ public final class ViewRootImpl implements ViewParent, } } + /** + * The callback will run on the render thread. + */ + private HardwareRenderer.FrameCompleteCallback createFrameCompleteCallback(Handler handler, + boolean reportNextDraw, ArrayList<Runnable> commitCallbacks) { + return frameNr -> { + // Use a new transaction here since mRtBLASTSyncTransaction can only be accessed by + // the render thread and mSurfaceChangedTransaction can only be accessed by the UI + // thread. The temporary transaction is used so mRtBLASTSyncTransaction can be merged + // with mSurfaceChangedTransaction without synchronization issues. + final Transaction t = new Transaction(); + finishBLASTSyncOnRT(!mSendNextFrameToWm, t); + handler.postAtFrontOfQueue(() -> { + mSurfaceChangedTransaction.merge(t); + if (reportNextDraw) { + // TODO: Use the frame number + pendingDrawFinished(); + } + if (commitCallbacks != null) { + for (int i = 0; i < commitCallbacks.size(); i++) { + commitCallbacks.get(i).run(); + } + } + }); + }; + } + + private boolean addFrameCompleteCallbackIfNeeded() { + if (mAttachInfo.mThreadedRenderer == null || !mAttachInfo.mThreadedRenderer.isEnabled()) { + return false; + } + + ArrayList<Runnable> commitCallbacks = mAttachInfo.mTreeObserver + .captureFrameCommitCallbacks(); + final boolean needFrameCompleteCallback = + mNextDrawUseBLASTSyncTransaction || mReportNextDraw + || (commitCallbacks != null && commitCallbacks.size() > 0); + if (needFrameCompleteCallback) { + mAttachInfo.mThreadedRenderer.setFrameCompleteCallback( + createFrameCompleteCallback(mAttachInfo.mHandler, mReportNextDraw, + commitCallbacks)); + return true; + } + return false; + } + + /** + * The callback will run on a worker thread pool from the render thread. + */ + private HardwareRenderer.FrameDrawingCallback createFrameDrawingCallback() { + return frame -> { + mRtNextFrameReportedConsumeWithBlast = true; + if (mBlastBufferQueue != null) { + // We don't need to synchronize mRtBLASTSyncTransaction here since it's not + // being modified and only sent to BlastBufferQueue. + mBlastBufferQueue.setNextTransaction(mRtBLASTSyncTransaction); + } + }; + } + + private void addFrameCallbackIfNeeded() { + if (!mNextDrawUseBLASTSyncTransaction) { + return; + } + + // Frame callbacks will always occur after submitting draw requests and before + // the draw actually occurs. This will ensure that we set the next transaction + // for the frame that's about to get drawn and not on a previous frame that. + // + // This is thread safe since mRtNextFrameReportConsumeWithBlast will only be + // modified in onFrameDraw and then again in onFrameComplete. This is to ensure the + // next frame completed should be reported with the blast sync transaction. + registerRtFrameCallback(createFrameDrawingCallback()); + mNextDrawUseBLASTSyncTransaction = false; + } + private void performDraw() { if (mAttachInfo.mDisplayState == Display.STATE_OFF && !mReportNextDraw) { return; @@ -3828,58 +3909,14 @@ public final class ViewRootImpl implements ViewParent, mIsDrawing = true; Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw"); - boolean usingAsyncReport = false; - boolean reportNextDraw = mReportNextDraw; // Capture the original value - if (mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled()) { - ArrayList<Runnable> commitCallbacks = mAttachInfo.mTreeObserver - .captureFrameCommitCallbacks(); - final boolean needFrameCompleteCallback = mNextDrawUseBLASTSyncTransaction || - (commitCallbacks != null && commitCallbacks.size() > 0) || - mReportNextDraw; - usingAsyncReport = mReportNextDraw; - if (needFrameCompleteCallback) { - final Handler handler = mAttachInfo.mHandler; - mAttachInfo.mThreadedRenderer.setFrameCompleteCallback((long frameNr) -> { - finishBLASTSync(!mSendNextFrameToWm); - handler.postAtFrontOfQueue(() -> { - if (reportNextDraw) { - // TODO: Use the frame number - pendingDrawFinished(); - } - if (commitCallbacks != null) { - for (int i = 0; i < commitCallbacks.size(); i++) { - commitCallbacks.get(i).run(); - } - } - }); - }); - } - } + boolean usingAsyncReport = addFrameCompleteCallbackIfNeeded(); + addFrameCallbackIfNeeded(); try { - if (mNextDrawUseBLASTSyncTransaction) { - // Frame callbacks will always occur after submitting draw requests and before - // the draw actually occurs. This will ensure that we set the next transaction - // for the frame that's about to get drawn and not on a previous frame that. - // - // This is thread safe since mRtNextFrameReportConsumeWithBlast will only be - // modified in onFrameDraw and then again in onFrameComplete. This is to ensure the - // next frame completed should be reported with the blast sync transaction. - registerRtFrameCallback(frame -> { - mRtNextFrameReportedConsumeWithBlast = true; - if (mBlastBufferQueue != null) { - // We don't need to synchronize mRtBLASTSyncTransaction here since it's not - // being modified and only sent to BlastBufferQueue. - mBlastBufferQueue.setNextTransaction(mRtBLASTSyncTransaction); - } - }); - mNextDrawUseBLASTSyncTransaction = false; - } boolean canUseAsync = draw(fullRedrawNeeded); if (usingAsyncReport && !canUseAsync) { mAttachInfo.mThreadedRenderer.setFrameCompleteCallback(null); usingAsyncReport = false; - finishBLASTSync(true /* apply */); } } finally { mIsDrawing = false; @@ -7447,7 +7484,7 @@ public final class ViewRootImpl implements ViewParent, (int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, frameNumber, mTmpFrames, mPendingMergedConfiguration, mSurfaceControl, mTempInsets, - mTempControls, mSurfaceSize, mBlastSurfaceControl); + mTempControls, mSurfaceSize); mPendingDisplayCutout.set(mTmpFrames.displayCutout); mPendingBackDropFrame.set(mTmpFrames.backdropFrame); if (mSurfaceControl.isValid()) { @@ -9844,7 +9881,12 @@ public final class ViewRootImpl implements ViewParent, mNextDrawUseBLASTSyncTransaction = true; } - private void finishBLASTSync(boolean apply) { + /** + * This should only be called from the render thread. + */ + private void finishBLASTSyncOnRT(boolean apply, Transaction t) { + // This is safe to modify on the render thread since the only other place it's modified + // is on the UI thread when the render thread is paused. mSendNextFrameToWm = false; if (mRtNextFrameReportedConsumeWithBlast) { mRtNextFrameReportedConsumeWithBlast = false; @@ -9855,7 +9897,7 @@ public final class ViewRootImpl implements ViewParent, if (apply) { mRtBLASTSyncTransaction.apply(); } else { - mSurfaceChangedTransaction.merge(mRtBLASTSyncTransaction); + t.merge(mRtBLASTSyncTransaction); } } } @@ -9868,17 +9910,6 @@ public final class ViewRootImpl implements ViewParent, return mRtBLASTSyncTransaction; } - /** - * @hide - */ - public SurfaceControl getRenderSurfaceControl() { - if (useBLAST()) { - return mBlastSurfaceControl; - } else { - return mSurfaceControl; - } - } - @Override public void onDescendantUnbufferedRequested() { mUnbufferedInputSource = mView.mUnbufferedInputSource; @@ -9895,4 +9926,8 @@ public final class ViewRootImpl implements ViewParent, boolean useBLAST() { return mUseBLASTAdapter && !mForceDisableBLAST; } + + int getSurfaceSequenceId() { + return mSurfaceSequenceId; + } } diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java index dbd8184e57bb..0c221eddf1a9 100644 --- a/core/java/android/view/WindowlessWindowManager.java +++ b/core/java/android/view/WindowlessWindowManager.java @@ -227,8 +227,7 @@ public class WindowlessWindowManager implements IWindowSession { int requestedWidth, int requestedHeight, int viewFlags, int flags, long frameNumber, ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration, SurfaceControl outSurfaceControl, InsetsState outInsetsState, - InsetsSourceControl[] outActiveControls, Point outSurfaceSize, - SurfaceControl outBLASTSurfaceControl) { + InsetsSourceControl[] outActiveControls, Point outSurfaceSize) { final State state; synchronized (this) { state = mStateForWindow.get(window.asBinder()); diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java index d80d2300dbce..f6d6fde6435f 100644 --- a/core/java/android/view/accessibility/AccessibilityEvent.java +++ b/core/java/android/view/accessibility/AccessibilityEvent.java @@ -199,7 +199,7 @@ import java.util.List; * <b>Window state changed</b> - represents the event of a change to a section of * the user interface that is visually distinct. Should be sent from either the * root view of a window or from a view that is marked as a pane - * {@link android.view.View#setAccessibilityPaneTitle(CharSequence)}. Not that changes + * {@link android.view.View#setAccessibilityPaneTitle(CharSequence)}. Note that changes * to true windows are represented by {@link #TYPE_WINDOWS_CHANGED}.</br> * <em>Type:</em> {@link #TYPE_WINDOW_STATE_CHANGED}</br> * <em>Properties:</em></br> diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index 6edf7a3204d4..83cbe38f6cb4 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -1291,7 +1291,7 @@ public class ResolverActivity extends Activity implements private void safelyStartActivityInternal(TargetInfo cti) { // If the target is suspended, the activity will not be successfully launched. // Do not unregister from package manager updates in this case - if (!cti.isSuspended()) { + if (!cti.isSuspended() && mRegistered) { if (mPersonalPackageMonitor != null) { mPersonalPackageMonitor.unregister(); } diff --git a/core/java/com/android/internal/content/PackageMonitor.java b/core/java/com/android/internal/content/PackageMonitor.java index 3682b7bcd891..af666d87d6f1 100644 --- a/core/java/com/android/internal/content/PackageMonitor.java +++ b/core/java/com/android/internal/content/PackageMonitor.java @@ -37,6 +37,7 @@ import java.util.Objects; * updating, and disappearing and reappearing on the SD card. */ public abstract class PackageMonitor extends android.content.BroadcastReceiver { + static final String TAG = "PackageMonitor"; static final IntentFilter sPackageFilt = new IntentFilter(); static final IntentFilter sNonDataFilt = new IntentFilter(); static final IntentFilter sExternalFilt = new IntentFilter(); @@ -48,6 +49,9 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver { sPackageFilt.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART); sPackageFilt.addAction(Intent.ACTION_PACKAGE_RESTARTED); sPackageFilt.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED); + sPackageFilt.addAction(Intent.ACTION_PACKAGE_STARTABLE); + sPackageFilt.addAction(Intent.ACTION_PACKAGE_UNSTARTABLE); + sPackageFilt.addAction(Intent.ACTION_PACKAGE_FULLY_LOADED); sPackageFilt.addDataScheme("package"); sNonDataFilt.addAction(Intent.ACTION_UID_REMOVED); sNonDataFilt.addAction(Intent.ACTION_USER_STOPPED); @@ -305,6 +309,13 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver { public void onPackageDataCleared(String packageName, int uid) { } + /** + * Callback to indicate the package's state has changed. + * @param packageName Name of an installed package + * @param uid The UID the package runs under. + */ + public void onPackageStateChanged(String packageName, int uid) {} + public int getChangingUserId() { return mChangeUserId; } @@ -452,12 +463,21 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver { String[] pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST); mSomePackagesChanged = true; onPackagesUnsuspended(pkgList); + } else if (Intent.ACTION_PACKAGE_STARTABLE.equals(action) + || Intent.ACTION_PACKAGE_UNSTARTABLE.equals(action) + || Intent.ACTION_PACKAGE_FULLY_LOADED.equals(action)) { + String pkg = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); + int uid = intent.getIntExtra(Intent.EXTRA_UID, 0); + mSomePackagesChanged = false; + if (pkg != null) { + onPackageStateChanged(pkg, uid); + } } if (mSomePackagesChanged) { onSomePackagesChanged(); } - + onFinishPackageChanges(); mChangeUserId = UserHandle.USER_NULL; } diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 17323ba2f16b..4c5f9886a7c6 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -65,7 +65,6 @@ import android.provider.Settings; import android.telephony.CellSignalStrength; import android.telephony.DataConnectionRealTimeInfo; import android.telephony.ModemActivityInfo; -import android.telephony.ModemActivityInfo.TransmitPower; import android.telephony.ServiceState; import android.telephony.SignalStrength; import android.telephony.TelephonyManager; @@ -7791,7 +7790,7 @@ public class BatteryStatsImpl extends BatteryStats { public ControllerActivityCounterImpl getOrCreateModemControllerActivityLocked() { if (mModemControllerActivity == null) { mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase, - ModemActivityInfo.TX_POWER_LEVELS); + ModemActivityInfo.getNumTxPowerLevels()); } return mModemControllerActivity; } @@ -9257,7 +9256,7 @@ public class BatteryStatsImpl extends BatteryStats { if (in.readInt() != 0) { mModemControllerActivity = new ControllerActivityCounterImpl(mBsi.mOnBatteryTimeBase, - ModemActivityInfo.TX_POWER_LEVELS, in); + ModemActivityInfo.getNumTxPowerLevels(), in); } else { mModemControllerActivity = null; } @@ -10520,7 +10519,7 @@ public class BatteryStatsImpl extends BatteryStats { mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, NUM_BT_TX_LEVELS); mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, - ModemActivityInfo.TX_POWER_LEVELS); + ModemActivityInfo.getNumTxPowerLevels()); mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null, mOnBatteryTimeBase); mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null, mOnBatteryTimeBase); @@ -11710,26 +11709,7 @@ public class BatteryStatsImpl extends BatteryStats { } } - private ModemActivityInfo mLastModemActivityInfo = - new ModemActivityInfo(0, 0, 0, new int[0], 0); - - private ModemActivityInfo getDeltaModemActivityInfo(ModemActivityInfo activityInfo) { - if (activityInfo == null) { - return null; - } - int[] txTimeMs = new int[ModemActivityInfo.TX_POWER_LEVELS]; - for (int i = 0; i < ModemActivityInfo.TX_POWER_LEVELS; i++) { - txTimeMs[i] = activityInfo.getTransmitPowerInfo().get(i).getTimeInMillis() - - mLastModemActivityInfo.getTransmitPowerInfo().get(i).getTimeInMillis(); - } - ModemActivityInfo deltaInfo = new ModemActivityInfo(activityInfo.getTimestamp(), - activityInfo.getSleepTimeMillis() - mLastModemActivityInfo.getSleepTimeMillis(), - activityInfo.getIdleTimeMillis() - mLastModemActivityInfo.getIdleTimeMillis(), - txTimeMs, - activityInfo.getReceiveTimeMillis() - mLastModemActivityInfo.getReceiveTimeMillis()); - mLastModemActivityInfo = activityInfo; - return deltaInfo; - } + private ModemActivityInfo mLastModemActivityInfo = null; /** * Distribute Cell radio energy info and network traffic to apps. @@ -11746,7 +11726,9 @@ public class BatteryStatsImpl extends BatteryStats { if (DEBUG_ENERGY) { Slog.d(TAG, "Updating mobile radio stats with " + activityInfo); } - ModemActivityInfo deltaInfo = getDeltaModemActivityInfo(activityInfo); + ModemActivityInfo deltaInfo = mLastModemActivityInfo == null ? activityInfo + : mLastModemActivityInfo.getDelta(activityInfo); + mLastModemActivityInfo = activityInfo; // Add modem tx power to history. addModemTxPowerToHistory(deltaInfo, elapsedRealtimeMs, uptimeMs); @@ -11778,10 +11760,9 @@ public class BatteryStatsImpl extends BatteryStats { mModemActivity.getSleepTimeCounter().addCountLocked( deltaInfo.getSleepTimeMillis()); mModemActivity.getRxTimeCounter().addCountLocked(deltaInfo.getReceiveTimeMillis()); - for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) { + for (int lvl = 0; lvl < ModemActivityInfo.getNumTxPowerLevels(); lvl++) { mModemActivity.getTxTimeCounters()[lvl] - .addCountLocked(deltaInfo.getTransmitPowerInfo() - .get(lvl).getTimeInMillis()); + .addCountLocked(deltaInfo.getTransmitDurationMillisAtPowerLevel(lvl)); } // POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V. @@ -11795,11 +11776,11 @@ public class BatteryStatsImpl extends BatteryStats { mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_IDLE) + deltaInfo.getReceiveTimeMillis() * mPowerProfile.getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_RX); - List<TransmitPower> txPowerInfo = deltaInfo.getTransmitPowerInfo(); - for (int i = 0; i < Math.min(txPowerInfo.size(), + for (int i = 0; i < Math.min(ModemActivityInfo.getNumTxPowerLevels(), CellSignalStrength.getNumSignalStrengthLevels()); i++) { - energyUsed += txPowerInfo.get(i).getTimeInMillis() * mPowerProfile - .getAveragePower(PowerProfile.POWER_MODEM_CONTROLLER_TX, i); + energyUsed += deltaInfo.getTransmitDurationMillisAtPowerLevel(i) + * mPowerProfile.getAveragePower( + PowerProfile.POWER_MODEM_CONTROLLER_TX, i); } // We store the power drain as mAms. @@ -11894,10 +11875,10 @@ public class BatteryStatsImpl extends BatteryStats { } if (totalTxPackets > 0 && entry.txPackets > 0) { - for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) { - long txMs = - entry.txPackets * deltaInfo.getTransmitPowerInfo() - .get(lvl).getTimeInMillis(); + for (int lvl = 0; lvl < ModemActivityInfo.getNumTxPowerLevels(); + lvl++) { + long txMs = entry.txPackets + * deltaInfo.getTransmitDurationMillisAtPowerLevel(lvl); txMs /= totalTxPackets; activityCounter.getTxTimeCounters()[lvl].addCountLocked(txMs); } @@ -11929,18 +11910,14 @@ public class BatteryStatsImpl extends BatteryStats { if (activityInfo == null) { return; } - List<TransmitPower> txPowerInfo = activityInfo.getTransmitPowerInfo(); - if (txPowerInfo == null || txPowerInfo.size() != ModemActivityInfo.TX_POWER_LEVELS) { - return; - } int levelMaxTimeSpent = 0; - for (int i = 1; i < txPowerInfo.size(); i++) { - if (txPowerInfo.get(i).getTimeInMillis() > txPowerInfo.get(levelMaxTimeSpent) - .getTimeInMillis()) { + for (int i = 1; i < ModemActivityInfo.getNumTxPowerLevels(); i++) { + if (activityInfo.getTransmitDurationMillisAtPowerLevel(i) + > activityInfo.getTransmitDurationMillisAtPowerLevel(levelMaxTimeSpent)) { levelMaxTimeSpent = i; } } - if (levelMaxTimeSpent == ModemActivityInfo.TX_POWER_LEVELS - 1) { + if (levelMaxTimeSpent == ModemActivityInfo.getNumTxPowerLevels() - 1) { mHistoryCur.states2 |= HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG; addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } @@ -13462,7 +13439,7 @@ public class BatteryStatsImpl extends BatteryStats { timeInRxSignalStrengthLevelMs[i] = getPhoneSignalStrengthTime(i, rawRealTimeUs, which) / 1000; } - long[] txTimeMs = new long[Math.min(ModemActivityInfo.TX_POWER_LEVELS, + long[] txTimeMs = new long[Math.min(ModemActivityInfo.getNumTxPowerLevels(), counter.getTxTimeCounters().length)]; long totalTxTimeMs = 0; for (int i = 0; i < txTimeMs.length; i++) { @@ -15601,7 +15578,7 @@ public class BatteryStatsImpl extends BatteryStats { mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, NUM_BT_TX_LEVELS, in); mModemActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, - ModemActivityInfo.TX_POWER_LEVELS, in); + ModemActivityInfo.getNumTxPowerLevels(), in); mHasWifiReporting = in.readInt() != 0; mHasBluetoothReporting = in.readInt() != 0; mHasModemReporting = in.readInt() != 0; diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl index caae5188b6a0..77c7ce8cf5c4 100644 --- a/core/java/com/android/internal/statusbar/IStatusBar.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl @@ -102,6 +102,13 @@ oneway interface IStatusBar void onCameraLaunchGestureDetected(int source); /** + * 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. + */ + void onEmergencyActionLaunchGestureDetected(); + + /** * Shows the picture-in-picture menu if an activity is in picture-in-picture mode. */ void showPictureInPictureMenu(); diff --git a/core/java/com/android/internal/util/LatencyTracker.java b/core/java/com/android/internal/util/LatencyTracker.java index 555f62c53387..c7ac1895855b 100644 --- a/core/java/com/android/internal/util/LatencyTracker.java +++ b/core/java/com/android/internal/util/LatencyTracker.java @@ -15,14 +15,22 @@ package com.android.internal.util; import android.content.Context; +import android.database.ContentObserver; +import android.net.Uri; import android.os.Build; import android.os.SystemClock; import android.os.Trace; +import android.os.UserHandle; +import android.provider.Settings; import android.util.EventLog; +import android.util.KeyValueListParser; import android.util.Log; import android.util.SparseLongArray; import com.android.internal.logging.EventLogTags; +import com.android.internal.os.BackgroundThread; + +import java.util.concurrent.ThreadLocalRandom; /** * Class to track various latencies in SystemUI. It then writes the latency to statsd and also @@ -34,6 +42,12 @@ import com.android.internal.logging.EventLogTags; */ public class LatencyTracker { private static final String TAG = "LatencyTracker"; + private static final String SETTINGS_ENABLED_KEY = "enabled"; + private static final String SETTINGS_SAMPLING_INTERVAL_KEY = "sampling_interval"; + /** Default to being enabled on debug builds. */ + private static final boolean DEFAULT_ENABLED = Build.IS_DEBUGGABLE; + /** Default to collecting data for 1/5 of all actions (randomly sampled). */ + private static final int DEFAULT_SAMPLING_INTERVAL = 5; /** * Time it takes until the first frame of the notification panel to be displayed while expanding @@ -76,7 +90,7 @@ public class LatencyTracker { */ public static final int ACTION_FACE_WAKE_AND_UNLOCK = 7; - private static final String[] NAMES = new String[] { + private static final String[] NAMES = new String[]{ "expand panel", "toggle recents", "fingerprint wake-and-unlock", @@ -84,9 +98,9 @@ public class LatencyTracker { "check credential unlocked", "turn on screen", "rotate the screen", - "face wake-and-unlock" }; + "face wake-and-unlock"}; - private static final int[] STATSD_ACTION = new int[] { + private static final int[] STATSD_ACTION = new int[]{ FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_EXPAND_PANEL, FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_TOGGLE_RECENTS, FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_FINGERPRINT_WAKE_AND_UNLOCK, @@ -100,20 +114,59 @@ public class LatencyTracker { private static LatencyTracker sLatencyTracker; private final SparseLongArray mStartRtc = new SparseLongArray(); + private final Context mContext; + private volatile int mSamplingInterval; + private volatile boolean mEnabled; public static LatencyTracker getInstance(Context context) { if (sLatencyTracker == null) { - sLatencyTracker = new LatencyTracker(); + synchronized (LatencyTracker.class) { + if (sLatencyTracker == null) { + sLatencyTracker = new LatencyTracker(context); + } + } } return sLatencyTracker; } + public LatencyTracker(Context context) { + mContext = context; + mEnabled = DEFAULT_ENABLED; + mSamplingInterval = DEFAULT_SAMPLING_INTERVAL; + + // Post initialization to the background in case we're running on the main thread. + BackgroundThread.getHandler().post(this::registerSettingsObserver); + BackgroundThread.getHandler().post(this::readSettings); + } + + private void registerSettingsObserver() { + Uri settingsUri = Settings.Global.getUriFor(Settings.Global.LATENCY_TRACKER); + mContext.getContentResolver().registerContentObserver( + settingsUri, false, new SettingsObserver(this), UserHandle.myUserId()); + } + + private void readSettings() { + KeyValueListParser parser = new KeyValueListParser(','); + String settingsValue = Settings.Global.getString(mContext.getContentResolver(), + Settings.Global.LATENCY_TRACKER); + + try { + parser.setString(settingsValue); + mSamplingInterval = parser.getInt(SETTINGS_SAMPLING_INTERVAL_KEY, + DEFAULT_SAMPLING_INTERVAL); + mEnabled = parser.getBoolean(SETTINGS_ENABLED_KEY, DEFAULT_ENABLED); + } catch (IllegalArgumentException e) { + Log.e(TAG, "Incorrect settings format", e); + mEnabled = false; + } + } + public static boolean isEnabled(Context ctx) { return getInstance(ctx).isEnabled(); } public boolean isEnabled() { - return Build.IS_DEBUGGABLE; + return mEnabled; } /** @@ -145,19 +198,48 @@ public class LatencyTracker { } mStartRtc.delete(action); Trace.asyncTraceEnd(Trace.TRACE_TAG_APP, NAMES[action], 0); - logAction(action, (int)(endRtc - startRtc)); + logAction(action, (int) (endRtc - startRtc)); } /** * Logs an action that has started and ended. This needs to be called from the main thread. * - * @param action The action to end. One of the ACTION_* values. - * @param duration The duration of the action in ms. + * @param action The action to end. One of the ACTION_* values. + * @param duration The duration of the action in ms. + */ + public void logAction(int action, int duration) { + boolean shouldSample = ThreadLocalRandom.current().nextInt() % mSamplingInterval == 0; + logActionDeprecated(action, duration, shouldSample); + } + + /** + * Logs an action that has started and ended. This needs to be called from the main thread. + * + * @param action The action to end. One of the ACTION_* values. + * @param duration The duration of the action in ms. + * @param writeToStatsLog Whether to write the measured latency to FrameworkStatsLog. */ - public static void logAction(int action, int duration) { + public static void logActionDeprecated(int action, int duration, boolean writeToStatsLog) { Log.i(TAG, "action=" + action + " latency=" + duration); EventLog.writeEvent(EventLogTags.SYSUI_LATENCY, action, duration); - FrameworkStatsLog.write( - FrameworkStatsLog.UI_ACTION_LATENCY_REPORTED, STATSD_ACTION[action], duration); + + if (writeToStatsLog) { + FrameworkStatsLog.write( + FrameworkStatsLog.UI_ACTION_LATENCY_REPORTED, STATSD_ACTION[action], duration); + } + } + + private static class SettingsObserver extends ContentObserver { + private final LatencyTracker mThisTracker; + + SettingsObserver(LatencyTracker thisTracker) { + super(BackgroundThread.getHandler()); + mThisTracker = thisTracker; + } + + @Override + public void onChange(boolean selfChange, Uri uri, int userId) { + mThisTracker.readSettings(); + } } } diff --git a/core/jni/android_view_InputEventReceiver.cpp b/core/jni/android_view_InputEventReceiver.cpp index 9ed71ac0fb7b..1ea918a900ad 100644 --- a/core/jni/android_view_InputEventReceiver.cpp +++ b/core/jni/android_view_InputEventReceiver.cpp @@ -343,7 +343,7 @@ status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env, jboolean(focusEvent->getHasFocus()), jboolean(focusEvent->getInTouchMode())); finishInputEvent(seq, true /* handled */); - return OK; + continue; } default: diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index e2f4f2f9294b..0a1b8e093e71 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -4518,6 +4518,12 @@ <permission android:name="android.permission.MANAGE_NOTIFICATIONS" android:protectionLevel="signature" /> + <!-- @SystemApi @TestApi Allows adding/removing enabled notification listener components. + @hide --> + <permission android:name="android.permission.MANAGE_NOTIFICATION_LISTENERS" + android:protectionLevel="signature|installer" /> + <uses-permission android:name="android.permission.MANAGE_NOTIFICATION_LISTENERS" /> + <!-- Allows notifications to be colorized <p>Not for use by third-party applications. @hide --> <permission android:name="android.permission.USE_COLORIZED_NOTIFICATIONS" diff --git a/core/sysprop/Android.bp b/core/sysprop/Android.bp index 7f20a0ba6642..237ede2006ea 100644 --- a/core/sysprop/Android.bp +++ b/core/sysprop/Android.bp @@ -19,3 +19,11 @@ sysprop_library { api_packages: ["android.sysprop"], vendor_available: false, } + +sysprop_library { + name: "com.android.sysprop.watchdog", + srcs: ["WatchdogProperties.sysprop"], + property_owner: "Platform", + api_packages: ["android.sysprop"], + vendor_available: false, +} diff --git a/core/sysprop/WatchdogProperties.sysprop b/core/sysprop/WatchdogProperties.sysprop new file mode 100644 index 000000000000..1bcc773a9a5d --- /dev/null +++ b/core/sysprop/WatchdogProperties.sysprop @@ -0,0 +1,45 @@ +# Copyright (C) 2020 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. + +module: "android.sysprop.WatchdogProperties" +owner: Platform + +# To escape the watchdog timeout loop, fatal reboot the system when +# watchdog timed out 'fatal_count' times in 'fatal_window_second' +# seconds, if both values are not 0. Default value of both is 0. +prop { + api_name: "fatal_count" + type: Integer + prop_name: "framework_watchdog.fatal_count" + scope: Internal + access: Readonly +} + +prop { + api_name: "fatal_window_second" + type: Integer + prop_name: "framework_watchdog.fatal_window.second" + scope: Internal + access: Readonly +} + +# The fatal counting can be disabled by setting property +# 'is_fatal_ignore' to true. +prop { + api_name: "is_fatal_ignore" + type: Boolean + prop_name: "persist.debug.framework_watchdog.fatal_ignore" + scope: Internal + access: Readonly +} diff --git a/core/sysprop/api/com.android.sysprop.localization-current.txt b/core/sysprop/api/com.android.sysprop.localization-current.txt index fe4f4578683c..e69de29bb2d1 100644 --- a/core/sysprop/api/com.android.sysprop.localization-current.txt +++ b/core/sysprop/api/com.android.sysprop.localization-current.txt @@ -1,9 +0,0 @@ -props { - module: "android.sysprop.LocalizationProperties" - prop { - api_name: "locale_filter" - type: String - scope: Internal - prop_name: "ro.localization.locale_filter" - } -} diff --git a/core/sysprop/api/com.android.sysprop.watchdog-current.txt b/core/sysprop/api/com.android.sysprop.watchdog-current.txt new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/core/sysprop/api/com.android.sysprop.watchdog-current.txt diff --git a/core/sysprop/api/com.android.sysprop.watchdog-latest.txt b/core/sysprop/api/com.android.sysprop.watchdog-latest.txt new file mode 100644 index 000000000000..d901aef945c9 --- /dev/null +++ b/core/sysprop/api/com.android.sysprop.watchdog-latest.txt @@ -0,0 +1,20 @@ +props { + module: "android.sysprop.WatchdogProperties" + prop { + api_name: "fatal_count" + type: Integer + scope: Internal + prop_name: "framework_watchdog.fatal_count" + } + prop { + api_name: "fatal_window_second" + type: Integer + scope: Internal + prop_name: "framework_watchdog.fatal_window.second" + } + prop { + api_name: "is_fatal_ignore" + scope: Internal + prop_name: "persist.debug.framework_watchdog.fatal_ignore" + } +} diff --git a/core/tests/coretests/src/android/hardware/display/VirtualDisplayTest.java b/core/tests/coretests/src/android/hardware/display/VirtualDisplayTest.java index 0f6284d22d10..01cf311f63b1 100644 --- a/core/tests/coretests/src/android/hardware/display/VirtualDisplayTest.java +++ b/core/tests/coretests/src/android/hardware/display/VirtualDisplayTest.java @@ -362,14 +362,12 @@ public class VirtualDisplayTest extends AndroidTestCase { private final class TestPresentation extends Presentation { private final int mColor; - private final int mWindowType; private final int mWindowFlags; public TestPresentation(Context context, Display display, int color, int windowType, int windowFlags) { - super(context, display); + super(context, display, 0 /* theme */, windowType); mColor = color; - mWindowType = windowType; mWindowFlags = windowFlags; } @@ -378,7 +376,6 @@ public class VirtualDisplayTest extends AndroidTestCase { super.onCreate(savedInstanceState); setTitle(TAG); - getWindow().setType(mWindowType); getWindow().addFlags(mWindowFlags); // Create a solid color image to use as the content of the presentation. diff --git a/core/tests/coretests/src/android/text/format/DateFormatTest.java b/core/tests/coretests/src/android/text/format/DateFormatTest.java index a3434e885012..212cc44eefab 100644 --- a/core/tests/coretests/src/android/text/format/DateFormatTest.java +++ b/core/tests/coretests/src/android/text/format/DateFormatTest.java @@ -21,13 +21,19 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import android.compat.testing.PlatformCompatChangeRule; import android.icu.text.DateFormatSymbols; import android.platform.test.annotations.Presubmit; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges; +import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges; + +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; import org.junit.runner.RunWith; import java.util.Arrays; @@ -38,6 +44,9 @@ import java.util.Locale; @RunWith(AndroidJUnit4.class) public class DateFormatTest { + @Rule + public TestRule compatChangeRule = new PlatformCompatChangeRule(); + @Test public void testHasDesignator() { assertTrue(DateFormat.hasDesignator("hh:mm:ss", DateFormat.MINUTE)); @@ -135,4 +144,29 @@ public class DateFormatTest { private static String best(Locale l, String skeleton) { return DateFormat.getBestDateTimePattern(l, skeleton); } + + @Test + @EnableCompatChanges({DateFormat.DISALLOW_DUPLICATE_FIELD_IN_SKELETON}) + public void testGetBestDateTimePattern_disableDuplicateField() { + assertIllegalArgumentException(Locale.US, "jmma"); + assertIllegalArgumentException(Locale.US, "ahmma"); + } + + @Test + @DisableCompatChanges({DateFormat.DISALLOW_DUPLICATE_FIELD_IN_SKELETON}) + public void testGetBestDateTimePattern_enableDuplicateField() { + // en-US uses 12-hour format by default. + assertEquals("h:mm a", DateFormat.getBestDateTimePattern(Locale.US, "jmma")); + assertEquals("h:mm a", DateFormat.getBestDateTimePattern(Locale.US, "ahmma")); + } + + private static void assertIllegalArgumentException(Locale l, String skeleton) { + try { + DateFormat.getBestDateTimePattern(l, skeleton); + fail("getBestDateTimePattern() does not fail with Locale: " + l + + " skeleton: " + skeleton); + } catch (IllegalArgumentException expected) { + // ignored + } + } } diff --git a/core/tests/coretests/src/android/text/format/OWNERS b/core/tests/coretests/src/android/text/format/OWNERS new file mode 100644 index 000000000000..32adc12bb901 --- /dev/null +++ b/core/tests/coretests/src/android/text/format/OWNERS @@ -0,0 +1,3 @@ +# Inherits OWNERS from parent directory, plus the following + +vichang@google.com diff --git a/data/etc/car/Android.bp b/data/etc/car/Android.bp index e122e0026aac..745de84a3f04 100644 --- a/data/etc/car/Android.bp +++ b/data/etc/car/Android.bp @@ -149,3 +149,11 @@ prebuilt_etc { src: "com.android.car.ui.paintbooth.xml", filename_from_src: true, } + +prebuilt_etc { + name: "allowed_privapp_com.android.car.provision", + system_ext_specific: true, + sub_dir: "permissions", + src: "com.android.car.provision.xml", + filename_from_src: true, +}
\ No newline at end of file diff --git a/data/etc/car/com.android.car.provision.xml b/data/etc/car/com.android.car.provision.xml new file mode 100644 index 000000000000..fa51d55ee8a1 --- /dev/null +++ b/data/etc/car/com.android.car.provision.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2020 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 + --> +<permissions> + <privapp-permissions package="com.android.car.provision"> + <permission name="android.permission.WRITE_SECURE_SETTINGS"/> + <permission name="android.permission.WRITE_SETTINGS"/> + </privapp-permissions> +</permissions> diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java index 28d7911c771f..a191fe56b31d 100644 --- a/graphics/java/android/graphics/Paint.java +++ b/graphics/java/android/graphics/Paint.java @@ -115,6 +115,21 @@ public class Paint { Align.LEFT, Align.CENTER, Align.RIGHT }; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(flag = true, value = { + ANTI_ALIAS_FLAG, + FILTER_BITMAP_FLAG, + DITHER_FLAG, + UNDERLINE_TEXT_FLAG, + STRIKE_THRU_TEXT_FLAG, + FAKE_BOLD_TEXT_FLAG, + LINEAR_TEXT_FLAG, + SUBPIXEL_TEXT_FLAG, + EMBEDDED_BITMAP_TEXT_FLAG + }) + public @interface PaintFlag{} + /** * Paint flag that enables antialiasing when drawing. * @@ -724,7 +739,7 @@ public class Paint { * * @return the paint's flags (see enums ending in _Flag for bit masks) */ - public int getFlags() { + public @PaintFlag int getFlags() { return nGetFlags(mNativePaint); } @@ -733,7 +748,7 @@ public class Paint { * * @param flags The new flag bits for the paint */ - public void setFlags(int flags) { + public void setFlags(@PaintFlag int flags) { nSetFlags(mNativePaint, flags); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java index 84b98f9e8047..17fd16bccc4a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java @@ -276,12 +276,11 @@ public class SystemWindows { long frameNumber, ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration, SurfaceControl outSurfaceControl, InsetsState outInsetsState, - InsetsSourceControl[] outActiveControls, Point outSurfaceSize, - SurfaceControl outBLASTSurfaceControl) { + InsetsSourceControl[] outActiveControls, Point outSurfaceSize) { int res = super.relayout(window, attrs, requestedWidth, requestedHeight, viewVisibility, flags, frameNumber, outFrames, mergedConfiguration, outSurfaceControl, outInsetsState, - outActiveControls, outSurfaceSize, outBLASTSurfaceControl); + outActiveControls, outSurfaceSize); if (res != 0) { return res; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java index 3485c7ae8ecb..15fd4245a819 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java @@ -67,7 +67,6 @@ import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.pip.phone.PipMenuActivityController; import com.android.wm.shell.pip.phone.PipMotionHelper; import com.android.wm.shell.pip.phone.PipUpdateThread; -import com.android.wm.shell.pip.phone.PipUtils; import com.android.wm.shell.splitscreen.SplitScreen; import java.io.PrintWriter; @@ -281,13 +280,8 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new; mSplitScreenOptional = splitScreenOptional; mTaskOrganizer = shellTaskOrganizer; - - if (!PipUtils.hasSystemFeature(context)) { - Log.w(TAG, "Device not support PIP feature"); - } else { - mTaskOrganizer.addListener(this, TASK_LISTENER_TYPE_PIP); - displayController.addDisplayWindowListener(this); - } + mTaskOrganizer.addListener(this, TASK_LISTENER_TYPE_PIP); + displayController.addDisplayWindowListener(this); } public Handler getUpdateHandler() { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java index d191c980375c..13f5ac3edc60 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java @@ -17,11 +17,10 @@ package com.android.wm.shell.pip.phone; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; +import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE; import static com.android.wm.shell.pip.PipAnimationController.isOutPipDirection; -import android.annotation.NonNull; -import android.annotation.Nullable; import android.app.ActivityManager; import android.app.PictureInPictureParams; import android.app.RemoteAction; @@ -34,11 +33,14 @@ import android.os.Handler; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; -import android.util.Log; +import android.util.Slog; import android.view.DisplayInfo; import android.view.IPinnedStackController; import android.window.WindowContainerTransaction; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import com.android.wm.shell.WindowManagerShellWrapper; import com.android.wm.shell.common.DisplayChangeController; import com.android.wm.shell.common.DisplayController; @@ -196,7 +198,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac } } - public PipController(Context context, + protected PipController(Context context, DisplayController displayController, PipAppOpsListener pipAppOpsListener, PipBoundsHandler pipBoundsHandler, @@ -207,34 +209,13 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac PipTouchHandler pipTouchHandler, WindowManagerShellWrapper windowManagerShellWrapper ) { - mContext = context; - - if (PipUtils.hasSystemFeature(mContext)) { - initController(context, displayController, pipAppOpsListener, pipBoundsHandler, - pipBoundsState, pipMediaController, pipMenuActivityController, pipTaskOrganizer, - pipTouchHandler, windowManagerShellWrapper); - } else { - Log.w(TAG, "Device not support PIP feature"); - } - } - - private void initController(Context context, - DisplayController displayController, - PipAppOpsListener pipAppOpsListener, - PipBoundsHandler pipBoundsHandler, - @NonNull PipBoundsState pipBoundsState, - PipMediaController pipMediaController, - PipMenuActivityController pipMenuActivityController, - PipTaskOrganizer pipTaskOrganizer, - PipTouchHandler pipTouchHandler, - WindowManagerShellWrapper windowManagerShellWrapper) { - // Ensure that we are the primary user's SystemUI. final int processUser = UserManager.get(context).getUserHandle(); if (processUser != UserHandle.USER_SYSTEM) { throw new IllegalStateException("Non-primary Pip component not currently supported."); } + mContext = context; mWindowManagerShellWrapper = windowManagerShellWrapper; mDisplayController = displayController; mPipBoundsHandler = pipBoundsHandler; @@ -258,7 +239,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac mWindowManagerShellWrapper.addPinnedStackListener( new PipControllerPinnedStackListener()); } catch (RemoteException e) { - Log.e(TAG, "Failed to register pinned stack listener", e); + Slog.e(TAG, "Failed to register pinned stack listener", e); } } @@ -465,4 +446,24 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac mPipTaskOrganizer.dump(pw, innerPrefix); mPipBoundsState.dump(pw, innerPrefix); } + + /** + * Instantiates {@link PipController}, returns {@code null} if the feature not supported. + */ + @Nullable + public static PipController create(Context context, DisplayController displayController, + PipAppOpsListener pipAppOpsListener, PipBoundsHandler pipBoundsHandler, + PipBoundsState pipBoundsState, PipMediaController pipMediaController, + PipMenuActivityController pipMenuActivityController, + PipTaskOrganizer pipTaskOrganizer, PipTouchHandler pipTouchHandler, + WindowManagerShellWrapper windowManagerShellWrapper) { + if (!context.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) { + Slog.w(TAG, "Device doesn't support Pip feature"); + return null; + } + + return new PipController(context, displayController, pipAppOpsListener, pipBoundsHandler, + pipBoundsState, pipMediaController, pipMenuActivityController, + pipTaskOrganizer, pipTouchHandler, windowManagerShellWrapper); + } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipUtils.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipUtils.java index 6a58ce0d4646..bd2ba32912bc 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipUtils.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipUtils.java @@ -18,7 +18,6 @@ package com.android.wm.shell.pip.phone; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; -import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE; import android.app.ActivityTaskManager; import android.app.ActivityTaskManager.RootTaskInfo; @@ -30,7 +29,6 @@ import android.util.Log; import android.util.Pair; public class PipUtils { - private static final String TAG = "PipUtils"; /** @@ -58,14 +56,4 @@ public class PipUtils { } return new Pair<>(null, 0); } - - /** - * The util to check if device has PIP feature - * - * @param context application context - * @return true if device has PIP feature, false otherwise. - */ - public static boolean hasSystemFeature(Context context) { - return context.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE); - } } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java index 2b987e98bc7e..a282a48e8494 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java @@ -18,17 +18,18 @@ package com.android.wm.shell.pip.phone; import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE; +import static org.junit.Assert.assertNull; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.never; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.content.Context; import android.content.pm.PackageManager; import android.os.RemoteException; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; -import android.testing.TestableContext; import android.testing.TestableLooper; import com.android.wm.shell.WindowManagerShellWrapper; @@ -37,10 +38,6 @@ import com.android.wm.shell.pip.PipBoundsHandler; import com.android.wm.shell.pip.PipBoundsState; import com.android.wm.shell.pip.PipTaskOrganizer; import com.android.wm.shell.pip.PipTestCase; -import com.android.wm.shell.pip.phone.PipAppOpsListener; -import com.android.wm.shell.pip.phone.PipController; -import com.android.wm.shell.pip.phone.PipMediaController; -import com.android.wm.shell.pip.phone.PipTouchHandler; import org.junit.Before; import org.junit.Test; @@ -55,49 +52,52 @@ import org.mockito.MockitoAnnotations; @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper public class PipControllerTest extends PipTestCase { - private com.android.wm.shell.pip.phone.PipController mPipController; - private TestableContext mSpiedContext; + private PipController mPipController; - @Mock private DisplayController mMockdDisplayController; - @Mock private PackageManager mPackageManager; - @Mock private com.android.wm.shell.pip.phone.PipMenuActivityController - mMockPipMenuActivityController; + @Mock private DisplayController mMockDisplayController; + @Mock private PipMenuActivityController mMockPipMenuActivityController; @Mock private PipAppOpsListener mMockPipAppOpsListener; @Mock private PipBoundsHandler mMockPipBoundsHandler; @Mock private PipMediaController mMockPipMediaController; @Mock private PipTaskOrganizer mMockPipTaskOrganizer; @Mock private PipTouchHandler mMockPipTouchHandler; @Mock private WindowManagerShellWrapper mMockWindowManagerShellWrapper; - private PipBoundsState mPipBoundsState; + @Mock private PipBoundsState mMockPipBoundsState; @Before public void setUp() throws RemoteException { MockitoAnnotations.initMocks(this); - mPipBoundsState = new PipBoundsState(); - - mSpiedContext = spy(mContext); - - when(mPackageManager.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)).thenReturn(false); - when(mSpiedContext.getPackageManager()).thenReturn(mPackageManager); - - mPipController = new PipController(mSpiedContext, mMockdDisplayController, - mMockPipAppOpsListener, mMockPipBoundsHandler, mPipBoundsState, + mPipController = new PipController(mContext, mMockDisplayController, + mMockPipAppOpsListener, mMockPipBoundsHandler, mMockPipBoundsState, mMockPipMediaController, mMockPipMenuActivityController, mMockPipTaskOrganizer, mMockPipTouchHandler, mMockWindowManagerShellWrapper); } @Test - public void testNonPipDevice_shouldNotRegisterPipTransitionCallback() { - verify(mMockPipTaskOrganizer, never()).registerPipTransitionCallback(any()); + public void instantiatePipController_registersPipTransitionCallback() { + verify(mMockPipTaskOrganizer).registerPipTransitionCallback(any()); + } + + @Test + public void instantiatePipController_addsDisplayChangingController() { + verify(mMockDisplayController).addDisplayChangingController(any()); } @Test - public void testNonPipDevice_shouldNotAddDisplayChangingController() { - verify(mMockdDisplayController, never()).addDisplayChangingController(any()); + public void instantiatePipController_addsDisplayWindowListener() { + verify(mMockDisplayController).addDisplayWindowListener(any()); } @Test - public void testNonPipDevice_shouldNotAddDisplayWindowListener() { - verify(mMockdDisplayController, never()).addDisplayWindowListener(any()); + public void createPip_notSupported_returnsNull() { + Context spyContext = spy(mContext); + PackageManager mockPackageManager = mock(PackageManager.class); + when(mockPackageManager.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)).thenReturn(false); + when(spyContext.getPackageManager()).thenReturn(mockPackageManager); + + assertNull(PipController.create(spyContext, mMockDisplayController, + mMockPipAppOpsListener, mMockPipBoundsHandler, mMockPipBoundsState, + mMockPipMediaController, mMockPipMenuActivityController, mMockPipTaskOrganizer, + mMockPipTouchHandler, mMockWindowManagerShellWrapper)); } } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTaskOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTaskOrganizerTest.java index 37b93bcdd051..46ebbf3846df 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTaskOrganizerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipTaskOrganizerTest.java @@ -16,20 +16,13 @@ package com.android.wm.shell.pip.phone; -import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE; - import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; -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.content.pm.PackageManager; import android.os.RemoteException; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; -import android.testing.TestableContext; import android.testing.TestableLooper; import com.android.wm.shell.ShellTaskOrganizer; @@ -58,39 +51,30 @@ import java.util.Optional; @TestableLooper.RunWithLooper public class PipTaskOrganizerTest extends PipTestCase { private PipTaskOrganizer mSpiedPipTaskOrganizer; - private TestableContext mSpiedContext; @Mock private DisplayController mMockdDisplayController; - @Mock private PackageManager mPackageManager; @Mock private PipBoundsHandler mMockPipBoundsHandler; @Mock private PipSurfaceTransactionHelper mMockPipSurfaceTransactionHelper; @Mock private PipUiEventLogger mMockPipUiEventLogger; @Mock private Optional<SplitScreen> mMockOptionalSplitScreen; @Mock private ShellTaskOrganizer mMockShellTaskOrganizer; - private PipBoundsState mPipBoundsState; + @Mock private PipBoundsState mMockPipBoundsState; @Before public void setUp() throws RemoteException { MockitoAnnotations.initMocks(this); - mPipBoundsState = new PipBoundsState(); - - mSpiedContext = spy(mContext); - - when(mPackageManager.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)).thenReturn(false); - when(mSpiedContext.getPackageManager()).thenReturn(mPackageManager); - - mSpiedPipTaskOrganizer = spy(new PipTaskOrganizer(mSpiedContext, mPipBoundsState, + mSpiedPipTaskOrganizer = new PipTaskOrganizer(mContext, mMockPipBoundsState, mMockPipBoundsHandler, mMockPipSurfaceTransactionHelper, mMockOptionalSplitScreen, - mMockdDisplayController, mMockPipUiEventLogger, mMockShellTaskOrganizer)); + mMockdDisplayController, mMockPipUiEventLogger, mMockShellTaskOrganizer); } @Test - public void testNonPipDevice_shellTaskOrganizer_shouldNotAddListener() { - verify(mMockShellTaskOrganizer, never()).addListener(any(), anyInt()); + public void instantiatePipTaskOrganizer_addsTaskListener() { + verify(mMockShellTaskOrganizer).addListener(any(), anyInt()); } @Test - public void testNonPipDevice_displayController_shouldNotAddDisplayWindowListener() { - verify(mMockdDisplayController, never()).addDisplayWindowListener(any()); + public void instantiatePipTaskOrganizer_addsDisplayWindowListener() { + verify(mMockdDisplayController).addDisplayWindowListener(any()); } } diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp index 212a4284a824..ad6363b4452d 100644 --- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp @@ -29,7 +29,7 @@ #include <SkSurface.h> #include <SkTypes.h> -#include <GrContext.h> +#include <GrDirectContext.h> #include <GrTypes.h> #include <vk/GrVkTypes.h> diff --git a/location/java/android/location/LocationRequest.java b/location/java/android/location/LocationRequest.java index e03643c4c632..4977c2161be9 100644 --- a/location/java/android/location/LocationRequest.java +++ b/location/java/android/location/LocationRequest.java @@ -21,6 +21,7 @@ import static java.lang.Math.min; import android.Manifest; import android.annotation.FloatRange; +import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; @@ -38,6 +39,8 @@ import android.util.TimeUtils; import com.android.internal.util.Preconditions; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.Objects; @@ -65,16 +68,41 @@ public final class LocationRequest implements Parcelable { */ public static final long PASSIVE_INTERVAL = Long.MAX_VALUE; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({QUALITY_LOW_POWER, QUALITY_BALANCED_POWER_ACCURACY, QUALITY_HIGH_ACCURACY}) + public @interface Quality {} + + /** + * A quality constant indicating a location provider may choose to satisfy this request by + * providing very accurate locations at the expense of potentially increased power usage. + */ + public static final int QUALITY_HIGH_ACCURACY = 100; + + /** + * A quality constant indicating a location provider may choose to satisfy this request by + * equally balancing power and accuracy constraints. + */ + public static final int QUALITY_BALANCED_POWER_ACCURACY = 102; + + /** + * A quality constant indicating a location provider may choose to satisfy this request by + * providing less accurate locations in order to save power. + */ + public static final int QUALITY_LOW_POWER = 104; + /** * Used with {@link #setQuality} to request the most accurate locations available. * * <p>This may be up to 1 meter accuracy, although this is implementation dependent. * * @hide + * @deprecated Use {@link #QUALITY_HIGH_ACCURACY} instead. */ + @Deprecated @SystemApi @TestApi - public static final int ACCURACY_FINE = 100; + public static final int ACCURACY_FINE = QUALITY_HIGH_ACCURACY; /** * Used with {@link #setQuality} to request "block" level accuracy. @@ -84,10 +112,12 @@ public final class LocationRequest implements Parcelable { * such as this often consumes less power. * * @hide + * @deprecated Use {@link #QUALITY_BALANCED_POWER_ACCURACY} instead. */ + @Deprecated @SystemApi @TestApi - public static final int ACCURACY_BLOCK = 102; + public static final int ACCURACY_BLOCK = QUALITY_BALANCED_POWER_ACCURACY; /** * Used with {@link #setQuality} to request "city" level accuracy. @@ -97,10 +127,12 @@ public final class LocationRequest implements Parcelable { * such as this often consumes less power. * * @hide + * @deprecated Use {@link #QUALITY_LOW_POWER} instead. */ + @Deprecated @SystemApi @TestApi - public static final int ACCURACY_CITY = 104; + public static final int ACCURACY_CITY = QUALITY_LOW_POWER; /** * Used with {@link #setQuality} to require no direct power impact (passive locations). @@ -123,7 +155,9 @@ public final class LocationRequest implements Parcelable { * possible. * * @hide + * @deprecated Use {@link #QUALITY_LOW_POWER} instead. */ + @Deprecated @SystemApi @TestApi public static final int POWER_LOW = 201; @@ -134,7 +168,9 @@ public final class LocationRequest implements Parcelable { * <p>This location request will allow high power location work. * * @hide + * @deprecated Use {@link #QUALITY_HIGH_ACCURACY} instead. */ + @Deprecated @SystemApi @TestApi public static final int POWER_HIGH = 203; @@ -144,7 +180,7 @@ public final class LocationRequest implements Parcelable { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "Use {@link " + "LocationManager} methods to provide the provider explicitly.") @Nullable private String mProvider; - private int mQuality; + private @Quality int mQuality; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "Use {@link " + "LocationRequest} instead.") private long mInterval; @@ -168,7 +204,7 @@ public final class LocationRequest implements Parcelable { public static LocationRequest create() { // 60 minutes is the default legacy interval return new LocationRequest.Builder(60 * 60 * 1000) - .setQuality(POWER_LOW) + .setQuality(QUALITY_LOW_POWER) .build(); } @@ -241,7 +277,7 @@ public final class LocationRequest implements Parcelable { private LocationRequest( @Nullable String provider, long intervalMillis, - int quality, + @Quality int quality, long expireAtRealtimeMillis, long durationMillis, int maxUpdates, @@ -251,9 +287,6 @@ public final class LocationRequest implements Parcelable { boolean locationSettingsIgnored, boolean lowPower, WorkSource workSource) { - Preconditions.checkArgument(intervalMillis != PASSIVE_INTERVAL || quality == POWER_NONE); - Preconditions.checkArgument(minUpdateIntervalMillis <= intervalMillis); - mProvider = provider; mInterval = intervalMillis; mQuality = quality; @@ -297,24 +330,39 @@ public final class LocationRequest implements Parcelable { @SystemApi @Deprecated public @NonNull LocationRequest setQuality(int quality) { - mQuality = Builder.checkQuality(quality, true); + switch (quality) { + case POWER_HIGH: + // fall through + case ACCURACY_FINE: + mQuality = QUALITY_HIGH_ACCURACY; + break; + case ACCURACY_BLOCK: + mQuality = QUALITY_BALANCED_POWER_ACCURACY; + break; + case POWER_LOW: + // fall through + case ACCURACY_CITY: + mQuality = QUALITY_LOW_POWER; + break; + case POWER_NONE: + mInterval = PASSIVE_INTERVAL; + break; + default: + throw new IllegalArgumentException("invalid quality: " + quality); + } + return this; } /** - * Returns the quality of the location request. - * - * @return the quality of the location request + * Returns the quality hint for this location request. The quality hint informs the provider how + * it should attempt to manage any accuracy vs power tradeoffs while attempting to satisfy this + * location request. * - * @hide + * @return the desired quality tradeoffs between accuracy and power */ - @SystemApi - public int getQuality() { - if (mInterval == PASSIVE_INTERVAL) { - return POWER_NONE; - } else { - return mQuality; - } + public @Quality int getQuality() { + return mQuality; } /** @@ -749,97 +797,65 @@ public final class LocationRequest implements Parcelable { if (mProvider != null) { s.append(mProvider).append(" "); } - if (mQuality != POWER_NONE && mQuality != ACCURACY_BLOCK) { - s.append(qualityToString(mQuality)).append(" "); - } if (mInterval != PASSIVE_INTERVAL) { s.append("@"); TimeUtils.formatDuration(mInterval, s); + + switch (mQuality) { + case QUALITY_HIGH_ACCURACY: + s.append(" HIGH_ACCURACY"); + break; + case QUALITY_BALANCED_POWER_ACCURACY: + s.append(" BALANCED"); + break; + case QUALITY_LOW_POWER: + s.append(" LOW_POWER"); + break; + } } else { s.append("PASSIVE"); } if (mExpireAtRealtimeMillis != Long.MAX_VALUE) { - s.append(" expireAt=").append(TimeUtils.formatRealtime(mExpireAtRealtimeMillis)); + s.append(", expireAt=").append(TimeUtils.formatRealtime(mExpireAtRealtimeMillis)); } if (mDurationMillis != Long.MAX_VALUE) { - s.append(" duration="); + s.append(", duration="); TimeUtils.formatDuration(mDurationMillis, s); } if (mMaxUpdates != Integer.MAX_VALUE) { - s.append(" maxUpdates=").append(mMaxUpdates); + s.append(", maxUpdates=").append(mMaxUpdates); } if (mMinUpdateIntervalMillis != IMPLICIT_MIN_UPDATE_INTERVAL && mMinUpdateIntervalMillis < mInterval) { - s.append(" minUpdateInterval="); + s.append(", minUpdateInterval="); TimeUtils.formatDuration(mMinUpdateIntervalMillis, s); } if (mMinUpdateDistanceMeters > 0.0) { - s.append(" minUpdateDistance=").append(mMinUpdateDistanceMeters); + s.append(", minUpdateDistance=").append(mMinUpdateDistanceMeters); } if (mLowPower) { - s.append(" lowPower"); + s.append(", lowPower"); } if (mHideFromAppOps) { - s.append(" hiddenFromAppOps"); + s.append(", hiddenFromAppOps"); } if (mLocationSettingsIgnored) { - s.append(" locationSettingsIgnored"); + s.append(", locationSettingsIgnored"); } - if (mWorkSource != null) { - s.append(" ").append(mWorkSource); + if (mWorkSource != null && !mWorkSource.isEmpty()) { + s.append(", ").append(mWorkSource); } s.append(']'); return s.toString(); } - private static String qualityToString(int quality) { - switch (quality) { - case ACCURACY_FINE: - return "ACCURACY_FINE"; - case ACCURACY_BLOCK: - return "ACCURACY_BLOCK"; - case ACCURACY_CITY: - return "ACCURACY_CITY"; - case POWER_NONE: - return "POWER_NONE"; - case POWER_LOW: - return "POWER_LOW"; - case POWER_HIGH: - return "POWER_HIGH"; - default: - return "???"; - } - } - /** * A builder class for {@link LocationRequest}. */ public static final class Builder { - private static int checkQuality(int quality, boolean allowDeprecated) { - switch (quality) { - case ACCURACY_FINE: - // fall through - case ACCURACY_BLOCK: - // fall through - case ACCURACY_CITY: - // fall through - case POWER_LOW: - // fall through - case POWER_HIGH: - return quality; - case POWER_NONE: - if (allowDeprecated) { - return quality; - } - // fall through - default: - throw new IllegalArgumentException("invalid quality: " + quality); - } - } - private long mIntervalMillis; - private int mQuality; + private @Quality int mQuality; private long mDurationMillis; private int mMaxUpdates; private long mMinUpdateIntervalMillis; @@ -857,7 +873,7 @@ public final class LocationRequest implements Parcelable { // gives us a range check setIntervalMillis(intervalMillis); - mQuality = ACCURACY_BLOCK; + mQuality = QUALITY_BALANCED_POWER_ACCURACY; mDurationMillis = Long.MAX_VALUE; mMaxUpdates = Integer.MAX_VALUE; mMinUpdateIntervalMillis = IMPLICIT_MIN_UPDATE_INTERVAL; @@ -885,9 +901,6 @@ public final class LocationRequest implements Parcelable { // handle edge cases that can only happen with location request that has been modified // by deprecated SystemApi methods - if (mQuality == POWER_NONE) { - mIntervalMillis = PASSIVE_INTERVAL; - } if (mIntervalMillis == PASSIVE_INTERVAL && mMinUpdateIntervalMillis == IMPLICIT_MIN_UPDATE_INTERVAL) { // this is the legacy default minimum update interval, so if we're forced to @@ -914,11 +927,17 @@ public final class LocationRequest implements Parcelable { } /** - * @hide + * Sets the request quality. The quality is a hint to providers on how they should weigh + * power vs accuracy tradeoffs. High accuracy locations may cost more power to produce, and + * lower accuracy locations may cost less power to produce. Defaults to + * {@link #QUALITY_BALANCED_POWER_ACCURACY}. */ - @SystemApi - public @NonNull Builder setQuality(int quality) { - mQuality = checkQuality(quality, false); + public @NonNull Builder setQuality(@Quality int quality) { + Preconditions.checkArgument( + quality == QUALITY_LOW_POWER || quality == QUALITY_BALANCED_POWER_ACCURACY + || quality == QUALITY_HIGH_ACCURACY, + "quality must be a defined QUALITY constant, not " + quality); + mQuality = quality; return this; } @@ -1102,7 +1121,7 @@ public final class LocationRequest implements Parcelable { return new LocationRequest( null, mIntervalMillis, - mIntervalMillis != PASSIVE_INTERVAL ? mQuality : POWER_NONE, + mQuality, Long.MAX_VALUE, mDurationMillis, mMaxUpdates, diff --git a/location/java/com/android/internal/location/ProviderRequest.java b/location/java/com/android/internal/location/ProviderRequest.java index fee86ceb453a..00ba5523b8d4 100644 --- a/location/java/com/android/internal/location/ProviderRequest.java +++ b/location/java/com/android/internal/location/ProviderRequest.java @@ -16,10 +16,15 @@ package com.android.internal.location; +import static android.location.LocationRequest.QUALITY_BALANCED_POWER_ACCURACY; +import static android.location.LocationRequest.QUALITY_HIGH_ACCURACY; +import static android.location.LocationRequest.QUALITY_LOW_POWER; + import android.annotation.IntRange; import android.annotation.NonNull; import android.compat.annotation.UnsupportedAppUsage; import android.location.LocationRequest; +import android.location.LocationRequest.Quality; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; @@ -41,7 +46,7 @@ public final class ProviderRequest implements Parcelable { public static final long INTERVAL_DISABLED = Long.MAX_VALUE; public static final ProviderRequest EMPTY_REQUEST = new ProviderRequest( - INTERVAL_DISABLED, false, false, Collections.emptyList(), new WorkSource()); + INTERVAL_DISABLED, QUALITY_BALANCED_POWER_ACCURACY, false, false, new WorkSource()); @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "{@link " + "ProviderRequest}") @@ -49,6 +54,7 @@ public final class ProviderRequest implements Parcelable { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "{@link " + "ProviderRequest}") public final long interval; + private final @Quality int mQuality; private final boolean mLowPower; private final boolean mLocationSettingsIgnored; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "{@link " @@ -56,15 +62,24 @@ public final class ProviderRequest implements Parcelable { public final List<LocationRequest> locationRequests; private final WorkSource mWorkSource; - private ProviderRequest(long intervalMillis, boolean lowPower, - boolean locationSettingsIgnored, @NonNull List<LocationRequest> locationRequests, - @NonNull WorkSource workSource) { + private ProviderRequest(long intervalMillis, @Quality int quality, boolean lowPower, + boolean locationSettingsIgnored, @NonNull WorkSource workSource) { reportLocation = intervalMillis != INTERVAL_DISABLED; interval = intervalMillis; + mQuality = quality; mLowPower = lowPower; mLocationSettingsIgnored = locationSettingsIgnored; - this.locationRequests = locationRequests; - mWorkSource = workSource; + if (intervalMillis != INTERVAL_DISABLED) { + locationRequests = Collections.singletonList(new LocationRequest.Builder(intervalMillis) + .setQuality(quality) + .setLowPower(lowPower) + .setLocationSettingsIgnored(locationSettingsIgnored) + .setWorkSource(workSource) + .build()); + } else { + locationRequests = Collections.emptyList(); + } + mWorkSource = Objects.requireNonNull(workSource); } /** @@ -84,6 +99,15 @@ public final class ProviderRequest implements Parcelable { } /** + * The quality hint for this location request. The quality hint informs the provider how it + * should attempt to manage any accuracy vs power tradeoffs while attempting to satisfy this + * provider request. + */ + public @Quality int getQuality() { + return mQuality; + } + + /** * Whether any applicable hardware low power modes should be used to satisfy this request. */ public boolean isLowPower() { @@ -100,13 +124,6 @@ public final class ProviderRequest implements Parcelable { } /** - * The full list of location requests contributing to this provider request. - */ - public @NonNull List<LocationRequest> getLocationRequests() { - return locationRequests; - } - - /** * The power blame for this provider request. */ public @NonNull WorkSource getWorkSource() { @@ -117,13 +134,17 @@ public final class ProviderRequest implements Parcelable { new Parcelable.Creator<ProviderRequest>() { @Override public ProviderRequest createFromParcel(Parcel in) { - return new ProviderRequest( - /* intervalMillis= */ in.readLong(), - /* lowPower= */ in.readBoolean(), - /* locationSettingsIgnored= */ in.readBoolean(), - /* locationRequests= */ - in.createTypedArrayList(LocationRequest.CREATOR), - /* workSource= */ in.readTypedObject(WorkSource.CREATOR)); + long intervalMillis = in.readLong(); + if (intervalMillis == INTERVAL_DISABLED) { + return EMPTY_REQUEST; + } else { + return new ProviderRequest( + intervalMillis, + /* quality= */ in.readInt(), + /* lowPower= */ in.readBoolean(), + /* locationSettingsIgnored= */ in.readBoolean(), + /* workSource= */ in.readTypedObject(WorkSource.CREATOR)); + } } @Override @@ -140,10 +161,12 @@ public final class ProviderRequest implements Parcelable { @Override public void writeToParcel(Parcel parcel, int flags) { parcel.writeLong(interval); - parcel.writeBoolean(mLowPower); - parcel.writeBoolean(mLocationSettingsIgnored); - parcel.writeTypedList(locationRequests); - parcel.writeTypedObject(mWorkSource, flags); + if (interval != INTERVAL_DISABLED) { + parcel.writeInt(mQuality); + parcel.writeBoolean(mLowPower); + parcel.writeBoolean(mLocationSettingsIgnored); + parcel.writeTypedObject(mWorkSource, flags); + } } @Override @@ -160,16 +183,16 @@ public final class ProviderRequest implements Parcelable { return that.interval == INTERVAL_DISABLED; } else { return interval == that.interval + && mQuality == that.mQuality && mLowPower == that.mLowPower && mLocationSettingsIgnored == that.mLocationSettingsIgnored - && locationRequests.equals(that.locationRequests) && mWorkSource.equals(that.mWorkSource); } } @Override public int hashCode() { - return Objects.hash(interval, mWorkSource); + return Objects.hash(interval, mQuality, mWorkSource); } @Override @@ -179,6 +202,13 @@ public final class ProviderRequest implements Parcelable { if (interval != INTERVAL_DISABLED) { s.append("@"); TimeUtils.formatDuration(interval, s); + if (mQuality != QUALITY_BALANCED_POWER_ACCURACY) { + if (mQuality == QUALITY_HIGH_ACCURACY) { + s.append(", HIGH_ACCURACY"); + } else if (mQuality == QUALITY_LOW_POWER) { + s.append(", LOW_POWER"); + } + } if (mLowPower) { s.append(", lowPower"); } @@ -200,9 +230,9 @@ public final class ProviderRequest implements Parcelable { */ public static class Builder { private long mIntervalMillis = INTERVAL_DISABLED; + private int mQuality = QUALITY_BALANCED_POWER_ACCURACY; private boolean mLowPower; private boolean mLocationSettingsIgnored; - private List<LocationRequest> mLocationRequests = Collections.emptyList(); private WorkSource mWorkSource = new WorkSource(); /** @@ -216,6 +246,20 @@ public final class ProviderRequest implements Parcelable { } /** + * Sets the request quality. The quality is a hint to providers on how they should weigh + * power vs accuracy tradeoffs. High accuracy locations may cost more power to produce, and + * lower accuracy locations may cost less power to produce. Defaults to + * {@link LocationRequest#QUALITY_BALANCED_POWER_ACCURACY}. + */ + public @NonNull Builder setQuality(@Quality int quality) { + Preconditions.checkArgument( + quality == QUALITY_LOW_POWER || quality == QUALITY_BALANCED_POWER_ACCURACY + || quality == QUALITY_HIGH_ACCURACY); + mQuality = quality; + return this; + } + + /** * Sets whether hardware low power mode should be used. False by default. */ public @NonNull Builder setLowPower(boolean lowPower) { @@ -232,15 +276,6 @@ public final class ProviderRequest implements Parcelable { } /** - * Sets the {@link LocationRequest}s associated with this request. Empty by default. - */ - public @NonNull Builder setLocationRequests( - @NonNull List<LocationRequest> locationRequests) { - this.mLocationRequests = Objects.requireNonNull(locationRequests); - return this; - } - - /** * Sets the work source for power blame. Empty by default. */ public @NonNull Builder setWorkSource(@NonNull WorkSource workSource) { @@ -255,8 +290,8 @@ public final class ProviderRequest implements Parcelable { if (mIntervalMillis == INTERVAL_DISABLED) { return EMPTY_REQUEST; } else { - return new ProviderRequest(mIntervalMillis, mLowPower, mLocationSettingsIgnored, - mLocationRequests, mWorkSource); + return new ProviderRequest(mIntervalMillis, mQuality, mLowPower, + mLocationSettingsIgnored, mWorkSource); } } } diff --git a/location/lib/api/current.txt b/location/lib/api/current.txt index f43eb639ee23..80636c665a1a 100644 --- a/location/lib/api/current.txt +++ b/location/lib/api/current.txt @@ -29,18 +29,18 @@ package com.android.location.provider { field public static final String FUSED_PROVIDER = "fused"; } - public final class LocationRequestUnbundled { - method public long getFastestInterval(); - method public long getInterval(); - method public int getQuality(); - method public float getSmallestDisplacement(); - method public boolean isLocationSettingsIgnored(); - field public static final int ACCURACY_BLOCK = 102; // 0x66 - field public static final int ACCURACY_CITY = 104; // 0x68 - field public static final int ACCURACY_FINE = 100; // 0x64 - field public static final int POWER_HIGH = 203; // 0xcb - field public static final int POWER_LOW = 201; // 0xc9 - field public static final int POWER_NONE = 200; // 0xc8 + @Deprecated public final class LocationRequestUnbundled { + method @Deprecated public long getFastestInterval(); + method @Deprecated public long getInterval(); + method @Deprecated @android.location.LocationRequest.Quality public int getQuality(); + method @Deprecated public float getSmallestDisplacement(); + method @Deprecated public boolean isLocationSettingsIgnored(); + field @Deprecated public static final int ACCURACY_BLOCK = 102; // 0x66 + field @Deprecated public static final int ACCURACY_CITY = 104; // 0x68 + field @Deprecated public static final int ACCURACY_FINE = 100; // 0x64 + field @Deprecated public static final int POWER_HIGH = 203; // 0xcb + field @Deprecated public static final int POWER_LOW = 201; // 0xc9 + field @Deprecated public static final int POWER_NONE = 200; // 0xc8 } public final class ProviderPropertiesUnbundled { @@ -49,7 +49,8 @@ package com.android.location.provider { public final class ProviderRequestUnbundled { method public long getInterval(); - method @NonNull public java.util.List<com.android.location.provider.LocationRequestUnbundled> getLocationRequests(); + method @Deprecated @NonNull public java.util.List<com.android.location.provider.LocationRequestUnbundled> getLocationRequests(); + method @android.location.LocationRequest.Quality @RequiresApi(android.os.Build.VERSION_CODES.S) public int getQuality(); method public boolean getReportLocation(); method @NonNull @RequiresApi(android.os.Build.VERSION_CODES.S) public android.os.WorkSource getWorkSource(); method @RequiresApi(android.os.Build.VERSION_CODES.Q) public boolean isLocationSettingsIgnored(); diff --git a/location/lib/java/com/android/location/provider/LocationRequestUnbundled.java b/location/lib/java/com/android/location/provider/LocationRequestUnbundled.java index 92e05ef68e3b..0e7c633eb5fb 100644 --- a/location/lib/java/com/android/location/provider/LocationRequestUnbundled.java +++ b/location/lib/java/com/android/location/provider/LocationRequestUnbundled.java @@ -17,6 +17,7 @@ package com.android.location.provider; import android.location.LocationRequest; +import android.location.LocationRequest.Quality; /** * This class is an interface to LocationRequests for unbundled applications. @@ -24,55 +25,50 @@ import android.location.LocationRequest; * <p>IMPORTANT: This class is effectively a public API for unbundled * applications, and must remain API stable. See README.txt in the root * of this package for more information. + * + * @deprecated Do not use. */ +@Deprecated public final class LocationRequestUnbundled { + /** - * Returned by {@link #getQuality} when requesting the most accurate locations available. - * - * <p>This may be up to 1 meter accuracy, although this is implementation dependent. + * @deprecated Use {@link LocationRequest#QUALITY_HIGH_ACCURACY} instead. */ + @Deprecated public static final int ACCURACY_FINE = LocationRequest.ACCURACY_FINE; /** - * Returned by {@link #getQuality} when requesting "block" level accuracy. - * - * <p>Block level accuracy is considered to be about 100 meter accuracy, - * although this is implementation dependent. Using a coarse accuracy - * such as this often consumes less power. + * @deprecated Use {@link LocationRequest#QUALITY_BALANCED_POWER_ACCURACY} instead. */ + @Deprecated public static final int ACCURACY_BLOCK = LocationRequest.ACCURACY_BLOCK; + /** - * Returned by {@link #getQuality} when requesting "city" level accuracy. - * - * <p>City level accuracy is considered to be about 10km accuracy, - * although this is implementation dependent. Using a coarse accuracy - * such as this often consumes less power. + * @deprecated Use {@link LocationRequest#QUALITY_LOW_POWER} instead. */ + @Deprecated public static final int ACCURACY_CITY = LocationRequest.ACCURACY_CITY; + /** - * Returned by {@link #getQuality} when requiring no direct power impact (passive locations). - * - * <p>This location request will not trigger any active location requests, - * but will receive locations triggered by other applications. Your application - * will not receive any direct power blame for location work. + * @deprecated Do not use. */ + @Deprecated public static final int POWER_NONE = LocationRequest.POWER_NONE; + /** - * Returned by {@link #getQuality} when requesting low power impact. - * - * <p>This location request will avoid high power location work where - * possible. + * @deprecated Use {@link LocationRequest#QUALITY_LOW_POWER} instead. */ + @Deprecated public static final int POWER_LOW = LocationRequest.POWER_LOW; + /** - * Returned by {@link #getQuality} when allowing high power consumption for location. - * - * <p>This location request will allow high power location work. + * @deprecated Use {@link LocationRequest#QUALITY_BALANCED_POWER_ACCURACY} instead. */ + @Deprecated public static final int POWER_HIGH = LocationRequest.POWER_HIGH; private final LocationRequest delegate; @@ -102,9 +98,9 @@ public final class LocationRequestUnbundled { /** * Get the quality of the request. * - * @return an accuracy or power constant + * @return a {@link LocationRequest} QUALITY_* constant */ - public int getQuality() { + public @Quality int getQuality() { return delegate.getQuality(); } diff --git a/location/lib/java/com/android/location/provider/ProviderRequestUnbundled.java b/location/lib/java/com/android/location/provider/ProviderRequestUnbundled.java index 6f5fcc7bfc8e..f7bac74bf92d 100644 --- a/location/lib/java/com/android/location/provider/ProviderRequestUnbundled.java +++ b/location/lib/java/com/android/location/provider/ProviderRequestUnbundled.java @@ -25,7 +25,7 @@ import androidx.annotation.RequiresApi; import com.android.internal.location.ProviderRequest; -import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** @@ -57,6 +57,16 @@ public final class ProviderRequestUnbundled { } /** + * The quality hint for this location request. The quality hint informs the provider how it + * should attempt to manage any accuracy vs power tradeoffs while attempting to satisfy this + * provider request. + */ + @RequiresApi(Build.VERSION_CODES.S) + public @LocationRequest.Quality int getQuality() { + return mRequest.getQuality(); + } + + /** * The interval at which a provider should report location. Will return * {@link #INTERVAL_DISABLED} for an inactive request. */ @@ -84,14 +94,22 @@ public final class ProviderRequestUnbundled { /** * The full list of location requests contributing to this provider request. + * + * @deprecated Do not use. */ + @Deprecated public @NonNull List<LocationRequestUnbundled> getLocationRequests() { - List<LocationRequestUnbundled> result = new ArrayList<>( - mRequest.getLocationRequests().size()); - for (LocationRequest r : mRequest.getLocationRequests()) { - result.add(new LocationRequestUnbundled(r)); + if (!mRequest.isActive()) { + return Collections.emptyList(); } - return result; + + return Collections.singletonList(new LocationRequestUnbundled( + new LocationRequest.Builder(mRequest.getIntervalMillis()) + .setQuality(mRequest.getQuality()) + .setLowPower(mRequest.isLowPower()) + .setLocationSettingsIgnored(mRequest.isLocationSettingsIgnored()) + .setWorkSource(mRequest.getWorkSource()) + .build())); } /** diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java index de2a7b2c15e3..fa6a4ff5af67 100644 --- a/media/java/android/media/AudioTrack.java +++ b/media/java/android/media/AudioTrack.java @@ -1263,14 +1263,20 @@ public class AudioTrack extends PlayerBase // TODO: Check mEncapsulationMode compatibility with MODE_STATIC, etc? - try { - // If the buffer size is not specified in streaming mode, - // use a single frame for the buffer size and let the - // native code figure out the minimum buffer size. - if (mMode == MODE_STREAM && mBufferSizeInBytes == 0) { - mBufferSizeInBytes = mFormat.getChannelCount() - * mFormat.getBytesPerSample(mFormat.getEncoding()); + // If the buffer size is not specified in streaming mode, + // use a single frame for the buffer size and let the + // native code figure out the minimum buffer size. + if (mMode == MODE_STREAM && mBufferSizeInBytes == 0) { + int bytesPerSample = 1; + try { + bytesPerSample = mFormat.getBytesPerSample(mFormat.getEncoding()); + } catch (IllegalArgumentException e) { + // do nothing } + mBufferSizeInBytes = mFormat.getChannelCount() * bytesPerSample; + } + + try { final AudioTrack track = new AudioTrack( mAttributes, mFormat, mBufferSizeInBytes, mMode, mSessionId, mOffload, mEncapsulationMode, mTunerConfiguration); diff --git a/media/java/android/media/MediaTranscodeManager.java b/media/java/android/media/MediaTranscodeManager.java index 8cbe52f7c481..8676462c5c54 100644 --- a/media/java/android/media/MediaTranscodeManager.java +++ b/media/java/android/media/MediaTranscodeManager.java @@ -443,7 +443,7 @@ public final class MediaTranscodeManager { } @Override - public void onAwaitNumberOfJobsChanged(int jobId, int oldAwaitNumber, + public void onAwaitNumberOfSessionsChanged(int jobId, int oldAwaitNumber, int newAwaitNumber) throws RemoteException { //TODO(hkuang): Implement this. } @@ -1081,7 +1081,7 @@ public final class MediaTranscodeManager { private final MediaTranscodeManager mManager; private Executor mListenerExecutor; private OnTranscodingFinishedListener mListener; - private int mJobId = -1; + private int mSessionId = -1; // Lock for internal state. private final Object mLock = new Object(); @GuardedBy("mLock") @@ -1104,7 +1104,7 @@ public final class MediaTranscodeManager { private TranscodingJob( @NonNull MediaTranscodeManager manager, @NonNull TranscodingRequest request, - @NonNull TranscodingJobParcel parcel, + @NonNull TranscodingSessionParcel parcel, @NonNull @CallbackExecutor Executor executor, @NonNull OnTranscodingFinishedListener listener) { Objects.requireNonNull(manager, "manager must not be null"); @@ -1112,7 +1112,7 @@ public final class MediaTranscodeManager { Objects.requireNonNull(executor, "listenerExecutor must not be null"); Objects.requireNonNull(listener, "listener must not be null"); mManager = manager; - mJobId = parcel.jobId; + mSessionId = parcel.sessionId; mListenerExecutor = executor; mListener = listener; mRequest = request; @@ -1196,16 +1196,16 @@ public final class MediaTranscodeManager { synchronized (mManager.mPendingTranscodingJobs) { try { // Submits the request to MediaTranscoding service. - TranscodingJobParcel jobParcel = new TranscodingJobParcel(); - if (!client.submitRequest(mRequest.writeToParcel(), jobParcel)) { + TranscodingSessionParcel sessionParcel = new TranscodingSessionParcel(); + if (!client.submitRequest(mRequest.writeToParcel(), sessionParcel)) { mHasRetried = true; throw new UnsupportedOperationException("Failed to enqueue request"); } // Replace the old job id wit the new one. - mJobId = jobParcel.jobId; + mSessionId = sessionParcel.sessionId; // Adds the new job back into pending jobs. - mManager.mPendingTranscodingJobs.put(mJobId, this); + mManager.mPendingTranscodingJobs.put(mSessionId, this); } catch (RemoteException re) { throw new MediaTranscodingException.ServiceNotAvailableException( "Failed to resubmit request to Transcoding service"); @@ -1229,7 +1229,7 @@ public final class MediaTranscodeManager { ITranscodingClient client = mManager.getTranscodingClient(); // The client may be gone. if (client != null) { - client.cancelJob(mJobId); + client.cancelSession(mSessionId); } } catch (RemoteException re) { //TODO(hkuang): Find out what to do if failing to cancel the job. @@ -1272,7 +1272,7 @@ public final class MediaTranscodeManager { * @return job id. */ public int getJobId() { - return mJobId; + return mSessionId; } /** @@ -1326,7 +1326,7 @@ public final class MediaTranscodeManager { break; } return String.format(" Job: {id: %d, status: %s, result: %s, progress: %d}", - mJobId, status, result, mProgress); + mSessionId, status, result, mProgress); } private void updateProgress(int newProgress) { @@ -1383,7 +1383,7 @@ public final class MediaTranscodeManager { // Submits the request to MediaTranscoding service. try { - TranscodingJobParcel jobParcel = new TranscodingJobParcel(); + TranscodingSessionParcel sessionParcel = new TranscodingSessionParcel(); // Synchronizes the access to mPendingTranscodingJobs to make sure the job Id is // inserted in the mPendingTranscodingJobs in the callback handler. synchronized (mPendingTranscodingJobs) { @@ -1399,15 +1399,15 @@ public final class MediaTranscodeManager { } } - if (!mTranscodingClient.submitRequest(requestParcel, jobParcel)) { + if (!mTranscodingClient.submitRequest(requestParcel, sessionParcel)) { throw new UnsupportedOperationException("Failed to enqueue request"); } } - // Wraps the TranscodingJobParcel into a TranscodingJob and returns it to client for + // Wraps the TranscodingSessionParcel into a TranscodingJob and returns it to client for // tracking. TranscodingJob job = new TranscodingJob(this, transcodingRequest, - jobParcel, + sessionParcel, listenerExecutor, listener); diff --git a/media/java/android/media/tv/TunedInfo.java b/media/java/android/media/tv/TunedInfo.java index 6fc57841ed3b..6199c89fe4fa 100644 --- a/media/java/android/media/tv/TunedInfo.java +++ b/media/java/android/media/tv/TunedInfo.java @@ -19,6 +19,7 @@ package android.media.tv; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SystemApi; import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; @@ -35,6 +36,7 @@ import java.util.Objects; * or pass-through input. * @hide */ +@SystemApi public final class TunedInfo implements Parcelable { static final String TAG = "TunedInfo"; diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java index 73539fb8a014..e9959be249ec 100644 --- a/media/java/android/media/tv/TvInputManager.java +++ b/media/java/android/media/tv/TvInputManager.java @@ -906,8 +906,8 @@ public final class TvInputManager { * @param tunedInfos a list of {@link TunedInfo} objects of new tuned information. * @hide */ - public void onCurrentTunedInfosUpdated( - @NonNull List<TunedInfo> tunedInfos) { + @SystemApi + public void onCurrentTunedInfosUpdated(@NonNull List<TunedInfo> tunedInfos) { } } @@ -969,7 +969,7 @@ public final class TvInputManager { }); } - public void onCurrentTunedInfosUpdated(final List<TunedInfo> currentTunedInfos) { + public void postCurrentTunedInfosUpdated(final List<TunedInfo> currentTunedInfos) { mHandler.post(new Runnable() { @Override public void run() { @@ -1286,7 +1286,7 @@ public final class TvInputManager { public void onCurrentTunedInfosUpdated(List<TunedInfo> currentTunedInfos) { synchronized (mLock) { for (TvInputCallbackRecord record : mCallbackRecords) { - record.onCurrentTunedInfosUpdated(currentTunedInfos); + record.postCurrentTunedInfosUpdated(currentTunedInfos); } } } @@ -1988,6 +1988,7 @@ public final class TvInputManager { * {@link TunedInfo#getChannelUri()} returns {@code null}. * @hide */ + @SystemApi @RequiresPermission("com.android.providers.tv.permission.ACCESS_WATCHED_PROGRAMS") @NonNull public List<TunedInfo> getCurrentTunedInfos() { diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java index 867eab017a28..56499e26bafe 100644 --- a/media/java/android/media/tv/tuner/Tuner.java +++ b/media/java/android/media/tv/tuner/Tuner.java @@ -136,6 +136,11 @@ public class Tuner implements AutoCloseable { */ public static final long INVALID_FILTER_ID_64BIT = android.hardware.tv.tuner.V1_1.Constants.Constant64Bit.INVALID_FILTER_ID_64BIT; + /** + * Invalid frequency that is used as the default frontend frequency setting. + */ + public static final int INVALID_FRONTEND_SETTING_FREQUENCY = + android.hardware.tv.tuner.V1_1.Constants.Constant.INVALID_FRONTEND_SETTING_FREQUENCY; /** @hide */ @IntDef(prefix = "SCAN_TYPE_", value = {SCAN_TYPE_UNDEFINED, SCAN_TYPE_AUTO, SCAN_TYPE_BLIND}) @@ -618,6 +623,10 @@ public class Tuner implements AutoCloseable { * OnTuneEventListener#SIGNAL_NO_SIGNAL} events sent to the {@link OnTuneEventListener} * specified in {@link #setOnTuneEventListener(Executor, OnTuneEventListener)}. * + * <p>Tuning with {@link android.media.tv.tuner.frontend.DtmbFrontendSettings} is only + * supported in Tuner 1.1 or higher version. Unsupported version will cause no-op. Use {@link + * TunerVersionChecker.getTunerVersion()} to get the version information. + * * @param settings Signal delivery information the frontend uses to * search and lock the signal. * @return result status of tune operation. @@ -628,6 +637,12 @@ public class Tuner implements AutoCloseable { public int tune(@NonNull FrontendSettings settings) { Log.d(TAG, "Tune to " + settings.getFrequency()); mFrontendType = settings.getType(); + if (mFrontendType == FrontendSettings.TYPE_DTMB) { + if (!TunerVersionChecker.checkHigherOrEqualVersionTo( + TunerVersionChecker.TUNER_VERSION_1_1, "Tuner with DTMB Frontend")) { + return RESULT_UNAVAILABLE; + } + } if (checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND)) { mFrontendInfo = null; Log.d(TAG, "Write Stats Log for tuning."); @@ -657,6 +672,10 @@ public class Tuner implements AutoCloseable { * * <p>Details for channels found are returned via {@link ScanCallback}. * + * <p>Scanning with {@link android.media.tv.tuner.frontend.DtmbFrontendSettings} is only + * supported in Tuner 1.1 or higher version. Unsupported version will cause no-op. Use {@link + * TunerVersionChecker.getTunerVersion()} to get the version information. + * * @param settings A {@link FrontendSettings} to configure the frontend. * @param scanType The scan type. * @throws SecurityException if the caller does not have appropriate permissions. @@ -672,6 +691,12 @@ public class Tuner implements AutoCloseable { + "started."); } mFrontendType = settings.getType(); + if (mFrontendType == FrontendSettings.TYPE_DTMB) { + if (!TunerVersionChecker.checkHigherOrEqualVersionTo( + TunerVersionChecker.TUNER_VERSION_1_1, "Scan with DTMB Frontend")) { + return RESULT_UNAVAILABLE; + } + } if (checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND)) { mScanCallback = scanCallback; mScanCallbackExecutor = executor; diff --git a/media/java/android/media/tv/tuner/dvr/DvrPlayback.java b/media/java/android/media/tv/tuner/dvr/DvrPlayback.java index bb00bb3b8d56..597278b0ea3e 100644 --- a/media/java/android/media/tv/tuner/dvr/DvrPlayback.java +++ b/media/java/android/media/tv/tuner/dvr/DvrPlayback.java @@ -123,13 +123,14 @@ public class DvrPlayback implements AutoCloseable { /** * Attaches a filter to DVR interface for playback. * - * <p>This method will be deprecated. Now it's a no-op. - * <p>Filters opened by {@link Tuner#openFilter} are used for DVR playback. + * @deprecated attaching filters is not valid in Dvr Playback use case. This API is a no-op. + * Filters opened by {@link Tuner#openFilter} are used for DVR playback. * * @param filter the filter to be attached. * @return result status of the operation. */ @Result + @Deprecated public int attachFilter(@NonNull Filter filter) { // no-op return Tuner.RESULT_UNAVAILABLE; @@ -138,13 +139,14 @@ public class DvrPlayback implements AutoCloseable { /** * Detaches a filter from DVR interface. * - * <p>This method will be deprecated. Now it's a no-op. - * <p>Filters opened by {@link Tuner#openFilter} are used for DVR playback. + * @deprecated detaching filters is not valid in Dvr Playback use case. This API is a no-op. + * Filters opened by {@link Tuner#openFilter} are used for DVR playback. * * @param filter the filter to be detached. * @return result status of the operation. */ @Result + @Deprecated public int detachFilter(@NonNull Filter filter) { // no-op return Tuner.RESULT_UNAVAILABLE; diff --git a/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java b/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java index f54b686304c1..2649fcf5a642 100644 --- a/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java +++ b/media/java/android/media/tv/tuner/filter/IpFilterConfiguration.java @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Size; import android.annotation.SystemApi; +import android.media.tv.tuner.TunerVersionChecker; /** * Filter configuration for a IP filter. @@ -28,20 +29,28 @@ import android.annotation.SystemApi; */ @SystemApi public final class IpFilterConfiguration extends FilterConfiguration { + /** + * Undefined filter type. + */ + public static final int INVALID_IP_FILTER_CONTEXT_ID = + android.hardware.tv.tuner.V1_1.Constants.Constant.INVALID_IP_FILTER_CONTEXT_ID; + private final byte[] mSrcIpAddress; private final byte[] mDstIpAddress; private final int mSrcPort; private final int mDstPort; private final boolean mPassthrough; + private final int mIpFilterContextId; private IpFilterConfiguration(Settings settings, byte[] srcAddr, byte[] dstAddr, int srcPort, - int dstPort, boolean passthrough) { + int dstPort, boolean passthrough, int ipCid) { super(settings); mSrcIpAddress = srcAddr; mDstIpAddress = dstAddr; mSrcPort = srcPort; mDstPort = dstPort; mPassthrough = passthrough; + mIpFilterContextId = ipCid; } @Override @@ -86,6 +95,15 @@ public final class IpFilterConfiguration extends FilterConfiguration { public boolean isPassthrough() { return mPassthrough; } + /** + * Gets the ip filter context id. Default value is {@link #INVALID_IP_FILTER_CONTEXT_ID}. + * + * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would return + * default value. Use {@link TunerVersionChecker.getTunerVersion()} to check the version. + */ + public int getIpFilterContextId() { + return mIpFilterContextId; + } /** * Creates a builder for {@link IpFilterConfiguration}. @@ -105,6 +123,7 @@ public final class IpFilterConfiguration extends FilterConfiguration { private int mDstPort = 0; private boolean mPassthrough = false; private Settings mSettings; + private int mIpCid = INVALID_IP_FILTER_CONTEXT_ID; private Builder() { } @@ -170,6 +189,21 @@ public final class IpFilterConfiguration extends FilterConfiguration { } /** + * Sets the ip filter context id. Default value is {@link #INVALID_IP_FILTER_CONTEXT_ID}. + * + * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause + * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version. + */ + @NonNull + public Builder setIpFilterContextId(int ipContextId) { + if (TunerVersionChecker.checkHigherOrEqualVersionTo( + TunerVersionChecker.TUNER_VERSION_1_1, "setIpFilterContextId")) { + mIpCid = ipContextId; + } + return this; + } + + /** * Builds a {@link IpFilterConfiguration} object. */ @NonNull @@ -180,8 +214,8 @@ public final class IpFilterConfiguration extends FilterConfiguration { "The lengths of src and dst IP address must be 4 or 16 and must be the same." + "srcLength=" + ipAddrLength + ", dstLength=" + mDstIpAddress.length); } - return new IpFilterConfiguration( - mSettings, mSrcIpAddress, mDstIpAddress, mSrcPort, mDstPort, mPassthrough); + return new IpFilterConfiguration(mSettings, mSrcIpAddress, mDstIpAddress, mSrcPort, + mDstPort, mPassthrough, mIpCid); } } } diff --git a/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java index 1d36da34429e..c6a5bb045a1d 100644 --- a/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java +++ b/media/java/android/media/tv/tuner/frontend/AnalogFrontendSettings.java @@ -21,6 +21,7 @@ import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.SystemApi; import android.hardware.tv.tuner.V1_0.Constants; +import android.media.tv.tuner.TunerVersionChecker; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -164,9 +165,32 @@ public class AnalogFrontendSettings extends FrontendSettings { */ public static final int SIF_L_PRIME = Constants.FrontendAnalogSifStandard.L_PRIME; + /** @hide */ + @IntDef(prefix = "AFT_FLAG_", + value = {AFT_FLAG_UNDEFINED, AFT_FLAG_TRUE, AFT_FLAG_FALSE}) + @Retention(RetentionPolicy.SOURCE) + public @interface AftFlag {} + + /** + * Aft flag is not defined. + */ + public static final int AFT_FLAG_UNDEFINED = + android.hardware.tv.tuner.V1_1.Constants.FrontendAnalogAftFlag.UNDEFINED; + /** + * Aft flag is set true. + */ + public static final int AFT_FLAG_TRUE = + android.hardware.tv.tuner.V1_1.Constants.FrontendAnalogAftFlag.AFT_TRUE; + /** + * Aft flag is not set. + */ + public static final int AFT_FLAG_FALSE = + android.hardware.tv.tuner.V1_1.Constants.FrontendAnalogAftFlag.AFT_FALSE; + private final int mSignalType; private final int mSifStandard; + private final int mAftFlag; @Override public int getType() { @@ -191,6 +215,14 @@ public class AnalogFrontendSettings extends FrontendSettings { } /** + * Gets AFT flag. + */ + @AftFlag + public int getAftFlag() { + return mAftFlag; + } + + /** * Creates a builder for {@link AnalogFrontendSettings}. */ @NonNull @@ -198,10 +230,11 @@ public class AnalogFrontendSettings extends FrontendSettings { return new Builder(); } - private AnalogFrontendSettings(int frequency, int signalType, int sifStandard) { + private AnalogFrontendSettings(int frequency, int signalType, int sifStandard, int aftFlag) { super(frequency); mSignalType = signalType; mSifStandard = sifStandard; + mAftFlag = aftFlag; } /** @@ -211,6 +244,7 @@ public class AnalogFrontendSettings extends FrontendSettings { private int mFrequency = 0; private int mSignalType = SIGNAL_TYPE_UNDEFINED; private int mSifStandard = SIF_UNDEFINED; + private int mAftFlag = AFT_FLAG_UNDEFINED; private Builder() {} @@ -227,6 +261,24 @@ public class AnalogFrontendSettings extends FrontendSettings { } /** + * Set Aft flag. + * + * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause + * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version. + * + * @param aftFlag the value to set the aft flag. The default value is + * {@link #AFT_FLAG_UNDEFINED}. + */ + @NonNull + public Builder setAftFlag(@AftFlag int aftFlag) { + if (TunerVersionChecker.checkHigherOrEqualVersionTo( + TunerVersionChecker.TUNER_VERSION_1_1, "setAftFlag")) { + mAftFlag = aftFlag; + } + return this; + } + + /** * Sets analog signal type. * * <p>Default value is {@link #SIGNAL_TYPE_UNDEFINED}. @@ -253,7 +305,7 @@ public class AnalogFrontendSettings extends FrontendSettings { */ @NonNull public AnalogFrontendSettings build() { - return new AnalogFrontendSettings(mFrequency, mSignalType, mSifStandard); + return new AnalogFrontendSettings(mFrequency, mSignalType, mSifStandard, mAftFlag); } } } diff --git a/media/java/android/media/tv/tuner/frontend/Atsc3FrontendSettings.java b/media/java/android/media/tv/tuner/frontend/Atsc3FrontendSettings.java index f9eabc5b50e5..ed1ce2d6a566 100644 --- a/media/java/android/media/tv/tuner/frontend/Atsc3FrontendSettings.java +++ b/media/java/android/media/tv/tuner/frontend/Atsc3FrontendSettings.java @@ -377,8 +377,8 @@ public class Atsc3FrontendSettings extends FrontendSettings { */ @NonNull public Atsc3FrontendSettings build() { - return new Atsc3FrontendSettings( - mFrequency, mBandwidth, mDemodOutputFormat, mPlpSettings); + return new Atsc3FrontendSettings(mFrequency, mBandwidth, mDemodOutputFormat, + mPlpSettings); } } diff --git a/media/java/android/media/tv/tuner/frontend/DtmbFrontendCapabilities.java b/media/java/android/media/tv/tuner/frontend/DtmbFrontendCapabilities.java new file mode 100644 index 000000000000..9fc3a234876b --- /dev/null +++ b/media/java/android/media/tv/tuner/frontend/DtmbFrontendCapabilities.java @@ -0,0 +1,114 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.tuner.frontend; + +import android.annotation.SystemApi; + +/** + * DTMB Capabilities. + * + * <p>DTMB Frontend is only supported in Tuner HAL 1.1 or higher. + * @hide + */ +@SystemApi +public class DtmbFrontendCapabilities extends FrontendCapabilities { + private final int mModulationCap; + private final int mTransmissionModeCap; + private final int mGuardIntervalCap; + private final int mTimeInterleaveModeCap; + private final int mCodeRateCap; + private final int mBandwidthCap; + + private DtmbFrontendCapabilities(int modulationCap, int transmissionModeCap, + int guardIntervalCap, int timeInterleaveModeCap, int codeRateCap, int bandwidthCap) { + mModulationCap = modulationCap; + mTransmissionModeCap = transmissionModeCap; + mGuardIntervalCap = guardIntervalCap; + mTimeInterleaveModeCap = timeInterleaveModeCap; + mCodeRateCap = codeRateCap; + mBandwidthCap = bandwidthCap; + } + + /** + * Gets modulation capability. + * + * @return full modulation capabilies. If the caps bitwise AND with any value from + * bit masks {@link DtmbFrontendSettings.Modulation} is true, then that modulation is supported. + */ + @DtmbFrontendSettings.Modulation + public int getModulationCapability() { + return mModulationCap; + } + + /** + * Gets Transmission Mode capability. + * + * @return full Transmission Mode capabilies. If the caps bitwise AND with any value from + * bit masks {@link DtmbFrontendSettings.TransmissionMode} is true, then that transmission mode + * is supported. + */ + @DtmbFrontendSettings.TransmissionMode + public int getTransmissionModeCapability() { + return mTransmissionModeCap; + } + + /** + * Gets Guard Interval capability. + * + * @return full Guard Interval capabilies. If the caps bitwise AND with any value from + * bit masks {@link DtmbFrontendSettings.GuardInterval} is true, then that Guard Interval is + * supported. + */ + @DtmbFrontendSettings.GuardInterval + public int getGuardIntervalCapability() { + return mGuardIntervalCap; + } + + /** + * Gets Time Interleave Mode capability. + * + * @return full Time Interleave Mode capabilies. If the caps bitwise AND with any value from + * bit masks {@link DtmbFrontendSettings.TimeInterleaveMode} is true, then that Time Interleave + * Mode is supported. + */ + @DtmbFrontendSettings.TimeInterleaveMode + public int getTimeInterleaveModeCapability() { + return mTimeInterleaveModeCap; + } + + /** + * Gets Code Rate capability. + * + * @return full Code Rate capabilies. If the caps bitwise AND with any value from + * bit masks {@link DtmbFrontendSettings.CodeRate} is true, then that Code Rate is supported. + */ + @DtmbFrontendSettings.CodeRate + public int getCodeRateCapability() { + return mCodeRateCap; + } + + /** + * Gets Bandwidth capability. + * + * @return full Bandwidth capabilies. If the caps bitwise AND with any value from + * bit masks {@link DtmbFrontendSettings.Bandwidth} is true, then that Bandwidth is supported. + */ + @DtmbFrontendSettings.Bandwidth + public int getBandwidthCapability() { + return mBandwidthCap; + } +} diff --git a/media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java new file mode 100644 index 000000000000..2c3fe6a2583c --- /dev/null +++ b/media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java @@ -0,0 +1,441 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.tv.tuner.frontend; + +import android.annotation.IntDef; +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.SuppressLint; +import android.annotation.SystemApi; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Frontend settings for DTMB. + * + * <p>DTMB Frontend is only supported in Tuner HAL 1.1 or higher. Use {@link + * android.media.tv.tuner.TunerVersionChecker.getTunerVersion()} to get the version information. + * + * @hide + */ +@SystemApi +public class DtmbFrontendSettings extends FrontendSettings { + + /** @hide */ + @IntDef(flag = true, + prefix = "BANDWIDTH_", + value = {BANDWIDTH_UNDEFINED, BANDWIDTH_AUTO, BANDWIDTH_6MHZ, BANDWIDTH_8MHZ}) + @Retention(RetentionPolicy.SOURCE) + public @interface Bandwidth {} + + /** + * Bandwidth not defined. + */ + public static final int BANDWIDTH_UNDEFINED = + android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbBandwidth.UNDEFINED; + /** + * Hardware is able to detect and set bandwidth automatically + */ + public static final int BANDWIDTH_AUTO = + android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbBandwidth.AUTO; + /** + * 6 MHz bandwidth. + */ + public static final int BANDWIDTH_6MHZ = + android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbBandwidth.BANDWIDTH_6MHZ; + /** + * 8 MHz bandwidth. + */ + public static final int BANDWIDTH_8MHZ = + android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbBandwidth.BANDWIDTH_8MHZ; + + + /** @hide */ + @IntDef(flag = true, + prefix = "TIME_INTERLEAVE_MODE_", + value = {TIME_INTERLEAVE_MODE_UNDEFINED, TIME_INTERLEAVE_MODE_AUTO, + TIME_INTERLEAVE_MODE_TIMER_INT_240, TIME_INTERLEAVE_MODE_TIMER_INT_720}) + @Retention(RetentionPolicy.SOURCE) + public @interface TimeInterleaveMode {} + + /** + * Time Interleave Mode undefined. + */ + public static final int TIME_INTERLEAVE_MODE_UNDEFINED = + android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbTimeInterleaveMode.UNDEFINED; + /** + * Hardware is able to detect and set time interleave mode automatically + */ + public static final int TIME_INTERLEAVE_MODE_AUTO = + android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbTimeInterleaveMode.AUTO; + /** + * Time Interleave Mode timer int 240. + */ + public static final int TIME_INTERLEAVE_MODE_TIMER_INT_240 = + android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbTimeInterleaveMode.TIMER_INT_240; + /** + * Time Interleave Mode timer int 720. + */ + public static final int TIME_INTERLEAVE_MODE_TIMER_INT_720 = + android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbTimeInterleaveMode.TIMER_INT_720; + + + /** @hide */ + @IntDef(flag = true, + prefix = "GUARD_INTERVAL_", + value = {GUARD_INTERVAL_UNDEFINED, GUARD_INTERVAL_AUTO, + GUARD_INTERVAL_PN_420_VARIOUS, GUARD_INTERVAL_PN_595_CONST, + GUARD_INTERVAL_PN_945_VARIOUS, GUARD_INTERVAL_PN_420_CONST, + GUARD_INTERVAL_PN_945_CONST, GUARD_INTERVAL_PN_RESERVED}) + @Retention(RetentionPolicy.SOURCE) + public @interface GuardInterval {} + + /** + * Guard Interval undefined. + */ + public static final int GUARD_INTERVAL_UNDEFINED = + android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbGuardInterval.UNDEFINED; + /** + * Hardware is able to detect and set Guard Interval automatically. + */ + public static final int GUARD_INTERVAL_AUTO = + android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbGuardInterval.AUTO; + /** + * PN_420_VARIOUS Guard Interval. + */ + public static final int GUARD_INTERVAL_PN_420_VARIOUS = + android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbGuardInterval.PN_420_VARIOUS; + /** + * PN_595_CONST Guard Interval. + */ + public static final int GUARD_INTERVAL_PN_595_CONST = + android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbGuardInterval.PN_595_CONST; + /** + * PN_945_VARIOUS Guard Interval. + */ + public static final int GUARD_INTERVAL_PN_945_VARIOUS = + android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbGuardInterval.PN_945_VARIOUS; + /** + * PN_420_CONST Guard Interval. + */ + public static final int GUARD_INTERVAL_PN_420_CONST = + android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbGuardInterval.PN_420_CONST; + /** + * PN_945_CONST Guard Interval. + */ + public static final int GUARD_INTERVAL_PN_945_CONST = + android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbGuardInterval.PN_945_CONST; + /** + * PN_RESERVED Guard Interval. + */ + public static final int GUARD_INTERVAL_PN_RESERVED = + android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbGuardInterval.PN_RESERVED; + + + /** @hide */ + @IntDef(flag = true, + prefix = "MODULATION_", + value = {MODULATION_CONSTELLATION_UNDEFINED, MODULATION_CONSTELLATION_AUTO, + MODULATION_CONSTELLATION_4QAM, MODULATION_CONSTELLATION_4QAM_NR, + MODULATION_CONSTELLATION_16QAM, MODULATION_CONSTELLATION_32QAM, + MODULATION_CONSTELLATION_64QAM}) + @Retention(RetentionPolicy.SOURCE) + public @interface Modulation {} + + /** + * Constellation not defined. + */ + public static final int MODULATION_CONSTELLATION_UNDEFINED = + android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbModulation.UNDEFINED; + /** + * Hardware is able to detect and set Constellation automatically. + */ + public static final int MODULATION_CONSTELLATION_AUTO = + android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbModulation.AUTO; + /** + * 4QAM Constellation. + */ + public static final int MODULATION_CONSTELLATION_4QAM = + android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbModulation.CONSTELLATION_4QAM; + /** + * 4QAM_NR Constellation. + */ + public static final int MODULATION_CONSTELLATION_4QAM_NR = + android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbModulation.CONSTELLATION_4QAM_NR; + /** + * 16QAM Constellation. + */ + public static final int MODULATION_CONSTELLATION_16QAM = + android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbModulation.CONSTELLATION_16QAM; + /** + * 32QAM Constellation. + */ + public static final int MODULATION_CONSTELLATION_32QAM = + android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbModulation.CONSTELLATION_32QAM; + /** + * 64QAM Constellation. + */ + public static final int MODULATION_CONSTELLATION_64QAM = + android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbModulation.CONSTELLATION_64QAM; + + /** @hide */ + @IntDef(flag = true, + prefix = "CODERATE_", + value = {CODERATE_UNDEFINED, CODERATE_AUTO, CODERATE_2_5, CODERATE_3_5, CODERATE_4_5}) + @Retention(RetentionPolicy.SOURCE) + public @interface CodeRate {} + + /** + * Code rate undefined. + */ + public static final int CODERATE_UNDEFINED = + android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbCodeRate.UNDEFINED; + /** + * Hardware is able to detect and set code rate automatically. + */ + public static final int CODERATE_AUTO = + android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbCodeRate.AUTO; + /** + * 2/5 code rate. + */ + public static final int CODERATE_2_5 = + android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbCodeRate.CODERATE_2_5; + /** + * 3/5 code rate. + */ + public static final int CODERATE_3_5 = + android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbCodeRate.CODERATE_3_5; + /** + * 4/5 code rate. + */ + public static final int CODERATE_4_5 = + android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbCodeRate.CODERATE_4_5; + + /** @hide */ + @IntDef(flag = true, + prefix = "TRANSMISSION_MODE_", + value = {TRANSMISSION_MODE_UNDEFINED, TRANSMISSION_MODE_AUTO, + TRANSMISSION_MODE_C1, TRANSMISSION_MODE_C3780}) + @Retention(RetentionPolicy.SOURCE) + public @interface TransmissionMode {} + + /** + * Transmission Mode undefined. + */ + public static final int TRANSMISSION_MODE_UNDEFINED = + android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbTransmissionMode.UNDEFINED; + /** + * Hardware is able to detect and set Transmission Mode automatically + */ + public static final int TRANSMISSION_MODE_AUTO = + android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbTransmissionMode.AUTO; + /** + * C1 Transmission Mode. + */ + public static final int TRANSMISSION_MODE_C1 = + android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbTransmissionMode.C1; + /** + * C3780 Transmission Mode. + */ + public static final int TRANSMISSION_MODE_C3780 = + android.hardware.tv.tuner.V1_1.Constants.FrontendDtmbTransmissionMode.C3780; + + + private final int mModulation; + private final int mCodeRate; + private final int mTransmissionMode; + private final int mBandwidth; + private final int mGuardInterval; + private final int mTimeInterleaveMode; + + private DtmbFrontendSettings(int frequency, int modulation, int codeRate, int transmissionMode, + int guardInterval, int timeInterleaveMode, int bandwidth) { + super(frequency); + mModulation = modulation; + mCodeRate = codeRate; + mTransmissionMode = transmissionMode; + mGuardInterval = guardInterval; + mTimeInterleaveMode = timeInterleaveMode; + mBandwidth = bandwidth; + } + + /** + * Gets Modulation. + */ + @Modulation + public int getModulation() { + return mModulation; + } + + /** + * Gets Code Rate. + */ + @Modulation + public int getCodeRate() { + return mCodeRate; + } + + /** + * Gets Transmission Mode. + */ + @Modulation + public int getTransmissionMode() { + return mTransmissionMode; + } + + /** + * Gets Bandwidth. + */ + @Modulation + public int getBandwidth() { + return mBandwidth; + } + + /** + * Gets Time Interleave Mode. + */ + @Modulation + public int getTimeInterleaveMode() { + return mTimeInterleaveMode; + } + + + /** + * Gets Guard Interval. + */ + @Modulation + public int getGuardInterval() { + return mGuardInterval; + } + + /** + * Creates a builder for {@link AtscFrontendSettings}. + */ + @NonNull + public static Builder builder() { + return new Builder(); + } + + /** + * Builder for {@link AtscFrontendSettings}. + */ + public static final class Builder { + private int mFrequency = 0; + private int mModulation = MODULATION_CONSTELLATION_UNDEFINED; + private int mCodeRate = CODERATE_UNDEFINED; + private int mTransmissionMode = TRANSMISSION_MODE_UNDEFINED; + private int mBandwidth = BANDWIDTH_UNDEFINED; + private int mTimeInterleaveMode = TIME_INTERLEAVE_MODE_UNDEFINED; + private int mGuardInterval = GUARD_INTERVAL_UNDEFINED; + + private Builder() { + } + + /** + * Sets frequency in Hz. + * + * <p>Default value is 0. + */ + @NonNull + @IntRange(from = 1) + @SuppressLint("MissingGetterMatchingBuilder") + public Builder setFrequency(int frequency) { + mFrequency = frequency; + return this; + } + + /** + * Sets Modulation. + * + * <p>Default value is {@link #MODULATION_CONSTELLATION_UNDEFINED}. + */ + @NonNull + public Builder setModulation(@Modulation int modulation) { + mModulation = modulation; + return this; + } + + /** + * Sets Code Rate. + * + * <p>Default value is {@link #CODERATE_UNDEFINED}. + */ + @NonNull + public Builder setCodeRate(@CodeRate int codeRate) { + mCodeRate = codeRate; + return this; + } + + /** + * Sets Bandwidth. + * + * <p>Default value is {@link #BANDWIDTH_UNDEFINED}. + */ + @NonNull + public Builder setBandwidth(@Bandwidth int bandwidth) { + mBandwidth = bandwidth; + return this; + } + + /** + * Sets Time Interleave Mode. + * + * <p>Default value is {@link #TIME_INTERLEAVE_MODE_UNDEFINED}. + */ + @NonNull + public Builder setTimeInterleaveMode(@TimeInterleaveMode int timeInterleaveMode) { + mTimeInterleaveMode = timeInterleaveMode; + return this; + } + + /** + * Sets Guard Interval. + * + * <p>Default value is {@link #GUARD_INTERVAL_UNDEFINED}. + */ + @NonNull + public Builder setGuardInterval(@GuardInterval int guardInterval) { + mGuardInterval = guardInterval; + return this; + } + /** + * Sets Transmission Mode. + * + * <p>Default value is {@link #TRANSMISSION_MODE_UNDEFINED}. + */ + @NonNull + public Builder setTransmissionMode(@TransmissionMode int transmissionMode) { + mTransmissionMode = transmissionMode; + return this; + } + + /** + * Builds a {@link DtmbFrontendSettings} object. + */ + @NonNull + public DtmbFrontendSettings build() { + return new DtmbFrontendSettings(mFrequency, mModulation, mCodeRate, + mTransmissionMode, mGuardInterval, mTimeInterleaveMode, mBandwidth); + } + } + + @Override + public int getType() { + return FrontendSettings.TYPE_DTMB; + } +} diff --git a/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java index 271e91e5cbb8..e6968bb4ec90 100644 --- a/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java +++ b/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java @@ -21,6 +21,8 @@ import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.SystemApi; import android.hardware.tv.tuner.V1_0.Constants; +import android.media.tv.tuner.TunerVersionChecker; +import android.media.tv.tuner.frontend.FrontendSettings.FrontendSpectralInversion; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -117,7 +119,11 @@ public class DvbcFrontendSettings extends FrontendSettings { public static final int ANNEX_C = Constants.FrontendDvbcAnnex.C; - /** @hide */ + /** + * @deprecated Use the {@link FrontendSettings#FrontendSpectralInversion} instead. + * @hide + */ + @Deprecated @IntDef(prefix = "SPECTRAL_INVERSION_", value = {SPECTRAL_INVERSION_UNDEFINED, SPECTRAL_INVERSION_NORMAL, SPECTRAL_INVERSION_INVERTED}) @@ -126,20 +132,97 @@ public class DvbcFrontendSettings extends FrontendSettings { /** * Spectral Inversion Type undefined. + * + * @deprecated Use the {@link FrontendSettings#FRONTEND_SPECTRAL_INVERSION_UNDEFINED} instead. */ + @Deprecated public static final int SPECTRAL_INVERSION_UNDEFINED = Constants.FrontendDvbcSpectralInversion.UNDEFINED; /** * Normal Spectral Inversion. + * + * @deprecated Use the {@link FrontendSettings#FRONTEND_SPECTRAL_INVERSION_NORMAL} instead. */ + @Deprecated public static final int SPECTRAL_INVERSION_NORMAL = Constants.FrontendDvbcSpectralInversion.NORMAL; /** * Inverted Spectral Inversion. + * + * @deprecated Use the {@link FrontendSettings#FRONTEND_SPECTRAL_INVERSION_INVERTED} instead. */ + @Deprecated public static final int SPECTRAL_INVERSION_INVERTED = Constants.FrontendDvbcSpectralInversion.INVERTED; + /** @hide */ + @IntDef(flag = true, + prefix = "TIME_INTERLEAVE_MODE_", + value = {TIME_INTERLEAVE_MODE_UNDEFINED, TIME_INTERLEAVE_MODE_AUTO, + TIME_INTERLEAVE_MODE_128_1_0, TIME_INTERLEAVE_MODE_128_1_1, + TIME_INTERLEAVE_MODE_64_2, TIME_INTERLEAVE_MODE_32_4, + TIME_INTERLEAVE_MODE_16_8, TIME_INTERLEAVE_MODE_8_16, + TIME_INTERLEAVE_MODE_128_2, TIME_INTERLEAVE_MODE_128_3, + TIME_INTERLEAVE_MODE_128_4}) + @Retention(RetentionPolicy.SOURCE) + public @interface TimeInterleaveMode {} + + /** + * Time interleave mode undefined. + */ + public static final int TIME_INTERLEAVE_MODE_UNDEFINED = + android.hardware.tv.tuner.V1_1.Constants.FrontendCableTimeInterleaveMode.UNDEFINED; + /** + * Hardware is able to detect and set Time Interleave Mode automatically. + */ + public static final int TIME_INTERLEAVE_MODE_AUTO = + android.hardware.tv.tuner.V1_1.Constants.FrontendCableTimeInterleaveMode.AUTO; + /** + * 128/1/0 Time Interleave Mode. + */ + public static final int TIME_INTERLEAVE_MODE_128_1_0 = android.hardware.tv.tuner.V1_1.Constants + .FrontendCableTimeInterleaveMode.INTERLEAVING_128_1_0; + /** + * 128/1/1 Time Interleave Mode. + */ + public static final int TIME_INTERLEAVE_MODE_128_1_1 = android.hardware.tv.tuner.V1_1.Constants + .FrontendCableTimeInterleaveMode.INTERLEAVING_128_1_1; + /** + * 64/2 Time Interleave Mode. + */ + public static final int TIME_INTERLEAVE_MODE_64_2 = android.hardware.tv.tuner.V1_1.Constants + .FrontendCableTimeInterleaveMode.INTERLEAVING_64_2; + /** + * 32/4 Time Interleave Mode. + */ + public static final int TIME_INTERLEAVE_MODE_32_4 = android.hardware.tv.tuner.V1_1.Constants + .FrontendCableTimeInterleaveMode.INTERLEAVING_32_4; + /** + * 16/8 Time Interleave Mode. + */ + public static final int TIME_INTERLEAVE_MODE_16_8 = android.hardware.tv.tuner.V1_1.Constants + .FrontendCableTimeInterleaveMode.INTERLEAVING_16_8; + /** + * 8/16 Time Interleave Mode. + */ + public static final int TIME_INTERLEAVE_MODE_8_16 = android.hardware.tv.tuner.V1_1.Constants + .FrontendCableTimeInterleaveMode.INTERLEAVING_8_16; + /** + * 128/2 Time Interleave Mode. + */ + public static final int TIME_INTERLEAVE_MODE_128_2 = android.hardware.tv.tuner.V1_1.Constants + .FrontendCableTimeInterleaveMode.INTERLEAVING_128_2; + /** + * 128/3 Time Interleave Mode. + */ + public static final int TIME_INTERLEAVE_MODE_128_3 = android.hardware.tv.tuner.V1_1.Constants + .FrontendCableTimeInterleaveMode.INTERLEAVING_128_3; + /** + * 128/4 Time Interleave Mode. + */ + public static final int TIME_INTERLEAVE_MODE_128_4 = android.hardware.tv.tuner.V1_1.Constants + .FrontendCableTimeInterleaveMode.INTERLEAVING_128_4; + private final int mModulation; private final long mInnerFec; @@ -147,9 +230,11 @@ public class DvbcFrontendSettings extends FrontendSettings { private final int mOuterFec; private final int mAnnex; private final int mSpectralInversion; + // Dvbc time interleave mode is only supported in Tuner 1.1 or higher. + private final int mInterleaveMode; private DvbcFrontendSettings(int frequency, int modulation, long innerFec, int symbolRate, - int outerFec, int annex, int spectralInversion) { + int outerFec, int annex, int spectralInversion, int interleaveMode) { super(frequency); mModulation = modulation; mInnerFec = innerFec; @@ -157,6 +242,7 @@ public class DvbcFrontendSettings extends FrontendSettings { mOuterFec = outerFec; mAnnex = annex; mSpectralInversion = spectralInversion; + mInterleaveMode = interleaveMode; } /** @@ -196,10 +282,17 @@ public class DvbcFrontendSettings extends FrontendSettings { /** * Gets Spectral Inversion. */ - @SpectralInversion + @FrontendSpectralInversion public int getSpectralInversion() { return mSpectralInversion; } + /** + * Gets Time Interleave Mode. + */ + @TimeInterleaveMode + public int getTimeInterleaveMode() { + return mInterleaveMode; + } /** * Creates a builder for {@link DvbcFrontendSettings}. @@ -219,7 +312,8 @@ public class DvbcFrontendSettings extends FrontendSettings { private int mSymbolRate = 0; private int mOuterFec = OUTER_FEC_UNDEFINED; private int mAnnex = ANNEX_UNDEFINED; - private int mSpectralInversion = SPECTRAL_INVERSION_UNDEFINED; + private int mSpectralInversion = FrontendSettings.FRONTEND_SPECTRAL_INVERSION_UNDEFINED; + private int mInterleaveMode = TIME_INTERLEAVE_MODE_UNDEFINED; private Builder() { } @@ -289,13 +383,30 @@ public class DvbcFrontendSettings extends FrontendSettings { /** * Sets Spectral Inversion. * - * <p>Default value is {@link #SPECTRAL_INVERSION_UNDEFINED}. + * <p>Default value is {@link FrontendSettings#FRONTEND_SPECTRAL_INVERSION_UNDEFINED}. */ @NonNull - public Builder setSpectralInversion(@SpectralInversion int spectralInversion) { + public Builder setSpectralInversion(@FrontendSpectralInversion int spectralInversion) { mSpectralInversion = spectralInversion; return this; } + /** + * Set the time interleave mode. + * + * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause + * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version. + * + * @param interleaveMode the value to set as the time interleave mode. Default value is + * {@link #TIME_INTERLEAVE_MODE_UNDEFINED}. + */ + @NonNull + public Builder setTimeInterleaveMode(@TimeInterleaveMode int interleaveMode) { + if (TunerVersionChecker.checkHigherOrEqualVersionTo( + TunerVersionChecker.TUNER_VERSION_1_1, "setTimeInterleaveMode")) { + mInterleaveMode = interleaveMode; + } + return this; + } /** * Builds a {@link DvbcFrontendSettings} object. @@ -303,7 +414,7 @@ public class DvbcFrontendSettings extends FrontendSettings { @NonNull public DvbcFrontendSettings build() { return new DvbcFrontendSettings(mFrequency, mModulation, mInnerFec, mSymbolRate, - mOuterFec, mAnnex, mSpectralInversion); + mOuterFec, mAnnex, mSpectralInversion, mInterleaveMode); } } diff --git a/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java index 60b070fa1fa8..343dbb137dd6 100644 --- a/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java +++ b/media/java/android/media/tv/tuner/frontend/DvbsFrontendSettings.java @@ -23,6 +23,8 @@ import android.annotation.Nullable; import android.annotation.SystemApi; import android.hardware.tv.tuner.V1_0.Constants; import android.media.tv.tuner.Tuner; +import android.media.tv.tuner.TunerVersionChecker; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -36,6 +38,44 @@ import java.lang.annotation.RetentionPolicy; public class DvbsFrontendSettings extends FrontendSettings { /** @hide */ @IntDef(flag = true, + prefix = "SCAN_TYPE_", + value = {SCAN_TYPE_UNDEFINED, SCAN_TYPE_DIRECT, SCAN_TYPE_DISEQC, + SCAN_TYPE_UNICABLE, SCAN_TYPE_JESS}) + @Retention(RetentionPolicy.SOURCE) + public @interface ScanType {} + + /** + * Dvbs scan type undefined. + */ + public static final int SCAN_TYPE_UNDEFINED = + android.hardware.tv.tuner.V1_1.Constants.FrontendDvbsScanType.UNDEFINED; + + /** + * Dvbs scan type DIRECT. + */ + public static final int SCAN_TYPE_DIRECT = + android.hardware.tv.tuner.V1_1.Constants.FrontendDvbsScanType.DIRECT; + + /** + * Dvbs scan type DISEQC. + */ + public static final int SCAN_TYPE_DISEQC = + android.hardware.tv.tuner.V1_1.Constants.FrontendDvbsScanType.DISEQC; + + /** + * Dvbs scan type UNICABLE. + */ + public static final int SCAN_TYPE_UNICABLE = + android.hardware.tv.tuner.V1_1.Constants.FrontendDvbsScanType.UNICABLE; + + /** + * Dvbs scan type JESS. + */ + public static final int SCAN_TYPE_JESS = + android.hardware.tv.tuner.V1_1.Constants.FrontendDvbsScanType.JESS; + + /** @hide */ + @IntDef(flag = true, prefix = "MODULATION_", value = {MODULATION_UNDEFINED, MODULATION_AUTO, MODULATION_MOD_QPSK, MODULATION_MOD_8PSK, MODULATION_MOD_16QAM, MODULATION_MOD_16PSK, @@ -218,9 +258,12 @@ public class DvbsFrontendSettings extends FrontendSettings { private final int mInputStreamId; private final int mStandard; private final int mVcmMode; + // Dvbs scan type is only supported in Tuner 1.1 or higher. + private final int mScanType; private DvbsFrontendSettings(int frequency, int modulation, DvbsCodeRate codeRate, - int symbolRate, int rolloff, int pilot, int inputStreamId, int standard, int vcm) { + int symbolRate, int rolloff, int pilot, int inputStreamId, int standard, int vcm, + int scanType) { super(frequency); mModulation = modulation; mCodeRate = codeRate; @@ -230,6 +273,7 @@ public class DvbsFrontendSettings extends FrontendSettings { mInputStreamId = inputStreamId; mStandard = standard; mVcmMode = vcm; + mScanType = scanType; } /** @@ -286,6 +330,13 @@ public class DvbsFrontendSettings extends FrontendSettings { public int getVcmMode() { return mVcmMode; } + /** + * Get scan type. + */ + @ScanType + public int getScanType() { + return mScanType; + } /** * Creates a builder for {@link DvbsFrontendSettings}. @@ -308,6 +359,7 @@ public class DvbsFrontendSettings extends FrontendSettings { private int mInputStreamId = Tuner.INVALID_STREAM_ID; private int mStandard = STANDARD_AUTO; private int mVcmMode = VCM_MODE_UNDEFINED; + private int mScanType = SCAN_TYPE_UNDEFINED; private Builder() { } @@ -325,6 +377,24 @@ public class DvbsFrontendSettings extends FrontendSettings { } /** + * Set the scan type. + * + * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause + * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version. + * + * @param scanType the value to set as the scan type. Default value is + * {@link android.media.tv.tuner.frontend.DvbsFrontendSettings#DVBS_SCAN_TYPE_UNDEFINED}. + */ + @NonNull + public Builder setScanType(@ScanType int scanType) { + if (TunerVersionChecker.checkHigherOrEqualVersionTo( + TunerVersionChecker.TUNER_VERSION_1_1, "setScanType")) { + mScanType = scanType; + } + return this; + } + + /** * Sets Modulation. * * <p>Default value is {@link #MODULATION_UNDEFINED}. @@ -411,7 +481,7 @@ public class DvbsFrontendSettings extends FrontendSettings { @NonNull public DvbsFrontendSettings build() { return new DvbsFrontendSettings(mFrequency, mModulation, mCodeRate, mSymbolRate, - mRolloff, mPilot, mInputStreamId, mStandard, mVcmMode); + mRolloff, mPilot, mInputStreamId, mStandard, mVcmMode, mScanType); } } diff --git a/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java index 5c057de7cfbe..07d179707b98 100644 --- a/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java +++ b/media/java/android/media/tv/tuner/frontend/DvbtFrontendSettings.java @@ -21,6 +21,7 @@ import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.SystemApi; import android.hardware.tv.tuner.V1_0.Constants; +import android.media.tv.tuner.TunerVersionChecker; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -75,8 +76,21 @@ public class DvbtFrontendSettings extends FrontendSettings { * 32K Transmission Mode. */ public static final int TRANSMISSION_MODE_32K = Constants.FrontendDvbtTransmissionMode.MODE_32K; - - + /** + * 8K Transmission Extended Mode. + */ + public static final int TRANSMISSION_MODE_EXTENDED_8K = + android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtTransmissionMode.MODE_8K_E; + /** + * 16K Transmission Extended Mode. + */ + public static final int TRANSMISSION_MODE_EXTENDED_16K = + android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtTransmissionMode.MODE_16K_E; + /** + * 32K Transmission Extended Mode. + */ + public static final int TRANSMISSION_MODE_EXTENDED_32K = + android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtTransmissionMode.MODE_32K_E; /** @hide */ @IntDef(flag = true, @@ -124,8 +138,9 @@ public class DvbtFrontendSettings extends FrontendSettings { @IntDef(flag = true, prefix = "CONSTELLATION_", value = {CONSTELLATION_UNDEFINED, CONSTELLATION_AUTO, CONSTELLATION_QPSK, - CONSTELLATION_16QAM, CONSTELLATION_64QAM, - CONSTELLATION_256QAM}) + CONSTELLATION_16QAM, CONSTELLATION_64QAM, CONSTELLATION_256QAM, + CONSTELLATION_QPSK_R, CONSTELLATION_16QAM_R, CONSTELLATION_64QAM_R, + CONSTELLATION_256QAM_R}) @Retention(RetentionPolicy.SOURCE) public @interface Constellation {} @@ -157,7 +172,30 @@ public class DvbtFrontendSettings extends FrontendSettings { */ public static final int CONSTELLATION_256QAM = Constants.FrontendDvbtConstellation.CONSTELLATION_256QAM; - + /** + * QPSK Rotated Constellation. + */ + public static final int CONSTELLATION_QPSK_R = + android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtConstellation + .CONSTELLATION_QPSK_R; + /** + * 16QAM Rotated Constellation. + */ + public static final int CONSTELLATION_16QAM_R = + android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtConstellation + .CONSTELLATION_16QAM_R; + /** + * 64QAM Rotated Constellation. + */ + public static final int CONSTELLATION_64QAM_R = + android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtConstellation + .CONSTELLATION_64QAM_R; + /** + * 256QAM Rotated Constellation. + */ + public static final int CONSTELLATION_256QAM_R = + android.hardware.tv.tuner.V1_1.Constants.FrontendDvbtConstellation + .CONSTELLATION_256QAM_R; /** @hide */ @IntDef(flag = true, @@ -366,8 +404,7 @@ public class DvbtFrontendSettings extends FrontendSettings { */ public static final int PLP_MODE_MANUAL = Constants.FrontendDvbtPlpMode.MANUAL; - - private final int mTransmissionMode; + private int mTransmissionMode; private final int mBandwidth; private final int mConstellation; private final int mHierarchy; @@ -489,6 +526,19 @@ public class DvbtFrontendSettings extends FrontendSettings { return mPlpGroupId; } + private static boolean isExtendedTransmissionMode(@TransmissionMode int transmissionMode) { + return transmissionMode == TRANSMISSION_MODE_EXTENDED_8K + || transmissionMode == TRANSMISSION_MODE_EXTENDED_16K + || transmissionMode == TRANSMISSION_MODE_EXTENDED_32K; + } + + private static boolean isExtendedConstellation(@Constellation int constellation) { + return constellation == CONSTELLATION_QPSK_R + || constellation == CONSTELLATION_16QAM_R + || constellation == CONSTELLATION_64QAM_R + || constellation == CONSTELLATION_256QAM_R; + } + /** * Creates a builder for {@link DvbtFrontendSettings}. */ @@ -534,13 +584,23 @@ public class DvbtFrontendSettings extends FrontendSettings { /** * Sets Transmission Mode. * + * <p>{@link #TRANSMISSION_MODE_EXTENDED_8K}, {@link #TRANSMISSION_MODE_EXTENDED_16K} and + * {@link #TRANSMISSION_MODE_EXTENDED_32K} are only supported by Tuner HAL 1.1 or higher. + * Unsupported version would cause no-op. Use {@link TunerVersionChecker.getTunerVersion()} + * to check the version. + * * <p>Default value is {@link #TRANSMISSION_MODE_UNDEFINED}. */ @NonNull public Builder setTransmissionMode(@TransmissionMode int transmissionMode) { - mTransmissionMode = transmissionMode; + if (!isExtendedTransmissionMode(transmissionMode) + || TunerVersionChecker.checkHigherOrEqualVersionTo( + TunerVersionChecker.TUNER_VERSION_1_1, "set TransmissionMode Ext")) { + mTransmissionMode = transmissionMode; + } return this; } + /** * Sets Bandwidth. * @@ -554,11 +614,20 @@ public class DvbtFrontendSettings extends FrontendSettings { /** * Sets Constellation. * + * <p>{@link #CONSTELLATION_QPSK_R}, {@link #CONSTELLATION_16QAM_R}, + * {@link #CONSTELLATION_64QAM_R} and {@link #CONSTELLATION_256QAM_Rare} are only supported + * by Tuner HAL 1.1 or higher. Unsupported version would cause no-op. Use + * {@link TunerVersionChecker.getTunerVersion()} to check the version. + * * <p>Default value is {@link #CONSTELLATION_UNDEFINED}. */ @NonNull public Builder setConstellation(@Constellation int constellation) { - mConstellation = constellation; + if (!isExtendedConstellation(constellation) + || TunerVersionChecker.checkHigherOrEqualVersionTo( + TunerVersionChecker.TUNER_VERSION_1_1, "set Constellation Ext")) { + mConstellation = constellation; + } return this; } /** diff --git a/media/java/android/media/tv/tuner/frontend/FrontendSettings.java b/media/java/android/media/tv/tuner/frontend/FrontendSettings.java index 2f2fa97f4e7a..2147622d349d 100644 --- a/media/java/android/media/tv/tuner/frontend/FrontendSettings.java +++ b/media/java/android/media/tv/tuner/frontend/FrontendSettings.java @@ -17,9 +17,12 @@ package android.media.tv.tuner.frontend; import android.annotation.IntDef; +import android.annotation.IntRange; import android.annotation.LongDef; import android.annotation.SystemApi; import android.hardware.tv.tuner.V1_0.Constants; +import android.media.tv.tuner.Tuner; +import android.media.tv.tuner.TunerVersionChecker; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -34,7 +37,7 @@ public abstract class FrontendSettings { /** @hide */ @IntDef(prefix = "TYPE_", value = {TYPE_UNDEFINED, TYPE_ANALOG, TYPE_ATSC, TYPE_ATSC3, TYPE_DVBC, TYPE_DVBS, - TYPE_DVBT, TYPE_ISDBS, TYPE_ISDBS3, TYPE_ISDBT}) + TYPE_DVBT, TYPE_ISDBS, TYPE_ISDBS3, TYPE_ISDBT, TYPE_DTMB}) @Retention(RetentionPolicy.SOURCE) public @interface Type {} @@ -78,7 +81,10 @@ public abstract class FrontendSettings { * Integrated Services Digital Broadcasting-Terrestrial (ISDB-T) frontend type. */ public static final int TYPE_ISDBT = Constants.FrontendType.ISDBT; - + /** + * Digital Terrestrial Multimedia Broadcast standard (DTMB) frontend type. + */ + public static final int TYPE_DTMB = android.hardware.tv.tuner.V1_1.Constants.FrontendType.DTMB; /** @hide */ @@ -241,9 +247,36 @@ public abstract class FrontendSettings { */ public static final long FEC_77_90 = Constants.FrontendInnerFec.FEC_77_90; + /** @hide */ + @IntDef(prefix = "FRONTEND_SPECTRAL_INVERSION_", + value = {FRONTEND_SPECTRAL_INVERSION_UNDEFINED, FRONTEND_SPECTRAL_INVERSION_NORMAL, + FRONTEND_SPECTRAL_INVERSION_INVERTED}) + @Retention(RetentionPolicy.SOURCE) + public @interface FrontendSpectralInversion {} + + /** + * Spectral Inversion Type undefined. + */ + public static final int FRONTEND_SPECTRAL_INVERSION_UNDEFINED = + Constants.FrontendDvbcSpectralInversion.UNDEFINED; + /** + * Normal Spectral Inversion. + */ + public static final int FRONTEND_SPECTRAL_INVERSION_NORMAL = + Constants.FrontendDvbcSpectralInversion.NORMAL; + /** + * Inverted Spectral Inversion. + */ + public static final int FRONTEND_SPECTRAL_INVERSION_INVERTED = + Constants.FrontendDvbcSpectralInversion.INVERTED; + private final int mFrequency; + // End frequency is only supported in Tuner 1.1 or higher. + private int mEndFrequency = Tuner.INVALID_FRONTEND_SETTING_FREQUENCY; + // General spectral inversion is only supported in Tuner 1.1 or higher. + private int mSpectralInversion = FRONTEND_SPECTRAL_INVERSION_UNDEFINED; FrontendSettings(int frequency) { mFrequency = frequency; @@ -263,4 +296,57 @@ public abstract class FrontendSettings { public int getFrequency() { return mFrequency; } + + /** + * Get the end frequency. + * + * @return the end frequency in Hz. + */ + public int getEndFrequency() { + return mEndFrequency; + } + + /** + * Get the spectral inversion. + * + * @return the value of the spectral inversion. + */ + @FrontendSpectralInversion + public int getFrontendSpectralInversion() { + return mSpectralInversion; + } + + /** + * Set Spectral Inversion. + * + * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause + * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version. + * + * @param inversion the value to set as the spectral inversion. Default value is {@link + * #FRONTEND_SPECTRAL_INVERSION_UNDEFINED}. + */ + public void setSpectralInversion(@FrontendSpectralInversion int inversion) { + if (TunerVersionChecker.checkHigherOrEqualVersionTo( + TunerVersionChecker.TUNER_VERSION_1_1, "setSpectralInversion")) { + mSpectralInversion = inversion; + } + } + + /** + * Set End Frequency. This API is only supported with Tuner HAL 1.1 or higher. Otherwise it + * would be no-op. + * + * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause + * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version. + * + * @param endFrequency the end frequency used during blind scan. The default value is + * {@link android.media.tv.tuner.Tuner#INVALID_FRONTEND_SETTING_FREQUENCY}. + */ + @IntRange(from = 1) + public void setEndFrequency(int endFrequency) { + if (TunerVersionChecker.checkHigherOrEqualVersionTo( + TunerVersionChecker.TUNER_VERSION_1_1, "setEndFrequency")) { + mEndFrequency = endFrequency; + } + } } diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp index f0f2d8fd676f..6a1acede029f 100644 --- a/media/jni/android_media_tv_Tuner.cpp +++ b/media/jni/android_media_tv_Tuner.cpp @@ -134,6 +134,22 @@ using ::android::hardware::tv::tuner::V1_0::PlaybackSettings; using ::android::hardware::tv::tuner::V1_0::RecordSettings; using ::android::hardware::tv::tuner::V1_1::Constant; using ::android::hardware::tv::tuner::V1_1::Constant64Bit; +using ::android::hardware::tv::tuner::V1_1::FrontendAnalogAftFlag; +using ::android::hardware::tv::tuner::V1_1::FrontendAnalogSettingsExt1_1; +using ::android::hardware::tv::tuner::V1_1::FrontendCableTimeInterleaveMode; +using ::android::hardware::tv::tuner::V1_1::FrontendDvbsScanType; +using ::android::hardware::tv::tuner::V1_1::FrontendDvbcSettingsExt1_1; +using ::android::hardware::tv::tuner::V1_1::FrontendDvbsSettingsExt1_1; +using ::android::hardware::tv::tuner::V1_1::FrontendDvbtSettingsExt1_1; +using ::android::hardware::tv::tuner::V1_1::FrontendDtmbBandwidth; +using ::android::hardware::tv::tuner::V1_1::FrontendDtmbCapabilities; +using ::android::hardware::tv::tuner::V1_1::FrontendDtmbCodeRate; +using ::android::hardware::tv::tuner::V1_1::FrontendDtmbGuardInterval; +using ::android::hardware::tv::tuner::V1_1::FrontendDtmbModulation; +using ::android::hardware::tv::tuner::V1_1::FrontendDtmbSettings; +using ::android::hardware::tv::tuner::V1_1::FrontendDtmbTimeInterleaveMode; +using ::android::hardware::tv::tuner::V1_1::FrontendDtmbTransmissionMode; +using ::android::hardware::tv::tuner::V1_1::FrontendSpectralInversion; struct fields_t { jfieldID tunerContext; @@ -1200,6 +1216,33 @@ jobject JTuner::getIsdbtFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabili guardIntervalCap); } +jobject JTuner::getDtmbFrontendCaps(JNIEnv *env, int id) { + jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DtmbFrontendCapabilities"); + jmethodID capsInit = env->GetMethodID(clazz, "<init>", "(IIIIII)V"); + + if (mTuner_1_1 == NULL) { + ALOGD("1.1 Tuner is not found. Dtmb Frontend Caps are not supported."); + return NULL; + } + + Result result; + FrontendDtmbCapabilities dtmbCaps; + mTuner_1_1->getFrontendDtmbCapabilities(id, + [&](Result r, const FrontendDtmbCapabilities& caps) { + dtmbCaps = caps; + result = r; + }); + jint modulationCap = dtmbCaps.modulationCap; + jint transmissionModeCap = dtmbCaps.transmissionModeCap; + jint guardIntervalCap = dtmbCaps.guardIntervalCap; + jint interleaveModeCap = dtmbCaps.interleaveModeCap; + jint codeRateCap = dtmbCaps.codeRateCap; + jint bandwidthCap = dtmbCaps.bandwidthCap; + + return env->NewObject(clazz, capsInit, modulationCap, transmissionModeCap, guardIntervalCap, + interleaveModeCap, codeRateCap, bandwidthCap); +} + jobject JTuner::getFrontendInfo(int id) { FrontendInfo feInfo; Result res; @@ -1230,6 +1273,15 @@ jobject JTuner::getFrontendInfo(int id) { FrontendInfo::FrontendCapabilities caps = feInfo.frontendCaps; jobject jcaps = NULL; + + if (feInfo.type == static_cast<FrontendType>( + ::android::hardware::tv::tuner::V1_1::FrontendType::DTMB)) { + if (mTuner_1_1 == NULL) { + return NULL; + } + jcaps = getDtmbFrontendCaps(env, id); + } + switch(feInfo.type) { case FrontendType::ANALOG: if (FrontendInfo::FrontendCapabilities::hidl_discriminator::analogCaps @@ -1377,12 +1429,21 @@ jobject JTuner::openLnbByName(jstring name) { return lnbObj; } -int JTuner::tune(const FrontendSettings& settings) { +int JTuner::tune(const FrontendSettings& settings, const FrontendSettingsExt1_1& settingsExt1_1) { if (mFe == NULL) { ALOGE("frontend is not initialized"); return (int)Result::INVALID_STATE; } - Result result = mFe->tune(settings); + Result result; + sp<::android::hardware::tv::tuner::V1_1::IFrontend> fe_1_1 = + ::android::hardware::tv::tuner::V1_1::IFrontend::castFrom(mFe); + if (fe_1_1 == NULL) { + ALOGD("1.1 frontend is not found. Using 1.0 instead."); + result = mFe->tune(settings); + return (int)result; + } + + result = fe_1_1->tune_1_1(settings, settingsExt1_1); return (int)result; } @@ -1395,12 +1456,22 @@ int JTuner::stopTune() { return (int)result; } -int JTuner::scan(const FrontendSettings& settings, FrontendScanType scanType) { +int JTuner::scan(const FrontendSettings& settings, FrontendScanType scanType, + const FrontendSettingsExt1_1& settingsExt1_1) { if (mFe == NULL) { ALOGE("frontend is not initialized"); return (int)Result::INVALID_STATE; } - Result result = mFe->scan(settings, scanType); + Result result; + sp<::android::hardware::tv::tuner::V1_1::IFrontend> fe_1_1 = + ::android::hardware::tv::tuner::V1_1::IFrontend::castFrom(mFe); + if (fe_1_1 == NULL) { + ALOGD("1.1 frontend is not found. Using 1.0 instead."); + result = mFe->scan(settings, scanType); + return (int)result; + } + + result = fe_1_1->scan_1_1(settings, scanType, settingsExt1_1); return (int)result; } @@ -2105,6 +2176,22 @@ static uint32_t getFrontendSettingsFreq(JNIEnv *env, const jobject& settings) { return freq; } +static uint32_t getFrontendSettingsEndFreq(JNIEnv *env, const jobject& settings) { + jclass clazz = env->FindClass("android/media/tv/tuner/frontend/FrontendSettings"); + jfieldID endFreqField = env->GetFieldID(clazz, "mEndFrequency", "I"); + uint32_t endFreq = static_cast<uint32_t>(env->GetIntField(settings, endFreqField)); + return endFreq; +} + +static FrontendSpectralInversion getFrontendSettingsSpectralInversion( + JNIEnv *env, const jobject& settings) { + jclass clazz = env->FindClass("android/media/tv/tuner/frontend/FrontendSettings"); + jfieldID inversionField = env->GetFieldID(clazz, "mSpectralInversion", "I"); + FrontendSpectralInversion inversion = + static_cast<FrontendSpectralInversion>(env->GetIntField(settings, inversionField)); + return inversion; +} + static FrontendSettings getAnalogFrontendSettings(JNIEnv *env, const jobject& settings) { FrontendSettings frontendSettings; uint32_t freq = getFrontendSettingsFreq(env, settings); @@ -2124,6 +2211,18 @@ static FrontendSettings getAnalogFrontendSettings(JNIEnv *env, const jobject& se return frontendSettings; } +static void getAnalogFrontendSettingsExt1_1(JNIEnv *env, const jobject& settings, + FrontendSettingsExt1_1& settingsExt1_1) { + jclass clazz = env->FindClass("android/media/tv/tuner/frontend/AnalogFrontendSettings"); + FrontendAnalogAftFlag aftFlag = + static_cast<FrontendAnalogAftFlag>( + env->GetIntField(settings, env->GetFieldID(clazz, "mAftFlag", "I"))); + FrontendAnalogSettingsExt1_1 analogExt1_1 { + .aftFlag = aftFlag, + }; + settingsExt1_1.settingExt.analog(analogExt1_1); +} + static hidl_vec<FrontendAtsc3PlpSettings> getAtsc3PlpSettings( JNIEnv *env, const jobject& settings) { jclass clazz = env->FindClass("android/media/tv/tuner/frontend/Atsc3FrontendSettings"); @@ -2243,6 +2342,19 @@ static FrontendSettings getDvbcFrontendSettings(JNIEnv *env, const jobject& sett return frontendSettings; } +static void getDvbcFrontendSettingsExt1_1(JNIEnv *env, const jobject& settings, + FrontendSettingsExt1_1& settingsExt1_1) { + jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbcFrontendSettings"); + FrontendCableTimeInterleaveMode interleaveMode = + static_cast<FrontendCableTimeInterleaveMode>( + env->GetIntField(settings, env->GetFieldID(clazz, "mInterleaveMode", "I"))); + + FrontendDvbcSettingsExt1_1 dvbcExt1_1 { + .interleaveMode = interleaveMode, + }; + settingsExt1_1.settingExt.dvbc(dvbcExt1_1); +} + static FrontendDvbsCodeRate getDvbsCodeRate(JNIEnv *env, const jobject& settings) { jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbsFrontendSettings"); jobject jcodeRate = @@ -2284,7 +2396,6 @@ static FrontendSettings getDvbsFrontendSettings(JNIEnv *env, const jobject& sett uint32_t freq = getFrontendSettingsFreq(env, settings); jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbsFrontendSettings"); - FrontendDvbsModulation modulation = static_cast<FrontendDvbsModulation>( env->GetIntField(settings, env->GetFieldID(clazz, "mModulation", "I"))); @@ -2323,6 +2434,22 @@ static FrontendSettings getDvbsFrontendSettings(JNIEnv *env, const jobject& sett return frontendSettings; } +static void getDvbsFrontendSettingsExt1_1(JNIEnv *env, const jobject& settings, + FrontendSettingsExt1_1& settingsExt1_1) { + jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbsFrontendSettings"); + FrontendDvbsScanType scanType = + static_cast<FrontendDvbsScanType>( + env->GetIntField(settings, env->GetFieldID(clazz, "mScanType", "I"))); + bool isDiseqcRxMessage = static_cast<bool>(env->GetBooleanField( + settings, env->GetFieldID(clazz, "mIsDiseqcRxMessage", "B"))); + + FrontendDvbsSettingsExt1_1 dvbsExt1_1 { + .scanType = scanType, + .isDiseqcRxMessage = isDiseqcRxMessage, + }; + settingsExt1_1.settingExt.dvbs(dvbsExt1_1); +} + static FrontendSettings getDvbtFrontendSettings(JNIEnv *env, const jobject& settings) { FrontendSettings frontendSettings; uint32_t freq = getFrontendSettingsFreq(env, settings); @@ -2389,6 +2516,25 @@ static FrontendSettings getDvbtFrontendSettings(JNIEnv *env, const jobject& sett return frontendSettings; } +static void getDvbtFrontendSettingsExt1_1(JNIEnv *env, const jobject& settings, + FrontendSettingsExt1_1& settingsExt1_1) { + jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DvbtFrontendSettings"); + + FrontendDvbtSettingsExt1_1 dvbtExt1_1; + int transmissionMode = + env->GetIntField(settings, env->GetFieldID(clazz, "mTransmissionMode", "I")); + dvbtExt1_1.transmissionMode = static_cast< + ::android::hardware::tv::tuner::V1_1::FrontendDvbtTransmissionMode>( + transmissionMode); + + int constellation = + env->GetIntField(settings, env->GetFieldID(clazz, "mConstellation", "I")); + dvbtExt1_1.constellation = static_cast< + ::android::hardware::tv::tuner::V1_1::FrontendDvbtConstellation>(constellation); + + settingsExt1_1.settingExt.dvbt(dvbtExt1_1); +} + static FrontendSettings getIsdbsFrontendSettings(JNIEnv *env, const jobject& settings) { FrontendSettings frontendSettings; uint32_t freq = getFrontendSettingsFreq(env, settings); @@ -2497,6 +2643,41 @@ static FrontendSettings getIsdbtFrontendSettings(JNIEnv *env, const jobject& set return frontendSettings; } +static void getDtmbFrontendSettings(JNIEnv *env, const jobject& settings, + FrontendSettingsExt1_1& settingsExt1_1) { + uint32_t freq = getFrontendSettingsFreq(env, settings); + jclass clazz = env->FindClass("android/media/tv/tuner/frontend/DtmbFrontendSettings"); + FrontendDtmbModulation modulation = + static_cast<FrontendDtmbModulation>( + env->GetIntField(settings, env->GetFieldID(clazz, "mModulation", "I"))); + FrontendDtmbBandwidth bandwidth = + static_cast<FrontendDtmbBandwidth>( + env->GetIntField(settings, env->GetFieldID(clazz, "mBandwidth", "I"))); + FrontendDtmbTransmissionMode transmissionMode = + static_cast<FrontendDtmbTransmissionMode>( + env->GetIntField(settings, env->GetFieldID(clazz, "mTransmissionMode", "I"))); + FrontendDtmbCodeRate codeRate = + static_cast<FrontendDtmbCodeRate>( + env->GetIntField(settings, env->GetFieldID(clazz, "mCodeRate", "I"))); + FrontendDtmbGuardInterval guardInterval = + static_cast<FrontendDtmbGuardInterval>( + env->GetIntField(settings, env->GetFieldID(clazz, "mGuardInterval", "I"))); + FrontendDtmbTimeInterleaveMode interleaveMode = + static_cast<FrontendDtmbTimeInterleaveMode>( + env->GetIntField(settings, env->GetFieldID(clazz, "mTimeInterleaveMode", "I"))); + + FrontendDtmbSettings frontendDtmbSettings { + .frequency = freq, + .modulation = modulation, + .bandwidth = bandwidth, + .transmissionMode = transmissionMode, + .codeRate = codeRate, + .guardInterval = guardInterval, + .interleaveMode = interleaveMode, + }; + settingsExt1_1.settingExt.dtmb(frontendDtmbSettings); +} + static FrontendSettings getFrontendSettings(JNIEnv *env, int type, jobject settings) { ALOGD("getFrontendSettings %d", type); @@ -2529,6 +2710,59 @@ static FrontendSettings getFrontendSettings(JNIEnv *env, int type, jobject setti } } +static FrontendSettingsExt1_1 getFrontendSettingsExt1_1(JNIEnv *env, int type, jobject settings) { + ALOGD("getFrontendSettingsExt1_1 %d", type); + + FrontendSettingsExt1_1 settingsExt1_1 { + .endFrequency = static_cast<uint32_t>(Constant::INVALID_FRONTEND_SETTING_FREQUENCY), + .inversion = FrontendSpectralInversion::UNDEFINED, + }; + settingsExt1_1.settingExt.noinit(); + + if (type == static_cast<int>(::android::hardware::tv::tuner::V1_1::FrontendType::DTMB)) { + getDtmbFrontendSettings(env, settings, settingsExt1_1); + } else { + FrontendType feType = static_cast<FrontendType>(type); + switch(feType) { + case FrontendType::DVBS: + getDvbsFrontendSettingsExt1_1(env, settings, settingsExt1_1); + break; + case FrontendType::DVBT: + getDvbtFrontendSettingsExt1_1(env, settings, settingsExt1_1); + break; + case FrontendType::ANALOG: + getAnalogFrontendSettingsExt1_1(env, settings, settingsExt1_1); + break; + case FrontendType::ATSC3: + break; + case FrontendType::ATSC: + break; + case FrontendType::DVBC: + getDvbcFrontendSettingsExt1_1(env, settings, settingsExt1_1); + break; + case FrontendType::ISDBS: + break; + case FrontendType::ISDBS3: + break; + case FrontendType::ISDBT: + break; + default: + // should never happen because a type is associated with a subclass of + // FrontendSettings and not set by users + jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException", + "Unsupported frontend type %d", type); + return FrontendSettingsExt1_1(); + } + } + + uint32_t endFreq = getFrontendSettingsEndFreq(env, settings); + FrontendSpectralInversion inversion = getFrontendSettingsSpectralInversion(env, settings); + settingsExt1_1.endFrequency = endFreq; + settingsExt1_1.inversion = inversion; + + return settingsExt1_1; +} + static sp<Filter> getFilter(JNIEnv *env, jobject filter) { return (Filter *)env->GetLongField(filter, gFields.filterContext); } @@ -2670,7 +2904,9 @@ static jint android_media_tv_Tuner_close_frontend_by_handle( static int android_media_tv_Tuner_tune(JNIEnv *env, jobject thiz, jint type, jobject settings) { sp<JTuner> tuner = getTuner(env, thiz); - return tuner->tune(getFrontendSettings(env, type, settings)); + FrontendSettings setting = getFrontendSettings(env, type, settings); + FrontendSettingsExt1_1 settingExt = getFrontendSettingsExt1_1(env, type, settings); + return tuner->tune(setting, settingExt); } static int android_media_tv_Tuner_stop_tune(JNIEnv *env, jobject thiz) { @@ -2681,8 +2917,9 @@ static int android_media_tv_Tuner_stop_tune(JNIEnv *env, jobject thiz) { static int android_media_tv_Tuner_scan( JNIEnv *env, jobject thiz, jint settingsType, jobject settings, jint scanType) { sp<JTuner> tuner = getTuner(env, thiz); - return tuner->scan(getFrontendSettings( - env, settingsType, settings), static_cast<FrontendScanType>(scanType)); + FrontendSettings setting = getFrontendSettings(env, settingsType, settings); + FrontendSettingsExt1_1 settingExt = getFrontendSettingsExt1_1(env, settingsType, settings); + return tuner->scan(setting, static_cast<FrontendScanType>(scanType), settingExt); } static int android_media_tv_Tuner_stop_scan(JNIEnv *env, jobject thiz) { @@ -3149,6 +3386,29 @@ static DemuxFilterSettings getFilterConfiguration( return filterSettings; } +static Result configureIpFilterContextId( + JNIEnv *env, sp<IFilter> iFilterSp, jobject ipFilterConfigObj) { + jclass clazz = env->FindClass( + "android/media/tv/tuner/filter/IpFilterConfiguration"); + uint32_t cid = env->GetIntField(ipFilterConfigObj, env->GetFieldID( + clazz, "mIpFilterContextId", "I")); + Result res = Result::SUCCESS; + if (cid != static_cast<uint32_t>(Constant::INVALID_IP_FILTER_CONTEXT_ID)) { + sp<::android::hardware::tv::tuner::V1_1::IFilter> iFilterSp_1_1; + iFilterSp_1_1 = ::android::hardware::tv::tuner::V1_1::IFilter::castFrom(iFilterSp); + + if (iFilterSp_1_1 != NULL) { + res = iFilterSp_1_1->configureIpCid(cid); + if (res != Result::SUCCESS) { + return res; + } + } else { + ALOGW("configureIpCid is not supported with the current HAL implementation."); + } + } + return res; +} + static jint copyData(JNIEnv *env, std::unique_ptr<MQ>& mq, EventFlag* flag, jbyteArray buffer, jlong offset, jlong size) { ALOGD("copyData, size=%ld, offset=%ld", (long) size, (long) offset); @@ -3192,6 +3452,13 @@ static jint android_media_tv_Tuner_configure_filter( return (jint) res; } + if (static_cast<DemuxFilterMainType>(type) == DemuxFilterMainType::IP) { + res = configureIpFilterContextId(env, iFilterSp, settings); + if (res != Result::SUCCESS) { + return (jint) res; + } + } + MQDescriptorSync<uint8_t> filterMQDesc; Result getQueueDescResult = Result::UNKNOWN_ERROR; if (filterSp->mFilterMQ == NULL) { diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h index 5a59a5881586..2b73f312be05 100644 --- a/media/jni/android_media_tv_Tuner.h +++ b/media/jni/android_media_tv_Tuner.h @@ -55,6 +55,7 @@ using ::android::hardware::tv::tuner::V1_0::FrontendScanMessage; using ::android::hardware::tv::tuner::V1_0::FrontendScanMessageType; using ::android::hardware::tv::tuner::V1_0::FrontendScanType; using ::android::hardware::tv::tuner::V1_0::FrontendSettings; +using ::android::hardware::tv::tuner::V1_1::FrontendSettingsExt1_1; using ::android::hardware::tv::tuner::V1_0::IDemux; using ::android::hardware::tv::tuner::V1_0::IDescrambler; using ::android::hardware::tv::tuner::V1_0::IDvr; @@ -217,9 +218,10 @@ struct JTuner : public RefBase { jobject openFrontendById(int id); jint closeFrontendById(int id); jobject getFrontendInfo(int id); - int tune(const FrontendSettings& settings); + int tune(const FrontendSettings& settings, const FrontendSettingsExt1_1& settingsExt1_1); int stopTune(); - int scan(const FrontendSettings& settings, FrontendScanType scanType); + int scan(const FrontendSettings& settings, FrontendScanType scanType, + const FrontendSettingsExt1_1& settingsExt1_1); int stopScan(); int setLnb(int id); int setLna(bool enable); @@ -265,6 +267,7 @@ private: static jobject getIsdbs3FrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps); static jobject getIsdbsFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps); static jobject getIsdbtFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps); + static jobject getDtmbFrontendCaps(JNIEnv *env, int id); }; class C2DataIdInfo : public C2Param { diff --git a/media/tests/AudioPolicyTest/AndroidManifest.xml b/media/tests/AudioPolicyTest/AndroidManifest.xml index adb058c82870..a7ab8286cdca 100644 --- a/media/tests/AudioPolicyTest/AndroidManifest.xml +++ b/media/tests/AudioPolicyTest/AndroidManifest.xml @@ -25,7 +25,7 @@ <application> <uses-library android:name="android.test.runner" /> <activity android:label="@string/app_name" android:name="AudioPolicyTest" - android:screenOrientation="landscape"> + android:screenOrientation="landscape" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER"/> diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt index 58e4ccc17a67..aed080e97f0e 100644 --- a/non-updatable-api/current.txt +++ b/non-updatable-api/current.txt @@ -10667,12 +10667,15 @@ package android.content { field public static final String ACTION_PACKAGE_CHANGED = "android.intent.action.PACKAGE_CHANGED"; field public static final String ACTION_PACKAGE_DATA_CLEARED = "android.intent.action.PACKAGE_DATA_CLEARED"; field public static final String ACTION_PACKAGE_FIRST_LAUNCH = "android.intent.action.PACKAGE_FIRST_LAUNCH"; + field public static final String ACTION_PACKAGE_FULLY_LOADED = "android.intent.action.PACKAGE_FULLY_LOADED"; field public static final String ACTION_PACKAGE_FULLY_REMOVED = "android.intent.action.PACKAGE_FULLY_REMOVED"; field @Deprecated public static final String ACTION_PACKAGE_INSTALL = "android.intent.action.PACKAGE_INSTALL"; field public static final String ACTION_PACKAGE_NEEDS_VERIFICATION = "android.intent.action.PACKAGE_NEEDS_VERIFICATION"; field public static final String ACTION_PACKAGE_REMOVED = "android.intent.action.PACKAGE_REMOVED"; field public static final String ACTION_PACKAGE_REPLACED = "android.intent.action.PACKAGE_REPLACED"; field public static final String ACTION_PACKAGE_RESTARTED = "android.intent.action.PACKAGE_RESTARTED"; + field public static final String ACTION_PACKAGE_STARTABLE = "android.intent.action.PACKAGE_STARTABLE"; + field public static final String ACTION_PACKAGE_UNSTARTABLE = "android.intent.action.PACKAGE_UNSTARTABLE"; field public static final String ACTION_PACKAGE_VERIFIED = "android.intent.action.PACKAGE_VERIFIED"; field public static final String ACTION_PASTE = "android.intent.action.PASTE"; field public static final String ACTION_PICK = "android.intent.action.PICK"; @@ -10837,6 +10840,7 @@ package android.content { field public static final String EXTRA_TIMEZONE = "time-zone"; field public static final String EXTRA_TITLE = "android.intent.extra.TITLE"; field public static final String EXTRA_UID = "android.intent.extra.UID"; + field public static final String EXTRA_UNSTARTABLE_REASON = "android.intent.extra.UNSTARTABLE_REASON"; field public static final String EXTRA_USER = "android.intent.extra.USER"; field public static final int FILL_IN_ACTION = 1; // 0x1 field public static final int FILL_IN_CATEGORIES = 4; // 0x4 @@ -11710,7 +11714,10 @@ package android.content.pm { method public android.graphics.drawable.Drawable getIcon(int); method public CharSequence getLabel(); method public String getName(); + method public float getProgress(); method public android.os.UserHandle getUser(); + method public boolean isLoading(); + method public boolean isStartable(); } public class LauncherApps { @@ -11750,6 +11757,7 @@ package android.content.pm { ctor public LauncherApps.Callback(); method public abstract void onPackageAdded(String, android.os.UserHandle); method public abstract void onPackageChanged(String, android.os.UserHandle); + method public void onPackageProgressChanged(@NonNull String, @NonNull android.os.UserHandle, float); method public abstract void onPackageRemoved(String, android.os.UserHandle); method public abstract void onPackagesAvailable(String[], android.os.UserHandle, boolean); method public void onPackagesSuspended(String[], android.os.UserHandle); @@ -12296,6 +12304,9 @@ package android.content.pm { field public static final int SYNCHRONOUS = 2; // 0x2 field @Nullable public static final java.util.List<java.security.cert.Certificate> TRUST_ALL; field @NonNull public static final java.util.List<java.security.cert.Certificate> TRUST_NONE; + field public static final int UNSTARTABLE_REASON_CONNECTION_ERROR = 1; // 0x1 + field public static final int UNSTARTABLE_REASON_INSUFFICIENT_STORAGE = 2; // 0x2 + field public static final int UNSTARTABLE_REASON_UNKNOWN = 0; // 0x0 field public static final int VERIFICATION_ALLOW = 1; // 0x1 field public static final int VERIFICATION_REJECT = -1; // 0xffffffff field public static final int VERSION_CODE_HIGHEST = -1; // 0xffffffff @@ -24074,9 +24085,13 @@ package android.location { method @IntRange(from=1, to=java.lang.Integer.MAX_VALUE) public int getMaxUpdates(); method @FloatRange(from=0, to=java.lang.Float.MAX_VALUE) public float getMinUpdateDistanceMeters(); method @IntRange(from=0) public long getMinUpdateIntervalMillis(); + method public int getQuality(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.location.LocationRequest> CREATOR; field public static final long PASSIVE_INTERVAL = 9223372036854775807L; // 0x7fffffffffffffffL + field public static final int QUALITY_BALANCED_POWER_ACCURACY = 102; // 0x66 + field public static final int QUALITY_HIGH_ACCURACY = 100; // 0x64 + field public static final int QUALITY_LOW_POWER = 104; // 0x68 } public static final class LocationRequest.Builder { @@ -24089,6 +24104,7 @@ package android.location { method @NonNull public android.location.LocationRequest.Builder setMaxUpdates(@IntRange(from=1, to=java.lang.Integer.MAX_VALUE) int); method @NonNull public android.location.LocationRequest.Builder setMinUpdateDistanceMeters(@FloatRange(from=0, to=java.lang.Float.MAX_VALUE) float); method @NonNull public android.location.LocationRequest.Builder setMinUpdateIntervalMillis(@IntRange(from=0) long); + method @NonNull public android.location.LocationRequest.Builder setQuality(int); } public interface OnNmeaMessageListener { @@ -51855,11 +51871,12 @@ package android.view { method @Nullable public android.net.Uri getLinkUri(); method public int getSource(); field public static final int FLAG_CONVERT_TO_PLAIN_TEXT = 1; // 0x1 - field public static final int SOURCE_AUTOFILL = 3; // 0x3 - field public static final int SOURCE_CLIPBOARD = 0; // 0x0 - field public static final int SOURCE_DRAG_AND_DROP = 2; // 0x2 - field public static final int SOURCE_INPUT_METHOD = 1; // 0x1 - field public static final int SOURCE_PROCESS_TEXT = 4; // 0x4 + field public static final int SOURCE_APP = 0; // 0x0 + field public static final int SOURCE_AUTOFILL = 4; // 0x4 + field public static final int SOURCE_CLIPBOARD = 1; // 0x1 + field public static final int SOURCE_DRAG_AND_DROP = 3; // 0x3 + field public static final int SOURCE_INPUT_METHOD = 2; // 0x2 + field public static final int SOURCE_PROCESS_TEXT = 5; // 0x5 } public static final class OnReceiveContentCallback.Payload.Builder { diff --git a/non-updatable-api/module-lib-current.txt b/non-updatable-api/module-lib-current.txt index e135a3b734cf..3c1d19f48ca7 100644 --- a/non-updatable-api/module-lib-current.txt +++ b/non-updatable-api/module-lib-current.txt @@ -133,6 +133,18 @@ package android.provider { } +package android.telephony { + + public abstract class CellSignalStrength { + method public static int getNumSignalStrengthLevels(); + } + + public class TelephonyManager { + method @NonNull public static int[] getAllNetworkTypes(); + } + +} + package android.util { public class AtomicFile { diff --git a/non-updatable-api/system-current.txt b/non-updatable-api/system-current.txt index 900f68b02be9..13ed7f134370 100644 --- a/non-updatable-api/system-current.txt +++ b/non-updatable-api/system-current.txt @@ -122,6 +122,7 @@ package android { field public static final String MANAGE_FACTORY_RESET_PROTECTION = "android.permission.MANAGE_FACTORY_RESET_PROTECTION"; field public static final String MANAGE_IPSEC_TUNNELS = "android.permission.MANAGE_IPSEC_TUNNELS"; field public static final String MANAGE_MUSIC_RECOGNITION = "android.permission.MANAGE_MUSIC_RECOGNITION"; + field public static final String MANAGE_NOTIFICATION_LISTENERS = "android.permission.MANAGE_NOTIFICATION_LISTENERS"; field public static final String MANAGE_ONE_TIME_PERMISSION_SESSIONS = "android.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS"; field public static final String MANAGE_ROLE_HOLDERS = "android.permission.MANAGE_ROLE_HOLDERS"; field public static final String MANAGE_ROLLBACKS = "android.permission.MANAGE_ROLLBACKS"; @@ -674,8 +675,10 @@ package android.app { public class NotificationManager { method @NonNull public java.util.List<java.lang.String> getAllowedAssistantAdjustments(); method @Nullable public android.content.ComponentName getAllowedNotificationAssistant(); + method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS) public java.util.List<android.content.ComponentName> getEnabledNotificationListeners(); method public boolean isNotificationAssistantAccessGranted(@NonNull android.content.ComponentName); method public void setNotificationAssistantAccessGranted(@Nullable android.content.ComponentName, boolean); + method @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS) public void setNotificationListenerAccessGranted(@NonNull android.content.ComponentName, boolean); field @RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE) public static final String ACTION_CLOSE_NOTIFICATION_HANDLER_PANEL = "android.app.action.CLOSE_NOTIFICATION_HANDLER_PANEL"; field @RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE) public static final String ACTION_OPEN_NOTIFICATION_HANDLER_PANEL = "android.app.action.OPEN_NOTIFICATION_HANDLER_PANEL"; field @RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE) public static final String ACTION_TOGGLE_NOTIFICATION_HANDLER_PANEL = "android.app.action.TOGGLE_NOTIFICATION_HANDLER_PANEL"; @@ -1388,20 +1391,20 @@ package android.app.time { package android.app.usage { public final class CacheQuotaHint implements android.os.Parcelable { - ctor public CacheQuotaHint(android.app.usage.CacheQuotaHint.Builder); + ctor public CacheQuotaHint(@NonNull android.app.usage.CacheQuotaHint.Builder); method public int describeContents(); method public long getQuota(); method public int getUid(); - method public android.app.usage.UsageStats getUsageStats(); - method public String getVolumeUuid(); - method public void writeToParcel(android.os.Parcel, int); + method @Nullable public android.app.usage.UsageStats getUsageStats(); + method @Nullable public String getVolumeUuid(); + method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.app.usage.CacheQuotaHint> CREATOR; field public static final long QUOTA_NOT_SET = -1L; // 0xffffffffffffffffL } public static final class CacheQuotaHint.Builder { ctor public CacheQuotaHint.Builder(); - ctor public CacheQuotaHint.Builder(android.app.usage.CacheQuotaHint); + ctor public CacheQuotaHint.Builder(@NonNull android.app.usage.CacheQuotaHint); method @NonNull public android.app.usage.CacheQuotaHint build(); method @NonNull public android.app.usage.CacheQuotaHint.Builder setQuota(long); method @NonNull public android.app.usage.CacheQuotaHint.Builder setUid(int); @@ -4111,7 +4114,6 @@ package android.location { method @Deprecated public long getInterval(); method @Deprecated public int getNumUpdates(); method @Deprecated @NonNull public String getProvider(); - method public int getQuality(); method @Deprecated public float getSmallestDisplacement(); method @NonNull public android.os.WorkSource getWorkSource(); method public boolean isHiddenFromAppOps(); @@ -4130,11 +4132,11 @@ package android.location { method @Deprecated @NonNull public android.location.LocationRequest setQuality(int); method @Deprecated @NonNull public android.location.LocationRequest setSmallestDisplacement(float); method @Deprecated public void setWorkSource(@Nullable android.os.WorkSource); - field public static final int ACCURACY_BLOCK = 102; // 0x66 - field public static final int ACCURACY_CITY = 104; // 0x68 - field public static final int ACCURACY_FINE = 100; // 0x64 - field public static final int POWER_HIGH = 203; // 0xcb - field public static final int POWER_LOW = 201; // 0xc9 + field @Deprecated public static final int ACCURACY_BLOCK = 102; // 0x66 + field @Deprecated public static final int ACCURACY_CITY = 104; // 0x68 + field @Deprecated public static final int ACCURACY_FINE = 100; // 0x64 + field @Deprecated public static final int POWER_HIGH = 203; // 0xcb + field @Deprecated public static final int POWER_LOW = 201; // 0xc9 field @Deprecated public static final int POWER_NONE = 200; // 0xc8 } @@ -4142,7 +4144,6 @@ package android.location { method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS) public android.location.LocationRequest.Builder setHiddenFromAppOps(boolean); method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public android.location.LocationRequest.Builder setLocationSettingsIgnored(boolean); method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.location.LocationRequest.Builder setLowPower(boolean); - method @NonNull public android.location.LocationRequest.Builder setQuality(int); method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.location.LocationRequest.Builder setWorkSource(@Nullable android.os.WorkSource); } @@ -4709,6 +4710,22 @@ package android.media.tv { field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.DvbDeviceInfo> CREATOR; } + public final class TunedInfo implements android.os.Parcelable { + method public int describeContents(); + method public int getAppTag(); + method public int getAppType(); + method @Nullable public android.net.Uri getChannelUri(); + method @NonNull public String getInputId(); + method public boolean isForeground(); + method public boolean isRecordingSession(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field public static final int APP_TAG_SELF = 0; // 0x0 + field public static final int APP_TYPE_NON_SYSTEM = 3; // 0x3 + field public static final int APP_TYPE_SELF = 1; // 0x1 + field public static final int APP_TYPE_SYSTEM = 2; // 0x2 + field @NonNull public static final android.os.Parcelable.Creator<android.media.tv.TunedInfo> CREATOR; + } + public final class TvContentRatingSystemInfo implements android.os.Parcelable { method public static android.media.tv.TvContentRatingSystemInfo createTvContentRatingSystemInfo(int, android.content.pm.ApplicationInfo); method public int describeContents(); @@ -4824,6 +4841,7 @@ package android.media.tv { method @RequiresPermission(android.Manifest.permission.MODIFY_PARENTAL_CONTROLS) public void addBlockedRating(@NonNull android.media.tv.TvContentRating); method @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT) public boolean captureFrame(String, android.view.Surface, android.media.tv.TvStreamConfig); method @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT) public java.util.List<android.media.tv.TvStreamConfig> getAvailableTvStreamConfigList(String); + method @NonNull @RequiresPermission("com.android.providers.tv.permission.ACCESS_WATCHED_PROGRAMS") public java.util.List<android.media.tv.TunedInfo> getCurrentTunedInfos(); method @NonNull @RequiresPermission("android.permission.DVB_DEVICE") public java.util.List<android.media.tv.DvbDeviceInfo> getDvbDeviceList(); method @RequiresPermission(android.Manifest.permission.TV_INPUT_HARDWARE) public java.util.List<android.media.tv.TvInputHardwareInfo> getHardwareList(); method @RequiresPermission(android.Manifest.permission.READ_CONTENT_RATING_SYSTEMS) public java.util.List<android.media.tv.TvContentRatingSystemInfo> getTvContentRatingSystemList(); @@ -4849,6 +4867,10 @@ package android.media.tv { method public abstract void onStreamConfigChanged(android.media.tv.TvStreamConfig[]); } + public abstract static class TvInputManager.TvInputCallback { + method public void onCurrentTunedInfosUpdated(@NonNull java.util.List<android.media.tv.TunedInfo>); + } + public abstract class TvInputService extends android.app.Service { method @Nullable public android.media.tv.TvInputInfo onHardwareAdded(android.media.tv.TvInputHardwareInfo); method @Nullable public String onHardwareRemoved(android.media.tv.TvInputHardwareInfo); @@ -4995,6 +5017,7 @@ package android.media.tv.tuner { field public static final int INVALID_AV_SYNC_ID = -1; // 0xffffffff field public static final int INVALID_FILTER_ID = -1; // 0xffffffff field public static final long INVALID_FILTER_ID_64BIT = -1L; // 0xffffffffffffffffL + field public static final int INVALID_FRONTEND_SETTING_FREQUENCY = -1; // 0xffffffff field public static final int INVALID_LTS_ID = -1; // 0xffffffff field public static final int INVALID_MMTP_RECORD_EVENT_MPT_SEQUENCE_NUM = -1; // 0xffffffff field public static final int INVALID_STREAM_ID = 65535; // 0xffff @@ -5028,10 +5051,10 @@ package android.media.tv.tuner { package android.media.tv.tuner.dvr { public class DvrPlayback implements java.lang.AutoCloseable { - method public int attachFilter(@NonNull android.media.tv.tuner.filter.Filter); + method @Deprecated public int attachFilter(@NonNull android.media.tv.tuner.filter.Filter); method public void close(); method public int configure(@NonNull android.media.tv.tuner.dvr.DvrSettings); - method public int detachFilter(@NonNull android.media.tv.tuner.filter.Filter); + method @Deprecated public int detachFilter(@NonNull android.media.tv.tuner.filter.Filter); method public int flush(); method public long read(long); method public long read(@NonNull byte[], long, long); @@ -5208,16 +5231,19 @@ package android.media.tv.tuner.filter { method @NonNull public static android.media.tv.tuner.filter.IpFilterConfiguration.Builder builder(); method @NonNull @Size(min=4, max=16) public byte[] getDstIpAddress(); method public int getDstPort(); + method public int getIpFilterContextId(); method @NonNull @Size(min=4, max=16) public byte[] getSrcIpAddress(); method public int getSrcPort(); method public int getType(); method public boolean isPassthrough(); + field public static final int INVALID_IP_FILTER_CONTEXT_ID = -1; // 0xffffffff } public static final class IpFilterConfiguration.Builder { method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration build(); method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration.Builder setDstIpAddress(@NonNull byte[]); method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration.Builder setDstPort(int); + method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration.Builder setIpFilterContextId(int); method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration.Builder setPassthrough(boolean); method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration.Builder setSettings(@Nullable android.media.tv.tuner.filter.Settings); method @NonNull public android.media.tv.tuner.filter.IpFilterConfiguration.Builder setSrcIpAddress(@NonNull byte[]); @@ -5437,9 +5463,13 @@ package android.media.tv.tuner.frontend { public class AnalogFrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings { method @NonNull public static android.media.tv.tuner.frontend.AnalogFrontendSettings.Builder builder(); + method public int getAftFlag(); method public int getSifStandard(); method public int getSignalType(); method public int getType(); + field public static final int AFT_FLAG_FALSE = 2; // 0x2 + field public static final int AFT_FLAG_TRUE = 1; // 0x1 + field public static final int AFT_FLAG_UNDEFINED = 0; // 0x0 field public static final int SIF_AUTO = 1; // 0x1 field public static final int SIF_BG = 2; // 0x2 field public static final int SIF_BG_A2 = 4; // 0x4 @@ -5472,6 +5502,7 @@ package android.media.tv.tuner.frontend { public static class AnalogFrontendSettings.Builder { method @NonNull public android.media.tv.tuner.frontend.AnalogFrontendSettings build(); + method @NonNull public android.media.tv.tuner.frontend.AnalogFrontendSettings.Builder setAftFlag(int); method @IntRange(from=1) @NonNull public android.media.tv.tuner.frontend.AnalogFrontendSettings.Builder setFrequency(int); method @NonNull public android.media.tv.tuner.frontend.AnalogFrontendSettings.Builder setSifStandard(int); method @NonNull public android.media.tv.tuner.frontend.AnalogFrontendSettings.Builder setSignalType(int); @@ -5587,6 +5618,69 @@ package android.media.tv.tuner.frontend { method @NonNull public android.media.tv.tuner.frontend.AtscFrontendSettings.Builder setModulation(int); } + public class DtmbFrontendCapabilities extends android.media.tv.tuner.frontend.FrontendCapabilities { + method public int getBandwidthCapability(); + method public int getCodeRateCapability(); + method public int getGuardIntervalCapability(); + method public int getModulationCapability(); + method public int getTimeInterleaveModeCapability(); + method public int getTransmissionModeCapability(); + } + + public class DtmbFrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings { + method @NonNull public static android.media.tv.tuner.frontend.DtmbFrontendSettings.Builder builder(); + method public int getBandwidth(); + method public int getCodeRate(); + method public int getGuardInterval(); + method public int getModulation(); + method public int getTimeInterleaveMode(); + method public int getTransmissionMode(); + method public int getType(); + field public static final int BANDWIDTH_6MHZ = 4; // 0x4 + field public static final int BANDWIDTH_8MHZ = 2; // 0x2 + field public static final int BANDWIDTH_AUTO = 1; // 0x1 + field public static final int BANDWIDTH_UNDEFINED = 0; // 0x0 + field public static final int CODERATE_2_5 = 2; // 0x2 + field public static final int CODERATE_3_5 = 4; // 0x4 + field public static final int CODERATE_4_5 = 8; // 0x8 + field public static final int CODERATE_AUTO = 1; // 0x1 + field public static final int CODERATE_UNDEFINED = 0; // 0x0 + field public static final int GUARD_INTERVAL_AUTO = 1; // 0x1 + field public static final int GUARD_INTERVAL_PN_420_CONST = 16; // 0x10 + field public static final int GUARD_INTERVAL_PN_420_VARIOUS = 2; // 0x2 + field public static final int GUARD_INTERVAL_PN_595_CONST = 4; // 0x4 + field public static final int GUARD_INTERVAL_PN_945_CONST = 32; // 0x20 + field public static final int GUARD_INTERVAL_PN_945_VARIOUS = 8; // 0x8 + field public static final int GUARD_INTERVAL_PN_RESERVED = 64; // 0x40 + field public static final int GUARD_INTERVAL_UNDEFINED = 0; // 0x0 + field public static final int MODULATION_CONSTELLATION_16QAM = 8; // 0x8 + field public static final int MODULATION_CONSTELLATION_32QAM = 16; // 0x10 + field public static final int MODULATION_CONSTELLATION_4QAM = 2; // 0x2 + field public static final int MODULATION_CONSTELLATION_4QAM_NR = 4; // 0x4 + field public static final int MODULATION_CONSTELLATION_64QAM = 32; // 0x20 + field public static final int MODULATION_CONSTELLATION_AUTO = 1; // 0x1 + field public static final int MODULATION_CONSTELLATION_UNDEFINED = 0; // 0x0 + field public static final int TIME_INTERLEAVE_MODE_AUTO = 1; // 0x1 + field public static final int TIME_INTERLEAVE_MODE_TIMER_INT_240 = 2; // 0x2 + field public static final int TIME_INTERLEAVE_MODE_TIMER_INT_720 = 4; // 0x4 + field public static final int TIME_INTERLEAVE_MODE_UNDEFINED = 0; // 0x0 + field public static final int TRANSMISSION_MODE_AUTO = 1; // 0x1 + field public static final int TRANSMISSION_MODE_C1 = 2; // 0x2 + field public static final int TRANSMISSION_MODE_C3780 = 4; // 0x4 + field public static final int TRANSMISSION_MODE_UNDEFINED = 0; // 0x0 + } + + public static final class DtmbFrontendSettings.Builder { + method @NonNull public android.media.tv.tuner.frontend.DtmbFrontendSettings build(); + method @NonNull public android.media.tv.tuner.frontend.DtmbFrontendSettings.Builder setBandwidth(int); + method @NonNull public android.media.tv.tuner.frontend.DtmbFrontendSettings.Builder setCodeRate(int); + method @IntRange(from=1) @NonNull public android.media.tv.tuner.frontend.DtmbFrontendSettings.Builder setFrequency(int); + method @NonNull public android.media.tv.tuner.frontend.DtmbFrontendSettings.Builder setGuardInterval(int); + method @NonNull public android.media.tv.tuner.frontend.DtmbFrontendSettings.Builder setModulation(int); + method @NonNull public android.media.tv.tuner.frontend.DtmbFrontendSettings.Builder setTimeInterleaveMode(int); + method @NonNull public android.media.tv.tuner.frontend.DtmbFrontendSettings.Builder setTransmissionMode(int); + } + public class DvbcFrontendCapabilities extends android.media.tv.tuner.frontend.FrontendCapabilities { method public int getAnnexCapability(); method public int getFecCapability(); @@ -5601,6 +5695,7 @@ package android.media.tv.tuner.frontend { method public int getOuterFec(); method public int getSpectralInversion(); method public int getSymbolRate(); + method public int getTimeInterleaveMode(); method public int getType(); field public static final int ANNEX_A = 1; // 0x1 field public static final int ANNEX_B = 2; // 0x2 @@ -5616,9 +5711,20 @@ package android.media.tv.tuner.frontend { field public static final int OUTER_FEC_OUTER_FEC_NONE = 1; // 0x1 field public static final int OUTER_FEC_OUTER_FEC_RS = 2; // 0x2 field public static final int OUTER_FEC_UNDEFINED = 0; // 0x0 - field public static final int SPECTRAL_INVERSION_INVERTED = 2; // 0x2 - field public static final int SPECTRAL_INVERSION_NORMAL = 1; // 0x1 - field public static final int SPECTRAL_INVERSION_UNDEFINED = 0; // 0x0 + field @Deprecated public static final int SPECTRAL_INVERSION_INVERTED = 2; // 0x2 + field @Deprecated public static final int SPECTRAL_INVERSION_NORMAL = 1; // 0x1 + field @Deprecated public static final int SPECTRAL_INVERSION_UNDEFINED = 0; // 0x0 + field public static final int TIME_INTERLEAVE_MODE_128_1_0 = 2; // 0x2 + field public static final int TIME_INTERLEAVE_MODE_128_1_1 = 4; // 0x4 + field public static final int TIME_INTERLEAVE_MODE_128_2 = 128; // 0x80 + field public static final int TIME_INTERLEAVE_MODE_128_3 = 256; // 0x100 + field public static final int TIME_INTERLEAVE_MODE_128_4 = 512; // 0x200 + field public static final int TIME_INTERLEAVE_MODE_16_8 = 32; // 0x20 + field public static final int TIME_INTERLEAVE_MODE_32_4 = 16; // 0x10 + field public static final int TIME_INTERLEAVE_MODE_64_2 = 8; // 0x8 + field public static final int TIME_INTERLEAVE_MODE_8_16 = 64; // 0x40 + field public static final int TIME_INTERLEAVE_MODE_AUTO = 1; // 0x1 + field public static final int TIME_INTERLEAVE_MODE_UNDEFINED = 0; // 0x0 } public static class DvbcFrontendSettings.Builder { @@ -5630,6 +5736,7 @@ package android.media.tv.tuner.frontend { method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder setOuterFec(int); method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder setSpectralInversion(int); method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder setSymbolRate(int); + method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder setTimeInterleaveMode(int); } public class DvbsCodeRate { @@ -5661,6 +5768,7 @@ package android.media.tv.tuner.frontend { method public int getModulation(); method public int getPilot(); method public int getRolloff(); + method public int getScanType(); method public int getStandard(); method public int getSymbolRate(); method public int getType(); @@ -5691,6 +5799,11 @@ package android.media.tv.tuner.frontend { field public static final int ROLLOFF_0_35 = 1; // 0x1 field public static final int ROLLOFF_0_5 = 6; // 0x6 field public static final int ROLLOFF_UNDEFINED = 0; // 0x0 + field public static final int SCAN_TYPE_DIRECT = 1; // 0x1 + field public static final int SCAN_TYPE_DISEQC = 2; // 0x2 + field public static final int SCAN_TYPE_JESS = 4; // 0x4 + field public static final int SCAN_TYPE_UNDEFINED = 0; // 0x0 + field public static final int SCAN_TYPE_UNICABLE = 3; // 0x3 field public static final int STANDARD_AUTO = 1; // 0x1 field public static final int STANDARD_S = 2; // 0x2 field public static final int STANDARD_S2 = 4; // 0x4 @@ -5708,6 +5821,7 @@ package android.media.tv.tuner.frontend { method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setModulation(int); method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setPilot(int); method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setRolloff(int); + method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setScanType(int); method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setStandard(int); method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setSymbolRate(int); method @NonNull public android.media.tv.tuner.frontend.DvbsFrontendSettings.Builder setVcmMode(int); @@ -5760,10 +5874,14 @@ package android.media.tv.tuner.frontend { field public static final int CODERATE_AUTO = 1; // 0x1 field public static final int CODERATE_UNDEFINED = 0; // 0x0 field public static final int CONSTELLATION_16QAM = 4; // 0x4 + field public static final int CONSTELLATION_16QAM_R = 64; // 0x40 field public static final int CONSTELLATION_256QAM = 16; // 0x10 + field public static final int CONSTELLATION_256QAM_R = 256; // 0x100 field public static final int CONSTELLATION_64QAM = 8; // 0x8 + field public static final int CONSTELLATION_64QAM_R = 128; // 0x80 field public static final int CONSTELLATION_AUTO = 1; // 0x1 field public static final int CONSTELLATION_QPSK = 2; // 0x2 + field public static final int CONSTELLATION_QPSK_R = 32; // 0x20 field public static final int CONSTELLATION_UNDEFINED = 0; // 0x0 field public static final int GUARD_INTERVAL_19_128 = 64; // 0x40 field public static final int GUARD_INTERVAL_19_256 = 128; // 0x80 @@ -5797,6 +5915,9 @@ package android.media.tv.tuner.frontend { field public static final int TRANSMISSION_MODE_4K = 8; // 0x8 field public static final int TRANSMISSION_MODE_8K = 4; // 0x4 field public static final int TRANSMISSION_MODE_AUTO = 1; // 0x1 + field public static final int TRANSMISSION_MODE_EXTENDED_16K = 256; // 0x100 + field public static final int TRANSMISSION_MODE_EXTENDED_32K = 512; // 0x200 + field public static final int TRANSMISSION_MODE_EXTENDED_8K = 128; // 0x80 field public static final int TRANSMISSION_MODE_UNDEFINED = 0; // 0x0 } @@ -5834,8 +5955,12 @@ package android.media.tv.tuner.frontend { } public abstract class FrontendSettings { + method public int getEndFrequency(); method public int getFrequency(); + method public int getFrontendSpectralInversion(); method public abstract int getType(); + method @IntRange(from=1) public void setEndFrequency(int); + method public void setSpectralInversion(int); field public static final long FEC_11_15 = 4194304L; // 0x400000L field public static final long FEC_11_20 = 8388608L; // 0x800000L field public static final long FEC_11_45 = 16777216L; // 0x1000000L @@ -5873,9 +5998,13 @@ package android.media.tv.tuner.frontend { field public static final long FEC_9_20 = 2097152L; // 0x200000L field public static final long FEC_AUTO = 1L; // 0x1L field public static final long FEC_UNDEFINED = 0L; // 0x0L + field public static final int FRONTEND_SPECTRAL_INVERSION_INVERTED = 2; // 0x2 + field public static final int FRONTEND_SPECTRAL_INVERSION_NORMAL = 1; // 0x1 + field public static final int FRONTEND_SPECTRAL_INVERSION_UNDEFINED = 0; // 0x0 field public static final int TYPE_ANALOG = 1; // 0x1 field public static final int TYPE_ATSC = 2; // 0x2 field public static final int TYPE_ATSC3 = 3; // 0x3 + field public static final int TYPE_DTMB = 10; // 0xa field public static final int TYPE_DVBC = 4; // 0x4 field public static final int TYPE_DVBS = 5; // 0x5 field public static final int TYPE_DVBT = 6; // 0x6 @@ -9902,6 +10031,25 @@ package android.telephony { field public static final String MBMS_STREAMING_SERVICE_ACTION = "android.telephony.action.EmbmsStreaming"; } + public final class ModemActivityInfo implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public android.telephony.ModemActivityInfo getDelta(@NonNull android.telephony.ModemActivityInfo); + method public long getIdleTimeMillis(); + method public static int getNumTxPowerLevels(); + method public long getReceiveTimeMillis(); + method public long getSleepTimeMillis(); + method public long getTimestampMillis(); + method public long getTransmitDurationMillisAtPowerLevel(int); + method @NonNull public android.util.Range<java.lang.Integer> getTransmitPowerRange(int); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ModemActivityInfo> CREATOR; + field public static final int TX_POWER_LEVEL_0 = 0; // 0x0 + field public static final int TX_POWER_LEVEL_1 = 1; // 0x1 + field public static final int TX_POWER_LEVEL_2 = 2; // 0x2 + field public static final int TX_POWER_LEVEL_3 = 3; // 0x3 + field public static final int TX_POWER_LEVEL_4 = 4; // 0x4 + } + public final class NetworkRegistrationInfo implements android.os.Parcelable { method @Nullable public android.telephony.DataSpecificRegistrationInfo getDataSpecificInfo(); method public int getRegistrationState(); diff --git a/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java b/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java index 6d31a8d69ebe..3bfe41045b44 100644 --- a/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java +++ b/packages/CarSystemUI/src/com/android/systemui/wmshell/CarWMShellModule.java @@ -26,19 +26,24 @@ import com.android.systemui.wm.DisplaySystemBarsController; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayImeController; import com.android.wm.shell.common.TransactionPool; +import com.android.wm.shell.pip.Pip; +import dagger.BindsOptionalOf; import dagger.Module; import dagger.Provides; /** Provides dependencies from {@link com.android.wm.shell} for CarSystemUI. */ @Module(includes = WMShellBaseModule.class) -public class CarWMShellModule { +public abstract class CarWMShellModule { @SysUISingleton @Provides - DisplayImeController provideDisplayImeController(Context context, + static DisplayImeController provideDisplayImeController(Context context, IWindowManager wmService, DisplayController displayController, @Main Handler mainHandler, TransactionPool transactionPool) { return new DisplaySystemBarsController(context, wmService, displayController, mainHandler, transactionPool); } + + @BindsOptionalOf + abstract Pip optionalPip(); } diff --git a/packages/FusedLocation/src/com/android/location/fused/FusedLocationProvider.java b/packages/FusedLocation/src/com/android/location/fused/FusedLocationProvider.java index 900e68d36c32..6827d6eb0180 100644 --- a/packages/FusedLocation/src/com/android/location/fused/FusedLocationProvider.java +++ b/packages/FusedLocation/src/com/android/location/fused/FusedLocationProvider.java @@ -19,6 +19,9 @@ package com.android.location.fused; import static android.content.Intent.ACTION_USER_SWITCHED; import static android.location.LocationManager.GPS_PROVIDER; import static android.location.LocationManager.NETWORK_PROVIDER; +import static android.location.LocationRequest.QUALITY_LOW_POWER; + +import static com.android.location.provider.ProviderRequestUnbundled.INTERVAL_DISABLED; import android.annotation.Nullable; import android.content.BroadcastReceiver; @@ -35,7 +38,6 @@ import android.os.WorkSource; import com.android.internal.annotations.GuardedBy; import com.android.internal.location.ProviderRequest; import com.android.location.provider.LocationProviderBase; -import com.android.location.provider.LocationRequestUnbundled; import com.android.location.provider.ProviderPropertiesUnbundled; import com.android.location.provider.ProviderRequestUnbundled; @@ -147,8 +149,8 @@ public class FusedLocationProvider extends LocationProviderBase { mRequest = new ProviderRequestUnbundled(ProviderRequest.EMPTY_REQUEST); mWorkSource = new WorkSource(); - mGpsInterval = Long.MAX_VALUE; - mNetworkInterval = Long.MAX_VALUE; + mGpsInterval = INTERVAL_DISABLED; + mNetworkInterval = INTERVAL_DISABLED; } void start() { @@ -175,30 +177,9 @@ public class FusedLocationProvider extends LocationProviderBase { @GuardedBy("mLock") private void updateRequirementsLocked() { - long gpsInterval = Long.MAX_VALUE; - long networkInterval = Long.MAX_VALUE; - if (mRequest.getReportLocation()) { - for (LocationRequestUnbundled request : mRequest.getLocationRequests()) { - switch (request.getQuality()) { - case LocationRequestUnbundled.ACCURACY_FINE: - case LocationRequestUnbundled.ACCURACY_BLOCK: - case LocationRequestUnbundled.POWER_HIGH: - if (request.getInterval() < gpsInterval) { - gpsInterval = request.getInterval(); - } - if (request.getInterval() < networkInterval) { - networkInterval = request.getInterval(); - } - break; - case LocationRequestUnbundled.ACCURACY_CITY: - case LocationRequestUnbundled.POWER_LOW: - if (request.getInterval() < networkInterval) { - networkInterval = request.getInterval(); - } - break; - } - } - } + long gpsInterval = mRequest.getQuality() < QUALITY_LOW_POWER ? mRequest.getInterval() + : INTERVAL_DISABLED; + long networkInterval = mRequest.getInterval(); if (gpsInterval != mGpsInterval) { resetProviderRequestLocked(GPS_PROVIDER, mGpsInterval, gpsInterval, mGpsListener); @@ -214,11 +195,12 @@ public class FusedLocationProvider extends LocationProviderBase { @GuardedBy("mLock") private void resetProviderRequestLocked(String provider, long oldInterval, long newInterval, LocationListener listener) { - if (oldInterval != Long.MAX_VALUE) { + if (oldInterval != INTERVAL_DISABLED && newInterval == INTERVAL_DISABLED) { mLocationManager.removeUpdates(listener); } - if (newInterval != Long.MAX_VALUE) { + if (newInterval != INTERVAL_DISABLED) { LocationRequest request = new LocationRequest.Builder(newInterval) + .setQuality(mRequest.getQuality()) .setLocationSettingsIgnored(mRequest.isLocationSettingsIgnored()) .setWorkSource(mWorkSource) .build(); @@ -254,10 +236,10 @@ public class FusedLocationProvider extends LocationProviderBase { void dump(PrintWriter writer) { synchronized (mLock) { writer.println("request: " + mRequest); - if (mGpsInterval != Long.MAX_VALUE) { + if (mGpsInterval != INTERVAL_DISABLED) { writer.println(" gps interval: " + mGpsInterval); } - if (mNetworkInterval != Long.MAX_VALUE) { + if (mNetworkInterval != INTERVAL_DISABLED) { writer.println(" network interval: " + mNetworkInterval); } if (mGpsLocation != null) { diff --git a/packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java b/packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java index d3aa977f85b1..61349d9bb8e8 100644 --- a/packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java +++ b/packages/FusedLocation/test/src/com/android/location/fused/tests/FusedLocationServiceTest.java @@ -48,7 +48,6 @@ import org.junit.runner.RunWith; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.IOException; -import java.util.Collections; import java.util.Random; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; @@ -60,7 +59,6 @@ public class FusedLocationServiceTest { private static final long TIMEOUT_MS = 5000; - private Context mContext; private Random mRandom; private LocationManager mLocationManager; @@ -72,15 +70,15 @@ public class FusedLocationServiceTest { long seed = System.currentTimeMillis(); Log.i(TAG, "location seed: " + seed); - mContext = InstrumentationRegistry.getTargetContext(); + Context context = InstrumentationRegistry.getTargetContext(); mRandom = new Random(seed); - mLocationManager = mContext.getSystemService(LocationManager.class); + mLocationManager = context.getSystemService(LocationManager.class); setMockLocation(true); mManager = new LocationProviderManagerCapture(); mProvider = ILocationProvider.Stub.asInterface( - new FusedLocationProvider(mContext).getBinder()); + new FusedLocationProvider(context).getBinder()); mProvider.setLocationProviderManager(mManager); mLocationManager.addTestProvider(NETWORK_PROVIDER, @@ -118,12 +116,9 @@ public class FusedLocationServiceTest { @Test public void testNetworkRequest() throws Exception { - LocationRequest request = new LocationRequest.Builder(1000).build(); - mProvider.setRequest( new ProviderRequest.Builder() .setIntervalMillis(1000) - .setLocationRequests(Collections.singletonList(request)) .build(), new WorkSource()); @@ -135,14 +130,10 @@ public class FusedLocationServiceTest { @Test public void testGpsRequest() throws Exception { - LocationRequest request = new LocationRequest.Builder(1000) - .setQuality(LocationRequest.POWER_HIGH) - .build(); - mProvider.setRequest( new ProviderRequest.Builder() + .setQuality(LocationRequest.QUALITY_HIGH_ACCURACY) .setIntervalMillis(1000) - .setLocationRequests(Collections.singletonList(request)) .build(), new WorkSource()); diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java b/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java index 8e140ca27971..83974afd083f 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java +++ b/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java @@ -254,7 +254,7 @@ public final class FusedPrintersProvider extends Loader<List<PrinterInfo>> mLocationManager.requestLocationUpdates( LocationManager.FUSED_PROVIDER, new LocationRequest.Builder(LOCATION_UPDATE_MS) - .setQuality(LocationRequest.POWER_LOW) + .setQuality(LocationRequest.QUALITY_LOW_POWER) .build(), new HandlerExecutor(new Handler(Looper.getMainLooper())), this); diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml index 2f97f272c8b8..e2b04d485488 100644 --- a/packages/SettingsLib/res/values-af/strings.xml +++ b/packages/SettingsLib/res/values-af/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Voordat jy \'n beperkte profiel kan skep, moet jy \'n skermslot opstel om jou programme en persoonlike data te beskerm."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Stel slot op"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Skakel oor na <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Skep tans nuwe gebruiker …"</string> + <string name="user_nickname" msgid="262624187455825083">"Bynaam"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Voeg gas by"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Verwyder gas"</string> <string name="guest_nickname" msgid="6332276931583337261">"Gas"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Neem \'n foto"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Kies \'n prent"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Kies foto"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Toestelverstek"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Gedeaktiveer"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Geaktiveer"</string> diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml index f0d8a40b54ef..0e3684e27527 100644 --- a/packages/SettingsLib/res/values-am/strings.xml +++ b/packages/SettingsLib/res/values-am/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"የተገደበ መገለጫ መፍጠር ከመቻልዎ በፊት መተግበሪያዎችዎን እና የግል ውሂብዎን ለመጠበቅ ቁልፍ ማያ ገጽ ማዋቀር አለብዎት።"</string> <string name="user_set_lock_button" msgid="1427128184982594856">"ቁልፍ አዘጋጅ"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"ወደ <xliff:g id="USER_NAME">%s</xliff:g> ቀይር"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"አዲስ ተጠቃሚ በመፍጠር ላይ…"</string> + <string name="user_nickname" msgid="262624187455825083">"ቅጽል ስም"</string> <string name="guest_new_guest" msgid="3482026122932643557">"እንግዳን አክል"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"እንግዳን አስወግድ"</string> <string name="guest_nickname" msgid="6332276931583337261">"እንግዳ"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"ፎቶ አንሳ"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"ምስል ይምረጡ"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"ፎቶ ይምረጡ"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"የመሣሪያ ነባሪ"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"ተሰናክሏል"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ነቅቷል"</string> diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml index 323ba44ba420..7ec46d223d11 100644 --- a/packages/SettingsLib/res/values-ar/strings.xml +++ b/packages/SettingsLib/res/values-ar/strings.xml @@ -549,19 +549,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"قبل أن تتمكن من إنشاء ملف شخصي مقيد، يلزمك إعداد تأمين للشاشة لحماية تطبيقاتك وبياناتك الشخصية."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"تعيين التأمين"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"التبديل إلى <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"جارٍ إنشاء مستخدم جديد…"</string> + <string name="user_nickname" msgid="262624187455825083">"اللقب"</string> <string name="guest_new_guest" msgid="3482026122932643557">"إضافة ضيف"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"إزالة جلسة الضيف"</string> <string name="guest_nickname" msgid="6332276931583337261">"ضيف"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"التقاط صورة"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"اختيار صورة"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"اختيار صورة"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"الإعداد التلقائي للجهاز"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"غير مفعّل"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"مفعّل"</string> diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml index 7679c649c350..fe0409451fb5 100644 --- a/packages/SettingsLib/res/values-as/strings.xml +++ b/packages/SettingsLib/res/values-as/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"আপুনি সীমিত প্ৰ\'ফাইল এটা সৃষ্টি কৰাৰ আগেয়ে, আপোনাৰ ব্যক্তিগত ডেটা আৰু এপবিলাকক সুৰক্ষিত কৰিবলৈ স্ক্ৰীণ লক এটা নিৰ্ধাৰণ কৰিব লাগিব।"</string> <string name="user_set_lock_button" msgid="1427128184982594856">"লক ছেট কৰক"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g>লৈ সলনি কৰক"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"নতুন ব্যৱহাৰকাৰী সৃষ্টি কৰি থকা হৈছে…"</string> + <string name="user_nickname" msgid="262624187455825083">"উপনাম"</string> <string name="guest_new_guest" msgid="3482026122932643557">"অতিথি যোগ কৰক"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"অতিথি আঁতৰাওক"</string> <string name="guest_nickname" msgid="6332276931583337261">"অতিথি"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"এখন ফট’ তোলক"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"এখন প্ৰতিচ্ছবি বাছনি কৰক"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"ফট’ বাছনি কৰক"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"ডিভাইচ ডিফ’ল্ট"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"অক্ষম কৰা আছে"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"সক্ষম কৰা আছে"</string> diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml index d0bf0edca17a..bd10cfb928ac 100644 --- a/packages/SettingsLib/res/values-az/strings.xml +++ b/packages/SettingsLib/res/values-az/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Məhdudlaşdırılmış profil yaratmadan öncə, Siz tətbiqlərinizi və şəxsi datanızı qorumaq üçün ekran kilidi quraşdırmalısınız."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Kilid ayarlayın"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> adlı istifadəçiyə keçin"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Yeni istifadəçi yaradılır…"</string> + <string name="user_nickname" msgid="262624187455825083">"Ləqəb"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Qonaq əlavə edin"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Qonağı silin"</string> <string name="guest_nickname" msgid="6332276931583337261">"Qonaq"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Foto çəkin"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Şəkil seçin"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Foto seçin"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Cihaz defoltu"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Deaktiv"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Aktiv"</string> diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml index 3beb9b84e383..0deb9273c63b 100644 --- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml +++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml @@ -546,19 +546,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Da biste mogli da napravite ograničeni profil, treba da podesite zaključavanje ekrana da biste zaštitili aplikacije i lične podatke."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Podesi zaključavanje"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Pređi na korisnika <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Pravi se novi korisnik…"</string> + <string name="user_nickname" msgid="262624187455825083">"Nadimak"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Dodaj gosta"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Ukloni gosta"</string> <string name="guest_nickname" msgid="6332276931583337261">"Gost"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Slikaj"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Odaberi sliku"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Izaberite sliku"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Podrazumevano za uređaj"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Onemogućeno"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Omogućeno"</string> diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml index af6da4e64a36..9aad825d91ae 100644 --- a/packages/SettingsLib/res/values-be/strings.xml +++ b/packages/SettingsLib/res/values-be/strings.xml @@ -547,19 +547,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Перш чым вы зможаце стварыць профіль з абмежаваннямi, вам трэба наладзіць блакiроўку экрана для абароны сваiх дадаткаў і асабістай інфармацыі."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Усталёўка блакiроўкi"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Пераключыцца на карыстальніка <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Ствараецца новы карыстальнік…"</string> + <string name="user_nickname" msgid="262624187455825083">"Псеўданім"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Дадаць госця"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Выдаліць госця"</string> <string name="guest_nickname" msgid="6332276931583337261">"Госць"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Зрабіць фота"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Выбраць відарыс"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Выбраць фота"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Стандартная прылада"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Выключана"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Уключана"</string> diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml index 0097c9ced9ad..8bf13fe56c05 100644 --- a/packages/SettingsLib/res/values-bg/strings.xml +++ b/packages/SettingsLib/res/values-bg/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Преди да можете да създадете потребителски профил с ограничена функционалност, трябва да настроите заключения екран, за да защитите приложенията и личните си данни."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Задаване на заключване"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Превключване към <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Създава се нов потребител…"</string> + <string name="user_nickname" msgid="262624187455825083">"Псевдоним"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Добавяне на гост"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Премахване на госта"</string> <string name="guest_nickname" msgid="6332276931583337261">"Гост"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Правене на снимка"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Избиране на изображение"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Избиране на снимката"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Стандартна настройка за у-вото"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Деактивирано"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Активирано"</string> diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml index c3515420efed..8bcf9a6ba19f 100644 --- a/packages/SettingsLib/res/values-bn/strings.xml +++ b/packages/SettingsLib/res/values-bn/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"আপনি একটি সীমাবদ্ধযুক্ত প্রোফাইল তৈরি করার আগে, আপনাকে আপনার অ্যাপ্লিকেশন এবং ব্যক্তিগত ডেটা সুরক্ষিত করার জন্য একটি স্ক্রিন লক সেট-আপ করতে হবে।"</string> <string name="user_set_lock_button" msgid="1427128184982594856">"লক সেট করুন"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g>-এ পাল্টান"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"নতুন ব্যবহারকারী তৈরি করা হচ্ছে…"</string> + <string name="user_nickname" msgid="262624187455825083">"বিশেষ নাম"</string> <string name="guest_new_guest" msgid="3482026122932643557">"অতিথি যোগ করুন"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"অতিথি সরান"</string> <string name="guest_nickname" msgid="6332276931583337261">"অতিথি"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"ফটো তুলুন"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"একটি ইমেজ বেছে নিন"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"ফটো বেছে নিন"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"ডিভাইসের ডিফল্ট"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"বন্ধ করা আছে"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"চালু করা আছে"</string> diff --git a/packages/SettingsLib/res/values-bs/arrays.xml b/packages/SettingsLib/res/values-bs/arrays.xml index 775cd15edc0b..6d2f1f36f233 100644 --- a/packages/SettingsLib/res/values-bs/arrays.xml +++ b/packages/SettingsLib/res/values-bs/arrays.xml @@ -27,7 +27,7 @@ <item msgid="8356618438494652335">"Autentifikacija…"</item> <item msgid="2837871868181677206">"Dobivanje IP adrese…"</item> <item msgid="4613015005934755724">"Povezano"</item> - <item msgid="3763530049995655072">"Suspendirano"</item> + <item msgid="3763530049995655072">"Obustavljeno"</item> <item msgid="7852381437933824454">"Prekidanje veze…"</item> <item msgid="5046795712175415059">"Isključen"</item> <item msgid="2473654476624070462">"Neuspješno"</item> @@ -41,7 +41,7 @@ <item msgid="3028983857109369308">"Autentifikacija s mrežom <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item> <item msgid="4287401332778341890">"Dobivanje IP adrese iz mreže <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item> <item msgid="1043944043827424501">"Povezano s mrežom <xliff:g id="NETWORK_NAME">%1$s</xliff:g>"</item> - <item msgid="7445993821842009653">"Suspendirano"</item> + <item msgid="7445993821842009653">"Obustavljeno"</item> <item msgid="1175040558087735707">"Prekidanje veze s mrežom <xliff:g id="NETWORK_NAME">%1$s</xliff:g>…"</item> <item msgid="699832486578171722">"Isključen"</item> <item msgid="522383512264986901">"Neuspješno"</item> diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml index 3d3587302e67..32f6aa7774a7 100644 --- a/packages/SettingsLib/res/values-bs/strings.xml +++ b/packages/SettingsLib/res/values-bs/strings.xml @@ -546,19 +546,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Prije nego vam se omogući kreiranje ograničenog profila, morate postaviti zaključavanje ekrana da biste zaštitili svoje aplikacije i lične podatke."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Postaviti zaključavanje"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Prebaci na korisnika <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Kreiranje novog korisnika…"</string> + <string name="user_nickname" msgid="262624187455825083">"Nadimak"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Dodaj gosta"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Ukloni gosta"</string> <string name="guest_nickname" msgid="6332276931583337261">"Gost"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Snimite fotografiju"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Odaberite sliku"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Odabir fotografije"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Zadana postavka uređaja"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Onemogućeno"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Omogućeno"</string> diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml index b1edd7877650..525a1878c45c 100644 --- a/packages/SettingsLib/res/values-ca/strings.xml +++ b/packages/SettingsLib/res/values-ca/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Per crear un perfil restringit, has de configurar una pantalla de bloqueig per protegir les aplicacions i les dades personals."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Defineix un bloqueig"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Canvia a <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"S\'està creant l\'usuari…"</string> + <string name="user_nickname" msgid="262624187455825083">"Àlies"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Afegeix un convidat"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Suprimeix el convidat"</string> <string name="guest_nickname" msgid="6332276931583337261">"Convidat"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Fes una foto"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Tria una imatge"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Selecciona una foto"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Opció predeter. del dispositiu"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Desactivat"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Activat"</string> diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml index bdce444ce81b..64ad700c65bc 100644 --- a/packages/SettingsLib/res/values-cs/strings.xml +++ b/packages/SettingsLib/res/values-cs/strings.xml @@ -547,19 +547,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Před vytvořením omezeného profilu je nutné nejprve nastavit zámek obrazovky k ochraně aplikací a dat."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Nastavit zámek"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Přepnout na uživatele <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Vytváření nového uživatele…"</string> + <string name="user_nickname" msgid="262624187455825083">"Přezdívka"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Přidat hosta"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Odstranit hosta"</string> <string name="guest_nickname" msgid="6332276931583337261">"Host"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Pořídit fotku"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Vybrat obrázek"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Vybrat fotku"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Výchozí nastavení zařízení"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Vypnuto"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Zapnuto"</string> diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml index 1dc0e4ed077f..433368bb9a83 100644 --- a/packages/SettingsLib/res/values-da/strings.xml +++ b/packages/SettingsLib/res/values-da/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Før du kan oprette en begrænset profil, skal du oprette en skærmlås for at beskytte dine apps og personlige data."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Konfigurer låseskærmen"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Skift til <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Opretter ny bruger…"</string> + <string name="user_nickname" msgid="262624187455825083">"Kaldenavn"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Tilføj gæsten"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Fjern gæsten"</string> <string name="guest_nickname" msgid="6332276931583337261">"Gæst"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Tag et billede"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Vælg et billede"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Vælg billede"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Enhedens standardindstilling"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Deaktiveret"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Aktiveret"</string> diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml index a9cdf1ff81bf..9946eed222e2 100644 --- a/packages/SettingsLib/res/values-de/strings.xml +++ b/packages/SettingsLib/res/values-de/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Vor dem Erstellen eines eingeschränkten Profils musst du eine Displaysperre einrichten, um deine Apps und personenbezogenen Daten zu schützen."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Sperre einrichten"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Zu <xliff:g id="USER_NAME">%s</xliff:g> wechseln"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Neuer Nutzer wird erstellt…"</string> + <string name="user_nickname" msgid="262624187455825083">"Alias"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Gast hinzufügen"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Gast entfernen"</string> <string name="guest_nickname" msgid="6332276931583337261">"Gast"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Foto machen"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Bild auswählen"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Foto auswählen"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Gerätestandard"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Deaktiviert"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Aktiviert"</string> diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml index 00b843495a9b..c265dbc427ec 100644 --- a/packages/SettingsLib/res/values-el/strings.xml +++ b/packages/SettingsLib/res/values-el/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Προκειμένου να μπορέσετε να δημιουργήσετε ένα περιορισμένο προφίλ, θα πρέπει να δημιουργήσετε ένα κλείδωμα οθόνης για την προστασία των εφαρμογών και των προσωπικών δεδομένων σας."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Ορισμός κλειδώματος"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Εναλλαγή σε <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Δημιουργία νέου χρήστη…"</string> + <string name="user_nickname" msgid="262624187455825083">"Ψευδώνυμο"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Προσθήκη επισκέπτη"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Κατάργηση επισκέπτη"</string> <string name="guest_nickname" msgid="6332276931583337261">"Επισκέπτης"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Λήψη φωτογραφίας"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Επιλογή εικόνας"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Επιλογή φωτογραφίας"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Προεπιλογή συσκευής"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Ανενεργή"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Ενεργή"</string> diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml index 4bb2d8a592f1..285c615f8224 100644 --- a/packages/SettingsLib/res/values-en-rAU/strings.xml +++ b/packages/SettingsLib/res/values-en-rAU/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Before you can create a restricted profile, you\'ll need to set up a screen lock to protect your apps and personal data."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Set lock"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Switch to <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Creating new user…"</string> + <string name="user_nickname" msgid="262624187455825083">"Nickname"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Add guest"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Remove guest"</string> <string name="guest_nickname" msgid="6332276931583337261">"Guest"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Take a photo"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Choose an image"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Select photo"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Device default"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Disabled"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Enabled"</string> diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml index 05c12d680c89..bbd5c7600818 100644 --- a/packages/SettingsLib/res/values-en-rCA/strings.xml +++ b/packages/SettingsLib/res/values-en-rCA/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Before you can create a restricted profile, you\'ll need to set up a screen lock to protect your apps and personal data."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Set lock"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Switch to <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Creating new user…"</string> + <string name="user_nickname" msgid="262624187455825083">"Nickname"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Add guest"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Remove guest"</string> <string name="guest_nickname" msgid="6332276931583337261">"Guest"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Take a photo"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Choose an image"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Select photo"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Device default"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Disabled"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Enabled"</string> diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml index 4bb2d8a592f1..285c615f8224 100644 --- a/packages/SettingsLib/res/values-en-rGB/strings.xml +++ b/packages/SettingsLib/res/values-en-rGB/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Before you can create a restricted profile, you\'ll need to set up a screen lock to protect your apps and personal data."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Set lock"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Switch to <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Creating new user…"</string> + <string name="user_nickname" msgid="262624187455825083">"Nickname"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Add guest"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Remove guest"</string> <string name="guest_nickname" msgid="6332276931583337261">"Guest"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Take a photo"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Choose an image"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Select photo"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Device default"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Disabled"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Enabled"</string> diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml index 4bb2d8a592f1..285c615f8224 100644 --- a/packages/SettingsLib/res/values-en-rIN/strings.xml +++ b/packages/SettingsLib/res/values-en-rIN/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Before you can create a restricted profile, you\'ll need to set up a screen lock to protect your apps and personal data."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Set lock"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Switch to <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Creating new user…"</string> + <string name="user_nickname" msgid="262624187455825083">"Nickname"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Add guest"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Remove guest"</string> <string name="guest_nickname" msgid="6332276931583337261">"Guest"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Take a photo"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Choose an image"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Select photo"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Device default"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Disabled"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Enabled"</string> diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml index 1dc5f5b332fc..ab421f6f4154 100644 --- a/packages/SettingsLib/res/values-es-rUS/strings.xml +++ b/packages/SettingsLib/res/values-es-rUS/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Para poder crear un perfil restringido, debes configurar un bloqueo de pantalla que proteja tus aplicaciones y datos personales."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Configurar bloqueo"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Cambiar a <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Creando usuario nuevo…"</string> + <string name="user_nickname" msgid="262624187455825083">"Sobrenombre"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Agregar invitado"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Quitar invitado"</string> <string name="guest_nickname" msgid="6332276931583337261">"Invitado"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Tomar una foto"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Elegir una imagen"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Seleccionar foto"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Predeterminado del dispositivo"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Inhabilitado"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Habilitado"</string> diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml index 977b4694d6c6..f6157b42312f 100644 --- a/packages/SettingsLib/res/values-es/strings.xml +++ b/packages/SettingsLib/res/values-es/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Para poder crear un perfil restringido, debes configurar una pantalla de bloqueo que proteja tus aplicaciones y datos personales."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Establecer bloqueo"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Cambiar a <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Creando usuario…"</string> + <string name="user_nickname" msgid="262624187455825083">"Apodo"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Añadir invitado"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Quitar invitado"</string> <string name="guest_nickname" msgid="6332276931583337261">"Invitado"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Hacer foto"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Seleccionar una imagen"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Seleccionar foto"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Predeterminado por el dispositivo"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Inhabilitado"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Habilitado"</string> diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml index 3c2593aa1ed7..72766c067525 100644 --- a/packages/SettingsLib/res/values-et/strings.xml +++ b/packages/SettingsLib/res/values-et/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Enne piiratud profiili loomist peate seadistama lukustusekraani, et oma rakendusi ja isiklikke andmeid kaitsta."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Määra lukk"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Lülita kasutajale <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Uue kasutaja loomine …"</string> + <string name="user_nickname" msgid="262624187455825083">"Hüüdnimi"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Lisa külaline"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Eemalda külaline"</string> <string name="guest_nickname" msgid="6332276931583337261">"Külaline"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Pildistage"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Valige pilt"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Valige foto"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Seadme vaikeseade"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Keelatud"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Lubatud"</string> diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml index 33ce3c73959d..c7462cef36b7 100644 --- a/packages/SettingsLib/res/values-eu/strings.xml +++ b/packages/SettingsLib/res/values-eu/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Profil murriztua sortu aurretik, aplikazioak eta datu pertsonalak babesteko, pantaila blokeatzeko metodo bat konfiguratu beharko duzu."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Ezarri blokeoa"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Aldatu <xliff:g id="USER_NAME">%s</xliff:g> erabiltzailera"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Beste erabiltzaile bat sortzen…"</string> + <string name="user_nickname" msgid="262624187455825083">"Goitizena"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Gehitu gonbidatua"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Kendu gonbidatua"</string> <string name="guest_nickname" msgid="6332276931583337261">"Gonbidatua"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Atera argazki bat"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Aukeratu irudi bat"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Hautatu argazki bat"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Gailuaren balio lehenetsia"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Desgaituta"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Gaituta"</string> diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml index 045378886eaa..c5a4f2fbc11b 100644 --- a/packages/SettingsLib/res/values-fa/strings.xml +++ b/packages/SettingsLib/res/values-fa/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"قبل از ایجاد یک نمایه محدود، باید یک قفل صفحه را برای محافظت از برنامهها و دادههای شخصی خود تنظیم کنید."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"تنظیم قفل"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"رفتن به <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"درحال ایجاد کاربر جدید…"</string> + <string name="user_nickname" msgid="262624187455825083">"نام مستعار"</string> <string name="guest_new_guest" msgid="3482026122932643557">"افزودن مهمان"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"حذف مهمان"</string> <string name="guest_nickname" msgid="6332276931583337261">"مهمان"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"عکس گرفتن"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"انتخاب تصویر"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"انتخاب عکس"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"پیشفرض دستگاه"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"غیرفعال"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"فعال"</string> diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml index 7f85572ba023..dd1c12a0dc27 100644 --- a/packages/SettingsLib/res/values-fi/strings.xml +++ b/packages/SettingsLib/res/values-fi/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Ennen kuin voit luoda rajoitetun profiilin, määritä näytön lukitus, joka suojelee sovelluksiasi ja henkilökohtaisia tietojasi."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Aseta lukitus"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Vaihda tähän käyttäjään: <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Luodaan uutta käyttäjää…"</string> + <string name="user_nickname" msgid="262624187455825083">"Lempinimi"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Lisää vieras"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Poista vieras"</string> <string name="guest_nickname" msgid="6332276931583337261">"Vieras"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Ota valokuva"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Valitse kuva"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Valitse valokuva"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Laitteen oletusasetus"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Ei käytössä"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Käytössä"</string> diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml index 1745e0298871..f0364c614d56 100644 --- a/packages/SettingsLib/res/values-fr-rCA/strings.xml +++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Avant de créer un profil limité, vous devez définir un écran de verrouillage pour protéger vos applications et vos données personnelles."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Définir verrouillage écran"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Passer à <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Créer un utilisateur…"</string> + <string name="user_nickname" msgid="262624187455825083">"Pseudo"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Ajouter un invité"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Supprimer l\'invité"</string> <string name="guest_nickname" msgid="6332276931583337261">"Invité"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Prendre une photo"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Sélectionner une image"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Sélectionnez une photo"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Valeur par défaut de l\'appareil"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Désactivé"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Activé"</string> diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml index 8c753ae26d3a..17d13c1568df 100644 --- a/packages/SettingsLib/res/values-fr/strings.xml +++ b/packages/SettingsLib/res/values-fr/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Avant de créer un profil limité, vous devez définir un écran de verrouillage pour protéger vos applications et vos données personnelles."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Définir verrouillage écran"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Passer à <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Création d\'un nouvel utilisateur…"</string> + <string name="user_nickname" msgid="262624187455825083">"Pseudo"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Ajouter un invité"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Supprimer l\'invité"</string> <string name="guest_nickname" msgid="6332276931583337261">"Invité"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Prendre une photo"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Choisir une image"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Sélectionner une photo"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Paramètre par défaut"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Désactivé"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Activé"</string> diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml index 414564b505e4..e0b21c38ff67 100644 --- a/packages/SettingsLib/res/values-gl/strings.xml +++ b/packages/SettingsLib/res/values-gl/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Para poder crear un perfil restrinxido, precisarás configurar un bloqueo da pantalla para protexer as túas aplicacións e datos persoais."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Establecer bloqueo"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Cambiar a <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Creando usuario novo…"</string> + <string name="user_nickname" msgid="262624187455825083">"Alcume"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Engadir convidado"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Quitar convidado"</string> <string name="guest_nickname" msgid="6332276931583337261">"Convidado"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Tirar foto"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Escoller imaxe"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Seleccionar foto"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Funcionamento predeterminado"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Desactivado"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Activado"</string> diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml index 634870ce77a4..08a2b99458cd 100644 --- a/packages/SettingsLib/res/values-gu/strings.xml +++ b/packages/SettingsLib/res/values-gu/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"તમે પ્રતિબંધિત પ્રોફાઇલ બનાવી શકો તે પહેલાં, તમારે તમારી ઍપ્લિકેશનો અને વ્યક્તિગત ડેટાની સુરક્ષા માટે એક લૉક સ્ક્રીન સેટ કરવાની જરૂર પડશે."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"લૉક સેટ કરો"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> પર સ્વિચ કરો"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"નવા વપરાશકર્તા બનાવી રહ્યાં છીએ…"</string> + <string name="user_nickname" msgid="262624187455825083">"ઉપનામ"</string> <string name="guest_new_guest" msgid="3482026122932643557">"અતિથિ ઉમેરો"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"અતિથિને કાઢી નાખો"</string> <string name="guest_nickname" msgid="6332276931583337261">"અતિથિ"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"ફોટો લો"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"છબી પસંદ કરો"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"ફોટો પસંદ કરો"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"ડિવાઇસ ડિફૉલ્ટ"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"બંધ છે"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ચાલુ છે"</string> diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml index bd052c03ccb1..8486e3444db6 100644 --- a/packages/SettingsLib/res/values-hi/strings.xml +++ b/packages/SettingsLib/res/values-hi/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"इससे पहले कि आप कोई प्रतिबंधित प्रोफ़ाइल बनाएं, आपको अपने ऐप्लिकेशन और व्यक्तिगत डेटा की सुरक्षा करने के लिए एक स्क्रीन लॉक सेट करना होगा."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"लॉक सेट करें"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> पर जाएं"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"नया उपयोगकर्ता बनाया जा रहा है…"</string> + <string name="user_nickname" msgid="262624187455825083">"प्रचलित नाम"</string> <string name="guest_new_guest" msgid="3482026122932643557">"मेहमान जोड़ें"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"मेहमान हटाएं"</string> <string name="guest_nickname" msgid="6332276931583337261">"मेहमान"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"फ़ोटो खींचें"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"कोई इमेज चुनें"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"फ़ोटो चुनें"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"डिवाइस की डिफ़ॉल्ट सेटिंग"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"बंद है"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"चालू है"</string> diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml index 3cff48068dda..a4ef3230fb5e 100644 --- a/packages/SettingsLib/res/values-hr/strings.xml +++ b/packages/SettingsLib/res/values-hr/strings.xml @@ -546,19 +546,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Prije izrade ograničenog profila trebate postaviti zaključavanje zaslona radi zaštite svojih aplikacija i osobnih podataka."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Postavi zaključavanje"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Prelazak na korisnika <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Izrada novog korisnika…"</string> + <string name="user_nickname" msgid="262624187455825083">"Nadimak"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Dodavanje gosta"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Uklanjanje gosta"</string> <string name="guest_nickname" msgid="6332276931583337261">"Gost"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Fotografiraj"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Odaberi sliku"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Odabir slike"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Zadana postavka uređaja"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Onemogućeno"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Omogućeno"</string> diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml index 854265caf47b..480552b7b6b5 100644 --- a/packages/SettingsLib/res/values-hu/strings.xml +++ b/packages/SettingsLib/res/values-hu/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Mielőtt létrehozhatna egy korlátozott profilt, be kell állítania egy képernyőzárat, hogy megvédje alkalmazásait és személyes adatait."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Képernyőzár beállítása"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Váltás erre: <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Új felhasználó létrehozása…"</string> + <string name="user_nickname" msgid="262624187455825083">"Becenév"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Vendég hozzáadása"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Vendég munkamenet eltávolítása"</string> <string name="guest_nickname" msgid="6332276931583337261">"Vendég"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Fotó készítése"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Kép kiválasztása"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Fotó kiválasztása"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Alapértelmezett"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Letiltva"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Engedélyezve"</string> diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml index 35b218edd1c2..9fbf998dd14f 100644 --- a/packages/SettingsLib/res/values-hy/strings.xml +++ b/packages/SettingsLib/res/values-hy/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Նախքան դուք կկարողանաք ստեղծել սահմանափակ պրոֆիլ, դուք պետք է կարգավորեք էկրանի կողպումը` ձեր ծրագրերը և անձնական տվյալները պաշտպանելու համար:"</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Կարգավորել կողպումը"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Անցնել <xliff:g id="USER_NAME">%s</xliff:g> պրոֆիլին"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Ստեղծվում է օգտատիրոջ նոր պրոֆիլ…"</string> + <string name="user_nickname" msgid="262624187455825083">"Կեղծանուն"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Ավելացնել հյուր"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Հեռացնել հյուրին"</string> <string name="guest_nickname" msgid="6332276931583337261">"Հյուր"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Լուսանկարել"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Ընտրել պատկեր"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Ընտրեք լուսանկար"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Կանխադրված տարբերակ"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Անջատված է"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Միացված է"</string> diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml index cf6455ffe0c6..b1391ecaae73 100644 --- a/packages/SettingsLib/res/values-in/strings.xml +++ b/packages/SettingsLib/res/values-in/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Sebelum dapat membuat profil yang dibatasi, Anda perlu menyiapkan kunci layar untuk melindungi aplikasi dan data pribadi Anda."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Setel kunci"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Beralih ke <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Membuat pengguna baru …"</string> + <string name="user_nickname" msgid="262624187455825083">"Nama panggilan"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Tambahkan tamu"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Hapus tamu"</string> <string name="guest_nickname" msgid="6332276931583337261">"Tamu"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Ambil foto"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Pilih gambar"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Pilih foto"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Default perangkat"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Nonaktif"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Aktif"</string> diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml index b4be963b44b2..1636c5542a8d 100644 --- a/packages/SettingsLib/res/values-is/strings.xml +++ b/packages/SettingsLib/res/values-is/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Áður en þú getur búið til takmarkað snið þarftu að setja upp skjálás til að vernda forritin þín og persónuleg gögn."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Velja lás"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Skipta yfir í <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Stofnar nýjan notanda…"</string> + <string name="user_nickname" msgid="262624187455825083">"Gælunafn"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Bæta gesti við"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Fjarlægja gest"</string> <string name="guest_nickname" msgid="6332276931583337261">"Gestur"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Taka mynd"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Velja mynd"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Velja mynd"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Sjálfgefin stilling tækis"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Slökkt"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Virkt"</string> diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml index 69b1b5eed9c9..b358d651ac19 100644 --- a/packages/SettingsLib/res/values-it/strings.xml +++ b/packages/SettingsLib/res/values-it/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Prima di poter creare un profilo con limitazioni, devi impostare un blocco schermo per proteggere le tue app e i tuoi dati personali."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Imposta blocco"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Passa a <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Creazione nuovo utente…"</string> + <string name="user_nickname" msgid="262624187455825083">"Nickname"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Aggiungi ospite"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Rimuovi ospite"</string> <string name="guest_nickname" msgid="6332276931583337261">"Ospite"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Scatta una foto"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Scegli un\'immagine"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Seleziona la foto"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Parametro predefinito"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Non attivo"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Attivo"</string> diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml index 158872df8365..0f2eb4bd5fb1 100644 --- a/packages/SettingsLib/res/values-iw/strings.xml +++ b/packages/SettingsLib/res/values-iw/strings.xml @@ -547,19 +547,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"לפני שתוכל ליצור פרופיל מוגבל, תצטרך להגדיר נעילת מסך כדי להגן על האפליקציות ועל הנתונים האישיים שלך."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"הגדרת נעילה"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"מעבר אל <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"בתהליך יצירה של משתמש חדש…"</string> + <string name="user_nickname" msgid="262624187455825083">"כינוי"</string> <string name="guest_new_guest" msgid="3482026122932643557">"הוספת אורח"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"הסרת אורח"</string> <string name="guest_nickname" msgid="6332276931583337261">"אורח"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"צילום תמונה"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"לבחירת תמונה"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"בחירת תמונה"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"ברירת המחדל של המכשיר"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"מושבת"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"מופעל"</string> diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml index 13fd53fc1198..dba1c95aade0 100644 --- a/packages/SettingsLib/res/values-ja/strings.xml +++ b/packages/SettingsLib/res/values-ja/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"制限付きプロファイルを作成する場合は、アプリや個人データを保護するように画面ロックを設定しておく必要があります。"</string> <string name="user_set_lock_button" msgid="1427128184982594856">"ロックを設定"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> に切り替え"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"新しいユーザーを作成しています…"</string> + <string name="user_nickname" msgid="262624187455825083">"ニックネーム"</string> <string name="guest_new_guest" msgid="3482026122932643557">"ゲストを追加"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"ゲストを削除"</string> <string name="guest_nickname" msgid="6332276931583337261">"ゲスト"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"写真を撮る"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"画像を選択"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"写真を選択"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"デバイスのデフォルト"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"無効"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"有効"</string> diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml index f411d00c595d..ffb5c9aa27a6 100644 --- a/packages/SettingsLib/res/values-kk/strings.xml +++ b/packages/SettingsLib/res/values-kk/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Шектелген профайл жасақтауға дейін қолданбалар мен жеке деректерді қорғау үшін экран бекітпесін тағайындау қажет."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Бекітпе тағайындау"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> пайдаланушысына ауысу"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Жаңа пайдаланушы профилі жасалуда…"</string> + <string name="user_nickname" msgid="262624187455825083">"Лақап ат"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Қонақты енгізу"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Қонақты өшіру"</string> <string name="guest_nickname" msgid="6332276931583337261">"Қонақ"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Фотосуретке түсіру"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Сурет таңдау"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Фотосурет таңдау"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Құрылғыны әдепкісінше реттеу"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Өшірулі"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Қосулы"</string> diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml index 9b7cc4c1ab47..6fbd2d124538 100644 --- a/packages/SettingsLib/res/values-km/strings.xml +++ b/packages/SettingsLib/res/values-km/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"មុនពេលអ្នកអាចបង្កើតប្រវត្តិរូបបានដាក់កម្រិត អ្នកត្រូវរៀបចំការចាក់សោអេក្រង់ ដើម្បីការពារកម្មវិធី និងទិន្នន័យផ្ទាល់ខ្លួនរបស់អ្នក។"</string> <string name="user_set_lock_button" msgid="1427128184982594856">"កំណត់ការចាក់សោ"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"ប្ដូរទៅ <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"កំពុងបង្កើតអ្នកប្រើប្រាស់ថ្មី…"</string> + <string name="user_nickname" msgid="262624187455825083">"ឈ្មោះហៅក្រៅ"</string> <string name="guest_new_guest" msgid="3482026122932643557">"បញ្ចូលភ្ញៀវ"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"លុបភ្ញៀវ"</string> <string name="guest_nickname" msgid="6332276931583337261">"ភ្ញៀវ"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"ថតរូប"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"ជ្រើសរើសរូបភាព"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"ជ្រើសរើសរូបថត"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"លំនាំដើមរបស់ឧបករណ៍"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"បានបិទ"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"បានបើក"</string> diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml index 1f74d9b60cc8..653d8ba062e9 100644 --- a/packages/SettingsLib/res/values-kn/strings.xml +++ b/packages/SettingsLib/res/values-kn/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"ನೀವು ನಿರ್ಬಂಧಿತ ಪ್ರೊಫೈಲ್ ಅನ್ನು ರಚಿಸಬಹುದಾದರ ಮೊದಲು, ನಿಮ್ಮ ಅಪ್ಲಿಕೇಶನ್ಗಳು ಮತ್ತು ವೈಯಕ್ತಿಕ ಡೇಟಾವನ್ನು ರಕ್ಷಿಸಲು ನೀವು ಪರದೆಯ ಲಾಕ್ ಹೊಂದಿಸುವ ಅಗತ್ಯವಿದೆ."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"ಲಾಕ್ ಹೊಂದಿಸಿ"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> ಗೆ ಬದಲಿಸಿ"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"ಹೊಸ ಬಳಕೆದಾರರನ್ನು ರಚಿಸಲಾಗುತ್ತಿದೆ…"</string> + <string name="user_nickname" msgid="262624187455825083">"ಅಡ್ಡ ಹೆಸರು"</string> <string name="guest_new_guest" msgid="3482026122932643557">"ಅತಿಥಿಯನ್ನು ಸೇರಿಸಿ"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"ಅತಿಥಿಯನ್ನು ತೆಗೆದುಹಾಕಿ"</string> <string name="guest_nickname" msgid="6332276931583337261">"ಅತಿಥಿ"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"ಫೋಟೋ ತೆಗೆದುಕೊಳ್ಳಿ"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"ಚಿತ್ರವನ್ನು ಆರಿಸಿ"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"ಫೋಟೋ ಆಯ್ಕೆಮಾಡಿ"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"ಸಾಧನದ ಡೀಫಾಲ್ಟ್"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string> diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml index d1308345a1f9..761f8133f569 100644 --- a/packages/SettingsLib/res/values-ko/strings.xml +++ b/packages/SettingsLib/res/values-ko/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"제한된 프로필을 만들기 전에 화면 잠금을 설정하여 앱과 개인 데이터를 보호해야 합니다."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"잠금 설정"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g>(으)로 전환"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"새로운 사용자를 만드는 중…"</string> + <string name="user_nickname" msgid="262624187455825083">"닉네임"</string> <string name="guest_new_guest" msgid="3482026122932643557">"게스트 추가"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"게스트 삭제"</string> <string name="guest_nickname" msgid="6332276931583337261">"게스트"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"사진 찍기"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"이미지 선택"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"사진 선택"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"기기 기본값"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"사용 중지됨"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"사용 설정됨"</string> diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml index 5672913174ee..c72b93f4498b 100644 --- a/packages/SettingsLib/res/values-ky/strings.xml +++ b/packages/SettingsLib/res/values-ky/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Чектелген профайл түзөөрдөн мурун, сиз өзүңүздүн колдонмолоруңузду жана жеке маалыматтарыңызды коргош үчүн, бөгөттөө көшөгөсүн орнотушуңуз керек болот."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Бөгөт коюу"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> аккаунтуна которулуу"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Жаңы колдонуучу түзүлүүдө…"</string> + <string name="user_nickname" msgid="262624187455825083">"Ылакап аты"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Конок кошуу"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Конокту өчүрүү"</string> <string name="guest_nickname" msgid="6332276931583337261">"Конок"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Сүрөткө тартуу"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Сүрөт тандаңыз"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Сүрөт тандаңыз"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Түзмөктүн демейки параметри"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Өчүк"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Күйүк"</string> diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml index b3b3c8107d81..78833086d2ca 100644 --- a/packages/SettingsLib/res/values-lo/strings.xml +++ b/packages/SettingsLib/res/values-lo/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"ກ່ອນທ່ານຈະສ້າງໂປຣໄຟລ໌ທີ່ຖືກຈຳກັດນັ້ນ, ທ່ານຈະຕ້ອງຕັ້ງຄ່າການລັອກໜ້າຈໍ ເພື່ອປ້ອງກັນແອັບຯ ແລະຂໍ້ມູນສ່ວນໂຕຂອງທ່ານກ່ອນ."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"ຕັ້ງການລັອກ"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"ສະຫຼັບໄປ <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"ກຳລັງສ້າງຜູ້ໃຊ້ໃໝ່…"</string> + <string name="user_nickname" msgid="262624187455825083">"ຊື່ຫຼິ້ນ"</string> <string name="guest_new_guest" msgid="3482026122932643557">"ເພີ່ມແຂກ"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"ລຶບແຂກອອກ"</string> <string name="guest_nickname" msgid="6332276931583337261">"ແຂກ"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"ຖ່າຍຮູບ"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"ເລືອກຮູບ"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"ເລືອກຮູບ"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"ຄ່າເລີ່ມຕົ້ນອຸປະກອນ"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"ປິດການນຳໃຊ້ແລ້ວ"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ເປີດການນຳໃຊ້ແລ້ວ"</string> diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml index 2e5385ecc770..e3aa3687d5f9 100644 --- a/packages/SettingsLib/res/values-lt/strings.xml +++ b/packages/SettingsLib/res/values-lt/strings.xml @@ -547,19 +547,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Prieš kuriant apribotą profilį reikės nustatyti ekrano užraktą, kad apsaugotumėte programas ir asmeninius duomenis."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Nustatyti užraktą"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Perjungti į <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Kuriamas naujas naudotojas…"</string> + <string name="user_nickname" msgid="262624187455825083">"Slapyvardis"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Pridėti svečią"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Pašalinti svečią"</string> <string name="guest_nickname" msgid="6332276931583337261">"Svečias"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Fotografuoti"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Pasirinkti vaizdą"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Pasirinkti nuotrauką"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Numatyt. įrenginio nustatymas"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Išjungta"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Įgalinta"</string> diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml index f4fe8e30a73b..e994974d813d 100644 --- a/packages/SettingsLib/res/values-lv/strings.xml +++ b/packages/SettingsLib/res/values-lv/strings.xml @@ -546,19 +546,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Lai varētu izveidot ierobežotu profilu, jums jāiestata ekrāna bloķēšana, kas aizsargās jūsu lietotni un personas datus."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Iestatīt bloķēšanu"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Pārslēgties uz: <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Notiek jauna lietotāja izveide…"</string> + <string name="user_nickname" msgid="262624187455825083">"Segvārds"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Pievienot viesi"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Noņemt viesi"</string> <string name="guest_nickname" msgid="6332276931583337261">"Viesis"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Uzņemt fotoattēlu"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Izvēlēties attēlu"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Atlasīt fotoattēlu"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Ierīces noklusējums"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Atspējots"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Iespējots"</string> diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml index 1e933fbe5591..e711747f328f 100644 --- a/packages/SettingsLib/res/values-mk/strings.xml +++ b/packages/SettingsLib/res/values-mk/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Пред да може да создадете ограничен профил, треба да поставите заклучување на екранот за да ги заштити вашите апликации и лични податоци."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Постави заклучување"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Префрли на <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Се создава нов корисник…"</string> + <string name="user_nickname" msgid="262624187455825083">"Прекар"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Додај гостин"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Отстрани гостин"</string> <string name="guest_nickname" msgid="6332276931583337261">"Гостин"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Фотографирајте"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Одберете слика"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Изберете фотографија"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Стандардно за уредот"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Оневозможено"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Овозможено"</string> diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml index 970f778119e3..cebd55213599 100644 --- a/packages/SettingsLib/res/values-ml/strings.xml +++ b/packages/SettingsLib/res/values-ml/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"ഒരു നിയന്ത്രിത പ്രൊഫൈൽ സൃഷ്ടിക്കുന്നതിനുമുമ്പ്, നിങ്ങളുടെ അപ്ലിക്കേഷനുകളും വ്യക്തിഗത ഡാറ്റയും പരിരക്ഷിക്കുന്നതിന് ഒരു സ്ക്രീൻ ലോക്ക് സജ്ജീകരിക്കേണ്ടതുണ്ട്."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"ലോക്ക് സജ്ജീകരിക്കുക"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> എന്നതിലേക്ക് മാറുക"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"പുതിയ ഉപയോക്താവിനെ സൃഷ്ടിക്കുന്നു…"</string> + <string name="user_nickname" msgid="262624187455825083">"വിളിപ്പേര്"</string> <string name="guest_new_guest" msgid="3482026122932643557">"അതിഥിയെ ചേർക്കുക"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"അതിഥിയെ നീക്കം ചെയ്യുക"</string> <string name="guest_nickname" msgid="6332276931583337261">"അതിഥി"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"ഒരു ഫോട്ടോ എടുക്കുക"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"ഒരു ചിത്രം തിരഞ്ഞെടുക്കുക"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"ഫോട്ടോ തിരഞ്ഞെടുക്കുക"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"ഉപകരണത്തിന്റെ ഡിഫോൾട്ട് പ്രവർത്തനം"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"പ്രവർത്തനരഹിതമാക്കി"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"പ്രവർത്തനക്ഷമമാക്കി"</string> diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml index 3dc498946ff0..80743665ca22 100644 --- a/packages/SettingsLib/res/values-mn/strings.xml +++ b/packages/SettingsLib/res/values-mn/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Та хязгаарлагдсан профайл үүсгэхийн өмнө өөрийн апп-ууд болон хувийн өгөгдлийг хамгаалахын тулд дэлгэцийн түгжээг тохируулах шаардлагатай."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Түгжээг тохируулах"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> руу сэлгэх"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Шинэ хэрэглэгч үүсгэж байна…"</string> + <string name="user_nickname" msgid="262624187455825083">"Хоч"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Зочин нэмэх"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Зочин хасах"</string> <string name="guest_nickname" msgid="6332276931583337261">"Зочин"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Зураг авах"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Зураг сонгох"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Зураг сонгох"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Төхөөрөмжийн өгөгдмөл"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Идэвхгүй болгосон"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Идэвхжүүлсэн"</string> diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml index 7e418a48b9aa..fbfe84cffbf8 100644 --- a/packages/SettingsLib/res/values-mr/strings.xml +++ b/packages/SettingsLib/res/values-mr/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"तुम्ही एक प्रतिबंधित प्रोफाईल तयार करु शकण्यापूर्वी तुम्हाला तुमचे अॅप्स आणि वैयक्तिक डेटा संरक्षित करण्यासाठी एक स्क्रीन लॉक सेट करण्याची आवश्यकता राहील."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"लॉक सेट करा"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> वर स्विच करा"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"नवीन वापरकर्ता तयार करत आहे…"</string> + <string name="user_nickname" msgid="262624187455825083">"टोपणनाव"</string> <string name="guest_new_guest" msgid="3482026122932643557">"अतिथी जोडा"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"अतिथी काढून टाका"</string> <string name="guest_nickname" msgid="6332276931583337261">"अतिथी"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"फोटो काढा"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"इमेज निवडा"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"फोटो निवडा"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"डिव्हाइस डीफॉल्ट"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"बंद केले आहे"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"सुरू केले आहे"</string> diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml index 4c23a8472c0e..d988dd01de92 100644 --- a/packages/SettingsLib/res/values-ms/strings.xml +++ b/packages/SettingsLib/res/values-ms/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Sebelum anda boleh membuat profil yang terhad, anda perlu menyediakan kunci skrin untuk melindungi apl dan data peribadi anda."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Tetapkan kunci"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Tukar kepada <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Mencipta pengguna baharu…"</string> + <string name="user_nickname" msgid="262624187455825083">"Nama panggilan"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Tambah tetamu"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Alih keluar tetamu"</string> <string name="guest_nickname" msgid="6332276931583337261">"Tetamu"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Ambil foto"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Pilih imej"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Pilih foto"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Lalai peranti"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Dilumpuhkan"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Didayakan"</string> diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml index aa3cf08de29c..5a167439ec82 100644 --- a/packages/SettingsLib/res/values-my/strings.xml +++ b/packages/SettingsLib/res/values-my/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"ကန့်သတ်ကိုယ်ရေးအချက်အလက်တစ်ခုကို မပြုလုပ်မီ သင်၏ အပလီကေးရှင်းများနှင့် ကိုယ်ပိုင်အချက်အလက်များကို ကာကွယ်ရန် မျက်နှာပြင်သော့ချခြင်းကို စီမံရန် လိုအပ်လိမ့်မည်"</string> <string name="user_set_lock_button" msgid="1427128184982594856">"သော့ချရန် သတ်မှတ်ပါ"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> သို့ ပြောင်းရန်"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"အသုံးပြုသူအသစ် ပြုလုပ်နေသည်…"</string> + <string name="user_nickname" msgid="262624187455825083">"နာမည်ပြောင်"</string> <string name="guest_new_guest" msgid="3482026122932643557">"ဧည့်သည့် ထည့်ရန်"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"ဧည့်သည်ကို ဖယ်ထုတ်ရန်"</string> <string name="guest_nickname" msgid="6332276931583337261">"ဧည့်သည်"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"ဓာတ်ပုံရိုက်ရန်"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"ပုံရွေးရန်"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"ဓာတ်ပုံရွေးရန်"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"စက်ပစ္စည်းမူရင်း"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"ပိတ်ထားသည်"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ဖွင့်ထားသည်"</string> diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml index 0c5431b6b24e..df96ea66ad25 100644 --- a/packages/SettingsLib/res/values-nb/strings.xml +++ b/packages/SettingsLib/res/values-nb/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Før du kan opprette en begrenset profil, må du konfigurere skjermlåsen for å beskytte appene og de personlige dataene dine."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Angi lås"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Bytt til <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Oppretter en ny bruker …"</string> + <string name="user_nickname" msgid="262624187455825083">"Kallenavn"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Legg til en gjest"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Fjern gjesten"</string> <string name="guest_nickname" msgid="6332276931583337261">"Gjest"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Ta et bilde"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Velg et bilde"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Velg et bilde"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Standard for enheten"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Slått av"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Slått på"</string> diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml index 4c230d30050e..54adb3a4ce1d 100644 --- a/packages/SettingsLib/res/values-ne/strings.xml +++ b/packages/SettingsLib/res/values-ne/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"निषेधयुक्त प्रोफाइल बनाउनु अघि तपाईँको एप र व्यक्तिगत डेटा सुरक्षा गर्नाका लागि तपाईँले स्क्रिन लक सेटअप गर्नु पर्दछ ।"</string> <string name="user_set_lock_button" msgid="1427128184982594856">"लक सेट गर्नुहोस्"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"प्रयोगकर्ता बदलेर <xliff:g id="USER_NAME">%s</xliff:g> पार्नुहोस्"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"नयाँ प्रयोगकर्ता बनाउँदै…"</string> + <string name="user_nickname" msgid="262624187455825083">"उपनाम"</string> <string name="guest_new_guest" msgid="3482026122932643557">"अतिथि थप्नुहोस्"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"अतिथि हटाउनुहोस्"</string> <string name="guest_nickname" msgid="6332276931583337261">"अतिथि"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"फोटो खिच्नुहोस्"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"कुनै फोटो छनौट गर्नुहोस्"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"फोटो चयन गर्नुहोस्"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"पूर्वनिर्धारित यन्त्र"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"असक्षम पारिएको छ"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"सक्षम पारिएको छ"</string> diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml index ae734a5b3fc8..729d57bac3b9 100644 --- a/packages/SettingsLib/res/values-nl/strings.xml +++ b/packages/SettingsLib/res/values-nl/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Voordat je een beperkt profiel kunt maken, moet je een schermvergrendeling instellen om je apps en persoonsgegevens te beschermen."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Vergrendeling instellen"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Overschakelen naar <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Nieuwe gebruiker maken…"</string> + <string name="user_nickname" msgid="262624187455825083">"Bijnaam"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Gast toevoegen"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Gast verwijderen"</string> <string name="guest_nickname" msgid="6332276931583337261">"Gast"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Foto maken"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Afbeelding kiezen"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Foto selecteren"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Apparaatstandaard"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Uitgeschakeld"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Ingeschakeld"</string> diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml index 18a88faf2fb4..1ce7d56ea6d6 100644 --- a/packages/SettingsLib/res/values-or/strings.xml +++ b/packages/SettingsLib/res/values-or/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"ପ୍ରତିବନ୍ଧିତ ପ୍ରୋଫାଇଲ୍ ତିଆରି କରିବାବେଳେ, ନିଜ ଆପ୍ ଓ ବ୍ୟକ୍ତିଗତ ତଥ୍ୟର ସୁରକ୍ଷା ପାଇଁ ଏକ ସ୍କ୍ରୀନ୍ ଲକ୍ ସେଟ୍ କରନ୍ତୁ।"</string> <string name="user_set_lock_button" msgid="1427128184982594856">"ଲକ୍ ସେଟ୍ କରନ୍ତୁ"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g>କୁ ସ୍ୱିଚ୍ କରନ୍ତୁ"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"ନୂଆ ଉପଯୋଗକର୍ତ୍ତା ତିଆରି କରାଯାଉଛି…"</string> + <string name="user_nickname" msgid="262624187455825083">"ଡାକନାମ"</string> <string name="guest_new_guest" msgid="3482026122932643557">"ଅତିଥି ଯୋଗ କରନ୍ତୁ"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"ଅତିଥିଙ୍କୁ କାଢ଼ି ଦିଅନ୍ତୁ"</string> <string name="guest_nickname" msgid="6332276931583337261">"ଅତିଥି"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"ଗୋଟିଏ ଫଟୋ ଉଠାନ୍ତୁ"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"ଏକ ଛବି ବାଛନ୍ତୁ"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"ଫଟୋ ବାଛନ୍ତୁ"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"ଡିଭାଇସ୍ ଡିଫଲ୍ଟ"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"ଅକ୍ଷମ କରାଯାଇଛି"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ସକ୍ଷମ କରାଯାଇଛି"</string> diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml index b1bde27fdf17..c122a280097b 100644 --- a/packages/SettingsLib/res/values-pa/strings.xml +++ b/packages/SettingsLib/res/values-pa/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"ਇਸਤੋਂ ਪਹਿਲਾਂ ਕਿ ਤੁਸੀਂ ਇੱਕ ਪ੍ਰਤਿਬੰਧਿਤ ਪ੍ਰੋਫਾਈਲ ਬਣਾ ਸਕੋ, ਤੁਹਾਨੂੰ ਆਪਣੀਆਂ ਐਪਾਂ ਅਤੇ ਨਿੱਜੀ ਡਾਟਾ ਸੁਰੱਖਿਅਤ ਕਰਨ ਲਈ ਇੱਕ ਸਕ੍ਰੀਨ ਲਾਕ ਸੈੱਟ ਅੱਪ ਕਰਨ ਦੀ ਲੋੜ ਹੈ।"</string> <string name="user_set_lock_button" msgid="1427128184982594856">" ਲਾਕ ਸੈੱਟ ਕਰੋ"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> \'ਤੇ ਜਾਓ"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"ਨਵਾਂ ਵਰਤੋਂਕਾਰ ਬਣਾਇਆ ਜਾ ਰਿਹਾ ਹੈ…"</string> + <string name="user_nickname" msgid="262624187455825083">"ਉਪਨਾਮ"</string> <string name="guest_new_guest" msgid="3482026122932643557">"ਮਹਿਮਾਨ ਸ਼ਾਮਲ ਕਰੋ"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"ਮਹਿਮਾਨ ਹਟਾਓ"</string> <string name="guest_nickname" msgid="6332276931583337261">"ਮਹਿਮਾਨ"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"ਇੱਕ ਫ਼ੋਟੋ ਖਿੱਚੋ"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"ਕੋਈ ਚਿੱਤਰ ਚੁਣੋ"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"ਫ਼ੋਟੋ ਚੁਣੋ"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"ਡੀਵਾਈਸ ਪੂਰਵ-ਨਿਰਧਾਰਤ"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"ਬੰਦ ਕੀਤਾ ਗਿਆ"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ਚਾਲੂ ਕੀਤਾ ਗਿਆ"</string> diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml index 7ea2d0c3e803..112ae476c86e 100644 --- a/packages/SettingsLib/res/values-pl/strings.xml +++ b/packages/SettingsLib/res/values-pl/strings.xml @@ -547,19 +547,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Zanim utworzysz profil z ograniczeniami, musisz skonfigurować ekran blokady, by chronić aplikacje i osobiste dane."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Ustaw blokadę"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Przełącz na: <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Tworzę nowego użytkownika…"</string> + <string name="user_nickname" msgid="262624187455825083">"Pseudonim"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Dodaj gościa"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Usuń gościa"</string> <string name="guest_nickname" msgid="6332276931583337261">"Gość"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Zrób zdjęcie"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Wybierz obraz"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Wybierz zdjęcie"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Ustawienie domyślne urządzenia"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Wyłączono"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Włączono"</string> diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml index de536b28aae9..7354835989ce 100644 --- a/packages/SettingsLib/res/values-pt-rPT/strings.xml +++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Antes de poder criar um perfil restrito, tem de configurar um bloqueio de ecrã para proteger as suas aplicações e dados pessoais."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Definir bloqueio"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Mudar para <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"A criar novo utilizador…"</string> + <string name="user_nickname" msgid="262624187455825083">"Pseudónimo"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Adicionar convidado"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Remover convidado"</string> <string name="guest_nickname" msgid="6332276931583337261">"Convidado"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Tirar uma foto"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Escolher uma imagem"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Selecionar foto"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Predefinição do dispositivo"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Desativada"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Ativada"</string> diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml index 934ef64161bb..32e70da5d216 100644 --- a/packages/SettingsLib/res/values-ro/strings.xml +++ b/packages/SettingsLib/res/values-ro/strings.xml @@ -546,19 +546,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Înainte de a putea crea un profil cu permisiuni limitate, va trebui să configurați blocarea ecranului pentru a vă proteja aplicațiile și datele personale."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Configurați blocarea"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Treceți la <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Se creează un utilizator nou…"</string> + <string name="user_nickname" msgid="262624187455825083">"Pseudonim"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Adăugați un invitat"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Ștergeți invitatul"</string> <string name="guest_nickname" msgid="6332276931583337261">"Invitat"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Faceți o fotografie"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Alegeți o imagine"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Selectați fotografia"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Prestabilit pentru dispozitiv"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Dezactivat"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Activat"</string> diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml index e75ee7fd77e1..b04d93bf552c 100644 --- a/packages/SettingsLib/res/values-ru/strings.xml +++ b/packages/SettingsLib/res/values-ru/strings.xml @@ -547,19 +547,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Чтобы создать профиль с ограниченным доступом, необходимо предварительно настроить блокировку экрана для защиты приложений и личных данных"</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Включить блокировку"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Переключиться на этот аккаунт: <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Создаем нового пользователя…"</string> + <string name="user_nickname" msgid="262624187455825083">"Псевдоним"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Добавить аккаунт гостя"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Удалить аккаунт гостя"</string> <string name="guest_nickname" msgid="6332276931583337261">"Гость"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Сделать снимок"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Выбрать фото"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Выбрать фотографию"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Вариант по умолчанию"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Отключено"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Включено"</string> diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml index dc9b70299fbe..86725c26e878 100644 --- a/packages/SettingsLib/res/values-si/strings.xml +++ b/packages/SettingsLib/res/values-si/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"සීමිත පැතිකඩක් නිර්මාණය කිරීමට කලින්. ඔබගේ යෙදුම් සහ පෞද්ගලික දත්ත ආරක්ෂා කිරීමට තිර අගුලක් සැකසිය යුතුයි."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"අගුල සකසන්න"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> වෙත මාරු වන්න"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"නව පරිශීලක තනමින්…"</string> + <string name="user_nickname" msgid="262624187455825083">"අපනාමය"</string> <string name="guest_new_guest" msgid="3482026122932643557">"අමුත්තා එක් කරන්න"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"අමුත්තා ඉවත් කරන්න"</string> <string name="guest_nickname" msgid="6332276931583337261">"අමුත්තා"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"ඡායාරූපයක් ගන්න"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"රූපයක් තෝරන්න"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"ඡායාරූපය තෝරන්න"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"උපාංගයේ පෙරනිමිය"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"අබල කළා"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"සබලයි"</string> diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml index 203f253019ee..91e9564a8c80 100644 --- a/packages/SettingsLib/res/values-sk/strings.xml +++ b/packages/SettingsLib/res/values-sk/strings.xml @@ -547,19 +547,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Pred vytvorením obmedzeného profilu je nutné najprv nastaviť zámku obrazovky na ochranu aplikácií a osobných údajov."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Nastaviť uzamknutie"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Prepnúť na používateľa <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Vytvára sa nový používateľ…"</string> + <string name="user_nickname" msgid="262624187455825083">"Prezývka"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Pridať hosťa"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Odobrať hosťa"</string> <string name="guest_nickname" msgid="6332276931583337261">"Hosť"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Odfotiť"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Vybrať obrázok"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Vybrať fotku"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Predvol. nastavenie zariadenia"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Vypnuté"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Zapnuté"</string> diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml index 3bfda06f5f49..45ffcde74872 100644 --- a/packages/SettingsLib/res/values-sl/strings.xml +++ b/packages/SettingsLib/res/values-sl/strings.xml @@ -547,19 +547,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Preden lahko ustvarite profil z omejitvami, morate nastaviti zaklepanje zaslona, da zaščitite aplikacije in osebne podatke."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Nastavi zaklepanje"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Preklop na račun <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Ustvarjanje novega uporabnika …"</string> + <string name="user_nickname" msgid="262624187455825083">"Vzdevek"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Dodajanje gosta"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Odstranitev gosta"</string> <string name="guest_nickname" msgid="6332276931583337261">"Gost"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Fotografiranje"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Izberi sliko"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Izbira fotografije"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Privzeta nastavitev naprave"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Onemogočeno"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Omogočeno"</string> diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml index 859cc704800f..c3983636ffe8 100644 --- a/packages/SettingsLib/res/values-sq/strings.xml +++ b/packages/SettingsLib/res/values-sq/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Para se të mund të krijosh një profil të kufizuar, duhet të konfigurosh një kyçje të ekranit për të mbrojtur aplikacionet dhe të dhënat e tua personale."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Cakto kyçjen"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Kalo te <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Po krijohet një përdorues i ri…"</string> + <string name="user_nickname" msgid="262624187455825083">"Pseudonimi"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Shto të ftuar"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Hiq të ftuarin"</string> <string name="guest_nickname" msgid="6332276931583337261">"I ftuar"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Bëj një fotografi"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Zgjidh një imazh"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Zgjidh një fotografi"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Parazgjedhja e pajisjes"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Joaktiv"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Aktiv"</string> diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml index 6c02c3c1ce6a..bb59bd11f2ba 100644 --- a/packages/SettingsLib/res/values-sr/strings.xml +++ b/packages/SettingsLib/res/values-sr/strings.xml @@ -546,19 +546,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Да бисте могли да направите ограничени профил, треба да подесите закључавање екрана да бисте заштитили апликације и личне податке."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Подеси закључавање"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Пређи на корисника <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Прави се нови корисник…"</string> + <string name="user_nickname" msgid="262624187455825083">"Надимак"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Додај госта"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Уклони госта"</string> <string name="guest_nickname" msgid="6332276931583337261">"Гост"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Сликај"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Одабери слику"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Изаберите слику"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Подразумевано за уређај"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Онемогућено"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Омогућено"</string> diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml index dc2167561709..e7b1482c3452 100644 --- a/packages/SettingsLib/res/values-sv/strings.xml +++ b/packages/SettingsLib/res/values-sv/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Innan du skapar en begränsad profil måste du konfigurera ett skärmlås för att skydda dina appar och personliga data."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Konfigurera lås"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Byt till <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Skapar ny användare …"</string> + <string name="user_nickname" msgid="262624187455825083">"Smeknamn"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Lägg till gäst"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Ta bort gäst"</string> <string name="guest_nickname" msgid="6332276931583337261">"Gäst"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Ta ett foto"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Välj en bild"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Välj foto"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Enhetens standardinställning"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Inaktiverat"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Aktiverat"</string> diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml index 8f80e558e5d8..1f0d167f6df2 100644 --- a/packages/SettingsLib/res/values-sw/strings.xml +++ b/packages/SettingsLib/res/values-sw/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Kabla uunde wasifu uliowekekwa vikwazo, utahitajika kuweka skrini iliyofungwa ili kulinda programu zako na data binafsi."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Weka ufunguo"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Badili utumie <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Inaweka mtumiaji mpya…"</string> + <string name="user_nickname" msgid="262624187455825083">"Jina wakilishi"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Weka mgeni"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Ondoa mgeni"</string> <string name="guest_nickname" msgid="6332276931583337261">"Mgeni"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Piga picha"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Chagua picha"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Chagua picha"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Hali chaguomsingi ya kifaa"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Imezimwa"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Imewashwa"</string> diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml index 106942104984..b6d8be8ae54d 100644 --- a/packages/SettingsLib/res/values-ta/strings.xml +++ b/packages/SettingsLib/res/values-ta/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"நீங்கள் வரையறுக்கப்பட்டச் சுயவிவரத்தை உருவாக்குவதற்கு முன்பு, உங்கள் ஆப்ஸ் மற்றும் தனிப்பட்ட தரவைப் பாதுகாக்கும் வகையில் நீங்கள் திரைப் பூட்டை அமைக்க வேண்டும்."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"பூட்டை அமை"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g>க்கு மாறு"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"புதிய பயனரை உருவாக்குகிறது…"</string> + <string name="user_nickname" msgid="262624187455825083">"புனைப்பெயர்"</string> <string name="guest_new_guest" msgid="3482026122932643557">"கெஸ்ட்டைச் சேர்"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"கெஸ்ட்டை அகற்று"</string> <string name="guest_nickname" msgid="6332276931583337261">"கெஸ்ட்"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"படமெடுங்கள்"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"படத்தைத் தேர்வுசெய்யுங்கள்"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"படத்தைத் தேர்ந்தெடுங்கள்"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"சாதனத்தின் இயல்புநிலை"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"முடக்கப்பட்டது"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"இயக்கப்பட்டது"</string> diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml index 3ad2375a77dc..5a8e734ab878 100644 --- a/packages/SettingsLib/res/values-te/strings.xml +++ b/packages/SettingsLib/res/values-te/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"మీరు పరిమితం చేయబడిన ప్రొఫైల్ను సృష్టించడానికి ముందు, మీ అనువర్తనాలు మరియు వ్యక్తిగత డేటాను రక్షించడానికి స్క్రీన్ లాక్ను సెటప్ చేయాల్సి ఉంటుంది."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"లాక్ను సెట్ చేయి"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g>కు మార్చు"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"కొత్త యూజర్ను క్రియేట్ చేస్తోంది…"</string> + <string name="user_nickname" msgid="262624187455825083">"మారుపేరు"</string> <string name="guest_new_guest" msgid="3482026122932643557">"అతిథిని జోడించండి"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"అతిథిని తీసివేయండి"</string> <string name="guest_nickname" msgid="6332276931583337261">"అతిథి"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"ఒక ఫోటో తీయండి"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"ఇమేజ్ను ఎంచుకోండి"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"ఫోటోను ఎంచుకోండి"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"పరికర ఆటోమేటిక్ సెట్టింగ్"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"డిజేబుల్ చేయబడింది"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"ఎనేబుల్ చేయబడింది"</string> diff --git a/packages/SettingsLib/res/values-th/arrays.xml b/packages/SettingsLib/res/values-th/arrays.xml index 58d8a452ddcb..21fe6e4d3c9f 100644 --- a/packages/SettingsLib/res/values-th/arrays.xml +++ b/packages/SettingsLib/res/values-th/arrays.xml @@ -138,15 +138,15 @@ <item msgid="1333279807604675720">"สเตอริโอ"</item> </string-array> <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_titles"> - <item msgid="1241278021345116816">"เพิ่มประสิทธิภาพสำหรับคุณภาพเสียง (990 kbps/909 kbps)"</item> + <item msgid="1241278021345116816">"เพิ่มประสิทธิภาพเพื่อคุณภาพเสียง (990 kbps/909 kbps)"</item> <item msgid="3523665555859696539">"คุณภาพเสียงและการเชื่อมต่อที่สมดุล (660 kbps/606 kbps)"</item> - <item msgid="886408010459747589">"เพิ่มประสิทธิภาพสำหรับคุณภาพการเชื่อมต่อ (330 kbps/303 kbps)"</item> + <item msgid="886408010459747589">"เพิ่มประสิทธิภาพเพื่อคุณภาพการเชื่อมต่อ (330 kbps/303 kbps)"</item> <item msgid="3808414041654351577">"ดีที่สุดเท่าที่ทำได้ (ปรับอัตราบิตอัตโนมัติ)"</item> </string-array> <string-array name="bluetooth_a2dp_codec_ldac_playback_quality_summaries"> - <item msgid="804499336721569838">"เพิ่มประสิทธิภาพสำหรับคุณภาพเสียง"</item> + <item msgid="804499336721569838">"เพิ่มประสิทธิภาพเพื่อคุณภาพเสียง"</item> <item msgid="7451422070435297462">"คุณภาพเสียงและการเชื่อมต่อที่สมดุล"</item> - <item msgid="6173114545795428901">"เพิ่มประสิทธิภาพสำหรับคุณภาพการเชื่อมต่อ"</item> + <item msgid="6173114545795428901">"เพิ่มประสิทธิภาพเพื่อคุณภาพการเชื่อมต่อ"</item> <item msgid="4349908264188040530">"ดีที่สุดเท่าที่ทำได้ (ปรับอัตราบิตอัตโนมัติ)"</item> </string-array> <string-array name="bluetooth_audio_active_device_summaries"> diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml index cc0ac748d124..2ae4131ba415 100644 --- a/packages/SettingsLib/res/values-th/strings.xml +++ b/packages/SettingsLib/res/values-th/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"ก่อนที่คุณจะสามารถสร้างโปรไฟล์ที่ถูกจำกัดได้ คุณจะต้องตั้งค่าล็อกหน้าจอเพื่อปกป้องแอปและข้อมูลส่วนตัวของคุณ"</string> <string name="user_set_lock_button" msgid="1427128184982594856">"ตั้งค่าล็อก"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"เปลี่ยนเป็น <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"กำลังสร้างผู้ใช้ใหม่…"</string> + <string name="user_nickname" msgid="262624187455825083">"ชื่อเล่น"</string> <string name="guest_new_guest" msgid="3482026122932643557">"เพิ่มผู้เข้าร่วม"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"นำผู้เข้าร่วมออก"</string> <string name="guest_nickname" msgid="6332276931583337261">"ผู้ใช้ชั่วคราว"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"ถ่ายรูป"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"เลือกรูปภาพ"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"เลือกรูปภาพ"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"ค่าเริ่มต้นของอุปกรณ์"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"ปิดใช้"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"เปิดใช้"</string> diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml index 77ab7cfcaa0d..e9f1da3c5c4b 100644 --- a/packages/SettingsLib/res/values-tl/strings.xml +++ b/packages/SettingsLib/res/values-tl/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Bago ka makakalikha ng pinaghihigpitang profile, kakailanganin mong mag-set up ng screen lock upang protektahan ang iyong apps at personal na data."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Itakda ang lock"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Lumipat sa <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Gumagawa ng bagong user…"</string> + <string name="user_nickname" msgid="262624187455825083">"Nickname"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Magdagdag ng bisita"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Alisin ang bisita"</string> <string name="guest_nickname" msgid="6332276931583337261">"Bisita"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Kumuha ng larawan"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Pumili ng larawan"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Pumili ng larawan"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Default ng device"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Naka-disable"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Na-enable"</string> diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml index 9d980c424ef9..0502359dc9da 100644 --- a/packages/SettingsLib/res/values-tr/strings.xml +++ b/packages/SettingsLib/res/values-tr/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Kısıtlanmış bir profil oluşturabilmeniz için uygulamalarınızı ve kişisel verilerinizi korumak üzere bir ekran kilidi oluşturmanız gerekir."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Kilidi ayarla"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> hesabına geç"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Yeni kullanıcı oluşturuluyor…"</string> + <string name="user_nickname" msgid="262624187455825083">"Takma ad"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Misafir ekle"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Misafir oturumunu kaldır"</string> <string name="guest_nickname" msgid="6332276931583337261">"Misafir"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Fotoğraf çek"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Resim seç"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Fotoğraf seç"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Cihaz varsayılanı"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Devre dışı"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Etkin"</string> diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml index 9a7b89fc8f58..b68aab46c028 100644 --- a/packages/SettingsLib/res/values-uk/strings.xml +++ b/packages/SettingsLib/res/values-uk/strings.xml @@ -547,19 +547,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Перш ніж створювати обмежений профіль, потрібно налаштувати блокування екрана, щоб захистити свої програми та особисті дані."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Налаштувати блокування"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Перейти до користувача <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Створення нового користувача…"</string> + <string name="user_nickname" msgid="262624187455825083">"Псевдонім"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Додати гостя"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Видалити гостя"</string> <string name="guest_nickname" msgid="6332276931583337261">"Гість"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Зробити фотографію"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Вибрати зображення"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Вибрати фотографію"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"За умовчанням для пристрою"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Вимкнено"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Увімкнено"</string> diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml index 1cc0859971f7..1802be6f90fc 100644 --- a/packages/SettingsLib/res/values-ur/strings.xml +++ b/packages/SettingsLib/res/values-ur/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"ایک محدود پروفائل بنانے سے پہلے، آپ کو اپنی ایپس اور ذاتی ڈیٹا کو محفوظ کرنے کیلئے ایک اسکرین لاک سیٹ اپ کرنا ہوگا۔"</string> <string name="user_set_lock_button" msgid="1427128184982594856">"لاک سیٹ کریں"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"<xliff:g id="USER_NAME">%s</xliff:g> پر سوئچ کریں"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"نیا صارف تخلیق کرنا…"</string> + <string name="user_nickname" msgid="262624187455825083">"عرفی نام"</string> <string name="guest_new_guest" msgid="3482026122932643557">"مہمان کو شامل کریں"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"مہمان کو ہٹائیں"</string> <string name="guest_nickname" msgid="6332276931583337261">"مہمان"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"ایک تصویر لیں"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"ایک تصویر منتخب کریں"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"تصویر منتخب کریں"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"آلہ ڈیفالٹ"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"غیر فعال"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"فعال"</string> diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml index 2ed6ca8e6beb..4d4808f77d04 100644 --- a/packages/SettingsLib/res/values-vi/strings.xml +++ b/packages/SettingsLib/res/values-vi/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Trước khi bạn có thể tạo tiểu sử bị hạn chế, bạn sẽ cần thiết lập một màn hình khóa để bảo vệ các ứng dụng và dữ liệu cá nhân của bạn."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Thiết lập khóa"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Chuyển sang <xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Đang tạo người dùng mới…"</string> + <string name="user_nickname" msgid="262624187455825083">"Biệt hiệu"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Thêm khách"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Xóa phiên khách"</string> <string name="guest_nickname" msgid="6332276931583337261">"Khách"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Chụp ảnh"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Chọn một hình ảnh"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Chọn ảnh"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Theo giá trị mặc định của thiết bị"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Đã tắt"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Đã bật"</string> diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml index 024ea790f8f4..b6e8eba2e159 100644 --- a/packages/SettingsLib/res/values-zh-rCN/strings.xml +++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"您需要先设置锁定屏幕来保护您的应用和个人数据,然后才可以创建受限个人资料。"</string> <string name="user_set_lock_button" msgid="1427128184982594856">"设置屏幕锁定方式"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"切换到<xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"正在创建新用户…"</string> + <string name="user_nickname" msgid="262624187455825083">"昵称"</string> <string name="guest_new_guest" msgid="3482026122932643557">"添加访客"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"移除访客"</string> <string name="guest_nickname" msgid="6332276931583337261">"访客"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"拍摄照片"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"选择图片"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"选择照片"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"设备默认设置"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"已停用"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"已启用"</string> diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml index 75f050f21fee..07bc88731a71 100644 --- a/packages/SettingsLib/res/values-zh-rHK/strings.xml +++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"建立限制存取的個人檔案前,您必須先設定上鎖畫面來保護您的應用程式和個人資料。"</string> <string name="user_set_lock_button" msgid="1427128184982594856">"設定上鎖畫面"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"切換至<xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"正在建立新使用者…"</string> + <string name="user_nickname" msgid="262624187455825083">"暱稱"</string> <string name="guest_new_guest" msgid="3482026122932643557">"新增訪客"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"移除訪客"</string> <string name="guest_nickname" msgid="6332276931583337261">"訪客"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"拍照"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"選擇圖片"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"揀相"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"裝置預設設定"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"已停用"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"已啟用"</string> diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml index 9866b476f310..833a82ff244f 100644 --- a/packages/SettingsLib/res/values-zh-rTW/strings.xml +++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"如要建立設有限制的個人資料,你必須先設定螢幕鎖定來保護你的應用程式和個人資料。"</string> <string name="user_set_lock_button" msgid="1427128184982594856">"設定鎖定"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"切換至<xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"正在建立新使用者…"</string> + <string name="user_nickname" msgid="262624187455825083">"暱稱"</string> <string name="guest_new_guest" msgid="3482026122932643557">"新增訪客"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"移除訪客"</string> <string name="guest_nickname" msgid="6332276931583337261">"訪客"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"拍照"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"選擇圖片"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"選取相片"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"裝置預設設定"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"已停用"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"已啟用"</string> diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml index b1825c49232c..0065eb616d0c 100644 --- a/packages/SettingsLib/res/values-zu/strings.xml +++ b/packages/SettingsLib/res/values-zu/strings.xml @@ -545,19 +545,14 @@ <string name="user_need_lock_message" msgid="4311424336209509301">"Ngaphambi kokuthi ungadala iphrofayela ekhawulelwe, kuzomele usethe ukukhiya isikrini ukuze uvikele izinhlelo zakho zokusebenza nedatha yakho yomuntu siqu."</string> <string name="user_set_lock_button" msgid="1427128184982594856">"Setha ukukhiya"</string> <string name="user_switch_to_user" msgid="6975428297154968543">"Shintshela ku-<xliff:g id="USER_NAME">%s</xliff:g>"</string> - <!-- no translation found for creating_new_user_dialog_message (7232880257538970375) --> - <skip /> - <!-- no translation found for user_nickname (262624187455825083) --> - <skip /> + <string name="creating_new_user_dialog_message" msgid="7232880257538970375">"Idala umsebenzisi omusha…"</string> + <string name="user_nickname" msgid="262624187455825083">"Isiteketiso"</string> <string name="guest_new_guest" msgid="3482026122932643557">"Engeza isivakashi"</string> <string name="guest_exit_guest" msgid="5908239569510734136">"Susa isihambeli"</string> <string name="guest_nickname" msgid="6332276931583337261">"Isihambeli"</string> - <!-- no translation found for user_image_take_photo (467512954561638530) --> - <skip /> - <!-- no translation found for user_image_choose_photo (1363820919146782908) --> - <skip /> - <!-- no translation found for user_image_photo_selector (433658323306627093) --> - <skip /> + <string name="user_image_take_photo" msgid="467512954561638530">"Thatha isithombe"</string> + <string name="user_image_choose_photo" msgid="1363820919146782908">"Khetha isithombe"</string> + <string name="user_image_photo_selector" msgid="433658323306627093">"Khetha isithombe"</string> <string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Idivayisi ezenzakalelayo"</string> <string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Ikhutshaziwe"</string> <string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Inikwe amandla"</string> diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java index 69be14413583..8bdde8be9498 100644 --- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java @@ -314,6 +314,7 @@ public class SettingsBackupTest { Settings.Global.KERNEL_CPU_THREAD_READER, Settings.Global.LANG_ID_UPDATE_CONTENT_URL, Settings.Global.LANG_ID_UPDATE_METADATA_URL, + Settings.Global.LATENCY_TRACKER, Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS, Settings.Global.LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS, Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST, diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index bba29dba0827..5f018a0322a3 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -335,6 +335,9 @@ <!-- Permission required for CTS test - android.server.biometrics --> <uses-permission android:name="android.permission.TEST_BIOMETRIC" /> + <!-- Permissions required for CTS test - NotificationManagerTest --> + <uses-permission android:name="android.permission.MANAGE_NOTIFICATION_LISTENERS" /> + <application android:label="@string/app_label" android:theme="@android:style/Theme.DeviceDefault.DayNight" android:defaultToDeviceProtectedStorage="true" diff --git a/packages/SystemUI/res/layout-land/global_screenshot_preview.xml b/packages/SystemUI/res/layout-land/global_screenshot_preview.xml index b1f4cb7d70de..040303a9b963 100644 --- a/packages/SystemUI/res/layout-land/global_screenshot_preview.xml +++ b/packages/SystemUI/res/layout-land/global_screenshot_preview.xml @@ -28,6 +28,6 @@ android:visibility="gone" android:background="@drawable/screenshot_rounded_corners" android:adjustViewBounds="true" - android:contentDescription="@string/screenshot_preview_description" + android:contentDescription="@string/screenshot_edit" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent"/>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/global_screenshot_action_chip.xml b/packages/SystemUI/res/layout/global_screenshot_action_chip.xml index 4b3534b1cbc8..1021186da8b9 100644 --- a/packages/SystemUI/res/layout/global_screenshot_action_chip.xml +++ b/packages/SystemUI/res/layout/global_screenshot_action_chip.xml @@ -19,7 +19,7 @@ android:id="@+id/global_screenshot_action_chip" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginEnd="@dimen/screenshot_action_chip_margin_right" + android:layout_marginStart="@dimen/screenshot_action_chip_margin_start" android:paddingVertical="@dimen/screenshot_action_chip_margin_vertical" android:layout_gravity="center" android:gravity="center" diff --git a/packages/SystemUI/res/layout/global_screenshot_preview.xml b/packages/SystemUI/res/layout/global_screenshot_preview.xml index e6295f54fcbe..c745854b1c6c 100644 --- a/packages/SystemUI/res/layout/global_screenshot_preview.xml +++ b/packages/SystemUI/res/layout/global_screenshot_preview.xml @@ -28,6 +28,6 @@ android:visibility="gone" android:background="@drawable/screenshot_rounded_corners" android:adjustViewBounds="true" - android:contentDescription="@string/screenshot_preview_description" + android:contentDescription="@string/screenshot_edit" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent"/>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/global_screenshot_static.xml b/packages/SystemUI/res/layout/global_screenshot_static.xml index 9ec2f20597e7..26edf3afc0c5 100644 --- a/packages/SystemUI/res/layout/global_screenshot_static.xml +++ b/packages/SystemUI/res/layout/global_screenshot_static.xml @@ -51,7 +51,12 @@ <LinearLayout android:id="@+id/global_screenshot_actions" android:layout_width="wrap_content" - android:layout_height="wrap_content"/> + android:layout_height="wrap_content"> + <include layout="@layout/global_screenshot_action_chip" + android:id="@+id/screenshot_share_chip"/> + <include layout="@layout/global_screenshot_action_chip" + android:id="@+id/screenshot_edit_chip"/> + </LinearLayout> </HorizontalScrollView> <include layout="@layout/global_screenshot_preview"/> </androidx.constraintlayout.widget.ConstraintLayout> diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index 3d7b779c8a46..6df8b4e733bb 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -54,6 +54,8 @@ <color name="global_actions_emergency_background">@color/GM2_red_400</color> <color name="global_actions_emergency_text">@color/GM2_grey_100</color> + <color name="global_actions_shutdown_ui_text">@color/control_primary_text</color> + <!-- Tint color for the content on the notification overflow card. --> <color name="keyguard_overflow_content_color">#ff686868</color> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 7cbbaf9a00ac..4b1ed0a25c90 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -323,7 +323,7 @@ <dimen name="screenshot_action_container_padding_right">8dp</dimen> <!-- Radius of the chip background on global screenshot actions --> <dimen name="screenshot_button_corner_radius">20dp</dimen> - <dimen name="screenshot_action_chip_margin_right">8dp</dimen> + <dimen name="screenshot_action_chip_margin_start">8dp</dimen> <dimen name="screenshot_action_chip_margin_vertical">10dp</dimen> <dimen name="screenshot_action_chip_padding_vertical">7dp</dimen> <dimen name="screenshot_action_chip_icon_size">18dp</dimen> @@ -1217,7 +1217,7 @@ <!-- Interior padding of the message bubble --> <dimen name="bubble_message_padding">4dp</dimen> <!-- Offset between bubbles in their stacked position. --> - <dimen name="bubble_stack_offset">5dp</dimen> + <dimen name="bubble_stack_offset">10dp</dimen> <!-- How far offscreen the bubble stack rests. Cuts off padding and part of icon bitmap. --> <dimen name="bubble_stack_offscreen">9dp</dimen> <!-- How far down the screen the stack starts. --> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index d1fb6cd4f209..e2ba615e84e6 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -233,6 +233,8 @@ <!-- Notification text displayed when we fail to take a screenshot. [CHAR LIMIT=100] --> <string name="screenshot_failed_to_capture_text">Taking screenshots isn\'t allowed by the app or your organization</string> + <!-- Content description indicating that tapping the element will allow editing the screenshot [CHAR LIMIT=NONE] --> + <string name="screenshot_edit">Edit screenshot</string> <!-- Content description indicating that tapping a button will dismiss the screenshots UI [CHAR LIMIT=NONE] --> <string name="screenshot_dismiss_ui_description">Dismiss screenshot</string> <!-- Content description indicating that the view is a preview of the screenshot that was just taken [CHAR LIMIT=NONE] --> @@ -2782,6 +2784,8 @@ <string name="controls_media_title">Media</string> <!-- Explanation for closing controls associated with a specific media session [CHAR_LIMIT=NONE] --> <string name="controls_media_close_session">Hide the current session.</string> + <!-- Explanation that controls associated with a specific media session are active [CHAR_LIMIT=NONE] --> + <string name="controls_media_active_session">Current session cannot be hidden.</string> <!-- Label for a button that will hide media controls [CHAR_LIMIT=30] --> <string name="controls_media_dismiss_button">Dismiss</string> <!-- Label for button to resume media playback [CHAR_LIMIT=NONE] --> diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/LatencyTrackerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/LatencyTrackerCompat.java index 0d5933e5f599..bf4fb0b6517e 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/LatencyTrackerCompat.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/LatencyTrackerCompat.java @@ -28,7 +28,18 @@ public class LatencyTrackerCompat { return LatencyTracker.isEnabled(context); } + /** + * @see LatencyTracker + * @deprecated Please use {@link LatencyTrackerCompat#logToggleRecents(Context, int)} instead. + */ + @Deprecated public static void logToggleRecents(int duration) { - LatencyTracker.logAction(LatencyTracker.ACTION_TOGGLE_RECENTS, duration); + LatencyTracker.logActionDeprecated(LatencyTracker.ACTION_TOGGLE_RECENTS, duration, false); + } + + /** @see LatencyTracker */ + public static void logToggleRecents(Context context, int duration) { + LatencyTracker.getInstance(context).logAction(LatencyTracker.ACTION_TOGGLE_RECENTS, + duration); } }
\ No newline at end of file diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java index 86129e0e204e..70021b6f3d45 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java @@ -65,7 +65,7 @@ public class SyncRtSurfaceTransactionApplierCompat { public SyncRtSurfaceTransactionApplierCompat(View targetView) { mTargetViewRootImpl = targetView != null ? targetView.getViewRootImpl() : null; mBarrierSurfaceControl = mTargetViewRootImpl != null - ? mTargetViewRootImpl.getRenderSurfaceControl() : null; + ? mTargetViewRootImpl.getSurfaceControl() : null; mApplyHandler = new Handler(new Callback() { @Override diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ViewRootImplCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ViewRootImplCompat.java index 73783ae7ece2..4a28d56a41e1 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ViewRootImplCompat.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ViewRootImplCompat.java @@ -34,10 +34,6 @@ public class ViewRootImplCompat { } public SurfaceControl getRenderSurfaceControl() { - return mViewRoot == null ? null : mViewRoot.getRenderSurfaceControl(); - } - - public SurfaceControl getSurfaceControl() { return mViewRoot == null ? null : mViewRoot.getSurfaceControl(); } diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java index 5122f6cf31a1..97196d1ef451 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java @@ -102,6 +102,18 @@ public class WindowManagerWrapper { } /** + * Sets if app requested fixed orientation should be ignored for given displayId. + */ + public void setIgnoreOrientationRequest(int displayId, boolean ignoreOrientationRequest) { + try { + WindowManagerGlobal.getWindowManagerService().setIgnoreOrientationRequest( + displayId, ignoreOrientationRequest); + } catch (RemoteException e) { + Log.e(TAG, "Failed to setIgnoreOrientationRequest()", e); + } + } + + /** * @return the stable insets for the primary display. */ public void getStableInsets(Rect outStableInsets) { diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java index 36d5543f1c01..901a7360f311 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java @@ -20,7 +20,7 @@ import static android.view.Display.DEFAULT_DISPLAY; import android.app.Presentation; import android.content.Context; import android.graphics.Color; -import android.graphics.Point; +import android.graphics.Rect; import android.hardware.display.DisplayManager; import android.media.MediaRouter; import android.media.MediaRouter.RouteInfo; @@ -127,7 +127,7 @@ public class KeyguardDisplayManager { Presentation presentation = mPresentations.get(displayId); if (presentation == null) { final Presentation newPresentation = new KeyguardPresentation(mContext, display, - mKeyguardStatusViewComponentFactory, LayoutInflater.from(mContext)); + mKeyguardStatusViewComponentFactory); newPresentation.setOnDismissListener(dialog -> { if (newPresentation.equals(mPresentations.get(displayId))) { mPresentations.remove(displayId); @@ -245,7 +245,6 @@ public class KeyguardDisplayManager { private static final int VIDEO_SAFE_REGION = 80; // Percentage of display width & height private static final int MOVE_CLOCK_TIMEOUT = 10000; // 10s private final KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory; - private final LayoutInflater mLayoutInflater; private KeyguardClockSwitchController mKeyguardClockSwitchController; private View mClock; private int mUsableWidth; @@ -264,18 +263,16 @@ public class KeyguardDisplayManager { }; KeyguardPresentation(Context context, Display display, - KeyguardStatusViewComponent.Factory keyguardStatusViewComponentFactory, - LayoutInflater layoutInflater) { - super(context, display, R.style.Theme_SystemUI_KeyguardPresentation); + KeyguardStatusViewComponent.Factory keyguardStatusViewComponentFactory) { + super(context, display, R.style.Theme_SystemUI_KeyguardPresentation, + WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); mKeyguardStatusViewComponentFactory = keyguardStatusViewComponentFactory; - mLayoutInflater = layoutInflater; - getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); setCancelable(false); } @Override public void cancel() { - // Do not allow anything to cancel KeyguardPresetation except KeyguardDisplayManager. + // Do not allow anything to cancel KeyguardPresentation except KeyguardDisplayManager. } @Override @@ -287,14 +284,15 @@ public class KeyguardDisplayManager { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - Point p = new Point(); - getDisplay().getSize(p); - mUsableWidth = VIDEO_SAFE_REGION * p.x/100; - mUsableHeight = VIDEO_SAFE_REGION * p.y/100; - mMarginLeft = (100 - VIDEO_SAFE_REGION) * p.x / 200; - mMarginTop = (100 - VIDEO_SAFE_REGION) * p.y / 200; + final Rect bounds = getWindow().getWindowManager().getMaximumWindowMetrics() + .getBounds(); + mUsableWidth = VIDEO_SAFE_REGION * bounds.width() / 100; + mUsableHeight = VIDEO_SAFE_REGION * bounds.height() / 100; + mMarginLeft = (100 - VIDEO_SAFE_REGION) * bounds.width() / 200; + mMarginTop = (100 - VIDEO_SAFE_REGION) * bounds.height() / 200; - setContentView(mLayoutInflater.inflate(R.layout.keyguard_presentation, null)); + setContentView(LayoutInflater.from(getContext()) + .inflate(R.layout.keyguard_presentation, null)); // Logic to make the lock screen fullscreen getWindow().getDecorView().setSystemUiVisibility( diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java index c4a305ec41e2..2592a2c4c768 100644 --- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java +++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java @@ -582,6 +582,10 @@ public class ScreenDecorations extends SystemUI implements Tunable { @Override protected void onConfigurationChanged(Configuration newConfig) { + if (DEBUG_DISABLE_SCREEN_DECORATIONS) { + Log.i(TAG, "ScreenDecorations is disabled"); + return; + } mHandler.post(() -> { int oldRotation = mRotation; mPendingRotationChange = false; @@ -766,6 +770,10 @@ public class ScreenDecorations extends SystemUI implements Tunable { @Override public void onTuningChanged(String key, String newValue) { + if (DEBUG_DISABLE_SCREEN_DECORATIONS) { + Log.i(TAG, "ScreenDecorations is disabled"); + return; + } mHandler.post(() -> { if (mOverlays == null) return; if (SIZE.equals(key)) { diff --git a/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java b/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java index 2365f128532e..47adffc216a5 100644 --- a/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java +++ b/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java @@ -111,9 +111,7 @@ public class SlicePermissionActivity extends Activity implements OnClickListener final String providerPkg = getIntent().getStringExtra("provider_pkg"); if (providerPkg == null || mProviderPkg.equals(providerPkg)) return; final String callingPkg = getCallingPkg(); - EventLog.writeEvent(0x534e4554, "159145361", getUid(callingPkg), String.format( - "pkg %s (disguised as %s) attempted to request permission to show %s slices in %s", - callingPkg, providerPkg, mProviderPkg, mCallingPkg)); + EventLog.writeEvent(0x534e4554, "159145361", getUid(callingPkg)); } @Nullable diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java index c3474bb7ca57..340ca044a1ef 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java @@ -249,8 +249,8 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold if ((configDiff & ActivityInfo.CONFIG_DENSITY) != 0) { updateDimensions(); if (isWindowVisible()) { - mWm.removeView(mMirrorView); - createMirrorWindow(); + deleteWindowMagnification(); + enableWindowMagnification(Float.NaN, Float.NaN, Float.NaN); } } else if ((configDiff & ActivityInfo.CONFIG_ORIENTATION) != 0) { onRotate(); diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleFlyoutView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleFlyoutView.java index 69f7828ff8fc..009114ffa0be 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleFlyoutView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleFlyoutView.java @@ -18,6 +18,8 @@ package com.android.systemui.bubbles; import static android.graphics.Paint.ANTI_ALIAS_FLAG; import static android.graphics.Paint.FILTER_BITMAP_FLAG; +import static com.android.systemui.Interpolators.ALPHA_IN; +import static com.android.systemui.Interpolators.ALPHA_OUT; import android.animation.ArgbEvaluator; import android.content.Context; @@ -56,6 +58,11 @@ public class BubbleFlyoutView extends FrameLayout { /** Max width of the flyout, in terms of percent of the screen width. */ private static final float FLYOUT_MAX_WIDTH_PERCENT = .6f; + /** Translation Y of fade animation. */ + private static final float FLYOUT_FADE_Y = 40f; + + private static final long FLYOUT_FADE_DURATION = 200L; + private final int mFlyoutPadding; private final int mFlyoutSpaceFromBubble; private final int mPointerSize; @@ -104,6 +111,9 @@ public class BubbleFlyoutView extends FrameLayout { /** The bounds of the flyout background, kept up to date as it transitions to the 'new' dot. */ private final RectF mBgRect = new RectF(); + /** The y position of the flyout, relative to the top of the screen. */ + private float mFlyoutY = 0f; + /** * Percent progress in the transition from flyout to 'new' dot. These two values are the inverse * of each other (if we're 40% transitioned to the dot, we're 60% flyout), but it makes the code @@ -221,18 +231,33 @@ public class BubbleFlyoutView extends FrameLayout { mSenderText.setTextSize(TypedValue.COMPLEX_UNIT_PX, newFontSize); } - /** Configures the flyout, collapsed into to dot form. */ - void setupFlyoutStartingAsDot( - Bubble.FlyoutMessage flyoutMessage, - PointF stackPos, - float parentWidth, - boolean arrowPointingLeft, - int dotColor, - @Nullable Runnable onLayoutComplete, - @Nullable Runnable onHide, - float[] dotCenter, - boolean hideDot) { + /* + * Fade animation for consecutive flyouts. + */ + void animateUpdate(Bubble.FlyoutMessage flyoutMessage, float parentWidth, float stackY) { + fade(false /* in */); + updateFlyoutMessage(flyoutMessage, parentWidth); + // Wait for TextViews to layout with updated height. + post(() -> { + mFlyoutY = stackY + (mBubbleSize - mFlyoutTextContainer.getHeight()) / 2f; + fade(true /* in */); + }); + } + private void fade(boolean in) { + setAlpha(in ? 0f : 1f); + setTranslationY(in ? mFlyoutY : mFlyoutY + FLYOUT_FADE_Y); + animate() + .alpha(in ? 1f : 0f) + .setDuration(FLYOUT_FADE_DURATION) + .setInterpolator(in ? ALPHA_IN : ALPHA_OUT); + animate() + .translationY(in ? mFlyoutY : mFlyoutY - FLYOUT_FADE_Y) + .setDuration(FLYOUT_FADE_DURATION) + .setInterpolator(in ? ALPHA_IN : ALPHA_OUT); + } + + private void updateFlyoutMessage(Bubble.FlyoutMessage flyoutMessage, float parentWidth) { final Drawable senderAvatar = flyoutMessage.senderAvatar; if (senderAvatar != null && flyoutMessage.isGroupChat) { mSenderAvatar.setVisibility(VISIBLE); @@ -256,6 +281,27 @@ public class BubbleFlyoutView extends FrameLayout { mSenderText.setVisibility(GONE); } + // Set the flyout TextView's max width in terms of percent, and then subtract out the + // padding so that the entire flyout view will be the desired width (rather than the + // TextView being the desired width + extra padding). + mMessageText.setMaxWidth(maxTextViewWidth); + mMessageText.setText(flyoutMessage.message); + } + + /** Configures the flyout, collapsed into dot form. */ + void setupFlyoutStartingAsDot( + Bubble.FlyoutMessage flyoutMessage, + PointF stackPos, + float parentWidth, + boolean arrowPointingLeft, + int dotColor, + @Nullable Runnable onLayoutComplete, + @Nullable Runnable onHide, + float[] dotCenter, + boolean hideDot) { + + updateFlyoutMessage(flyoutMessage, parentWidth); + mArrowPointingLeft = arrowPointingLeft; mDotColor = dotColor; mOnHide = onHide; @@ -263,24 +309,12 @@ public class BubbleFlyoutView extends FrameLayout { setCollapsePercent(1f); - // Set the flyout TextView's max width in terms of percent, and then subtract out the - // padding so that the entire flyout view will be the desired width (rather than the - // TextView being the desired width + extra padding). - mMessageText.setMaxWidth(maxTextViewWidth); - mMessageText.setText(flyoutMessage.message); - - // Wait for the TextView to lay out so we know its line count. + // Wait for TextViews to layout with updated height. post(() -> { - float restingTranslationY; - // Multi line flyouts get top-aligned to the bubble. - if (mMessageText.getLineCount() > 1) { - restingTranslationY = stackPos.y + mBubbleIconTopPadding; - } else { - // Single line flyouts are vertically centered with respect to the bubble. - restingTranslationY = - stackPos.y + (mBubbleSize - mFlyoutTextContainer.getHeight()) / 2f; - } - setTranslationY(restingTranslationY); + // Flyout is vertically centered with respect to the bubble. + mFlyoutY = + stackPos.y + (mBubbleSize - mFlyoutTextContainer.getHeight()) / 2f; + setTranslationY(mFlyoutY); // Calculate the translation required to position the flyout next to the bubble stack, // with the desired padding. @@ -300,7 +334,7 @@ public class BubbleFlyoutView extends FrameLayout { final float dotPositionY = stackPos.y + mDotCenter[1] - adjustmentForScaleAway; final float distanceFromFlyoutLeftToDotCenterX = mRestingTranslationX - dotPositionX; - final float distanceFromLayoutTopToDotCenterY = restingTranslationY - dotPositionY; + final float distanceFromLayoutTopToDotCenterY = mFlyoutY - dotPositionY; mTranslationXWhenDot = -distanceFromFlyoutLeftToDotCenterX; mTranslationYWhenDot = -distanceFromLayoutTopToDotCenterY; diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java index e2674de3a723..431719f98ad9 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java @@ -2171,11 +2171,7 @@ public class BubbleStackView extends FrameLayout return getStatusBarHeight() + mBubbleSize + mBubblePaddingTop; } - /** - * Animates in the flyout for the given bubble, if available, and then hides it after some time. - */ - @VisibleForTesting - void animateInFlyoutForBubble(Bubble bubble) { + private boolean shouldShowFlyout(Bubble bubble) { Bubble.FlyoutMessage flyoutMessage = bubble.getFlyoutMessage(); final BadgedImageView bubbleView = bubble.getIconView(); if (flyoutMessage == null @@ -2187,11 +2183,22 @@ public class BubbleStackView extends FrameLayout || mIsGestureInProgress || mBubbleToExpandAfterFlyoutCollapse != null || bubbleView == null) { - if (bubbleView != null) { + if (bubbleView != null && mFlyout.getVisibility() != VISIBLE) { bubbleView.removeDotSuppressionFlag(BadgedImageView.SuppressionFlag.FLYOUT_VISIBLE); } // Skip the message if none exists, we're expanded or animating expansion, or we're // about to expand a bubble from the previous tapped flyout, or if bubble view is null. + return false; + } + return true; + } + + /** + * Animates in the flyout for the given bubble, if available, and then hides it after some time. + */ + @VisibleForTesting + void animateInFlyoutForBubble(Bubble bubble) { + if (!shouldShowFlyout(bubble)) { return; } @@ -2209,25 +2216,22 @@ public class BubbleStackView extends FrameLayout } // Stop suppressing the dot now that the flyout has morphed into the dot. - bubbleView.removeDotSuppressionFlag( + bubble.getIconView().removeDotSuppressionFlag( BadgedImageView.SuppressionFlag.FLYOUT_VISIBLE); - mFlyout.setVisibility(INVISIBLE); - // Hide the stack after a delay, if needed. updateTemporarilyInvisibleAnimation(false /* hideImmediately */); }; - mFlyout.setVisibility(INVISIBLE); // Suppress the dot when we are animating the flyout. - bubbleView.addDotSuppressionFlag( + bubble.getIconView().addDotSuppressionFlag( BadgedImageView.SuppressionFlag.FLYOUT_VISIBLE); // Start flyout expansion. Post in case layout isn't complete and getWidth returns 0. post(() -> { // An auto-expanding bubble could have been posted during the time it takes to // layout. - if (isExpanded()) { + if (isExpanded() || bubble.getIconView() == null) { return; } final Runnable expandFlyoutAfterDelay = () -> { @@ -2244,18 +2248,21 @@ public class BubbleStackView extends FrameLayout mFlyout.postDelayed(mAnimateInFlyout, 200); }; - if (bubble.getIconView() == null) { - return; - } - mFlyout.setupFlyoutStartingAsDot(flyoutMessage, - mStackAnimationController.getStackPosition(), getWidth(), - mStackAnimationController.isStackOnLeftSide(), - bubble.getIconView().getDotColor() /* dotColor */, - expandFlyoutAfterDelay /* onLayoutComplete */, - mAfterFlyoutHidden, - bubble.getIconView().getDotCenter(), - !bubble.showDot()); + if (mFlyout.getVisibility() == View.VISIBLE) { + mFlyout.animateUpdate(bubble.getFlyoutMessage(), getWidth(), + mStackAnimationController.getStackPosition().y); + } else { + mFlyout.setVisibility(INVISIBLE); + mFlyout.setupFlyoutStartingAsDot(bubble.getFlyoutMessage(), + mStackAnimationController.getStackPosition(), getWidth(), + mStackAnimationController.isStackOnLeftSide(), + bubble.getIconView().getDotColor() /* dotColor */, + expandFlyoutAfterDelay /* onLayoutComplete */, + mAfterFlyoutHidden, + bubble.getIconView().getDotCenter(), + !bubble.showDot()); + } mFlyout.bringToFront(); }); mFlyout.removeCallbacks(mHideFlyout); diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/StackEducationView.kt b/packages/SystemUI/src/com/android/systemui/bubbles/StackEducationView.kt index 9e7a2fb68d58..216df2e1f402 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/StackEducationView.kt +++ b/packages/SystemUI/src/com/android/systemui/bubbles/StackEducationView.kt @@ -128,7 +128,7 @@ class StackEducationView constructor(context: Context) : LinearLayout(context) { private fun setShouldShow(shouldShow: Boolean) { context.getSharedPreferences(context.packageName, Context.MODE_PRIVATE) - .edit().putBoolean(PREF_MANAGED_EDUCATION, !shouldShow).apply() + .edit().putBoolean(PREF_STACK_EDUCATION, !shouldShow).apply() } } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java index fd73207a1e3e..7fdc01961aa5 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java @@ -274,16 +274,14 @@ public class ExpandedAnimationController // Then, draw a line across the screen to the bubble's resting position. path.lineTo(getBubbleLeft(index), expandedY); } else { - final float sideMultiplier = - mLayout.isFirstChildXLeftOfCenter(mCollapsePoint.x) ? -1 : 1; - final float stackedX = mCollapsePoint.x + (sideMultiplier * index * mStackOffsetPx); + final float stackedX = mCollapsePoint.x; // If we're collapsing, draw a line from the bubble's current position to the side // of the screen where the bubble will be stacked. path.lineTo(stackedX, expandedY); // Then, draw a line down to the stack position. - path.lineTo(stackedX, mCollapsePoint.y); + path.lineTo(stackedX, mCollapsePoint.y + index * mStackOffsetPx); } // The lead bubble should be the bubble with the longest distance to travel when we're diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java index 4c902b99d4ea..12051241f049 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java @@ -744,15 +744,13 @@ public class StackAnimationController extends @Override float getOffsetForChainedPropertyAnimation(DynamicAnimation.ViewProperty property) { - if (property.equals(DynamicAnimation.TRANSLATION_X)) { + if (property.equals(DynamicAnimation.TRANSLATION_Y)) { // If we're in the dismiss target, have the bubbles pile on top of each other with no // offset. if (isStackStuckToTarget()) { return 0f; } else { - // Offset to the left if we're on the left, or the right otherwise. - return mLayout.isFirstChildXLeftOfCenter(mStackPosition.x) - ? -mStackOffset : mStackOffset; + return mStackOffset; } } else { return 0f; diff --git a/packages/SystemUI/src/com/android/systemui/doze/dagger/DozeScope.java b/packages/SystemUI/src/com/android/systemui/doze/dagger/DozeScope.java index 7a8b8166a969..435859afc03f 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/dagger/DozeScope.java +++ b/packages/SystemUI/src/com/android/systemui/doze/dagger/DozeScope.java @@ -24,7 +24,7 @@ import java.lang.annotation.Retention; import javax.inject.Scope; /** - * Scope annotation for singleton items within the StatusBarComponent. + * Scope annotation for singleton items within the DozeComponent. */ @Documented @Retention(RUNTIME) diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java index b55b29a80410..a330be6449e2 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java @@ -140,8 +140,14 @@ public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks d.setContentView(R.layout.shutdown_dialog); d.setCancelable(false); - int color = Utils.getColorAttrDefaultColor(mContext, - com.android.systemui.R.attr.wallpaperTextColor); + int color; + if (mBlurUtils.supportsBlursOnWindows()) { + color = Utils.getColorAttrDefaultColor(mContext, + com.android.systemui.R.attr.wallpaperTextColor); + } else { + color = mContext.getResources().getColor( + com.android.systemui.R.color.global_actions_shutdown_ui_text); + } ProgressBar bar = d.findViewById(R.id.progress); bar.getIndeterminateDrawable().setTint(color); diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselScrollHandler.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselScrollHandler.kt index d80aafb714d3..cb14f31abd16 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselScrollHandler.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselScrollHandler.kt @@ -282,10 +282,12 @@ class MediaCarouselScrollHandler( scrollXAmount = -1 * relativePos } if (scrollXAmount != 0) { + val dx = if (isRtl) -scrollXAmount else scrollXAmount + val newScrollX = scrollView.relativeScrollX + dx // Delay the scrolling since scrollView calls springback which cancels // the animation again.. mainExecutor.execute { - scrollView.smoothScrollBy(if (isRtl) -scrollXAmount else scrollXAmount, 0) + scrollView.smoothScrollTo(newScrollX, scrollView.scrollY) } } val currentTranslation = scrollView.getContentTranslation() @@ -553,4 +555,4 @@ class MediaCarouselScrollHandler( } } } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java index 5b096ea363b6..c18a6a45e286 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java +++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java @@ -354,7 +354,15 @@ public class MediaControlPanel { final MediaController controller = getController(); mBackgroundExecutor.execute(() -> mSeekBarViewModel.updateController(controller)); + // Guts label + boolean isDismissible = data.isClearable(); + mViewHolder.getSettingsText().setText(isDismissible + ? R.string.controls_media_close_session + : R.string.controls_media_active_session); + // Dismiss + mViewHolder.getDismissLabel().setAlpha(isDismissible ? 1 : DISABLED_ALPHA); + mViewHolder.getDismiss().setEnabled(isDismissible); mViewHolder.getDismiss().setOnClickListener(v -> { if (mKey != null) { closeGuts(); diff --git a/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt b/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt index 666a6038a8b6..16327bd9064a 100644 --- a/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt +++ b/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt @@ -60,8 +60,10 @@ class PlayerViewHolder private constructor(itemView: View) { val action4 = itemView.requireViewById<ImageButton>(R.id.action4) // Settings screen + val settingsText = itemView.requireViewById<TextView>(R.id.remove_text) val cancel = itemView.requireViewById<View>(R.id.cancel) - val dismiss = itemView.requireViewById<View>(R.id.dismiss) + val dismiss = itemView.requireViewById<ViewGroup>(R.id.dismiss) + val dismissLabel = dismiss.getChildAt(0) val settings = itemView.requireViewById<View>(R.id.settings) init { diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java index 5279a20a67a7..ddf30ad663dd 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java +++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java @@ -95,7 +95,6 @@ import com.android.wm.shell.onehanded.OneHanded; import com.android.wm.shell.onehanded.OneHandedEvents; import com.android.wm.shell.pip.Pip; import com.android.wm.shell.pip.PipAnimationController; -import com.android.wm.shell.pip.phone.PipUtils; import com.android.wm.shell.splitscreen.SplitScreen; import java.io.FileDescriptor; @@ -151,7 +150,6 @@ public class OverviewProxyService extends CurrentUserTracker implements private int mConnectionBackoffAttempts; private boolean mBound; private boolean mIsEnabled; - private boolean mHasPipFeature; private int mCurrentBoundedUserId = -1; private float mNavBarButtonAlpha; private boolean mInputFocusTransferStarted; @@ -377,9 +375,7 @@ public class OverviewProxyService extends CurrentUserTracker implements @Override public void setShelfHeight(boolean visible, int shelfHeight) { - if (!verifyCaller("setShelfHeight") || !mHasPipFeature) { - Log.w(TAG_OPS, - "ByPass setShelfHeight, FEATURE_PICTURE_IN_PICTURE:" + mHasPipFeature); + if (!verifyCaller("setShelfHeight")) { return; } final long token = Binder.clearCallingIdentity(); @@ -405,9 +401,7 @@ public class OverviewProxyService extends CurrentUserTracker implements @Override public void notifySwipeToHomeFinished() { - if (!verifyCaller("notifySwipeToHomeFinished") || !mHasPipFeature) { - Log.w(TAG_OPS, "ByPass notifySwipeToHomeFinished, FEATURE_PICTURE_IN_PICTURE:" - + mHasPipFeature); + if (!verifyCaller("notifySwipeToHomeFinished")) { return; } final long token = Binder.clearCallingIdentity(); @@ -422,9 +416,7 @@ public class OverviewProxyService extends CurrentUserTracker implements @Override public void setPinnedStackAnimationListener(IPinnedStackAnimationListener listener) { - if (!verifyCaller("setPinnedStackAnimationListener") || !mHasPipFeature) { - Log.w(TAG_OPS, "ByPass setPinnedStackAnimationListener, FEATURE_PICTURE_IN_PICTURE:" - + mHasPipFeature); + if (!verifyCaller("setPinnedStackAnimationListener")) { return; } mIPinnedStackAnimationListener = listener; @@ -509,7 +501,7 @@ public class OverviewProxyService extends CurrentUserTracker implements public Rect startSwipePipToHome(ComponentName componentName, ActivityInfo activityInfo, PictureInPictureParams pictureInPictureParams, int launcherRotation, int shelfHeight) { - if (!verifyCaller("startSwipePipToHome") || !mHasPipFeature) { + if (!verifyCaller("startSwipePipToHome")) { return null; } final long binderToken = Binder.clearCallingIdentity(); @@ -525,7 +517,7 @@ public class OverviewProxyService extends CurrentUserTracker implements @Override public void stopSwipePipToHome(ComponentName componentName, Rect destinationBounds) { - if (!verifyCaller("stopSwipePipToHome") || !mHasPipFeature) { + if (!verifyCaller("stopSwipePipToHome")) { return; } final long binderToken = Binder.clearCallingIdentity(); @@ -650,7 +642,6 @@ public class OverviewProxyService extends CurrentUserTracker implements super(broadcastDispatcher); mContext = context; mPipOptional = pipOptional; - mHasPipFeature = PipUtils.hasSystemFeature(mContext); mStatusBarOptionalLazy = statusBarOptionalLazy; mHandler = new Handler(); mNavBarControllerLazy = navBarControllerLazy; diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java index aaa335c25d5d..7d697539bf90 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java @@ -45,6 +45,7 @@ import android.graphics.Region; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; +import android.graphics.drawable.Icon; import android.graphics.drawable.InsetDrawable; import android.graphics.drawable.LayerDrawable; import android.media.MediaActionSound; @@ -194,6 +195,8 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset private ImageView mActionsContainerBackground; private HorizontalScrollView mActionsContainer; private LinearLayout mActionsView; + private ScreenshotActionChip mShareChip; + private ScreenshotActionChip mEditChip; private ImageView mBackgroundProtection; private FrameLayout mDismissButton; @@ -215,6 +218,14 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset private int mLeftInset; private int mRightInset; + private ArrayList<ScreenshotActionChip> mSmartChips = new ArrayList<>(); + private PendingInteraction mPendingInteraction; + private enum PendingInteraction { + PREVIEW, + EDIT, + SHARE + } + // standard material ease private final Interpolator mFastOutSlowIn; @@ -548,6 +559,9 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset mOnCompleteRunnable.run(); }); + mShareChip = mActionsContainer.findViewById(R.id.screenshot_share_chip); + mEditChip = mActionsContainer.findViewById(R.id.screenshot_edit_chip); + mScreenshotFlash = mScreenshotLayout.findViewById(R.id.global_screenshot_flash); mScreenshotSelectorView = mScreenshotLayout.findViewById(R.id.global_screenshot_selector); mScreenshotLayout.setFocusable(true); @@ -756,11 +770,11 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); - createScreenshotActionsShadeAnimation(imageData).start(); + setChipIntents(imageData); } }); } else { - createScreenshotActionsShadeAnimation(imageData).start(); + setChipIntents(imageData); } }); } @@ -895,19 +909,14 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset mScreenshotAnimatedView.setVisibility(View.GONE); mScreenshotPreview.setVisibility(View.VISIBLE); mScreenshotLayout.forceLayout(); + createScreenshotActionsShadeAnimation().start(); } }); return dropInAnimation; } - private ValueAnimator createScreenshotActionsShadeAnimation(SavedImageData imageData) { - LayoutInflater inflater = LayoutInflater.from(mContext); - mActionsView.removeAllViews(); - mScreenshotLayout.invalidate(); - mScreenshotLayout.requestLayout(); - mScreenshotLayout.getViewTreeObserver().dispatchOnGlobalLayout(); - + private ValueAnimator createScreenshotActionsShadeAnimation() { // By default the activities won't be able to start immediately; override this to keep // the same behavior as if started from a notification try { @@ -917,61 +926,35 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset ArrayList<ScreenshotActionChip> chips = new ArrayList<>(); - for (Notification.Action smartAction : imageData.smartActions) { - ScreenshotActionChip actionChip = (ScreenshotActionChip) inflater.inflate( - R.layout.global_screenshot_action_chip, mActionsView, false); - actionChip.setText(smartAction.title); - actionChip.setIcon(smartAction.getIcon(), false); - actionChip.setPendingIntent(smartAction.actionIntent, - () -> { - mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SMART_ACTION_TAPPED); - dismissScreenshot("chip tapped", false); - mOnCompleteRunnable.run(); - }); - mActionsView.addView(actionChip); - chips.add(actionChip); - } - - ScreenshotActionChip shareChip = (ScreenshotActionChip) inflater.inflate( - R.layout.global_screenshot_action_chip, mActionsView, false); - shareChip.setText(imageData.shareAction.title); - shareChip.setIcon(imageData.shareAction.getIcon(), true); - shareChip.setPendingIntent(imageData.shareAction.actionIntent, () -> { - mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SHARE_TAPPED); - dismissScreenshot("chip tapped", false); - mOnCompleteRunnable.run(); + mShareChip.setText(mContext.getString(com.android.internal.R.string.share)); + mShareChip.setIcon(Icon.createWithResource(mContext, R.drawable.ic_screenshot_share), true); + mShareChip.setOnClickListener(v -> { + mShareChip.setIsPending(true); + mEditChip.setIsPending(false); + mPendingInteraction = PendingInteraction.SHARE; }); - mActionsView.addView(shareChip); - chips.add(shareChip); - - ScreenshotActionChip editChip = (ScreenshotActionChip) inflater.inflate( - R.layout.global_screenshot_action_chip, mActionsView, false); - editChip.setText(imageData.editAction.title); - editChip.setIcon(imageData.editAction.getIcon(), true); - editChip.setPendingIntent(imageData.editAction.actionIntent, () -> { - mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_EDIT_TAPPED); - dismissScreenshot("chip tapped", false); - mOnCompleteRunnable.run(); + chips.add(mShareChip); + + mEditChip.setText(mContext.getString(com.android.internal.R.string.screenshot_edit)); + mEditChip.setIcon(Icon.createWithResource(mContext, R.drawable.ic_screenshot_edit), true); + mEditChip.setOnClickListener(v -> { + mEditChip.setIsPending(true); + mShareChip.setIsPending(false); + mPendingInteraction = PendingInteraction.EDIT; }); - mActionsView.addView(editChip); - chips.add(editChip); + chips.add(mEditChip); mScreenshotPreview.setOnClickListener(v -> { - try { - imageData.editAction.actionIntent.send(); - mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_PREVIEW_TAPPED); - dismissScreenshot("screenshot preview tapped", false); - mOnCompleteRunnable.run(); - } catch (PendingIntent.CanceledException e) { - Log.e(TAG, "Intent cancelled", e); - } + mShareChip.setIsPending(false); + mEditChip.setIsPending(false); + mPendingInteraction = PendingInteraction.PREVIEW; }); - mScreenshotPreview.setContentDescription(imageData.editAction.title); // remove the margin from the last chip so that it's correctly aligned with the end LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) - mActionsView.getChildAt(mActionsView.getChildCount() - 1).getLayoutParams(); - params.setMarginEnd(0); + mActionsView.getChildAt(0).getLayoutParams(); + params.setMarginStart(0); + mActionsView.getChildAt(0).setLayoutParams(params); ValueAnimator animator = ValueAnimator.ofFloat(0, 1); animator.setDuration(SCREENSHOT_ACTIONS_EXPANSION_DURATION_MS); @@ -1004,6 +987,63 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset return animator; } + private void setChipIntents(SavedImageData imageData) { + mShareChip.setPendingIntent(imageData.shareAction.actionIntent, () -> { + mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SHARE_TAPPED); + dismissScreenshot("chip tapped", false); + mOnCompleteRunnable.run(); + }); + + mEditChip.setPendingIntent(imageData.editAction.actionIntent, () -> { + mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_EDIT_TAPPED); + dismissScreenshot("chip tapped", false); + mOnCompleteRunnable.run(); + }); + + mScreenshotPreview.setOnClickListener(v -> { + try { + imageData.editAction.actionIntent.send(); + mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_PREVIEW_TAPPED); + dismissScreenshot("screenshot preview tapped", false); + mOnCompleteRunnable.run(); + } catch (PendingIntent.CanceledException e) { + Log.e(TAG, "Intent cancelled", e); + } + }); + + if (mPendingInteraction != null) { + switch(mPendingInteraction) { + case PREVIEW: + mScreenshotPreview.callOnClick(); + break; + case SHARE: + mShareChip.callOnClick(); + break; + case EDIT: + mEditChip.callOnClick(); + break; + } + } else { + LayoutInflater inflater = LayoutInflater.from(mContext); + + for (Notification.Action smartAction : imageData.smartActions) { + ScreenshotActionChip actionChip = (ScreenshotActionChip) inflater.inflate( + R.layout.global_screenshot_action_chip, mActionsView, false); + actionChip.setText(smartAction.title); + actionChip.setIcon(smartAction.getIcon(), false); + actionChip.setPendingIntent(smartAction.actionIntent, + () -> { + mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SMART_ACTION_TAPPED); + dismissScreenshot("chip tapped", false); + mOnCompleteRunnable.run(); + }); + actionChip.setAlpha(1); + mActionsView.addView(actionChip); + mSmartChips.add(actionChip); + } + } + } + private AnimatorSet createScreenshotDismissAnimation() { ValueAnimator alphaAnim = ValueAnimator.ofFloat(0, 1); alphaAnim.setStartDelay(SCREENSHOT_DISMISS_ALPHA_OFFSET_MS); @@ -1046,9 +1086,16 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset mDismissButton.setVisibility(View.GONE); mScreenshotPreview.setVisibility(View.GONE); mScreenshotPreview.setLayerType(View.LAYER_TYPE_NONE, null); - mScreenshotPreview.setContentDescription( - mContext.getResources().getString(R.string.screenshot_preview_description)); mScreenshotPreview.setOnClickListener(null); + mShareChip.setOnClickListener(null); + mEditChip.setOnClickListener(null); + mShareChip.setIsPending(false); + mEditChip.setIsPending(false); + mPendingInteraction = null; + for (ScreenshotActionChip chip : mSmartChips) { + mActionsView.removeView(chip); + } + mSmartChips.clear(); mScreenshotLayout.setAlpha(1); mDismissButton.setTranslationY(0); mActionsContainer.setTranslationY(0); diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionChip.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionChip.java index a48870240384..3370946ec274 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionChip.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotActionChip.java @@ -16,7 +16,6 @@ package com.android.systemui.screenshot; -import android.annotation.ColorInt; import android.app.PendingIntent; import android.content.Context; import android.graphics.drawable.Icon; @@ -35,9 +34,9 @@ public class ScreenshotActionChip extends FrameLayout { private static final String TAG = "ScreenshotActionChip"; - private ImageView mIcon; - private TextView mText; - private @ColorInt int mIconColor; + private ImageView mIconView; + private TextView mTextView; + private boolean mIsPending = false; public ScreenshotActionChip(Context context) { this(context, null); @@ -54,25 +53,29 @@ public class ScreenshotActionChip extends FrameLayout { public ScreenshotActionChip( Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); - - mIconColor = context.getColor(R.color.global_screenshot_button_icon); } @Override protected void onFinishInflate() { - mIcon = findViewById(R.id.screenshot_action_chip_icon); - mText = findViewById(R.id.screenshot_action_chip_text); + mIconView = findViewById(R.id.screenshot_action_chip_icon); + mTextView = findViewById(R.id.screenshot_action_chip_text); + } + + @Override + public void setPressed(boolean pressed) { + // override pressed state to true if there is an action pending + super.setPressed(mIsPending || pressed); } void setIcon(Icon icon, boolean tint) { - mIcon.setImageIcon(icon); + mIconView.setImageIcon(icon); if (!tint) { - mIcon.setImageTintList(null); + mIconView.setImageTintList(null); } } void setText(CharSequence text) { - mText.setText(text); + mTextView.setText(text); } void setPendingIntent(PendingIntent intent, Runnable finisher) { @@ -85,4 +88,9 @@ public class ScreenshotActionChip extends FrameLayout { } }); } + + void setIsPending(boolean isPending) { + mIsPending = isPending; + setPressed(mIsPending); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java index 0184fa7a5bfd..dcee9fa9e648 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java @@ -140,6 +140,8 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController< private static final int MSG_SUPPRESS_AMBIENT_DISPLAY = 56 << MSG_SHIFT; private static final int MSG_REQUEST_WINDOW_MAGNIFICATION_CONNECTION = 57 << MSG_SHIFT; private static final int MSG_HANDLE_WINDOW_MANAGER_LOGGING_COMMAND = 58 << MSG_SHIFT; + //TODO(b/169175022) Update name and when feature name is locked. + private static final int MSG_EMERGENCY_ACTION_LAUNCH_GESTURE = 59 << MSG_SHIFT; public static final int FLAG_EXCLUDE_NONE = 0; public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0; @@ -258,6 +260,11 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController< default void showAssistDisclosure() { } default void startAssist(Bundle args) { } default void onCameraLaunchGestureDetected(int source) { } + + /** + * Notifies SysUI that the emergency action gesture was detected. + */ + default void onEmergencyActionLaunchGestureDetected() { } default void showPictureInPictureMenu() { } default void setTopAppHidesStatusBar(boolean topAppHidesStatusBar) { } @@ -730,6 +737,14 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController< } @Override + public void onEmergencyActionLaunchGestureDetected() { + synchronized (mLock) { + mHandler.removeMessages(MSG_EMERGENCY_ACTION_LAUNCH_GESTURE); + mHandler.obtainMessage(MSG_EMERGENCY_ACTION_LAUNCH_GESTURE).sendToTarget(); + } + } + + @Override public void addQsTile(ComponentName tile) { synchronized (mLock) { mHandler.obtainMessage(MSG_ADD_QS_TILE, tile).sendToTarget(); @@ -1186,6 +1201,10 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController< mCallbacks.get(i).onCameraLaunchGestureDetected(msg.arg1); } break; + case MSG_EMERGENCY_ACTION_LAUNCH_GESTURE: + for (int i = 0; i < mCallbacks.size(); i++) { + mCallbacks.get(i).onEmergencyActionLaunchGestureDetected(); + } case MSG_SHOW_PICTURE_IN_PICTURE_MENU: for (int i = 0; i < mCallbacks.size(); i++) { mCallbacks.get(i).showPictureInPictureMenu(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java index 1fdf631a858d..ef4108b9762d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java @@ -175,8 +175,8 @@ public class KeyguardClockPositionAlgorithm { } /** - * Update lock screen mode for testing different layouts - */ + * Update lock screen mode for testing different layouts + */ public void onLockScreenModeChanged(int mode) { mLockScreenMode = mode; } @@ -241,6 +241,13 @@ public class KeyguardClockPositionAlgorithm { clockYDark = MathUtils.lerp(clockYBouncer, clockYDark, shadeExpansion); float darkAmount = mBypassEnabled && !mHasCustomClock ? 1.0f : mDarkAmount; + + // TODO(b/12836565) - prototyping only adjustment + if (mLockScreenMode != KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL) { + // This will keep the clock at the top for AOD + darkAmount = 0f; + } + return (int) (MathUtils.lerp(clockY, clockYDark, darkAmount) + mEmptyDragAmount); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 873d40ff6e1e..88a387d34f8d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -69,6 +69,7 @@ import android.content.IntentFilter; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.ResolveInfo; import android.content.res.Configuration; import android.graphics.Point; import android.graphics.PointF; @@ -152,6 +153,7 @@ import com.android.systemui.dagger.qualifiers.UiBackground; import com.android.systemui.demomode.DemoMode; import com.android.systemui.demomode.DemoModeCommandReceiver; import com.android.systemui.demomode.DemoModeController; +import com.android.systemui.emergency.EmergencyGesture; import com.android.systemui.fragments.ExtensionFragmentListener; import com.android.systemui.fragments.FragmentHostManager; import com.android.systemui.keyguard.DismissCallbackRegistry; @@ -819,7 +821,7 @@ public class StatusBar extends SystemUI implements DemoMode, updateScrimController(); }; - + mActivityIntentHelper = new ActivityIntentHelper(mContext); DateTimeView.setReceiverHandler(timeTickHandler); } @@ -833,8 +835,6 @@ public class StatusBar extends SystemUI implements DemoMode, mBubblesOptional.get().setExpandListener(mBubbleExpandListener); } - mActivityIntentHelper = new ActivityIntentHelper(mContext); - mColorExtractor.addOnColorsChangedListener(this); mStatusBarStateController.addCallback(this, SysuiStatusBarStateController.RANK_STATUS_BAR); @@ -3980,6 +3980,27 @@ public class StatusBar extends SystemUI implements DemoMode, } } + @Override + public void onEmergencyActionLaunchGestureDetected() { + // TODO (b/169793384) Polish the panic gesture to be just like its older brother, camera. + Intent emergencyIntent = new Intent(EmergencyGesture.ACTION_LAUNCH_EMERGENCY); + PackageManager pm = mContext.getPackageManager(); + ResolveInfo resolveInfo = pm.resolveActivity(emergencyIntent, /*flags=*/0); + if (resolveInfo == null) { + Log.wtf(TAG, "Couldn't find an app to process the emergency intent."); + return; + } + + if (mVibrator != null && mVibrator.hasVibrator()) { + mVibrator.vibrate(500L); + } + + emergencyIntent.setComponent(new ComponentName(resolveInfo.activityInfo.packageName, + resolveInfo.activityInfo.name)); + emergencyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(emergencyIntent, /*dismissShade=*/true); + } + boolean isCameraAllowedByAdmin() { if (mDevicePolicyManager.getCameraDisabled(null, mLockscreenUserManager.getCurrentUserId())) { diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java index f55445ca1de3..28343ed5d1f6 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java @@ -46,20 +46,24 @@ import dagger.Provides; */ @Module public abstract class TvPipModule { - @SysUISingleton @Provides - static Pip providePipController(Context context, + static Optional<Pip> providePip( + Context context, PipBoundsHandler pipBoundsHandler, PipTaskOrganizer pipTaskOrganizer, WindowManagerShellWrapper windowManagerShellWrapper) { - return new PipController(context, pipBoundsHandler, pipTaskOrganizer, - windowManagerShellWrapper); + return Optional.of( + new PipController( + context, + pipBoundsHandler, + pipTaskOrganizer, + windowManagerShellWrapper)); } @SysUISingleton @Provides - static PipControlsViewController providePipControlsViewContrller( + static PipControlsViewController providePipControlsViewController( PipControlsView pipControlsView, PipController pipController, LayoutInflater layoutInflater, Handler handler) { return new PipControlsViewController(pipControlsView, pipController, layoutInflater, diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java index 56efffc29d85..7e1a2e830660 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java @@ -52,6 +52,8 @@ public class TvWMShellModule { transactionPool); } + @SysUISingleton + @Provides static SplitScreen provideSplitScreen(Context context, DisplayController displayController, SystemWindows systemWindows, DisplayImeController displayImeController, @Main Handler handler, diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java index 9281a090fd97..3c4c3fcdf4f4 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java @@ -167,9 +167,6 @@ public final class WMShell extends SystemUI @VisibleForTesting void initPip(Pip pip) { - if (!PipUtils.hasSystemFeature(mContext)) { - return; - } mCommandQueue.addCallback(new CommandQueue.Callbacks() { @Override public void showPictureInPictureMenu() { diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java index 09678b5d1772..ac6e5ded3de3 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java @@ -41,7 +41,6 @@ import com.android.wm.shell.common.SystemWindows; import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.onehanded.OneHanded; import com.android.wm.shell.onehanded.OneHandedController; -import com.android.wm.shell.pip.Pip; import com.android.wm.shell.pip.PipSurfaceTransactionHelper; import com.android.wm.shell.pip.PipUiEventLogger; import com.android.wm.shell.pip.phone.PipAppOpsListener; @@ -117,7 +116,7 @@ public abstract class WMShellBaseModule { @SysUISingleton @Provides - static PipSurfaceTransactionHelper providesPipSurfaceTransactionHelper(Context context) { + static PipSurfaceTransactionHelper providePipSurfaceTransactionHelper(Context context) { return new PipSurfaceTransactionHelper(context); } @@ -159,9 +158,6 @@ public abstract class WMShellBaseModule { } @BindsOptionalOf - abstract Pip optionalPip(); - - @BindsOptionalOf abstract SplitScreen optionalSplitScreen(); @BindsOptionalOf diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java index 975757a4c259..81cb1f487ed8 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java @@ -68,24 +68,6 @@ public class WMShellModule { @SysUISingleton @Provides - static Pip providePipController(Context context, - DisplayController displayController, - PipAppOpsListener pipAppOpsListener, - PipBoundsHandler pipBoundsHandler, - PipBoundsState pipBoundsState, - PipMediaController pipMediaController, - PipMenuActivityController pipMenuActivityController, - PipTaskOrganizer pipTaskOrganizer, - PipTouchHandler pipTouchHandler, - WindowManagerShellWrapper windowManagerShellWrapper) { - return new PipController(context, displayController, - pipAppOpsListener, pipBoundsHandler, pipBoundsState, pipMediaController, - pipMenuActivityController, pipTaskOrganizer, pipTouchHandler, - windowManagerShellWrapper); - } - - @SysUISingleton - @Provides static SplitScreen provideSplitScreen(Context context, DisplayController displayController, SystemWindows systemWindows, DisplayImeController displayImeController, @Main Handler handler, @@ -97,26 +79,39 @@ public class WMShellModule { @SysUISingleton @Provides + static Optional<Pip> providePip(Context context, DisplayController displayController, + PipAppOpsListener pipAppOpsListener, PipBoundsHandler pipBoundsHandler, + PipBoundsState pipBoundsState, PipMediaController pipMediaController, + PipMenuActivityController pipMenuActivityController, PipTaskOrganizer pipTaskOrganizer, + PipTouchHandler pipTouchHandler, WindowManagerShellWrapper windowManagerShellWrapper) { + return Optional.ofNullable(PipController.create(context, displayController, + pipAppOpsListener, pipBoundsHandler, pipBoundsState, pipMediaController, + pipMenuActivityController, pipTaskOrganizer, pipTouchHandler, + windowManagerShellWrapper)); + } + + @SysUISingleton + @Provides static PipBoundsState providePipBoundsState() { return new PipBoundsState(); } @SysUISingleton @Provides - static PipBoundsHandler providesPipBoundsHandler(Context context) { + static PipBoundsHandler providePipBoundsHandler(Context context) { return new PipBoundsHandler(context); } @SysUISingleton @Provides - static PipMenuActivityController providesPipMenuActivityController(Context context, + static PipMenuActivityController providePipMenuActivityController(Context context, PipMediaController pipMediaController, PipTaskOrganizer pipTaskOrganizer) { return new PipMenuActivityController(context, pipMediaController, pipTaskOrganizer); } @SysUISingleton @Provides - static PipTouchHandler providesPipTouchHandler(Context context, + static PipTouchHandler providePipTouchHandler(Context context, PipMenuActivityController menuActivityController, PipBoundsHandler pipBoundsHandler, PipBoundsState pipBoundsState, PipTaskOrganizer pipTaskOrganizer, @@ -128,7 +123,7 @@ public class WMShellModule { @SysUISingleton @Provides - static PipTaskOrganizer providesPipTaskOrganizer(Context context, + static PipTaskOrganizer providePipTaskOrganizer(Context context, PipBoundsState pipBoundsState, PipBoundsHandler pipBoundsHandler, PipSurfaceTransactionHelper pipSurfaceTransactionHelper, diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml index 2b4ed4e8f1cd..d541c8fbdff1 100644 --- a/packages/SystemUI/tests/AndroidManifest.xml +++ b/packages/SystemUI/tests/AndroidManifest.xml @@ -70,6 +70,13 @@ android:exported="false" android:resizeableActivity="true" /> + <activity android:name="com.android.systemui.emergency.EmergencyActivityTest" + android:exported="true"> + <intent-filter> + <action android:name="com.android.systemui.action.LAUNCH_EMERGENCY"/> + </intent-filter> + </activity> + <activity android:name="com.android.systemui.globalactions.GlobalActionsImeTest$TestActivity" android:excludeFromRecents="true" diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java index ae159c73b99f..62906f3656c7 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java @@ -20,9 +20,11 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; import android.content.Context; +import android.hardware.display.DisplayManager; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.util.AttributeSet; +import android.view.Display; import android.view.LayoutInflater; import android.view.View; @@ -104,9 +106,10 @@ public class KeyguardPresentationTest extends SysuiTestCase { @Test public void testInflation_doesntCrash() { - KeyguardPresentation keyguardPresentation = new KeyguardPresentation(mContext, - mContext.getDisplayNoVerify(), mKeyguardStatusViewComponentFactory, - mLayoutInflater); + final Display display = mContext.getSystemService(DisplayManager.class).getDisplay( + Display.DEFAULT_DISPLAY); + KeyguardPresentation keyguardPresentation = new KeyguardPresentation(mContext, display, + mKeyguardStatusViewComponentFactory); keyguardPresentation.onCreate(null /*savedInstanceState */); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java index 5f2fd697b86d..f1606c5660ed 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java @@ -224,11 +224,12 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { @Test - public void onDensityChanged_enabled_updateDimensionsAndLayout() { + public void onDensityChanged_enabled_updateDimensionsAndResetWindowMagnification() { mInstrumentation.runOnMainSync(() -> { mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN, Float.NaN); Mockito.reset(mWindowManager); + Mockito.reset(mMirrorWindowControl); }); mInstrumentation.runOnMainSync(() -> { @@ -237,7 +238,9 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { verify(mResources, atLeastOnce()).getDimensionPixelSize(anyInt()); verify(mWindowManager).removeView(any()); + verify(mMirrorWindowControl).destroyControl(); verify(mWindowManager).addView(any(), any()); + verify(mMirrorWindowControl).showControl(); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/emergency/EmergencyActivityTest.java b/packages/SystemUI/tests/src/com/android/systemui/emergency/EmergencyActivityTest.java new file mode 100644 index 000000000000..a52a598ee7ec --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/emergency/EmergencyActivityTest.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2020 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.emergency; + +import android.app.Activity; +import android.os.Bundle; + +import com.android.systemui.R; + +/** + * Test activity for resolving {@link EmergencyGesture#ACTION_LAUNCH_EMERGENCY} action. + */ +public class EmergencyActivityTest extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt index 182a056be557..af677c9d9f64 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt @@ -111,9 +111,11 @@ public class MediaControlPanelTest : SysuiTestCase() { private lateinit var action2: ImageButton private lateinit var action3: ImageButton private lateinit var action4: ImageButton + private lateinit var settingsText: TextView private lateinit var settings: View private lateinit var cancel: View - private lateinit var dismiss: View + private lateinit var dismiss: FrameLayout + private lateinit var dismissLabel: View private lateinit var session: MediaSession private val device = MediaDeviceData(true, null, DEVICE_NAME) @@ -171,12 +173,16 @@ public class MediaControlPanelTest : SysuiTestCase() { whenever(holder.action3).thenReturn(action3) action4 = ImageButton(context) whenever(holder.action4).thenReturn(action4) + settingsText = TextView(context) + whenever(holder.settingsText).thenReturn(settingsText) settings = View(context) whenever(holder.settings).thenReturn(settings) cancel = View(context) whenever(holder.cancel).thenReturn(cancel) - dismiss = View(context) + dismiss = FrameLayout(context) whenever(holder.dismiss).thenReturn(dismiss) + dismissLabel = View(context) + whenever(holder.dismissLabel).thenReturn(dismissLabel) // Create media session val metadataBuilder = MediaMetadata.Builder().apply { @@ -330,6 +336,7 @@ public class MediaControlPanelTest : SysuiTestCase() { notificationKey = KEY) player.bind(state, mediaKey) + assertThat(dismiss.isEnabled).isEqualTo(true) dismiss.callOnClick() val captor = ArgumentCaptor.forClass(ActivityStarter.OnDismissAction::class.java) verify(keyguardDismissUtil).executeWhenUnlocked(captor.capture(), anyBoolean()) @@ -337,4 +344,16 @@ public class MediaControlPanelTest : SysuiTestCase() { captor.value.onDismiss() verify(mediaDataManager).dismissMediaData(eq(mediaKey), anyLong()) } + + @Test + fun dismissButtonDisabled() { + val mediaKey = "key for dismissal" + player.attach(holder) + val state = MediaData(USER_ID, true, BG_COLOR, APP, null, ARTIST, TITLE, null, emptyList(), + emptyList(), PACKAGE, session.getSessionToken(), null, null, true, null, + isClearable = false, notificationKey = KEY) + player.bind(state, mediaKey) + + assertThat(dismiss.isEnabled).isEqualTo(false) + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java index a6ea9966a0f1..d6a7acbcbd78 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java @@ -24,6 +24,7 @@ import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; import static junit.framework.TestCase.fail; +import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; @@ -34,6 +35,7 @@ import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -43,6 +45,7 @@ import android.app.StatusBarManager; import android.app.trust.TrustManager; import android.content.BroadcastReceiver; import android.content.ContentResolver; +import android.content.Intent; import android.content.IntentFilter; import android.hardware.display.AmbientDisplayConfiguration; import android.hardware.fingerprint.FingerprintManager; @@ -84,6 +87,7 @@ import com.android.systemui.bubbles.Bubbles; import com.android.systemui.classifier.FalsingManagerFake; import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.demomode.DemoModeController; +import com.android.systemui.emergency.EmergencyGesture; import com.android.systemui.keyguard.DismissCallbackRegistry; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.keyguard.ScreenLifecycle; @@ -146,6 +150,7 @@ import com.android.wm.shell.splitscreen.SplitScreen; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -873,6 +878,19 @@ public class StatusBarTest extends SysuiTestCase { verify(mDozeServiceHost).setDozeSuppressed(false); } + @Test + public void onEmergencyActionLaunchGesture_launchesEmergencyIntent() { + ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); + StatusBar statusBarSpy = spy(mStatusBar); + + statusBarSpy.onEmergencyActionLaunchGestureDetected(); + + verify(statusBarSpy).startActivity(intentCaptor.capture(), eq(true)); + Intent sentIntent = intentCaptor.getValue(); + assertEquals(sentIntent.getAction(), EmergencyGesture.ACTION_LAUNCH_EMERGENCY); + + } + public static class TestableNotificationInterruptStateProviderImpl extends NotificationInterruptStateProviderImpl { diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java index 2bc07ed43e29..a58f1fdeb3f3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java @@ -16,17 +16,12 @@ package com.android.systemui.wmshell; -import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE; - import static org.mockito.ArgumentMatchers.any; -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.content.pm.PackageManager; import android.test.suitebuilder.annotation.SmallTest; -import android.testing.TestableContext; import androidx.test.runner.AndroidJUnit4; @@ -94,7 +89,6 @@ public class WMShellTest extends SysuiTestCase { mTaskOrganizer, mProtoTracer); when(mPip.getPipTouchHandler()).thenReturn(mPipTouchHandler); - } @Test @@ -112,26 +106,6 @@ public class WMShellTest extends SysuiTestCase { } @Test - public void nonPipDevice_shouldNotInitPip() { - final TestableContext nonPipContext = getNonPipFeatureContext(); - final WMShell nonPipWMShell = new WMShell(nonPipContext, mCommandQueue, - mConfigurationController, mMockInputConsumerController, mKeyguardUpdateMonitor, - mTaskStackChangeListeners, mDisplayImeController, mNavigationModeController, - mScreenLifecycle, mSysUiState, Optional.of(mPip), Optional.of(mSplitScreen), - Optional.of(mOneHanded), mTaskOrganizer, mProtoTracer); - nonPipWMShell.initPip(mPip); - - verify(mCommandQueue, never()).addCallback(any()); - verify(mKeyguardUpdateMonitor, never()).registerCallback(any()); - verify(mConfigurationController, never()).addCallback(any()); - verify(mSysUiState, never()).addCallback(any()); - verify(mTaskStackChangeListeners, never()).registerTaskStackListener(any()); - verify(mMockInputConsumerController, never()).setInputListener(any()); - verify(mMockInputConsumerController, never()).setRegistrationListener(any()); - verify(mPip, never()).registerSessionListenerForCurrentUser(); - } - - @Test public void initSplitScreen_registersCallbacks() { mWMShell.initSplitScreen(mSplitScreen); @@ -156,11 +130,4 @@ public class WMShellTest extends SysuiTestCase { OneHandedGestureHandler.OneHandedGestureEventCallback.class)); verify(mOneHanded).registerTransitionCallback(any(OneHandedTransitionCallback.class)); } - - TestableContext getNonPipFeatureContext() { - TestableContext spiedContext = spy(mContext); - when(mMockPackageManager.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)).thenReturn(false); - when(spiedContext.getPackageManager()).thenReturn(mMockPackageManager); - return spiedContext; - } } diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheredClient.java b/packages/Tethering/common/TetheringLib/src/android/net/TetheredClient.java index 645b00001330..0b223f42b954 100644 --- a/packages/Tethering/common/TetheringLib/src/android/net/TetheredClient.java +++ b/packages/Tethering/common/TetheringLib/src/android/net/TetheredClient.java @@ -19,7 +19,6 @@ package android.net; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; -import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; @@ -34,7 +33,6 @@ import java.util.Objects; * @hide */ @SystemApi -@TestApi public final class TetheredClient implements Parcelable { @NonNull private final MacAddress mMacAddress; diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java index db8436859281..13b05a841d24 100644 --- a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java +++ b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java @@ -23,7 +23,6 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; -import android.annotation.TestApi; import android.content.Context; import android.os.Bundle; import android.os.ConditionVariable; @@ -55,7 +54,6 @@ import java.util.function.Supplier; * @hide */ @SystemApi -@TestApi public class TetheringManager { private static final String TAG = TetheringManager.class.getSimpleName(); private static final int DEFAULT_TIMEOUT_MS = 60_000; diff --git a/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java b/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java index 0cf14e3f868c..9fc1d7e5bcd0 100644 --- a/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java +++ b/packages/Tethering/src/com/android/networkstack/tethering/PrivateAddressCoordinator.java @@ -36,6 +36,7 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.util.SparseArray; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; @@ -135,7 +136,6 @@ public class PrivateAddressCoordinator { private void handleMaybePrefixConflict(final List<IpPrefix> prefixes) { for (IpServer downstream : mDownstreams) { final IpPrefix target = getDownstreamPrefix(downstream); - if (target == null) continue; for (IpPrefix source : prefixes) { if (isConflictPrefix(source, target)) { @@ -179,6 +179,7 @@ public class PrivateAddressCoordinator { final LinkAddress cachedAddress = mCachedAddresses.get(ipServer.interfaceType()); if (useLastAddress && cachedAddress != null && !isConflictWithUpstream(asIpPrefix(cachedAddress))) { + mDownstreams.add(ipServer); return cachedAddress; } @@ -370,7 +371,6 @@ public class PrivateAddressCoordinator { // in mCachedAddresses. for (IpServer downstream : mDownstreams) { final IpPrefix target = getDownstreamPrefix(downstream); - if (target == null) continue; if (isConflictPrefix(prefix, target)) return target; } @@ -378,9 +378,9 @@ public class PrivateAddressCoordinator { return null; } + @NonNull private IpPrefix getDownstreamPrefix(final IpServer downstream) { final LinkAddress address = downstream.getAddress(); - if (address == null) return null; return asIpPrefix(address); } diff --git a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java index da13e341fb54..8cb80bad809c 100644 --- a/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java +++ b/packages/Tethering/tests/unit/src/com/android/networkstack/tethering/PrivateAddressCoordinatorTest.java @@ -104,24 +104,30 @@ public final class PrivateAddressCoordinatorTest { mTetheringPrefixes)); } + private LinkAddress requestDownstreamAddress(final IpServer ipServer, boolean useLastAddress) { + final LinkAddress address = mPrivateAddressCoordinator.requestDownstreamAddress( + ipServer, useLastAddress); + when(ipServer.getAddress()).thenReturn(address); + return address; + } + @Test public void testRequestDownstreamAddressWithoutUsingLastAddress() throws Exception { final IpPrefix bluetoothPrefix = asIpPrefix(mBluetoothAddress); - final LinkAddress address = mPrivateAddressCoordinator.requestDownstreamAddress( - mHotspotIpServer, false /* useLastAddress */); + final LinkAddress address = requestDownstreamAddress(mHotspotIpServer, + false /* useLastAddress */); final IpPrefix hotspotPrefix = asIpPrefix(address); assertNotEquals(hotspotPrefix, bluetoothPrefix); - when(mHotspotIpServer.getAddress()).thenReturn(address); - final LinkAddress newAddress = mPrivateAddressCoordinator.requestDownstreamAddress( - mHotspotIpServer, false /* useLastAddress */); + final LinkAddress newAddress = requestDownstreamAddress(mHotspotIpServer, + false /* useLastAddress */); final IpPrefix testDupRequest = asIpPrefix(newAddress); assertNotEquals(hotspotPrefix, testDupRequest); assertNotEquals(bluetoothPrefix, testDupRequest); mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer); - final LinkAddress usbAddress = mPrivateAddressCoordinator.requestDownstreamAddress( - mUsbIpServer, false /* useLastAddress */); + final LinkAddress usbAddress = requestDownstreamAddress(mUsbIpServer, + false /* useLastAddress */); final IpPrefix usbPrefix = asIpPrefix(usbAddress); assertNotEquals(usbPrefix, bluetoothPrefix); assertNotEquals(usbPrefix, hotspotPrefix); @@ -132,29 +138,26 @@ public final class PrivateAddressCoordinatorTest { public void testSanitizedAddress() throws Exception { int fakeSubAddr = 0x2b00; // 43.0. when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeSubAddr); - LinkAddress actualAddress = mPrivateAddressCoordinator.requestDownstreamAddress( - mHotspotIpServer, false /* useLastAddress */); + LinkAddress actualAddress = requestDownstreamAddress(mHotspotIpServer, + false /* useLastAddress */); assertEquals(new LinkAddress("192.168.43.2/24"), actualAddress); mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer); fakeSubAddr = 0x2d01; // 45.1. when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeSubAddr); - actualAddress = mPrivateAddressCoordinator.requestDownstreamAddress( - mHotspotIpServer, false /* useLastAddress */); + actualAddress = requestDownstreamAddress(mHotspotIpServer, false /* useLastAddress */); assertEquals(new LinkAddress("192.168.45.2/24"), actualAddress); mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer); fakeSubAddr = 0x2eff; // 46.255. when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeSubAddr); - actualAddress = mPrivateAddressCoordinator.requestDownstreamAddress( - mHotspotIpServer, false /* useLastAddress */); + actualAddress = requestDownstreamAddress(mHotspotIpServer, false /* useLastAddress */); assertEquals(new LinkAddress("192.168.46.254/24"), actualAddress); mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer); fakeSubAddr = 0x2f05; // 47.5. when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeSubAddr); - actualAddress = mPrivateAddressCoordinator.requestDownstreamAddress( - mHotspotIpServer, false /* useLastAddress */); + actualAddress = requestDownstreamAddress(mHotspotIpServer, false /* useLastAddress */); assertEquals(new LinkAddress("192.168.47.5/24"), actualAddress); mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer); } @@ -164,8 +167,8 @@ public final class PrivateAddressCoordinatorTest { // - Test bluetooth prefix is reserved. when(mPrivateAddressCoordinator.getRandomInt()).thenReturn( getSubAddress(mBluetoothAddress.getAddress().getAddress())); - final LinkAddress hotspotAddress = mPrivateAddressCoordinator.requestDownstreamAddress( - mHotspotIpServer, false /* useLastAddress */); + final LinkAddress hotspotAddress = requestDownstreamAddress(mHotspotIpServer, + false /* useLastAddress */); final IpPrefix hotspotPrefix = asIpPrefix(hotspotAddress); assertNotEquals(asIpPrefix(mBluetoothAddress), hotspotPrefix); mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer); @@ -173,8 +176,8 @@ public final class PrivateAddressCoordinatorTest { // - Test previous enabled hotspot prefix(cached prefix) is reserved. when(mPrivateAddressCoordinator.getRandomInt()).thenReturn( getSubAddress(hotspotAddress.getAddress().getAddress())); - final LinkAddress usbAddress = mPrivateAddressCoordinator.requestDownstreamAddress( - mUsbIpServer, false /* useLastAddress */); + final LinkAddress usbAddress = requestDownstreamAddress(mUsbIpServer, + false /* useLastAddress */); final IpPrefix usbPrefix = asIpPrefix(usbAddress); assertNotEquals(asIpPrefix(mBluetoothAddress), usbPrefix); assertNotEquals(hotspotPrefix, usbPrefix); @@ -183,8 +186,8 @@ public final class PrivateAddressCoordinatorTest { // - Test wifi p2p prefix is reserved. when(mPrivateAddressCoordinator.getRandomInt()).thenReturn( getSubAddress(mLegacyWifiP2pAddress.getAddress().getAddress())); - final LinkAddress etherAddress = mPrivateAddressCoordinator.requestDownstreamAddress( - mEthernetIpServer, false /* useLastAddress */); + final LinkAddress etherAddress = requestDownstreamAddress(mEthernetIpServer, + false /* useLastAddress */); final IpPrefix etherPrefix = asIpPrefix(etherAddress); assertNotEquals(asIpPrefix(mLegacyWifiP2pAddress), etherPrefix); assertNotEquals(asIpPrefix(mBluetoothAddress), etherPrefix); @@ -196,13 +199,12 @@ public final class PrivateAddressCoordinatorTest { public void testRequestLastDownstreamAddress() throws Exception { final int fakeHotspotSubAddr = 0x2b05; // 43.5 when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeHotspotSubAddr); - final LinkAddress hotspotAddress = mPrivateAddressCoordinator.requestDownstreamAddress( - mHotspotIpServer, true /* useLastAddress */); + final LinkAddress hotspotAddress = requestDownstreamAddress(mHotspotIpServer, + true /* useLastAddress */); assertEquals("Wrong wifi prefix: ", new LinkAddress("192.168.43.5/24"), hotspotAddress); - when(mHotspotIpServer.getAddress()).thenReturn(hotspotAddress); - final LinkAddress usbAddress = mPrivateAddressCoordinator.requestDownstreamAddress( - mUsbIpServer, true /* useLastAddress */); + final LinkAddress usbAddress = requestDownstreamAddress(mUsbIpServer, + true /* useLastAddress */); assertEquals("Wrong wifi prefix: ", new LinkAddress("192.168.45.5/24"), usbAddress); mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer); @@ -211,24 +213,19 @@ public final class PrivateAddressCoordinatorTest { final int newFakeSubAddr = 0x3c05; when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeHotspotSubAddr); - final LinkAddress newHotspotAddress = mPrivateAddressCoordinator.requestDownstreamAddress( - mHotspotIpServer, true /* useLastAddress */); + final LinkAddress newHotspotAddress = requestDownstreamAddress(mHotspotIpServer, + true /* useLastAddress */); assertEquals(hotspotAddress, newHotspotAddress); - final LinkAddress newUsbAddress = mPrivateAddressCoordinator.requestDownstreamAddress( - mUsbIpServer, true /* useLastAddress */); + final LinkAddress newUsbAddress = requestDownstreamAddress(mUsbIpServer, + true /* useLastAddress */); assertEquals(usbAddress, newUsbAddress); - // BUG: the code should detect a conflict, but it doesn't. - // Regression introduced in r.android.com/168169687. - // Ensure conflict notification works when using cached address. - when(mHotspotIpServer.getAddress()).thenReturn(newHotspotAddress); - when(mUsbIpServer.getAddress()).thenReturn(usbAddress); final UpstreamNetworkState wifiUpstream = buildUpstreamNetworkState(mWifiNetwork, new LinkAddress("192.168.88.23/16"), null, makeNetworkCapabilities(TRANSPORT_WIFI)); mPrivateAddressCoordinator.updateUpstreamPrefix(wifiUpstream); - verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT); - verify(mUsbIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT); + verify(mHotspotIpServer).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT); + verify(mUsbIpServer).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT); } private UpstreamNetworkState buildUpstreamNetworkState(final Network network, @@ -259,11 +256,10 @@ public final class PrivateAddressCoordinatorTest { // Force always get subAddress "43.5" for conflict testing. when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(fakeHotspotSubAddr); // - Enable hotspot with prefix 192.168.43.0/24 - final LinkAddress hotspotAddr = mPrivateAddressCoordinator.requestDownstreamAddress( - mHotspotIpServer, true /* useLastAddress */); + final LinkAddress hotspotAddr = requestDownstreamAddress(mHotspotIpServer, + true /* useLastAddress */); final IpPrefix hotspotPrefix = asIpPrefix(hotspotAddr); assertEquals("Wrong wifi prefix: ", predefinedPrefix, hotspotPrefix); - when(mHotspotIpServer.getAddress()).thenReturn(hotspotAddr); // - test mobile network with null NetworkCapabilities. Ideally this should not happen // because NetworkCapabilities update should always happen before LinkProperties update // and the UpstreamNetworkState update, just make sure no crash in this case. @@ -314,24 +310,22 @@ public final class PrivateAddressCoordinatorTest { reset(mHotspotIpServer); // - Restart hotspot again and its prefix is different previous. mPrivateAddressCoordinator.releaseDownstream(mHotspotIpServer); - final LinkAddress hotspotAddr2 = mPrivateAddressCoordinator.requestDownstreamAddress( - mHotspotIpServer, true /* useLastAddress */); + final LinkAddress hotspotAddr2 = requestDownstreamAddress(mHotspotIpServer, + true /* useLastAddress */); final IpPrefix hotspotPrefix2 = asIpPrefix(hotspotAddr2); assertNotEquals(hotspotPrefix, hotspotPrefix2); - when(mHotspotIpServer.getAddress()).thenReturn(hotspotAddr2); mPrivateAddressCoordinator.updateUpstreamPrefix(v4OnlyWifi); verify(mHotspotIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT); // - Usb tethering can be enabled and its prefix is different with conflict one. - final LinkAddress usbAddr = mPrivateAddressCoordinator.requestDownstreamAddress( - mUsbIpServer, true /* useLastAddress */); + final LinkAddress usbAddr = requestDownstreamAddress(mUsbIpServer, + true /* useLastAddress */); final IpPrefix usbPrefix = asIpPrefix(usbAddr); assertNotEquals(predefinedPrefix, usbPrefix); assertNotEquals(hotspotPrefix2, usbPrefix); - when(mUsbIpServer.getAddress()).thenReturn(usbAddr); // - Disable wifi upstream, then wifi's prefix can be selected again. mPrivateAddressCoordinator.removeUpstreamPrefix(mWifiNetwork); - final LinkAddress ethAddr = mPrivateAddressCoordinator.requestDownstreamAddress( - mEthernetIpServer, true /* useLastAddress */); + final LinkAddress ethAddr = requestDownstreamAddress(mEthernetIpServer, + true /* useLastAddress */); final IpPrefix ethPrefix = asIpPrefix(ethAddr); assertEquals(predefinedPrefix, ethPrefix); } @@ -340,21 +334,19 @@ public final class PrivateAddressCoordinatorTest { public void testChooseAvailablePrefix() throws Exception { final int randomAddress = 0x8605; // 134.5 when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(randomAddress); - final LinkAddress addr0 = mPrivateAddressCoordinator.requestDownstreamAddress( - mHotspotIpServer, true/* useLastAddress */); + final LinkAddress addr0 = requestDownstreamAddress(mHotspotIpServer, + true /* useLastAddress */); // Check whether return address is prefix 192.168.0.0/16 + subAddress 0.0.134.5. assertEquals("Wrong prefix: ", new LinkAddress("192.168.134.5/24"), addr0); - when(mHotspotIpServer.getAddress()).thenReturn(addr0); final UpstreamNetworkState wifiUpstream = buildUpstreamNetworkState(mWifiNetwork, new LinkAddress("192.168.134.13/26"), null, makeNetworkCapabilities(TRANSPORT_WIFI)); mPrivateAddressCoordinator.updateUpstreamPrefix(wifiUpstream); // Check whether return address is next prefix of 192.168.134.0/24. - final LinkAddress addr1 = mPrivateAddressCoordinator.requestDownstreamAddress( - mHotspotIpServer, true/* useLastAddress */); + final LinkAddress addr1 = requestDownstreamAddress(mHotspotIpServer, + true /* useLastAddress */); assertEquals("Wrong prefix: ", new LinkAddress("192.168.135.5/24"), addr1); - when(mHotspotIpServer.getAddress()).thenReturn(addr1); final UpstreamNetworkState wifiUpstream2 = buildUpstreamNetworkState(mWifiNetwork, new LinkAddress("192.168.149.16/19"), null, makeNetworkCapabilities(TRANSPORT_WIFI)); @@ -362,10 +354,9 @@ public final class PrivateAddressCoordinatorTest { // The conflict range is 128 ~ 159, so the address is 192.168.160.5/24. - final LinkAddress addr2 = mPrivateAddressCoordinator.requestDownstreamAddress( - mHotspotIpServer, true/* useLastAddress */); + final LinkAddress addr2 = requestDownstreamAddress(mHotspotIpServer, + true /* useLastAddress */); assertEquals("Wrong prefix: ", new LinkAddress("192.168.160.5/24"), addr2); - when(mHotspotIpServer.getAddress()).thenReturn(addr2); final UpstreamNetworkState mobileUpstream = buildUpstreamNetworkState(mMobileNetwork, new LinkAddress("192.168.129.53/18"), null, makeNetworkCapabilities(TRANSPORT_CELLULAR)); @@ -378,10 +369,9 @@ public final class PrivateAddressCoordinatorTest { mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream2); // The conflict range are 128 ~ 159 and 159 ~ 191, so the address is 192.168.192.5/24. - final LinkAddress addr3 = mPrivateAddressCoordinator.requestDownstreamAddress( - mHotspotIpServer, true/* useLastAddress */); + final LinkAddress addr3 = requestDownstreamAddress(mHotspotIpServer, + true /* useLastAddress */); assertEquals("Wrong prefix: ", new LinkAddress("192.168.192.5/24"), addr3); - when(mHotspotIpServer.getAddress()).thenReturn(addr3); final UpstreamNetworkState mobileUpstream3 = buildUpstreamNetworkState(mMobileNetwork3, new LinkAddress("192.168.188.133/17"), null, makeNetworkCapabilities(TRANSPORT_CELLULAR)); @@ -389,20 +379,18 @@ public final class PrivateAddressCoordinatorTest { // Conflict range: 128 ~ 255. The next available address is 192.168.0.5 because // 192.168.134/24 ~ 192.168.255.255/24 is not available. - final LinkAddress addr4 = mPrivateAddressCoordinator.requestDownstreamAddress( - mHotspotIpServer, true/* useLastAddress */); + final LinkAddress addr4 = requestDownstreamAddress(mHotspotIpServer, + true /* useLastAddress */); assertEquals("Wrong prefix: ", new LinkAddress("192.168.0.5/24"), addr4); - when(mHotspotIpServer.getAddress()).thenReturn(addr4); final UpstreamNetworkState mobileUpstream4 = buildUpstreamNetworkState(mMobileNetwork4, new LinkAddress("192.168.3.59/21"), null, makeNetworkCapabilities(TRANSPORT_CELLULAR)); mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream4); // Conflict ranges: 128 ~ 255 and 0 ~ 7, so the address is 192.168.8.5/24. - final LinkAddress addr5 = mPrivateAddressCoordinator.requestDownstreamAddress( - mHotspotIpServer, true/* useLastAddress */); + final LinkAddress addr5 = requestDownstreamAddress(mHotspotIpServer, + true /* useLastAddress */); assertEquals("Wrong prefix: ", new LinkAddress("192.168.8.5/24"), addr5); - when(mHotspotIpServer.getAddress()).thenReturn(addr5); final UpstreamNetworkState mobileUpstream5 = buildUpstreamNetworkState(mMobileNetwork5, new LinkAddress("192.168.68.43/21"), null, makeNetworkCapabilities(TRANSPORT_CELLULAR)); @@ -410,41 +398,37 @@ public final class PrivateAddressCoordinatorTest { // Update an upstream that does *not* conflict, check whether return the same address // 192.168.5/24. - final LinkAddress addr6 = mPrivateAddressCoordinator.requestDownstreamAddress( - mHotspotIpServer, true/* useLastAddress */); + final LinkAddress addr6 = requestDownstreamAddress(mHotspotIpServer, + true /* useLastAddress */); assertEquals("Wrong prefix: ", new LinkAddress("192.168.8.5/24"), addr6); - when(mHotspotIpServer.getAddress()).thenReturn(addr6); final UpstreamNetworkState mobileUpstream6 = buildUpstreamNetworkState(mMobileNetwork6, new LinkAddress("192.168.10.97/21"), null, makeNetworkCapabilities(TRANSPORT_CELLULAR)); mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream6); // Conflict ranges: 0 ~ 15 and 128 ~ 255, so the address is 192.168.16.5/24. - final LinkAddress addr7 = mPrivateAddressCoordinator.requestDownstreamAddress( - mHotspotIpServer, true/* useLastAddress */); + final LinkAddress addr7 = requestDownstreamAddress(mHotspotIpServer, + true /* useLastAddress */); assertEquals("Wrong prefix: ", new LinkAddress("192.168.16.5/24"), addr7); - when(mHotspotIpServer.getAddress()).thenReturn(addr7); final UpstreamNetworkState mobileUpstream7 = buildUpstreamNetworkState(mMobileNetwork6, new LinkAddress("192.168.0.0/17"), null, makeNetworkCapabilities(TRANSPORT_CELLULAR)); mPrivateAddressCoordinator.updateUpstreamPrefix(mobileUpstream7); // Choose prefix from next range(172.16.0.0/12) when no available prefix in 192.168.0.0/16. - final LinkAddress addr8 = mPrivateAddressCoordinator.requestDownstreamAddress( - mHotspotIpServer, true/* useLastAddress */); + final LinkAddress addr8 = requestDownstreamAddress(mHotspotIpServer, + true /* useLastAddress */); assertEquals("Wrong prefix: ", new LinkAddress("172.16.134.5/24"), addr8); - when(mHotspotIpServer.getAddress()).thenReturn(addr6); } @Test public void testChoosePrefixFromDifferentRanges() throws Exception { final int randomAddress = 0x1f2b2a; // 31.43.42 when(mPrivateAddressCoordinator.getRandomInt()).thenReturn(randomAddress); - final LinkAddress classC1 = mPrivateAddressCoordinator.requestDownstreamAddress( - mHotspotIpServer, true/* useLastAddress */); + final LinkAddress classC1 = requestDownstreamAddress(mHotspotIpServer, + true /* useLastAddress */); // Check whether return address is prefix 192.168.0.0/16 + subAddress 0.0.43.42. assertEquals("Wrong prefix: ", new LinkAddress("192.168.43.42/24"), classC1); - when(mHotspotIpServer.getAddress()).thenReturn(classC1); final UpstreamNetworkState wifiUpstream = buildUpstreamNetworkState(mWifiNetwork, new LinkAddress("192.168.88.23/17"), null, makeNetworkCapabilities(TRANSPORT_WIFI)); @@ -452,10 +436,9 @@ public final class PrivateAddressCoordinatorTest { verifyNotifyConflictAndRelease(mHotspotIpServer); // Check whether return address is next address of prefix 192.168.128.0/17. - final LinkAddress classC2 = mPrivateAddressCoordinator.requestDownstreamAddress( - mHotspotIpServer, true/* useLastAddress */); + final LinkAddress classC2 = requestDownstreamAddress(mHotspotIpServer, + true /* useLastAddress */); assertEquals("Wrong prefix: ", new LinkAddress("192.168.128.42/24"), classC2); - when(mHotspotIpServer.getAddress()).thenReturn(classC2); final UpstreamNetworkState mobileUpstream = buildUpstreamNetworkState(mMobileNetwork, new LinkAddress("192.1.2.3/8"), null, makeNetworkCapabilities(TRANSPORT_CELLULAR)); @@ -463,10 +446,9 @@ public final class PrivateAddressCoordinatorTest { verifyNotifyConflictAndRelease(mHotspotIpServer); // Check whether return address is under prefix 172.16.0.0/12. - final LinkAddress classB1 = mPrivateAddressCoordinator.requestDownstreamAddress( - mHotspotIpServer, true/* useLastAddress */); + final LinkAddress classB1 = requestDownstreamAddress(mHotspotIpServer, + true /* useLastAddress */); assertEquals("Wrong prefix: ", new LinkAddress("172.31.43.42/24"), classB1); - when(mHotspotIpServer.getAddress()).thenReturn(classB1); final UpstreamNetworkState mobileUpstream2 = buildUpstreamNetworkState(mMobileNetwork2, new LinkAddress("172.28.123.100/14"), null, makeNetworkCapabilities(TRANSPORT_CELLULAR)); @@ -475,16 +457,14 @@ public final class PrivateAddressCoordinatorTest { // 172.28.0.0 ~ 172.31.255.255 is not available. // Check whether return address is next address of prefix 172.16.0.0/14. - final LinkAddress classB2 = mPrivateAddressCoordinator.requestDownstreamAddress( - mHotspotIpServer, true/* useLastAddress */); + final LinkAddress classB2 = requestDownstreamAddress(mHotspotIpServer, + true /* useLastAddress */); assertEquals("Wrong prefix: ", new LinkAddress("172.16.0.42/24"), classB2); - when(mHotspotIpServer.getAddress()).thenReturn(classB2); // Check whether new downstream is next address of address 172.16.0.42/24. - final LinkAddress classB3 = mPrivateAddressCoordinator.requestDownstreamAddress( - mUsbIpServer, true/* useLastAddress */); + final LinkAddress classB3 = requestDownstreamAddress(mUsbIpServer, + true /* useLastAddress */); assertEquals("Wrong prefix: ", new LinkAddress("172.16.1.42/24"), classB3); - when(mUsbIpServer.getAddress()).thenReturn(classB3); final UpstreamNetworkState mobileUpstream3 = buildUpstreamNetworkState(mMobileNetwork3, new LinkAddress("172.16.0.1/24"), null, makeNetworkCapabilities(TRANSPORT_CELLULAR)); @@ -493,10 +473,9 @@ public final class PrivateAddressCoordinatorTest { verify(mUsbIpServer, never()).sendMessage(IpServer.CMD_NOTIFY_PREFIX_CONFLICT); // Check whether return address is next address of prefix 172.16.1.42/24. - final LinkAddress classB4 = mPrivateAddressCoordinator.requestDownstreamAddress( - mHotspotIpServer, true/* useLastAddress */); + final LinkAddress classB4 = requestDownstreamAddress(mHotspotIpServer, + true /* useLastAddress */); assertEquals("Wrong prefix: ", new LinkAddress("172.16.2.42/24"), classB4); - when(mHotspotIpServer.getAddress()).thenReturn(classB4); final UpstreamNetworkState mobileUpstream4 = buildUpstreamNetworkState(mMobileNetwork4, new LinkAddress("172.16.0.1/13"), null, makeNetworkCapabilities(TRANSPORT_CELLULAR)); @@ -505,15 +484,13 @@ public final class PrivateAddressCoordinatorTest { verifyNotifyConflictAndRelease(mUsbIpServer); // Check whether return address is next address of prefix 172.16.0.1/13. - final LinkAddress classB5 = mPrivateAddressCoordinator.requestDownstreamAddress( - mHotspotIpServer, true/* useLastAddress */); + final LinkAddress classB5 = requestDownstreamAddress(mHotspotIpServer, + true /* useLastAddress */); assertEquals("Wrong prefix: ", new LinkAddress("172.24.0.42/24"), classB5); - when(mHotspotIpServer.getAddress()).thenReturn(classB5); // Check whether return address is next address of prefix 172.24.0.42/24. - final LinkAddress classB6 = mPrivateAddressCoordinator.requestDownstreamAddress( - mUsbIpServer, true/* useLastAddress */); + final LinkAddress classB6 = requestDownstreamAddress(mUsbIpServer, + true /* useLastAddress */); assertEquals("Wrong prefix: ", new LinkAddress("172.24.1.42/24"), classB6); - when(mUsbIpServer.getAddress()).thenReturn(classB6); final UpstreamNetworkState mobileUpstream5 = buildUpstreamNetworkState(mMobileNetwork5, new LinkAddress("172.24.0.1/12"), null, makeNetworkCapabilities(TRANSPORT_CELLULAR)); @@ -522,13 +499,12 @@ public final class PrivateAddressCoordinatorTest { verifyNotifyConflictAndRelease(mUsbIpServer); // Check whether return address is prefix 10.0.0.0/8 + subAddress 0.31.43.42. - final LinkAddress classA1 = mPrivateAddressCoordinator.requestDownstreamAddress( - mHotspotIpServer, true/* useLastAddress */); + final LinkAddress classA1 = requestDownstreamAddress(mHotspotIpServer, + true /* useLastAddress */); assertEquals("Wrong prefix: ", new LinkAddress("10.31.43.42/24"), classA1); - when(mHotspotIpServer.getAddress()).thenReturn(classA1); // Check whether new downstream is next address of address 10.31.43.42/24. - final LinkAddress classA2 = mPrivateAddressCoordinator.requestDownstreamAddress( - mUsbIpServer, true/* useLastAddress */); + final LinkAddress classA2 = requestDownstreamAddress(mUsbIpServer, + true /* useLastAddress */); assertEquals("Wrong prefix: ", new LinkAddress("10.31.44.42/24"), classA2); } @@ -547,8 +523,8 @@ public final class PrivateAddressCoordinatorTest { } private void assertReseveredWifiP2pPrefix() throws Exception { - LinkAddress address = mPrivateAddressCoordinator.requestDownstreamAddress( - mHotspotIpServer, true /* useLastAddress */); + LinkAddress address = requestDownstreamAddress(mHotspotIpServer, + true /* useLastAddress */); final IpPrefix hotspotPrefix = asIpPrefix(address); final IpPrefix legacyWifiP2pPrefix = asIpPrefix(mLegacyWifiP2pAddress); assertNotEquals(legacyWifiP2pPrefix, hotspotPrefix); @@ -567,8 +543,8 @@ public final class PrivateAddressCoordinatorTest { assertReseveredWifiP2pPrefix(); // If #shouldEnableWifiP2pDedicatedIp() is enabled, wifi P2P gets the configured address. - LinkAddress address = mPrivateAddressCoordinator.requestDownstreamAddress( - mWifiP2pIpServer, true /* useLastAddress */); + LinkAddress address = requestDownstreamAddress(mWifiP2pIpServer, + true /* useLastAddress */); assertEquals(mLegacyWifiP2pAddress, address); mPrivateAddressCoordinator.releaseDownstream(mWifiP2pIpServer); } diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index d71b919818ea..e1c499389ec5 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -2633,6 +2633,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } @Override + @SuppressWarnings("AndroidFrameworkPendingIntentMutability") public PendingIntent getPendingIntentActivity(Context context, int requestCode, Intent intent, int flags) { return PendingIntent.getActivity(context, requestCode, intent, flags); diff --git a/services/core/Android.bp b/services/core/Android.bp index 26c28d5c95b1..4b10ab773698 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -122,6 +122,7 @@ java_library_static { "netd_aidl_interfaces-platform-java", "overlayable_policy_aidl-java", "SurfaceFlingerProperties", + "com.android.sysprop.watchdog", ], } diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java index 43c54b4a97b3..72a21522b545 100644 --- a/services/core/java/android/content/pm/PackageManagerInternal.java +++ b/services/core/java/android/content/pm/PackageManagerInternal.java @@ -1106,4 +1106,17 @@ public abstract class PackageManagerInternal { } } + /** + * Retrieve all of the information we know about a particular activity class including its + * package states. + * + * @param packageName a specific package + * @param filterCallingUid The results will be filtered in the context of this UID instead + * of the calling UID. + * @param userId The user for whom the package is installed + * @return IncrementalStatesInfo that contains information about package states. + */ + public abstract IncrementalStatesInfo getIncrementalStatesInfo(String packageName, + int filterCallingUid, int userId); + } diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java index b3d4085288dd..95a7a221697a 100644 --- a/services/core/java/com/android/server/GestureLauncherService.java +++ b/services/core/java/com/android/server/GestureLauncherService.java @@ -38,7 +38,6 @@ import android.os.SystemProperties; import android.os.Trace; import android.os.UserHandle; import android.provider.Settings; -import android.telecom.TelecomManager; import android.util.MutableBoolean; import android.util.Slog; import android.view.KeyEvent; @@ -46,7 +45,6 @@ import android.view.KeyEvent; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; -import com.android.server.LocalServices; import com.android.server.statusbar.StatusBarManagerInternal; import com.android.server.wm.WindowManagerInternal; @@ -529,15 +527,9 @@ public class GestureLauncherService extends SystemService { "userSetupComplete = %s, performing panic gesture.", userSetupComplete)); } - // TODO(b/160006048): Not all devices have telephony. Check system feature first. - TelecomManager telecomManager = (TelecomManager) mContext.getSystemService( - Context.TELECOM_SERVICE); - mContext.startActivity(telecomManager.createLaunchEmergencyDialerIntent(null).addFlags( - Intent.FLAG_ACTIVITY_NEW_TASK - | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS - | Intent.FLAG_ACTIVITY_SINGLE_TOP).putExtra( - "com.android.phone.EmergencyDialer.extra.ENTRY_TYPE", - 2)); // 2 maps to power button, forcing into fast emergency dialer experience. + StatusBarManagerInternal service = LocalServices.getService( + StatusBarManagerInternal.class); + service.onEmergencyActionLaunchGestureDetected(); return true; } finally { Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java index 990a547144a0..494448340101 100644 --- a/services/core/java/com/android/server/Watchdog.java +++ b/services/core/java/com/android/server/Watchdog.java @@ -23,7 +23,9 @@ import android.content.Intent; import android.content.IntentFilter; import android.hidl.manager.V1_0.IServiceManager; import android.os.Binder; +import android.os.Build; import android.os.Debug; +import android.os.FileUtils; import android.os.Handler; import android.os.IPowerManager; import android.os.Looper; @@ -31,10 +33,12 @@ import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; +import android.os.SystemProperties; import android.util.EventLog; import android.util.Log; import android.util.Slog; import android.util.SparseArray; +import android.sysprop.WatchdogProperties; import com.android.internal.os.ProcessCpuTracker; import com.android.internal.os.ZygoteConnectionConstants; @@ -42,12 +46,16 @@ import com.android.internal.util.FrameworkStatsLog; import com.android.server.am.ActivityManagerService; import com.android.server.wm.SurfaceAnimationThread; +import java.io.BufferedReader; import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.StringWriter; import java.util.ArrayList; import java.util.Arrays; +import java.util.concurrent.TimeUnit; import java.util.HashSet; import java.util.List; @@ -75,6 +83,12 @@ public class Watchdog { private static final int WAITED_HALF = 2; private static final int OVERDUE = 3; + // Track watchdog timeout history and break the crash loop if there is. + private static final String TIMEOUT_HISTORY_FILE = "/data/system/watchdog-timeout-history.txt"; + private static final String PROP_FATAL_LOOP_COUNT = "framework_watchdog.fatal_count"; + private static final String PROP_FATAL_LOOP_WINDOWS_SECS = + "framework_watchdog.fatal_window.second"; + // Which native processes to dump into dropbox's stack traces public static final String[] NATIVE_STACKS_OF_INTEREST = new String[] { "/system/bin/audioserver", @@ -699,6 +713,10 @@ public class Watchdog { Slog.w(TAG, "*** WATCHDOG KILLING SYSTEM PROCESS: " + subject); WatchdogDiagnostics.diagnoseCheckers(blockedCheckers); Slog.w(TAG, "*** GOODBYE!"); + if (!Build.IS_USER && isCrashLoopFound() + && !WatchdogProperties.is_fatal_ignore().orElse(false)) { + breakCrashLoop(); + } Process.killProcess(Process.myPid()); System.exit(10); } @@ -716,4 +734,107 @@ public class Watchdog { Slog.w(TAG, "Failed to write to /proc/sysrq-trigger", e); } } + + private void resetTimeoutHistory() { + writeTimeoutHistory(new ArrayList<String>()); + } + + private void writeTimeoutHistory(Iterable<String> crashHistory) { + String data = String.join(",", crashHistory); + + try (FileWriter writer = new FileWriter(TIMEOUT_HISTORY_FILE)) { + writer.write(SystemProperties.get("ro.boottime.zygote")); + writer.write(":"); + writer.write(data); + } catch (IOException e) { + Slog.e(TAG, "Failed to write file " + TIMEOUT_HISTORY_FILE, e); + } + } + + private String[] readTimeoutHistory() { + final String[] emptyStringArray = {}; + + try (BufferedReader reader = new BufferedReader(new FileReader(TIMEOUT_HISTORY_FILE))) { + String line = reader.readLine(); + if (line == null) { + return emptyStringArray; + } + + String[] data = line.trim().split(":"); + String boottime = data.length >= 1 ? data[0] : ""; + String history = data.length >= 2 ? data[1] : ""; + if (SystemProperties.get("ro.boottime.zygote").equals(boottime) && !history.isEmpty()) { + return history.split(","); + } else { + return emptyStringArray; + } + } catch (FileNotFoundException e) { + return emptyStringArray; + } catch (IOException e) { + Slog.e(TAG, "Failed to read file " + TIMEOUT_HISTORY_FILE, e); + return emptyStringArray; + } + } + + private boolean hasActiveUsbConnection() { + try { + final String state = FileUtils.readTextFile( + new File("/sys/class/android_usb/android0/state"), + 128 /*max*/, null /*ellipsis*/).trim(); + if ("CONFIGURED".equals(state)) { + return true; + } + } catch (IOException e) { + Slog.w(TAG, "Failed to determine if device was on USB", e); + } + return false; + } + + private boolean isCrashLoopFound() { + int fatalCount = WatchdogProperties.fatal_count().orElse(0); + long fatalWindowMs = TimeUnit.SECONDS.toMillis( + WatchdogProperties.fatal_window_second().orElse(0)); + if (fatalCount == 0 || fatalWindowMs == 0) { + if (fatalCount != fatalWindowMs) { + Slog.w(TAG, String.format("sysprops '%s' and '%s' should be set or unset together", + PROP_FATAL_LOOP_COUNT, PROP_FATAL_LOOP_WINDOWS_SECS)); + } + return false; + } + + // new-history = [last (fatalCount - 1) items in old-history] + [nowMs]. + long nowMs = SystemClock.elapsedRealtime(); // Time since boot including deep sleep. + String[] rawCrashHistory = readTimeoutHistory(); + ArrayList<String> crashHistory = new ArrayList<String>(Arrays.asList(Arrays.copyOfRange( + rawCrashHistory, + Math.max(0, rawCrashHistory.length - fatalCount - 1), + rawCrashHistory.length))); + // Something wrong here. + crashHistory.add(String.valueOf(nowMs)); + writeTimeoutHistory(crashHistory); + + // Returns false if the device has an active USB connection. + if (hasActiveUsbConnection()) { + return false; + } + + long firstCrashMs; + try { + firstCrashMs = Long.parseLong(crashHistory.get(0)); + } catch (NumberFormatException t) { + Slog.w(TAG, "Failed to parseLong " + crashHistory.get(0), t); + resetTimeoutHistory(); + return false; + } + return crashHistory.size() >= fatalCount && nowMs - firstCrashMs < fatalWindowMs; + } + + private void breakCrashLoop() { + try (FileWriter kmsg = new FileWriter("/dev/kmsg_debug", /* append= */ true)) { + kmsg.append("Fatal reset to escape the system_server crashing loop\n"); + } catch (IOException e) { + Slog.w(TAG, "Failed to append to kmsg", e); + } + doSysRq('c'); + } } diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 0f095ab8b85f..31712becec05 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -56,6 +56,8 @@ import android.app.Service; import android.app.ServiceStartArgs; import android.app.admin.DevicePolicyEventLogger; import android.appwidget.AppWidgetManagerInternal; +import android.compat.annotation.ChangeId; +import android.compat.annotation.Disabled; import android.content.ComponentName; import android.content.ComponentName.WithComponentName; import android.content.Context; @@ -79,6 +81,7 @@ import android.os.Message; import android.os.Process; import android.os.RemoteCallback; import android.os.RemoteException; +import android.os.ServiceManager; import android.os.SystemClock; import android.os.SystemProperties; import android.os.TransactionTooLargeException; @@ -100,6 +103,7 @@ import android.webkit.WebViewZygote; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.app.procstats.ServiceState; +import com.android.internal.compat.IPlatformCompat; import com.android.internal.messages.nano.SystemMessageProto; import com.android.internal.notification.SystemNotificationChannels; import com.android.internal.os.BatteryStatsImpl; @@ -234,6 +238,16 @@ public final class ActiveServices { private static final SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + private final IPlatformCompat mPlatformCompat; + + /** + * The BG-launch FGS restriction feature is going to be allowed only for apps targetSdkVersion + * is higher than R. + */ + @ChangeId + @Disabled + static final long FGS_BG_START_RESTRICTION_CHANGE_ID = 170668199L; + final Runnable mLastAnrDumpClearer = new Runnable() { @Override public void run() { synchronized (mAm) { @@ -430,6 +444,9 @@ public final class ActiveServices { } mMaxStartingBackground = maxBg > 0 ? maxBg : ActivityManager.isLowRamDeviceStatic() ? 1 : 8; + + final IBinder b = ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE); + mPlatformCompat = IPlatformCompat.Stub.asInterface(b); } void systemServicesReady() { @@ -557,7 +574,8 @@ public final class ActiveServices { r.mLoggedInfoAllowStartForeground = true; } if (r.mAllowStartForeground == FGS_FEATURE_DENIED - && mAm.mConstants.mFlagFgsStartRestrictionEnabled) { + && (mAm.mConstants.mFlagFgsStartRestrictionEnabled + || isChangeEnabled(FGS_BG_START_RESTRICTION_CHANGE_ID, r))) { if (mAm.mConstants.mFlagFgsStartTempAllowListEnabled && mAm.isOnDeviceIdleWhitelistLocked(r.appInfo.uid, false)) { // uid is on DeviceIdleController's allowlist. @@ -1468,7 +1486,8 @@ public final class ActiveServices { r.mLoggedInfoAllowStartForeground = true; } if (r.mAllowStartForeground == FGS_FEATURE_DENIED - && mAm.mConstants.mFlagFgsStartRestrictionEnabled) { + && (mAm.mConstants.mFlagFgsStartRestrictionEnabled + || isChangeEnabled(FGS_BG_START_RESTRICTION_CHANGE_ID, r))) { if (mAm.mConstants.mFlagFgsStartTempAllowListEnabled && mAm.isOnDeviceIdleWhitelistLocked(r.appInfo.uid, false)) { // uid is on DeviceIdleController's allowlist. @@ -5101,4 +5120,12 @@ public final class ActiveServices { context.getSystemService(NotificationManager.class).notifyAsUser(Long.toString(now), NOTE_FOREGROUND_SERVICE_BG_LAUNCH, n.build(), UserHandle.ALL); } + + private boolean isChangeEnabled(long changeId, ServiceRecord r) { + boolean enabled = false; + try { + enabled = mPlatformCompat.isChangeEnabled(changeId, r.appInfo); + } catch (RemoteException e) { } + return enabled; + } } diff --git a/services/core/java/com/android/server/am/ActiveUids.java b/services/core/java/com/android/server/am/ActiveUids.java index 4e1435e14679..c86c29f8ac2a 100644 --- a/services/core/java/com/android/server/am/ActiveUids.java +++ b/services/core/java/com/android/server/am/ActiveUids.java @@ -16,7 +16,12 @@ package com.android.server.am; +import android.app.ActivityManager; +import android.os.UserHandle; import android.util.SparseArray; +import android.util.proto.ProtoOutputStream; + +import java.io.PrintWriter; /** Class for tracking active uids for running processes. */ final class ActiveUids { @@ -71,4 +76,43 @@ final class ActiveUids { int indexOfKey(int uid) { return mActiveUids.indexOfKey(uid); } + + boolean dump(PrintWriter pw, String dumpPackage, int dumpAppId, + String header, boolean needSep) { + boolean printed = false; + for (int i = 0; i < mActiveUids.size(); i++) { + final UidRecord uidRec = mActiveUids.valueAt(i); + if (dumpPackage != null && UserHandle.getAppId(uidRec.uid) != dumpAppId) { + continue; + } + if (!printed) { + printed = true; + if (needSep) { + pw.println(); + } + pw.print(" "); pw.println(header); + } + pw.print(" UID "); UserHandle.formatUid(pw, uidRec.uid); + pw.print(": "); pw.println(uidRec); + pw.print(" curProcState="); pw.print(uidRec.mCurProcState); + pw.print(" curCapability="); + ActivityManager.printCapabilitiesFull(pw, uidRec.curCapability); + pw.println(); + for (int j = uidRec.procRecords.size() - 1; j >= 0; j--) { + pw.print(" proc="); + pw.println(uidRec.procRecords.valueAt(j)); + } + } + return printed; + } + + void dumpProto(ProtoOutputStream proto, String dumpPackage, int dumpAppId, long fieldId) { + for (int i = 0; i < mActiveUids.size(); i++) { + UidRecord uidRec = mActiveUids.valueAt(i); + if (dumpPackage != null && UserHandle.getAppId(uidRec.uid) != dumpAppId) { + continue; + } + uidRec.dumpDebug(proto, fieldId); + } + } } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 9afda8c0fba4..f0c9845424c6 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -1979,7 +1979,6 @@ public class ActivityManagerService extends IActivityManager.Stub mConstants = hasHandlerThread ? new ActivityManagerConstants(mContext, this, mHandler) : null; final ActiveUids activeUids = new ActiveUids(this, false /* postChangesToAtm */); - mUidObserverController = new UidObserverController(this); mPlatformCompat = null; mProcessList = injector.getProcessList(this); mProcessList.init(this, activeUids, mPlatformCompat); @@ -1997,6 +1996,7 @@ public class ActivityManagerService extends IActivityManager.Stub mServices = hasHandlerThread ? new ActiveServices(this) : null; mSystemThread = null; mUiHandler = injector.getUiHandler(null /* service */); + mUidObserverController = new UidObserverController(mUiHandler); mUserController = hasHandlerThread ? new UserController(this) : null; mPendingIntentController = hasHandlerThread ? new PendingIntentController(handlerThread.getLooper(), mUserController, @@ -2077,7 +2077,7 @@ public class ActivityManagerService extends IActivityManager.Stub mCpHelper = new ContentProviderHelper(this, true); mPackageWatchdog = PackageWatchdog.getInstance(mUiContext); mAppErrors = new AppErrors(mUiContext, this, mPackageWatchdog); - mUidObserverController = new UidObserverController(this); + mUidObserverController = new UidObserverController(mUiHandler); final File systemDir = SystemServiceManager.ensureSystemDir(); @@ -8816,37 +8816,6 @@ public class ActivityManagerService extends IActivityManager.Stub return -1; } - boolean dumpUids(PrintWriter pw, String dumpPackage, int dumpAppId, ActiveUids uids, - String header, boolean needSep) { - boolean printed = false; - for (int i=0; i<uids.size(); i++) { - UidRecord uidRec = uids.valueAt(i); - if (dumpPackage != null && UserHandle.getAppId(uidRec.uid) != dumpAppId) { - continue; - } - if (!printed) { - printed = true; - if (needSep) { - pw.println(); - } - pw.print(" "); - pw.println(header); - needSep = true; - } - pw.print(" UID "); UserHandle.formatUid(pw, uidRec.uid); - pw.print(": "); pw.println(uidRec); - pw.print(" curProcState="); pw.print(uidRec.mCurProcState); - pw.print(" curCapability="); - ActivityManager.printCapabilitiesFull(pw, uidRec.curCapability); - pw.println(); - for (int j = uidRec.procRecords.size() - 1; j >= 0; j--) { - pw.print(" proc="); - pw.println(uidRec.procRecords.valueAt(j)); - } - } - return printed; - } - void dumpBinderProxyInterfaceCounts(PrintWriter pw, String header) { final BinderProxy.InterfaceCount[] proxyCounts = BinderProxy.getSortedInterfaceCounts(50); @@ -9096,19 +9065,13 @@ public class ActivityManagerService extends IActivityManager.Stub needSep = dumpProcessesToGc(pw, needSep, dumpPackage); if (mProcessList.mActiveUids.size() > 0) { - if (dumpUids(pw, dumpPackage, dumpAppId, mProcessList.mActiveUids, - "UID states:", needSep)) { - needSep = true; - } + needSep |= mProcessList.mActiveUids.dump(pw, dumpPackage, dumpAppId, + "UID states:", needSep); } if (dumpAll) { - if (mUidObserverController.mValidateUids.size() > 0) { - if (dumpUids(pw, dumpPackage, dumpAppId, mUidObserverController.mValidateUids, - "UID validation:", needSep)) { - needSep = true; - } - } + needSep |= mUidObserverController.dumpValidateUids(pw, + dumpPackage, dumpAppId, "UID validation:", needSep); } if (needSep) { @@ -9377,22 +9340,12 @@ public class ActivityManagerService extends IActivityManager.Stub ActivityManagerServiceDumpProcessesProto.ACTIVE_INSTRUMENTATIONS); } - int whichAppId = getAppId(dumpPackage); - for (int i = 0; i < mProcessList.mActiveUids.size(); i++) { - UidRecord uidRec = mProcessList.mActiveUids.valueAt(i); - if (dumpPackage != null && UserHandle.getAppId(uidRec.uid) != whichAppId) { - continue; - } - uidRec.dumpDebug(proto, ActivityManagerServiceDumpProcessesProto.ACTIVE_UIDS); - } + final int dumpAppId = getAppId(dumpPackage); + mProcessList.mActiveUids.dumpProto(proto, dumpPackage, dumpAppId, + ActivityManagerServiceDumpProcessesProto.ACTIVE_UIDS); - for (int i = 0; i < mUidObserverController.mValidateUids.size(); i++) { - UidRecord uidRec = mUidObserverController.mValidateUids.valueAt(i); - if (dumpPackage != null && UserHandle.getAppId(uidRec.uid) != whichAppId) { - continue; - } - uidRec.dumpDebug(proto, ActivityManagerServiceDumpProcessesProto.VALIDATE_UIDS); - } + mUidObserverController.dumpValidateUidsProto(proto, dumpPackage, dumpAppId, + ActivityManagerServiceDumpProcessesProto.VALIDATE_UIDS); if (mProcessList.getLruSizeLocked() > 0) { long lruToken = proto.start(ActivityManagerServiceDumpProcessesProto.LRU_PROCS); @@ -14892,6 +14845,58 @@ public class ActivityManagerService extends IActivityManager.Stub return false; } + private boolean isEphemeralLocked(int uid) { + final String[] packages = mContext.getPackageManager().getPackagesForUid(uid); + if (packages == null || packages.length != 1) { // Ephemeral apps cannot share uid + return false; + } + return getPackageManagerInternalLocked().isPackageEphemeral( + UserHandle.getUserId(uid), packages[0]); + } + + void enqueueUidChangeLocked(UidRecord uidRec, int uid, int change) { + uid = uidRec != null ? uidRec.uid : uid; + if (uid < 0) { + throw new IllegalArgumentException("No UidRecord or uid"); + } + + final int procState = uidRec != null + ? uidRec.setProcState : PROCESS_STATE_NONEXISTENT; + final long procStateSeq = uidRec != null ? uidRec.curProcStateSeq : 0; + final int capability = uidRec != null ? uidRec.setCapability : 0; + final boolean ephemeral = uidRec != null ? uidRec.ephemeral : isEphemeralLocked(uid); + + if (uidRec != null && !uidRec.idle && (change & UidRecord.CHANGE_GONE) != 0) { + // If this uid is going away, and we haven't yet reported it is gone, + // then do so now. + change |= UidRecord.CHANGE_IDLE; + } + final int enqueuedChange = mUidObserverController.enqueueUidChange( + uid, change, procState, procStateSeq, capability, ephemeral); + if (uidRec != null) { + uidRec.lastReportedChange = enqueuedChange; + uidRec.updateLastDispatchedProcStateSeq(enqueuedChange); + } + + // Directly update the power manager, since we sit on top of it and it is critical + // it be kept in sync (so wake locks will be held as soon as appropriate). + if (mLocalPowerManager != null) { + // TODO: dispatch cached/uncached changes here, so we don't need to report + // all proc state changes. + if ((enqueuedChange & UidRecord.CHANGE_ACTIVE) != 0) { + mLocalPowerManager.uidActive(uid); + } + if ((enqueuedChange & UidRecord.CHANGE_IDLE) != 0) { + mLocalPowerManager.uidIdle(uid); + } + if ((enqueuedChange & UidRecord.CHANGE_GONE) != 0) { + mLocalPowerManager.uidGone(uid); + } else { + mLocalPowerManager.updateUidProcState(uid, procState); + } + } + } + final void setProcessTrackerStateLocked(ProcessRecord proc, int memFactor, long now) { synchronized (mProcessStats.mLock) { if (proc.thread != null && proc.baseProcessTracker != null) { @@ -15157,7 +15162,7 @@ public class ActivityManagerService extends IActivityManager.Stub @GuardedBy("this") final void doStopUidLocked(int uid, final UidRecord uidRec) { mServices.stopInBackgroundLocked(uid); - mUidObserverController.enqueueUidChangeLocked(uidRec, uid, UidRecord.CHANGE_IDLE); + enqueueUidChangeLocked(uidRec, uid, UidRecord.CHANGE_IDLE); } /** @@ -16707,7 +16712,7 @@ public class ActivityManagerService extends IActivityManager.Stub + totalTime + ". Uid: " + callingUid + " procStateSeq: " + procStateSeq + " UidRec: " + record + " validateUidRec: " - + mUidObserverController.mValidateUids.get(callingUid)); + + mUidObserverController.getValidateUidRecord(callingUid)); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index 58ac2dc869ce..9d49236191a9 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -1147,7 +1147,7 @@ public final class OomAdjuster { uidRec.setWhitelist = uidRec.curWhitelist; uidRec.setIdle = uidRec.idle; mService.mAtmInternal.onUidProcStateChanged(uidRec.uid, uidRec.setProcState); - mService.mUidObserverController.enqueueUidChangeLocked(uidRec, -1, uidChange); + mService.enqueueUidChangeLocked(uidRec, -1, uidChange); mService.noteUidProcessState(uidRec.uid, uidRec.getCurProcState(), uidRec.curCapability); if (uidRec.foregroundServices) { diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index cf0223bac289..6f6cad043a42 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -2948,7 +2948,7 @@ public final class ProcessList { // No more processes using this uid, tell clients it is gone. if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS, "No more processes in " + uidRecord); - mService.mUidObserverController.enqueueUidChangeLocked(uidRecord, -1, + mService.enqueueUidChangeLocked(uidRecord, -1, UidRecord.CHANGE_GONE); EventLogTags.writeAmUidStopped(uid); mActiveUids.remove(uid); diff --git a/services/core/java/com/android/server/am/UidObserverController.java b/services/core/java/com/android/server/am/UidObserverController.java index 4d9260aec62e..b3488c3850b5 100644 --- a/services/core/java/com/android/server/am/UidObserverController.java +++ b/services/core/java/com/android/server/am/UidObserverController.java @@ -23,11 +23,13 @@ import static com.android.server.am.ActivityManagerService.TAG_UID_OBSERVERS; import android.app.ActivityManager; import android.app.ActivityManagerProto; import android.app.IUidObserver; +import android.os.Handler; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.util.Slog; +import android.util.SparseArray; import android.util.SparseIntArray; import android.util.proto.ProtoOutputStream; import android.util.proto.ProtoUtils; @@ -40,158 +42,150 @@ import java.io.PrintWriter; import java.util.ArrayList; public class UidObserverController { - private final ActivityManagerService mService; + /** If a UID observer takes more than this long, send a WTF. */ + private static final int SLOW_UID_OBSERVER_THRESHOLD_MS = 20; + + private final Handler mHandler; + + private final Object mLock = new Object(); + + @GuardedBy("mLock") final RemoteCallbackList<IUidObserver> mUidObservers = new RemoteCallbackList<>(); - UidRecord.ChangeItem[] mActiveUidChanges = new UidRecord.ChangeItem[5]; - final ArrayList<UidRecord.ChangeItem> mPendingUidChanges = new ArrayList<>(); - final ArrayList<UidRecord.ChangeItem> mAvailUidChanges = new ArrayList<>(); + @GuardedBy("mLock") + private final SparseArray<ChangeRecord> mPendingUidChanges = new SparseArray<>(); + @GuardedBy("mLock") + private final ArrayList<ChangeRecord> mAvailUidChanges = new ArrayList<>(); + + private ChangeRecord[] mActiveUidChanges = new ChangeRecord[5]; /** Total # of UID change events dispatched, shown in dumpsys. */ - int mUidChangeDispatchCount; + @GuardedBy("mLock") + private int mUidChangeDispatchCount; - /** If a UID observer takes more than this long, send a WTF. */ - private static final int SLOW_UID_OBSERVER_THRESHOLD_MS = 20; + private final Runnable mDispatchRunnable = this::dispatchUidsChanged; /** * This is for verifying the UID report flow. */ - static final boolean VALIDATE_UID_STATES = true; - final ActiveUids mValidateUids; + private static final boolean VALIDATE_UID_STATES = true; + private final ActiveUids mValidateUids; - UidObserverController(ActivityManagerService service) { - mService = service; - mValidateUids = new ActiveUids(mService, false /* postChangesToAtm */); + UidObserverController(Handler handler) { + mHandler = handler; + mValidateUids = new ActiveUids(null /* service */, false /* postChangesToAtm */); } - @GuardedBy("mService") void register(IUidObserver observer, int which, int cutpoint, String callingPackage, int callingUid) { - mUidObservers.register(observer, new UidObserverRegistration(callingUid, - callingPackage, which, cutpoint)); + synchronized (mLock) { + mUidObservers.register(observer, new UidObserverRegistration(callingUid, + callingPackage, which, cutpoint)); + } } - @GuardedBy("mService") void unregister(IUidObserver observer) { - mUidObservers.unregister(observer); + synchronized (mLock) { + mUidObservers.unregister(observer); + } } - @GuardedBy("mService") - final void enqueueUidChangeLocked(UidRecord uidRec, int uid, int change) { - final UidRecord.ChangeItem pendingChange; - if (uidRec == null || uidRec.pendingChange == null) { + int enqueueUidChange(int uid, int change, int procState, long procStateSeq, + int capability, boolean ephemeral) { + synchronized (mLock) { if (mPendingUidChanges.size() == 0) { if (DEBUG_UID_OBSERVERS) { Slog.i(TAG_UID_OBSERVERS, "*** Enqueueing dispatch uid changed!"); } - mService.mUiHandler.post(this::dispatchUidsChanged); + mHandler.post(mDispatchRunnable); } - final int size = mAvailUidChanges.size(); - if (size > 0) { - pendingChange = mAvailUidChanges.remove(size - 1); - if (DEBUG_UID_OBSERVERS) { - Slog.i(TAG_UID_OBSERVERS, "Retrieving available item: " + pendingChange); - } + + ChangeRecord changeRecord = mPendingUidChanges.get(uid); + if (changeRecord == null) { + changeRecord = getOrCreateChangeRecordLocked(); + mPendingUidChanges.put(uid, changeRecord); } else { - pendingChange = new UidRecord.ChangeItem(); - if (DEBUG_UID_OBSERVERS) { - Slog.i(TAG_UID_OBSERVERS, "Allocating new item: " + pendingChange); - } - } - if (uidRec != null) { - uidRec.pendingChange = pendingChange; - if ((change & UidRecord.CHANGE_GONE) != 0 && !uidRec.idle) { - // If this uid is going away, and we haven't yet reported it is gone, - // then do so now. - change |= UidRecord.CHANGE_IDLE; - } - } else if (uid < 0) { - throw new IllegalArgumentException("No UidRecord or uid"); - } - pendingChange.uidRecord = uidRec; - pendingChange.uid = uidRec != null ? uidRec.uid : uid; - mPendingUidChanges.add(pendingChange); - } else { - pendingChange = uidRec.pendingChange; - // If there is no change in idle or active state, then keep whatever was pending. - if ((change & (UidRecord.CHANGE_IDLE | UidRecord.CHANGE_ACTIVE)) == 0) { - change |= (pendingChange.change & (UidRecord.CHANGE_IDLE - | UidRecord.CHANGE_ACTIVE)); - } - // If there is no change in cached or uncached state, then keep whatever was pending. - if ((change & (UidRecord.CHANGE_CACHED | UidRecord.CHANGE_UNCACHED)) == 0) { - change |= (pendingChange.change & (UidRecord.CHANGE_CACHED - | UidRecord.CHANGE_UNCACHED)); - } - // If this is a report of the UID being gone, then we shouldn't keep any previous - // report of it being active or cached. (That is, a gone uid is never active, - // and never cached.) - if ((change & UidRecord.CHANGE_GONE) != 0) { - change &= ~(UidRecord.CHANGE_ACTIVE | UidRecord.CHANGE_CACHED); - if (!uidRec.idle) { - // If this uid is going away, and we haven't yet reported it is gone, - // then do so now. - change |= UidRecord.CHANGE_IDLE; - } + change = mergeWithPendingChange(change, changeRecord.change); } + + changeRecord.uid = uid; + changeRecord.change = change; + changeRecord.procState = procState; + changeRecord.procStateSeq = procStateSeq; + changeRecord.capability = capability; + changeRecord.ephemeral = ephemeral; + + return changeRecord.change; } - pendingChange.change = change; - pendingChange.processState = uidRec != null - ? uidRec.setProcState : PROCESS_STATE_NONEXISTENT; - pendingChange.capability = uidRec != null ? uidRec.setCapability : 0; - pendingChange.ephemeral = uidRec != null ? uidRec.ephemeral : isEphemeralLocked(uid); - pendingChange.procStateSeq = uidRec != null ? uidRec.curProcStateSeq : 0; - if (uidRec != null) { - uidRec.lastReportedChange = change; - uidRec.updateLastDispatchedProcStateSeq(change); + } + + SparseArray<ChangeRecord> getPendingUidChangesForTest() { + return mPendingUidChanges; + } + + ActiveUids getValidateUidsForTest() { + return mValidateUids; + } + + @VisibleForTesting + static int mergeWithPendingChange(int currentChange, int pendingChange) { + // If there is no change in idle or active state, then keep whatever was pending. + if ((currentChange & (UidRecord.CHANGE_IDLE | UidRecord.CHANGE_ACTIVE)) == 0) { + currentChange |= (pendingChange & (UidRecord.CHANGE_IDLE + | UidRecord.CHANGE_ACTIVE)); + } + // If there is no change in cached or uncached state, then keep whatever was pending. + if ((currentChange & (UidRecord.CHANGE_CACHED | UidRecord.CHANGE_UNCACHED)) == 0) { + currentChange |= (pendingChange & (UidRecord.CHANGE_CACHED + | UidRecord.CHANGE_UNCACHED)); } + // If this is a report of the UID being gone, then we shouldn't keep any previous + // report of it being active or cached. (That is, a gone uid is never active, + // and never cached.) + if ((currentChange & UidRecord.CHANGE_GONE) != 0) { + currentChange &= ~(UidRecord.CHANGE_ACTIVE | UidRecord.CHANGE_CACHED); + } + return currentChange; + } - // Directly update the power manager, since we sit on top of it and it is critical - // it be kept in sync (so wake locks will be held as soon as appropriate). - if (mService.mLocalPowerManager != null) { - // TO DO: dispatch cached/uncached changes here, so we don't need to report - // all proc state changes. - if ((change & UidRecord.CHANGE_ACTIVE) != 0) { - mService.mLocalPowerManager.uidActive(pendingChange.uid); - } - if ((change & UidRecord.CHANGE_IDLE) != 0) { - mService.mLocalPowerManager.uidIdle(pendingChange.uid); + @GuardedBy("mLock") + private ChangeRecord getOrCreateChangeRecordLocked() { + final ChangeRecord changeRecord; + final int size = mAvailUidChanges.size(); + if (size > 0) { + changeRecord = mAvailUidChanges.remove(size - 1); + if (DEBUG_UID_OBSERVERS) { + Slog.i(TAG_UID_OBSERVERS, "Retrieving available item: " + changeRecord); } - if ((change & UidRecord.CHANGE_GONE) != 0) { - mService.mLocalPowerManager.uidGone(pendingChange.uid); - } else { - mService.mLocalPowerManager.updateUidProcState(pendingChange.uid, - pendingChange.processState); + } else { + changeRecord = new ChangeRecord(); + if (DEBUG_UID_OBSERVERS) { + Slog.i(TAG_UID_OBSERVERS, "Allocating new item: " + changeRecord); } } + return changeRecord; } @VisibleForTesting void dispatchUidsChanged() { - int numUidChanges; - synchronized (mService) { + final int numUidChanges; + synchronized (mLock) { numUidChanges = mPendingUidChanges.size(); if (mActiveUidChanges.length < numUidChanges) { - mActiveUidChanges = new UidRecord.ChangeItem[numUidChanges]; + mActiveUidChanges = new ChangeRecord[numUidChanges]; } for (int i = 0; i < numUidChanges; i++) { - final UidRecord.ChangeItem change = mPendingUidChanges.get(i); - mActiveUidChanges[i] = change; - if (change.uidRecord != null) { - change.uidRecord.pendingChange = null; - change.uidRecord = null; - } + mActiveUidChanges[i] = mPendingUidChanges.valueAt(i); } mPendingUidChanges.clear(); if (DEBUG_UID_OBSERVERS) { Slog.i(TAG_UID_OBSERVERS, "*** Delivering " + numUidChanges + " uid changes"); } + mUidChangeDispatchCount += numUidChanges; } - mUidChangeDispatchCount += numUidChanges; int i = mUidObservers.beginBroadcast(); - while (i > 0) { - i--; + while (i-- > 0) { dispatchUidsChangedForObserver(mUidObservers.getBroadcastItem(i), (UidObserverRegistration) mUidObservers.getBroadcastCookie(i), numUidChanges); } @@ -199,7 +193,7 @@ public class UidObserverController { if (VALIDATE_UID_STATES && mUidObservers.getRegisteredCallbackCount() > 0) { for (int j = 0; j < numUidChanges; ++j) { - final UidRecord.ChangeItem item = mActiveUidChanges[j]; + final ChangeRecord item = mActiveUidChanges[j]; if ((item.change & UidRecord.CHANGE_GONE) != 0) { mValidateUids.remove(item.uid); } else { @@ -213,14 +207,14 @@ public class UidObserverController { } else if ((item.change & UidRecord.CHANGE_ACTIVE) != 0) { validateUid.idle = false; } - validateUid.setCurProcState(validateUid.setProcState = item.processState); + validateUid.setCurProcState(validateUid.setProcState = item.procState); validateUid.curCapability = validateUid.setCapability = item.capability; validateUid.lastDispatchedProcStateSeq = item.procStateSeq; } } } - synchronized (mService) { + synchronized (mLock) { for (int j = 0; j < numUidChanges; j++) { mAvailUidChanges.add(mActiveUidChanges[j]); } @@ -234,7 +228,7 @@ public class UidObserverController { } try { for (int j = 0; j < changesSize; j++) { - UidRecord.ChangeItem item = mActiveUidChanges[j]; + final ChangeRecord item = mActiveUidChanges[j]; final int change = item.change; if (change == UidRecord.CHANGE_PROCSTATE && (reg.mWhich & ActivityManager.UID_OBSERVER_PROCSTATE) == 0) { @@ -285,7 +279,7 @@ public class UidObserverController { if ((reg.mWhich & ActivityManager.UID_OBSERVER_PROCSTATE) != 0) { if (DEBUG_UID_OBSERVERS) { Slog.i(TAG_UID_OBSERVERS, "UID CHANGED uid=" + item.uid - + ": " + item.processState + ": " + item.capability); + + ": " + item.procState + ": " + item.capability); } boolean doReport = true; if (reg.mCutpoint >= ActivityManager.MIN_PROCESS_STATE) { @@ -293,17 +287,17 @@ public class UidObserverController { ActivityManager.PROCESS_STATE_UNKNOWN); if (lastState != ActivityManager.PROCESS_STATE_UNKNOWN) { final boolean lastAboveCut = lastState <= reg.mCutpoint; - final boolean newAboveCut = item.processState <= reg.mCutpoint; + final boolean newAboveCut = item.procState <= reg.mCutpoint; doReport = lastAboveCut != newAboveCut; } else { - doReport = item.processState != PROCESS_STATE_NONEXISTENT; + doReport = item.procState != PROCESS_STATE_NONEXISTENT; } } if (doReport) { if (reg.mLastProcStates != null) { - reg.mLastProcStates.put(item.uid, item.processState); + reg.mLastProcStates.put(item.uid, item.procState); } - observer.onUidStateChanged(item.uid, item.processState, + observer.onUidStateChanged(item.uid, item.procState, item.procStateSeq, item.capability); } } @@ -320,94 +314,82 @@ public class UidObserverController { } } - private boolean isEphemeralLocked(int uid) { - final String[] packages = mService.mContext.getPackageManager().getPackagesForUid(uid); - if (packages == null || packages.length != 1) { // Ephemeral apps cannot share uid - return false; - } - return mService.getPackageManagerInternalLocked().isPackageEphemeral( - UserHandle.getUserId(uid), packages[0]); + UidRecord getValidateUidRecord(int uid) { + return mValidateUids.get(uid); } - @GuardedBy("mService") void dump(PrintWriter pw, String dumpPackage) { - final int count = mUidObservers.getRegisteredCallbackCount(); - boolean printed = false; - for (int i = 0; i < count; i++) { - final UidObserverRegistration reg = (UidObserverRegistration) - mUidObservers.getRegisteredCallbackCookie(i); - if (dumpPackage == null || dumpPackage.equals(reg.mPkg)) { - if (!printed) { - pw.println(" mUidObservers:"); - printed = true; - } - pw.print(" "); UserHandle.formatUid(pw, reg.mUid); - pw.print(" "); pw.print(reg.mPkg); - final IUidObserver observer = mUidObservers.getRegisteredCallbackItem(i); - pw.print(" "); pw.print(observer.getClass().getTypeName()); pw.print(":"); - if ((reg.mWhich & ActivityManager.UID_OBSERVER_IDLE) != 0) { - pw.print(" IDLE"); - } - if ((reg.mWhich & ActivityManager.UID_OBSERVER_ACTIVE) != 0) { - pw.print(" ACT"); - } - if ((reg.mWhich & ActivityManager.UID_OBSERVER_GONE) != 0) { - pw.print(" GONE"); - } - if ((reg.mWhich & ActivityManager.UID_OBSERVER_PROCSTATE) != 0) { - pw.print(" STATE"); - pw.print(" (cut="); pw.print(reg.mCutpoint); - pw.print(")"); - } - pw.println(); - if (reg.mLastProcStates != null) { - final int size = reg.mLastProcStates.size(); - for (int j = 0; j < size; j++) { - pw.print(" Last "); - UserHandle.formatUid(pw, reg.mLastProcStates.keyAt(j)); - pw.print(": "); pw.println(reg.mLastProcStates.valueAt(j)); + synchronized (mLock) { + final int count = mUidObservers.getRegisteredCallbackCount(); + boolean printed = false; + for (int i = 0; i < count; i++) { + final UidObserverRegistration reg = (UidObserverRegistration) + mUidObservers.getRegisteredCallbackCookie(i); + if (dumpPackage == null || dumpPackage.equals(reg.mPkg)) { + if (!printed) { + pw.println(" mUidObservers:"); + printed = true; } + reg.dump(pw, mUidObservers.getRegisteredCallbackItem(i)); } } - } - pw.println(); - pw.print(" mUidChangeDispatchCount="); - pw.print(mUidChangeDispatchCount); - pw.println(); - pw.println(" Slow UID dispatches:"); - final int size = mUidObservers.beginBroadcast(); - for (int i = 0; i < size; i++) { - UidObserverRegistration r = - (UidObserverRegistration) mUidObservers.getBroadcastCookie(i); - pw.print(" "); - pw.print(mUidObservers.getBroadcastItem(i).getClass().getTypeName()); - pw.print(": "); - pw.print(r.mSlowDispatchCount); - pw.print(" / Max "); - pw.print(r.mMaxDispatchTime); - pw.println("ms"); + pw.println(); + pw.print(" mUidChangeDispatchCount="); + pw.print(mUidChangeDispatchCount); + pw.println(); + pw.println(" Slow UID dispatches:"); + for (int i = 0; i < count; i++) { + final UidObserverRegistration reg = (UidObserverRegistration) + mUidObservers.getRegisteredCallbackCookie(i); + pw.print(" "); + pw.print(mUidObservers.getRegisteredCallbackItem(i).getClass().getTypeName()); + pw.print(": "); + pw.print(reg.mSlowDispatchCount); + pw.print(" / Max "); + pw.print(reg.mMaxDispatchTime); + pw.println("ms"); + } } - mUidObservers.finishBroadcast(); } - @GuardedBy("mService") void dumpDebug(ProtoOutputStream proto, String dumpPackage) { - final int count = mUidObservers.getRegisteredCallbackCount(); - for (int i = 0; i < count; i++) { - final UidObserverRegistration reg = (UidObserverRegistration) - mUidObservers.getRegisteredCallbackCookie(i); - if (dumpPackage == null || dumpPackage.equals(reg.mPkg)) { - reg.dumpDebug(proto, ActivityManagerServiceDumpProcessesProto.UID_OBSERVERS); + synchronized (mLock) { + final int count = mUidObservers.getRegisteredCallbackCount(); + for (int i = 0; i < count; i++) { + final UidObserverRegistration reg = (UidObserverRegistration) + mUidObservers.getRegisteredCallbackCookie(i); + if (dumpPackage == null || dumpPackage.equals(reg.mPkg)) { + reg.dumpDebug(proto, ActivityManagerServiceDumpProcessesProto.UID_OBSERVERS); + } } } } + boolean dumpValidateUids(PrintWriter pw, String dumpPackage, int dumpAppId, + String header, boolean needSep) { + return mValidateUids.dump(pw, dumpPackage, dumpAppId, header, needSep); + } + + void dumpValidateUidsProto(ProtoOutputStream proto, String dumpPackage, + int dumpAppId, long fieldId) { + mValidateUids.dumpProto(proto, dumpPackage, dumpAppId, fieldId); + } + + static final class ChangeRecord { + public int uid; + public int change; + public int procState; + public int capability; + public boolean ephemeral; + public long procStateSeq; + } + private static final class UidObserverRegistration { - final int mUid; - final String mPkg; - final int mWhich; - final int mCutpoint; + private final int mUid; + private final String mPkg; + private final int mWhich; + private final int mCutpoint; /** * Total # of callback calls that took more than {@link #SLOW_UID_OBSERVER_THRESHOLD_MS}. @@ -439,10 +421,42 @@ public class UidObserverController { this.mPkg = pkg; this.mWhich = which; this.mCutpoint = cutpoint; - if (cutpoint >= ActivityManager.MIN_PROCESS_STATE) { - mLastProcStates = new SparseIntArray(); - } else { - mLastProcStates = null; + mLastProcStates = cutpoint >= ActivityManager.MIN_PROCESS_STATE + ? new SparseIntArray() : null; + } + + void dump(PrintWriter pw, IUidObserver observer) { + pw.print(" "); + UserHandle.formatUid(pw, mUid); + pw.print(" "); + pw.print(mPkg); + pw.print(" "); + pw.print(observer.getClass().getTypeName()); + pw.print(":"); + if ((mWhich & ActivityManager.UID_OBSERVER_IDLE) != 0) { + pw.print(" IDLE"); + } + if ((mWhich & ActivityManager.UID_OBSERVER_ACTIVE) != 0) { + pw.print(" ACT"); + } + if ((mWhich & ActivityManager.UID_OBSERVER_GONE) != 0) { + pw.print(" GONE"); + } + if ((mWhich & ActivityManager.UID_OBSERVER_PROCSTATE) != 0) { + pw.print(" STATE"); + pw.print(" (cut="); + pw.print(mCutpoint); + pw.print(")"); + } + pw.println(); + if (mLastProcStates != null) { + final int size = mLastProcStates.size(); + for (int j = 0; j < size; j++) { + pw.print(" Last "); + UserHandle.formatUid(pw, mLastProcStates.keyAt(j)); + pw.print(": "); + pw.println(mLastProcStates.valueAt(j)); + } } } diff --git a/services/core/java/com/android/server/am/UidRecord.java b/services/core/java/com/android/server/am/UidRecord.java index c84ccb298bef..dfd6149cfcb7 100644 --- a/services/core/java/com/android/server/am/UidRecord.java +++ b/services/core/java/com/android/server/am/UidRecord.java @@ -107,17 +107,6 @@ public final class UidRecord { UidRecordProto.CHANGE_UNCACHED, }; - static final class ChangeItem { - UidRecord uidRecord; - int uid; - int change; - int processState; - int capability; - boolean ephemeral; - long procStateSeq; - } - - ChangeItem pendingChange; int lastReportedChange; public UidRecord(int _uid) { diff --git a/services/core/java/com/android/server/biometrics/sensors/ClientMonitorCallbackConverter.java b/services/core/java/com/android/server/biometrics/sensors/ClientMonitorCallbackConverter.java index cb7db92ee132..c87f62f94499 100644 --- a/services/core/java/com/android/server/biometrics/sensors/ClientMonitorCallbackConverter.java +++ b/services/core/java/com/android/server/biometrics/sensors/ClientMonitorCallbackConverter.java @@ -89,7 +89,8 @@ public final class ClientMonitorCallbackConverter { } } - void onError(int sensorId, int cookie, int error, int vendorCode) throws RemoteException { + public void onError(int sensorId, int cookie, int error, int vendorCode) + throws RemoteException { if (mSensorReceiver != null) { mSensorReceiver.onError(sensorId, cookie, error, vendorCode); } else if (mFaceServiceReceiver != null) { diff --git a/services/core/java/com/android/server/biometrics/sensors/LockoutConsumer.java b/services/core/java/com/android/server/biometrics/sensors/LockoutConsumer.java new file mode 100644 index 000000000000..153bd4668a4f --- /dev/null +++ b/services/core/java/com/android/server/biometrics/sensors/LockoutConsumer.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2020 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.biometrics.sensors; + +/** + * Interface that clients interested/eligible for lockout events should implement. + */ +public interface LockoutConsumer { + void onLockoutTimed(long durationMillis); + void onLockoutPermanent(); +} diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceUserState.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceUserState.java index 42c7d16951d7..3fdd27948656 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/FaceUserState.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceUserState.java @@ -17,7 +17,6 @@ package com.android.server.biometrics.sensors.face; import android.content.Context; -import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.face.Face; import android.util.AtomicFile; import android.util.Slog; @@ -41,7 +40,7 @@ import java.util.ArrayList; * Class managing the set of faces per user across device reboots. * @hide */ -public class FaceUserState extends BiometricUserState { +public class FaceUserState extends BiometricUserState<Face> { private static final String TAG = "FaceState"; private static final String FACE_FILE = "settings_face.xml"; @@ -72,19 +71,9 @@ public class FaceUserState extends BiometricUserState { } @Override - public void addBiometric(BiometricAuthenticator.Identifier identifier) { - if (identifier instanceof Face) { - super.addBiometric(identifier); - } else { - Slog.w(TAG, "Attempted to add non-face identifier"); - } - } - - @Override - protected ArrayList getCopy(ArrayList array) { - ArrayList<Face> result = new ArrayList<>(array.size()); - for (int i = 0; i < array.size(); i++) { - Face f = (Face) array.get(i); + protected ArrayList<Face> getCopy(ArrayList<Face> array) { + final ArrayList<Face> result = new ArrayList<>(); + for (Face f : array) { result.add(new Face(f.getName(), f.getBiometricId(), f.getDeviceId())); } return result; diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceUtils.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceUtils.java index 0197028cfd6e..f47b22839e70 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/FaceUtils.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceUtils.java @@ -30,7 +30,7 @@ import java.util.List; /** * Utility class for dealing with faces and face settings. */ -public class FaceUtils implements BiometricUtils { +public class FaceUtils implements BiometricUtils<Face> { private static final Object sInstanceLock = new Object(); private static FaceUtils sInstance; @@ -56,9 +56,8 @@ public class FaceUtils implements BiometricUtils { } @Override - public void addBiometricForUser(Context ctx, int userId, - BiometricAuthenticator.Identifier identifier) { - getStateForUser(ctx, userId).addBiometric(identifier); + public void addBiometricForUser(Context ctx, int userId, Face face) { + getStateForUser(ctx, userId).addBiometric(face); } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java index 45de538c62d9..dc22970d617c 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java @@ -33,10 +33,9 @@ import android.content.pm.PackageManager; import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.biometrics.IBiometricSensorReceiver; import android.hardware.biometrics.IBiometricServiceLockoutResetCallback; +import android.hardware.biometrics.ITestSession; import android.hardware.biometrics.fingerprint.IFingerprint; import android.hardware.biometrics.fingerprint.SensorProps; -import android.hardware.biometrics.ITestService; -import android.hardware.biometrics.SensorPropertiesInternal; import android.hardware.fingerprint.Fingerprint; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.hardware.fingerprint.IFingerprintClientActiveCallback; @@ -53,6 +52,8 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; import android.provider.Settings; +import android.util.ArrayMap; +import android.util.ArraySet; import android.util.EventLog; import android.util.Pair; import android.util.Slog; @@ -91,54 +92,52 @@ public class FingerprintService extends SystemService { private final GestureAvailabilityDispatcher mGestureAvailabilityDispatcher; private final LockPatternUtils mLockPatternUtils; @NonNull private List<ServiceProvider> mServiceProviders; - @Nullable private TestService mTestService; + @NonNull private final ArrayMap<Integer, TestSession> mTestSessions; - private final class TestService extends ITestService.Stub { + private final class TestSession extends ITestSession.Stub { + private final int mSensorId; - @Override - public List<SensorPropertiesInternal> getSensorPropertiesInternal( - String opPackageName) { - Utils.checkPermission(getContext(), TEST_BIOMETRIC); - return null; + TestSession(int sensorId) { + mSensorId = sensorId; } @Override - public void enableTestHal(int sensorId, boolean enableTestHal) { + public void enableTestHal(boolean enableTestHal) { Utils.checkPermission(getContext(), TEST_BIOMETRIC); } @Override - public void enrollStart(int sensorId, int userId) { + public void startEnroll(int userId) { Utils.checkPermission(getContext(), TEST_BIOMETRIC); } @Override - public void enrollFinish(int sensorId, int userId) { + public void finishEnroll(int userId) { Utils.checkPermission(getContext(), TEST_BIOMETRIC); } @Override - public void authenticateSuccess(int sensorId, int userId) { + public void acceptAuthentication(int userId) { Utils.checkPermission(getContext(), TEST_BIOMETRIC); } @Override - public void authenticateReject(int sensorId, int userId) { + public void rejectAuthentication(int userId) { Utils.checkPermission(getContext(), TEST_BIOMETRIC); } @Override - public void notifyAcquired(int sensorId, int userId) { + public void notifyAcquired(int userId) { Utils.checkPermission(getContext(), TEST_BIOMETRIC); } @Override - public void notifyError(int sensorId, int userId) { + public void notifyError(int userId) { Utils.checkPermission(getContext(), TEST_BIOMETRIC); } @Override - public void internalCleanup(int sensorId, int userId) { + public void cleanupInternalState(int userId) { Utils.checkPermission(getContext(), TEST_BIOMETRIC); } } @@ -148,15 +147,17 @@ public class FingerprintService extends SystemService { */ private final class FingerprintServiceWrapper extends IFingerprintService.Stub { @Override - public ITestService getTestService(String opPackageName) { + public ITestSession createTestSession(int sensorId, String opPackageName) { Utils.checkPermission(getContext(), TEST_BIOMETRIC); - synchronized (this) { - if (mTestService == null) { - mTestService = new TestService(); + final TestSession session; + synchronized (mTestSessions) { + if (!mTestSessions.containsKey(sensorId)) { + mTestSessions.put(sensorId, new TestSession(sensorId)); } + session = mTestSessions.get(sensorId); } - return mTestService; + return session; } @Override // Binder call @@ -620,6 +621,7 @@ public class FingerprintService extends SystemService { mLockoutResetDispatcher = new LockoutResetDispatcher(context); mLockPatternUtils = new LockPatternUtils(context); mServiceProviders = new ArrayList<>(); + mTestSessions = new ArrayMap<>(); initializeAidlHals(); } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintUserState.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintUserState.java index 56312bcb16e4..f32d28c4d7ee 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintUserState.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintUserState.java @@ -17,7 +17,6 @@ package com.android.server.biometrics.sensors.fingerprint; import android.content.Context; -import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.fingerprint.Fingerprint; import android.util.AtomicFile; import android.util.Slog; @@ -40,7 +39,7 @@ import java.util.ArrayList; * Class managing the set of fingerprint per user across device reboots. * @hide */ -public class FingerprintUserState extends BiometricUserState { +public class FingerprintUserState extends BiometricUserState<Fingerprint> { private static final String TAG = "FingerprintState"; private static final String FINGERPRINT_FILE = "settings_fingerprint.xml"; @@ -72,19 +71,9 @@ public class FingerprintUserState extends BiometricUserState { } @Override - public void addBiometric(BiometricAuthenticator.Identifier identifier) { - if (identifier instanceof Fingerprint) { - super.addBiometric(identifier); - } else { - Slog.w(TAG, "Attempted to add non-fingerprint identifier"); - } - } - - @Override - protected ArrayList getCopy(ArrayList array) { - ArrayList<Fingerprint> result = new ArrayList<>(); - for (int i = 0; i < array.size(); i++) { - Fingerprint fp = (Fingerprint) array.get(i); + protected ArrayList<Fingerprint> getCopy(ArrayList<Fingerprint> array) { + final ArrayList<Fingerprint> result = new ArrayList<>(); + for (Fingerprint fp : array) { result.add(new Fingerprint(fp.getName(), fp.getGroupId(), fp.getBiometricId(), fp.getDeviceId())); } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintUtils.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintUtils.java index f0bfe12db32a..3bf3a5b3ea37 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintUtils.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintUtils.java @@ -30,7 +30,7 @@ import java.util.List; /** * Utility class for dealing with fingerprints and fingerprint settings. */ -public class FingerprintUtils implements BiometricUtils { +public class FingerprintUtils implements BiometricUtils<Fingerprint> { private static final Object sInstanceLock = new Object(); private static FingerprintUtils sInstance; @@ -56,9 +56,8 @@ public class FingerprintUtils implements BiometricUtils { } @Override - public void addBiometricForUser(Context context, int userId, - BiometricAuthenticator.Identifier identifier) { - getStateForUser(context, userId).addBiometric(identifier); + public void addBiometricForUser(Context context, int userId, Fingerprint fingerprint) { + getStateForUser(context, userId).addBiometric(fingerprint); } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java new file mode 100644 index 000000000000..e923943bd386 --- /dev/null +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2020 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.biometrics.sensors.fingerprint.aidl; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.app.TaskStackListener; +import android.content.Context; +import android.hardware.biometrics.BiometricAuthenticator; +import android.hardware.biometrics.BiometricFingerprintConstants; +import android.hardware.biometrics.BiometricsProtoEnums; +import android.hardware.biometrics.common.ICancellationSignal; +import android.hardware.biometrics.fingerprint.ISession; +import android.hardware.fingerprint.IUdfpsOverlayController; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Slog; + +import com.android.server.biometrics.sensors.AuthenticationClient; +import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; +import com.android.server.biometrics.sensors.LockoutConsumer; +import com.android.server.biometrics.sensors.LockoutTracker; +import com.android.server.biometrics.sensors.fingerprint.Udfps; +import com.android.server.biometrics.sensors.fingerprint.UdfpsHelper; + +import java.util.ArrayList; + +/** + * Fingerprint-specific authentication client supporting the + * {@link android.hardware.biometrics.fingerprint.IFingerprint} AIDL interface. + */ +public class FingerprintAuthenticationClient extends AuthenticationClient<ISession> implements + Udfps, LockoutConsumer { + private static final String TAG = "FingerprintAuthenticationClient"; + + @NonNull private final LockoutCache mLockoutCache; + @Nullable private final IUdfpsOverlayController mUdfpsOverlayController; + @Nullable private ICancellationSignal mCancellationSignal; + + public FingerprintAuthenticationClient(@NonNull Context context, + @NonNull LazyDaemon<ISession> lazyDaemon, @NonNull IBinder token, + @NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId, + boolean restricted, @NonNull String owner, int cookie, boolean requireConfirmation, + int sensorId, boolean isStrongBiometric, int statsClient, + @Nullable TaskStackListener taskStackListener, @NonNull LockoutCache lockoutCache, + @Nullable IUdfpsOverlayController udfpsOverlayController) { + super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted, owner, + cookie, requireConfirmation, sensorId, isStrongBiometric, + BiometricsProtoEnums.MODALITY_FINGERPRINT, statsClient, taskStackListener, + lockoutCache); + mLockoutCache = lockoutCache; + mUdfpsOverlayController = udfpsOverlayController; + } + + @Override + public void onAuthenticated(BiometricAuthenticator.Identifier identifier, + boolean authenticated, ArrayList<Byte> token) { + super.onAuthenticated(identifier, authenticated, token); + + if (authenticated) { + UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController); + mCallback.onClientFinished(this, true /* success */); + } + } + + @Override + protected void startHalOperation() { + UdfpsHelper.showUdfpsOverlay(getSensorId(), mUdfpsOverlayController); + try { + mCancellationSignal = getFreshDaemon().authenticate(mSequentialId, mOperationId); + } catch (RemoteException e) { + Slog.e(TAG, "Remote exception", e); + onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE, + 0 /* vendorCode */); + UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController); + mCallback.onClientFinished(this, false /* success */); + } + } + + @Override + protected void stopHalOperation() { + UdfpsHelper.hideUdfpsOverlay(getSensorId(), mUdfpsOverlayController); + try { + mCancellationSignal.cancel(); + } catch (RemoteException e) { + Slog.e(TAG, "Remote exception", e); + onError(BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE, + 0 /* vendorCode */); + mCallback.onClientFinished(this, false /* success */); + } + } + + @Override + public void onPointerDown(int x, int y, float minor, float major) { + try { + getFreshDaemon().onPointerDown(0 /* pointerId */, x, y, minor, major); + } catch (RemoteException e) { + Slog.e(TAG, "Remote exception", e); + } + } + + @Override + public void onPointerUp() { + try { + getFreshDaemon().onPointerUp(0 /* pointerId */); + } catch (RemoteException e) { + Slog.e(TAG, "Remote exception", e); + } + } + + @Override + public void onLockoutTimed(long durationMillis) { + mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_TIMED); + // Lockout metrics are logged as an error code. + final int error = BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT; + logOnError(getContext(), error, 0 /* vendorCode */, getTargetUserId()); + + try { + getListener().onError(getSensorId(), getCookie(), error, 0 /* vendorCode */); + } catch (RemoteException e) { + Slog.e(TAG, "Remote exception", e); + } + } + + @Override + public void onLockoutPermanent() { + mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_PERMANENT); + // Lockout metrics are logged as an error code. + final int error = BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT_PERMANENT; + logOnError(getContext(), error, 0 /* vendorCode */, getTargetUserId()); + + try { + getListener().onError(getSensorId(), getCookie(), error, 0 /* vendorCode */); + } catch (RemoteException e) { + Slog.e(TAG, "Remote exception", e); + } + } +} diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java index 33f5418ee620..c96bef167e8b 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java @@ -21,6 +21,7 @@ import android.annotation.Nullable; import android.content.Context; import android.hardware.biometrics.BiometricFaceConstants; import android.hardware.biometrics.BiometricFingerprintConstants; +import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.biometrics.common.ICancellationSignal; import android.hardware.biometrics.fingerprint.ISession; import android.hardware.fingerprint.IUdfpsOverlayController; @@ -48,11 +49,12 @@ public class FingerprintEnrollClient extends EnrollClient<ISession> implements U public FingerprintEnrollClient(@NonNull Context context, @NonNull LazyDaemon<ISession> lazyDaemon, @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId, - @NonNull byte[] hardwareAuthToken, @NonNull String owner, @NonNull BiometricUtils utils, - int statsModality, int sensorId, + @NonNull byte[] hardwareAuthToken, @NonNull String owner, + @NonNull FingerprintUtils utils, int sensorId, @Nullable IUdfpsOverlayController udfpsOvelayController, int maxTemplatesPerUser) { super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, owner, utils, - 0 /* timeoutSec */, statsModality, sensorId, true /* shouldVibrate */); + 0 /* timeoutSec */, BiometricsProtoEnums.MODALITY_FINGERPRINT, sensorId, + true /* shouldVibrate */); mUdfpsOverlayController = udfpsOvelayController; mMaxTemplatesPerUser = maxTemplatesPerUser; } @@ -83,7 +85,7 @@ public class FingerprintEnrollClient extends EnrollClient<ISession> implements U protected void startHalOperation() { UdfpsHelper.showUdfpsOverlay(getSensorId(), mUdfpsOverlayController); try { - getFreshDaemon().enroll(mSequentialId, + mCancellationSignal = getFreshDaemon().enroll(mSequentialId, HardwareAuthTokenUtils.toHardwareAuthToken(mHardwareAuthToken)); } catch (RemoteException e) { Slog.e(TAG, "Remote exception when requesting enroll", e); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java index 0b59086fb907..bac83b9e21ef 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java @@ -19,12 +19,14 @@ package com.android.server.biometrics.sensors.fingerprint.aidl; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; +import android.app.ActivityTaskManager; +import android.app.IActivityTaskManager; +import android.app.TaskStackListener; import android.content.Context; import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.biometrics.fingerprint.IFingerprint; import android.hardware.biometrics.fingerprint.SensorProps; import android.hardware.fingerprint.Fingerprint; -import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.hardware.fingerprint.IFingerprintServiceReceiver; import android.hardware.fingerprint.IUdfpsOverlayController; @@ -37,12 +39,15 @@ import android.util.Slog; import android.util.SparseArray; import android.view.Surface; +import com.android.server.biometrics.Utils; +import com.android.server.biometrics.sensors.AuthenticationClient; import com.android.server.biometrics.sensors.ClientMonitor; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.LockoutResetDispatcher; import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils; import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher; import com.android.server.biometrics.sensors.fingerprint.ServiceProvider; +import com.android.server.biometrics.sensors.fingerprint.Udfps; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -52,6 +57,7 @@ import java.util.List; /** * Provider for a single instance of the {@link IFingerprint} HAL. */ +@SuppressWarnings("deprecation") public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvider { @NonNull private final Context mContext; @@ -60,9 +66,48 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi @NonNull private final ClientMonitor.LazyDaemon<IFingerprint> mLazyDaemon; @NonNull private final Handler mHandler; @NonNull private final LockoutResetDispatcher mLockoutResetDispatcher; + @NonNull private final IActivityTaskManager mActivityTaskManager; + @NonNull private final BiometricTaskStackListener mTaskStackListener; @Nullable private IUdfpsOverlayController mUdfpsOverlayController; + private final class BiometricTaskStackListener extends TaskStackListener { + @Override + public void onTaskStackChanged() { + mHandler.post(() -> { + for (int i = 0; i < mSensors.size(); i++) { + final ClientMonitor<?> client = mSensors.get(i).getScheduler() + .getCurrentClient(); + if (!(client instanceof AuthenticationClient)) { + Slog.e(getTag(), "Task stack changed for client: " + client); + continue; + } + if (Utils.isKeyguard(mContext, client.getOwnerString())) { + continue; // Keyguard is always allowed + } + + try { + final List<ActivityManager.RunningTaskInfo> runningTasks = + mActivityTaskManager.getTasks(1); + if (!runningTasks.isEmpty()) { + final String topPackage = + runningTasks.get(0).topActivity.getPackageName(); + if (!topPackage.contentEquals(client.getOwnerString()) + && !client.isAlreadyDone()) { + Slog.e(getTag(), "Stopping background authentication, top: " + + topPackage + " currentClient: " + client); + mSensors.get(i).getScheduler() + .cancelAuthentication(client.getToken()); + } + } + } catch (RemoteException e) { + Slog.e(getTag(), "Unable to get running tasks", e); + } + } + }); + } + } + public FingerprintProvider(@NonNull Context context, @NonNull SensorProps[] props, @NonNull String halInstanceName, @NonNull LockoutResetDispatcher lockoutResetDispatcher, @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) { @@ -72,6 +117,8 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi mLazyDaemon = this::getHalInstance; mHandler = new Handler(Looper.getMainLooper()); mLockoutResetDispatcher = lockoutResetDispatcher; + mActivityTaskManager = ActivityTaskManager.getService(); + mTaskStackListener = new BiometricTaskStackListener(); for (SensorProps prop : props) { final int sensorId = prop.commonProps.sensorId; @@ -135,7 +182,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client, callback); } - private void scheduleCreateSessionWithoutHandler(@NonNull IFingerprint daemon, int sensorId, + private void createNewSessionWithoutHandler(@NonNull IFingerprint daemon, int sensorId, int userId) throws RemoteException { // Note that per IFingerprint createSession contract, this method will block until all // existing operations are canceled/finished. However, also note that this is fine, since @@ -178,7 +225,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi try { if (!mSensors.get(sensorId).hasSessionForUser(userId)) { - scheduleCreateSessionWithoutHandler(daemon, sensorId, userId); + createNewSessionWithoutHandler(daemon, sensorId, userId); } final FingerprintResetLockoutClient client = new FingerprintResetLockoutClient( @@ -222,19 +269,15 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi final IFingerprint daemon = getHalInstance(); if (daemon == null) { Slog.e(getTag(), "Null daemon during enroll, sensorId: " + sensorId); - - try { - receiver.onError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE, - 0 /* vendorCode */); - } catch (RemoteException e) { - Slog.e(getTag(), "Unable to send HW_UNAVAILABLE", e); - } + // If this happens, we need to send HW_UNAVAILABLE after the scheduler gets to + // this operation. We should not send the callback yet, since the scheduler may + // be processing something else. return; } try { if (!mSensors.get(sensorId).hasSessionForUser(userId)) { - scheduleCreateSessionWithoutHandler(daemon, sensorId, userId); + createNewSessionWithoutHandler(daemon, sensorId, userId); } final int maxTemplatesPerUser = mSensors.get(sensorId).getSensorProperties() @@ -242,8 +285,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi final FingerprintEnrollClient client = new FingerprintEnrollClient(mContext, mSensors.get(sensorId).getLazySession(), token, new ClientMonitorCallbackConverter(receiver), userId, hardwareAuthToken, - opPackageName, FingerprintUtils.getInstance(), - BiometricsProtoEnums.MODALITY_FINGERPRINT, sensorId, + opPackageName, FingerprintUtils.getInstance(), sensorId, mUdfpsOverlayController, maxTemplatesPerUser); scheduleForSensor(sensorId, client, new ClientMonitor.Callback() { @Override @@ -262,7 +304,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi @Override public void cancelEnrollment(int sensorId, @NonNull IBinder token) { - + mHandler.post(() -> mSensors.get(sensorId).getScheduler().cancelEnrollment(token)); } @Override @@ -277,24 +319,74 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName, boolean restricted, int statsClient, boolean isKeyguard) { + mHandler.post(() -> { + final IFingerprint daemon = getHalInstance(); + if (daemon == null) { + Slog.e(getTag(), "Null daemon during authenticate, sensorId: " + sensorId); + // If this happens, we need to send HW_UNAVAILABLE after the scheduler gets to + // this operation. We should not send the callback yet, since the scheduler may + // be processing something else. + return; + } + try { + if (!mSensors.get(sensorId).hasSessionForUser(userId)) { + createNewSessionWithoutHandler(daemon, sensorId, userId); + } + + final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId); + final FingerprintAuthenticationClient client = new FingerprintAuthenticationClient( + mContext, mSensors.get(sensorId).getLazySession(), token, callback, userId, + operationId, restricted, opPackageName, cookie, + false /* requireConfirmation */, sensorId, isStrongBiometric, statsClient, + mTaskStackListener, mSensors.get(sensorId).getLockoutCache(), + mUdfpsOverlayController); + mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client); + } catch (RemoteException e) { + Slog.e(getTag(), "Remote exception when scheduling authenticate", e); + } + }); } @Override public void startPreparedClient(int sensorId, int cookie) { - + mHandler.post(() -> mSensors.get(sensorId).getScheduler().startPreparedClient(cookie)); } @Override public void cancelAuthentication(int sensorId, @NonNull IBinder token) { - + mHandler.post(() -> mSensors.get(sensorId).getScheduler().cancelAuthentication(token)); } @Override public void scheduleRemove(int sensorId, @NonNull IBinder token, @NonNull IFingerprintServiceReceiver receiver, int fingerId, int userId, @NonNull String opPackageName) { + mHandler.post(() -> { + final IFingerprint daemon = getHalInstance(); + if (daemon == null) { + Slog.e(getTag(), "Null daemon during remove, sensorId: " + sensorId); + // If this happens, we need to send HW_UNAVAILABLE after the scheduler gets to + // this operation. We should not send the callback yet, since the scheduler may + // be processing something else. + return; + } + + try { + if (!mSensors.get(sensorId).hasSessionForUser(userId)) { + createNewSessionWithoutHandler(daemon, sensorId, userId); + } + final FingerprintRemovalClient client = new FingerprintRemovalClient(mContext, + mSensors.get(sensorId).getLazySession(), token, + new ClientMonitorCallbackConverter(receiver), fingerId, userId, + opPackageName, FingerprintUtils.getInstance(), sensorId, + mSensors.get(sensorId).getAuthenticatorIds()); + mSensors.get(sensorId).getScheduler().scheduleClientMonitor(client); + } catch (RemoteException e) { + Slog.e(getTag(), "Remote exception when scheduling remove", e); + } + }); } @Override @@ -320,7 +412,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi @Override public int getLockoutModeForUser(int sensorId, int userId) { - return 0; + return mSensors.get(sensorId).getLockoutCache().getLockoutModeForUser(userId); } @Override @@ -330,12 +422,24 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi @Override public void onPointerDown(int sensorId, int x, int y, float minor, float major) { - + final ClientMonitor<?> client = mSensors.get(sensorId).getScheduler().getCurrentClient(); + if (!(client instanceof Udfps)) { + Slog.e(getTag(), "onPointerDown received during client: " + client); + return; + } + final Udfps udfps = (Udfps) client; + udfps.onPointerDown(x, y, minor, major); } @Override public void onPointerUp(int sensorId) { - + final ClientMonitor<?> client = mSensors.get(sensorId).getScheduler().getCurrentClient(); + if (!(client instanceof Udfps)) { + Slog.e(getTag(), "onPointerUp received during client: " + client); + return; + } + final Udfps udfps = (Udfps) client; + udfps.onPointerUp(); } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintRemovalClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintRemovalClient.java new file mode 100644 index 000000000000..df063dc34017 --- /dev/null +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintRemovalClient.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2020 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.biometrics.sensors.fingerprint.aidl; + +import android.annotation.NonNull; +import android.content.Context; +import android.hardware.biometrics.BiometricsProtoEnums; +import android.hardware.biometrics.fingerprint.ISession; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Slog; + +import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; +import com.android.server.biometrics.sensors.RemovalClient; +import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils; + +import java.util.Map; + +/** + * Fingerprint-specific removal client supporting the + * {@link android.hardware.biometrics.fingerprint.IFingerprint} interface. + */ +public class FingerprintRemovalClient extends RemovalClient<ISession> { + private static final String TAG = "FingerprintRemovalClient"; + + public FingerprintRemovalClient(@NonNull Context context, + @NonNull LazyDaemon<ISession> lazyDaemon, @NonNull IBinder token, + @NonNull ClientMonitorCallbackConverter listener, int biometricId, int userId, + @NonNull String owner, @NonNull FingerprintUtils utils, int sensorId, + @NonNull Map<Integer, Long> authenticatorIds) { + super(context, lazyDaemon, token, listener, biometricId, userId, owner, utils, sensorId, + authenticatorIds, BiometricsProtoEnums.MODALITY_FINGERPRINT); + } + + @Override + protected void startHalOperation() { + try { + final int[] ids = new int[] {mBiometricId}; + getFreshDaemon().removeEnrollments(mSequentialId, ids); + } catch (RemoteException e) { + Slog.e(TAG, "Remote exception when requesting remove", e); + mCallback.onClientFinished(this, false /* success */); + } + } +} diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java index 2ed695d8821e..b7aa2d579f54 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java @@ -37,12 +37,15 @@ import com.android.server.biometrics.sensors.AuthenticationConsumer; import com.android.server.biometrics.sensors.BiometricScheduler; import com.android.server.biometrics.sensors.ClientMonitor; import com.android.server.biometrics.sensors.Interruptable; +import com.android.server.biometrics.sensors.LockoutConsumer; import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils; import com.android.server.biometrics.sensors.fingerprint.GestureAvailabilityDispatcher; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * Maintains the state of a single sensor within an instance of the @@ -55,6 +58,7 @@ class Sensor { @NonNull private final FingerprintSensorPropertiesInternal mSensorProperties; @NonNull private final BiometricScheduler mScheduler; @NonNull private final LockoutCache mLockoutCache; + @NonNull private final Map<Integer, Long> mAuthenticatorIds; @Nullable private Session mCurrentSession; // TODO: Death recipient @NonNull private final ClientMonitor.LazyDaemon<ISession> mLazySession; @@ -84,6 +88,7 @@ class Sensor { mSensorProperties = sensorProperties; mScheduler = new BiometricScheduler(tag, gestureAvailabilityDispatcher); mLockoutCache = new LockoutCache(); + mAuthenticatorIds = new HashMap<>(); mLazySession = () -> mCurrentSession != null ? mCurrentSession.mSession : null; } @@ -209,12 +214,32 @@ class Sensor { @Override public void onLockoutTimed(long durationMillis) { + mHandler.post(() -> { + final ClientMonitor<?> client = mScheduler.getCurrentClient(); + if (!(client instanceof LockoutConsumer)) { + Slog.e(mTag, "onLockoutTimed for non-lockout consumer: " + + Utils.getClientName(client)); + return; + } + final LockoutConsumer lockoutConsumer = (LockoutConsumer) client; + lockoutConsumer.onLockoutTimed(durationMillis); + }); } @Override public void onLockoutPermanent() { + mHandler.post(() -> { + final ClientMonitor<?> client = mScheduler.getCurrentClient(); + if (!(client instanceof LockoutConsumer)) { + Slog.e(mTag, "onLockoutPermanent for non-lockout consumer: " + + Utils.getClientName(client)); + return; + } + final LockoutConsumer lockoutConsumer = (LockoutConsumer) client; + lockoutConsumer.onLockoutPermanent(); + }); } @Override @@ -270,4 +295,8 @@ class Sensor { @NonNull LockoutCache getLockoutCache() { return mLockoutCache; } + + @NonNull Map<Integer, Long> getAuthenticatorIds() { + return mAuthenticatorIds; + } } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java index fedcfa576d35..da68bc8b79da 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java @@ -594,16 +594,12 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider @Override public void startPreparedClient(int sensorId, int cookie) { - mHandler.post(() -> { - mScheduler.startPreparedClient(cookie); - }); + mHandler.post(() -> mScheduler.startPreparedClient(cookie)); } @Override public void cancelAuthentication(int sensorId, @NonNull IBinder token) { - mHandler.post(() -> { - mScheduler.cancelAuthentication(token); - }); + mHandler.post(() -> mScheduler.cancelAuthentication(token)); } @Override diff --git a/services/core/java/com/android/server/location/LocationProviderManager.java b/services/core/java/com/android/server/location/LocationProviderManager.java index 52065710f38e..179fb7d2f723 100644 --- a/services/core/java/com/android/server/location/LocationProviderManager.java +++ b/services/core/java/com/android/server/location/LocationProviderManager.java @@ -23,15 +23,12 @@ import static android.location.LocationManager.GPS_PROVIDER; import static android.location.LocationManager.KEY_LOCATION_CHANGED; import static android.location.LocationManager.KEY_PROVIDER_ENABLED; import static android.location.LocationManager.PASSIVE_PROVIDER; -import static android.location.LocationRequest.PASSIVE_INTERVAL; import static android.os.IPowerManager.LOCATION_MODE_NO_CHANGE; import static android.os.PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF; import static android.os.PowerManager.LOCATION_MODE_FOREGROUND_ONLY; import static android.os.PowerManager.LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF; import static android.os.PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF; -import static com.android.internal.location.ProviderRequest.EMPTY_REQUEST; -import static com.android.internal.location.ProviderRequest.INTERVAL_DISABLED; import static com.android.server.location.LocationManagerService.D; import static com.android.server.location.LocationManagerService.TAG; import static com.android.server.location.LocationPermissions.PERMISSION_COARSE; @@ -503,14 +500,7 @@ class LocationProviderManager extends LocationRequest.Builder builder = new LocationRequest.Builder(baseRequest); if (mPermissionLevel < PERMISSION_FINE) { - switch (baseRequest.getQuality()) { - case LocationRequest.ACCURACY_FINE: - builder.setQuality(LocationRequest.ACCURACY_BLOCK); - break; - case LocationRequest.POWER_HIGH: - builder.setQuality(LocationRequest.POWER_LOW); - break; - } + builder.setQuality(LocationRequest.QUALITY_LOW_POWER); if (baseRequest.getIntervalMillis() < MIN_COARSE_INTERVAL_MS) { builder.setIntervalMillis(MIN_COARSE_INTERVAL_MS); } @@ -1709,7 +1699,7 @@ class LocationProviderManager extends @Override protected boolean registerWithService(ProviderRequest request, Collection<Registration> registrations) { - return reregisterWithService(EMPTY_REQUEST, request, registrations); + return reregisterWithService(ProviderRequest.EMPTY_REQUEST, request, registrations); } @GuardedBy("mLock") @@ -1778,8 +1768,8 @@ class LocationProviderManager extends Preconditions.checkState(Thread.holdsLock(mLock)); } - mLocationEventLog.logProviderUpdateRequest(mName, EMPTY_REQUEST); - mProvider.setRequest(EMPTY_REQUEST); + mLocationEventLog.logProviderUpdateRequest(mName, ProviderRequest.EMPTY_REQUEST); + mProvider.setRequest(ProviderRequest.EMPTY_REQUEST); } @GuardedBy("mLock") @@ -1839,27 +1829,27 @@ class LocationProviderManager extends Preconditions.checkState(Thread.holdsLock(mLock)); } - long intervalMs = INTERVAL_DISABLED; + long intervalMs = ProviderRequest.INTERVAL_DISABLED; + int quality = LocationRequest.QUALITY_LOW_POWER; boolean locationSettingsIgnored = false; boolean lowPower = true; - ArrayList<LocationRequest> locationRequests = new ArrayList<>(registrations.size()); for (Registration registration : registrations) { LocationRequest request = registration.getRequest(); // passive requests do not contribute to the provider request - if (request.getIntervalMillis() == PASSIVE_INTERVAL) { + if (request.getIntervalMillis() == LocationRequest.PASSIVE_INTERVAL) { continue; } intervalMs = min(request.getIntervalMillis(), intervalMs); + quality = min(request.getQuality(), quality); locationSettingsIgnored |= request.isLocationSettingsIgnored(); lowPower &= request.isLowPower(); - locationRequests.add(request); } - if (intervalMs == INTERVAL_DISABLED) { - return EMPTY_REQUEST; + if (intervalMs == ProviderRequest.INTERVAL_DISABLED) { + return ProviderRequest.EMPTY_REQUEST; } // calculate who to blame for power in a somewhat arbitrary fashion. we pick a threshold @@ -1872,7 +1862,7 @@ class LocationProviderManager extends } catch (ArithmeticException e) { // check for and handle overflow by setting to one below the passive interval so passive // requests are automatically skipped - thresholdIntervalMs = PASSIVE_INTERVAL - 1; + thresholdIntervalMs = LocationRequest.PASSIVE_INTERVAL - 1; } WorkSource workSource = new WorkSource(); @@ -1884,9 +1874,9 @@ class LocationProviderManager extends return new ProviderRequest.Builder() .setIntervalMillis(intervalMs) + .setQuality(quality) .setLocationSettingsIgnored(locationSettingsIgnored) .setLowPower(lowPower) - .setLocationRequests(locationRequests) .setWorkSource(workSource) .build(); } diff --git a/services/core/java/com/android/server/location/PassiveLocationProviderManager.java b/services/core/java/com/android/server/location/PassiveLocationProviderManager.java index fc10d5fcf1b7..b7718611cffc 100644 --- a/services/core/java/com/android/server/location/PassiveLocationProviderManager.java +++ b/services/core/java/com/android/server/location/PassiveLocationProviderManager.java @@ -63,15 +63,7 @@ class PassiveLocationProviderManager extends LocationProviderManager { @Override protected ProviderRequest mergeRegistrations(Collection<Registration> registrations) { - boolean locationSettingsIgnored = false; - for (Registration registration : registrations) { - locationSettingsIgnored |= registration.getRequest().isLocationSettingsIgnored(); - } - - return new ProviderRequest.Builder() - .setIntervalMillis(0) - .setLocationSettingsIgnored(locationSettingsIgnored) - .build(); + return new ProviderRequest.Builder().setIntervalMillis(0).build(); } @Override @@ -79,4 +71,9 @@ class PassiveLocationProviderManager extends LocationProviderManager { Collection<Registration> registrations) { return 0; } + + @Override + protected String getServiceState() { + return mProvider.getCurrentRequest().isActive() ? "registered" : "unregistered"; + } } diff --git a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java index e144b403240c..e25e605cf7d2 100644 --- a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java +++ b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java @@ -708,12 +708,12 @@ public class GnssLocationProvider extends AbstractLocationProvider implements // For fast GNSS TTFF provider = LocationManager.NETWORK_PROVIDER; locationListener = mNetworkLocationListener; - locationRequest.setQuality(LocationRequest.POWER_LOW); + locationRequest.setQuality(LocationRequest.QUALITY_LOW_POWER); } else { // For Device-Based Hybrid (E911) provider = LocationManager.FUSED_PROVIDER; locationListener = mFusedLocationListener; - locationRequest.setQuality(LocationRequest.ACCURACY_FINE); + locationRequest.setQuality(LocationRequest.QUALITY_HIGH_ACCURACY); } // Ignore location settings if in emergency mode. This is only allowed for diff --git a/services/core/java/com/android/server/net/NetworkStatsAccess.java b/services/core/java/com/android/server/net/NetworkStatsAccess.java index 5a8fbf3d26b5..7cdc4cc7479d 100644 --- a/services/core/java/com/android/server/net/NetworkStatsAccess.java +++ b/services/core/java/com/android/server/net/NetworkStatsAccess.java @@ -27,6 +27,7 @@ import android.app.AppOpsManager; import android.app.admin.DevicePolicyManagerInternal; import android.content.Context; import android.content.pm.PackageManager; +import android.os.Process; import android.os.UserHandle; import android.telephony.TelephonyManager; @@ -110,11 +111,12 @@ public final class NetworkStatsAccess { boolean hasCarrierPrivileges = tm != null && tm.checkCarrierPrivilegesForPackageAnyPhone(callingPackage) == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; - boolean isDeviceOwner = dpmi != null && dpmi.isActiveDeviceOwner(callingUid); + final boolean isDeviceOwner = dpmi != null && dpmi.isActiveDeviceOwner(callingUid); + final int appId = UserHandle.getAppId(callingUid); if (hasCarrierPrivileges || isDeviceOwner - || UserHandle.getAppId(callingUid) == android.os.Process.SYSTEM_UID) { - // Carrier-privileged apps and device owners, and the system can access data usage for - // all apps on the device. + || appId == Process.SYSTEM_UID || appId == Process.NETWORK_STACK_UID) { + // Carrier-privileged apps and device owners, and the system (including the + // network stack) can access data usage for all apps on the device. return NetworkStatsAccess.Level.DEVICE; } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 23798c0622fc..03bf74f40205 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -4769,7 +4769,7 @@ public class NotificationManagerService extends SystemService { @Override public List<ComponentName> getEnabledNotificationListeners(int userId) { - checkCallerIsSystem(); + checkNotificationListenerAccess(); return mListeners.getAllowedComponents(userId); } @@ -4838,7 +4838,7 @@ public class NotificationManagerService extends SystemService { public void setNotificationListenerAccessGrantedForUser(ComponentName listener, int userId, boolean granted) { Objects.requireNonNull(listener); - checkCallerIsSystemOrShell(); + checkNotificationListenerAccess(); final long identity = Binder.clearCallingIdentity(); try { if (mAllowedManagedServicePackages.test( @@ -5111,6 +5111,14 @@ public class NotificationManagerService extends SystemService { } }; + protected void checkNotificationListenerAccess() { + if (!isCallerSystemOrPhone()) { + getContext().enforceCallingPermission( + permission.MANAGE_NOTIFICATION_LISTENERS, + "Caller must hold " + permission.MANAGE_NOTIFICATION_LISTENERS); + } + } + @VisibleForTesting protected void setNotificationAssistantAccessGrantedForUserInternal( ComponentName assistant, int baseUserId, boolean granted) { diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java index ad022c764547..7992fea4a675 100644 --- a/services/core/java/com/android/server/pm/ApexManager.java +++ b/services/core/java/com/android/server/pm/ApexManager.java @@ -777,12 +777,15 @@ public abstract class ApexManager { void registerApkInApex(AndroidPackage pkg) { synchronized (mLock) { for (ActiveApexInfo aai : mActiveApexInfosCache) { - if (pkg.getBaseApkPath().startsWith(aai.apexDirectory.getAbsolutePath())) { + if (pkg.getBaseApkPath().startsWith( + aai.apexDirectory.getAbsolutePath() + File.separator)) { List<String> apks = mApksInApex.get(aai.apexModuleName); if (apks == null) { apks = Lists.newArrayList(); mApksInApex.put(aai.apexModuleName, apks); } + Slog.i(TAG, "Registering " + pkg.getPackageName() + " as apk-in-apex of " + + aai.apexModuleName); apks.add(pkg.getPackageName()); } } diff --git a/services/core/java/com/android/server/pm/IncrementalStates.java b/services/core/java/com/android/server/pm/IncrementalStates.java index dda5fafb8cb1..ababb8365c4f 100644 --- a/services/core/java/com/android/server/pm/IncrementalStates.java +++ b/services/core/java/com/android/server/pm/IncrementalStates.java @@ -376,10 +376,10 @@ public final class IncrementalStates { case IDataLoaderStatusListener.STREAM_INTEGRITY_ERROR: // fall through case IDataLoaderStatusListener.STREAM_SOURCE_ERROR: { - return PackageManager.UNSTARTABLE_REASON_DATALOADER_TRANSPORT; + return PackageManager.UNSTARTABLE_REASON_CONNECTION_ERROR; } case IDataLoaderStatusListener.STREAM_STORAGE_ERROR: { - return PackageManager.UNSTARTABLE_REASON_DATALOADER_STORAGE; + return PackageManager.UNSTARTABLE_REASON_INSUFFICIENT_STORAGE; } default: return PackageManager.UNSTARTABLE_REASON_UNKNOWN; diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java index 9bb6f7892972..66ae50e4e140 100644 --- a/services/core/java/com/android/server/pm/LauncherAppsService.java +++ b/services/core/java/com/android/server/pm/LauncherAppsService.java @@ -44,6 +44,8 @@ import android.content.pm.IOnAppsChangedListener; import android.content.pm.IPackageInstallerCallback; import android.content.pm.IPackageManager; import android.content.pm.IShortcutChangeCallback; +import android.content.pm.IncrementalStatesInfo; +import android.content.pm.LauncherActivityInfoInternal; import android.content.pm.LauncherApps; import android.content.pm.LauncherApps.ShortcutQuery; import android.content.pm.PackageInfo; @@ -369,18 +371,13 @@ public class LauncherAppsService extends SystemService { } } - private ResolveInfo getHiddenAppActivityInfo(String packageName, int callingUid, - UserHandle user) { + private LauncherActivityInfoInternal getHiddenAppActivityInfo(String packageName, + int callingUid, UserHandle user) { Intent intent = new Intent(); intent.setComponent(new ComponentName(packageName, PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME)); - final PackageManagerInternal pmInt = - LocalServices.getService(PackageManagerInternal.class); - List<ResolveInfo> apps = pmInt.queryIntentActivities(intent, - intent.resolveTypeIfNeeded(mContext.getContentResolver()), - PackageManager.MATCH_DIRECT_BOOT_AWARE - | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, - callingUid, user.getIdentifier()); + final List<LauncherActivityInfoInternal> apps = queryIntentLauncherActivities(intent, + callingUid, user); if (apps.size() > 0) { return apps.get(0); } @@ -399,14 +396,14 @@ public class LauncherAppsService extends SystemService { } @Override - public ParceledListSlice<ResolveInfo> getLauncherActivities(String callingPackage, - String packageName, UserHandle user) throws RemoteException { - ParceledListSlice<ResolveInfo> launcherActivities = queryActivitiesForUser( - callingPackage, - new Intent(Intent.ACTION_MAIN) - .addCategory(Intent.CATEGORY_LAUNCHER) - .setPackage(packageName), - user); + public ParceledListSlice<LauncherActivityInfoInternal> getLauncherActivities( + String callingPackage, String packageName, UserHandle user) throws RemoteException { + ParceledListSlice<LauncherActivityInfoInternal> launcherActivities = + queryActivitiesForUser(callingPackage, + new Intent(Intent.ACTION_MAIN) + .addCategory(Intent.CATEGORY_LAUNCHER) + .setPackage(packageName), + user); if (Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.SHOW_HIDDEN_LAUNCHER_ICON_APPS_ENABLED, 1) == 0) { return launcherActivities; @@ -428,7 +425,8 @@ public class LauncherAppsService extends SystemService { return launcherActivities; } - final ArrayList<ResolveInfo> result = new ArrayList<>(launcherActivities.getList()); + final ArrayList<LauncherActivityInfoInternal> result = new ArrayList<>( + launcherActivities.getList()); final PackageManagerInternal pmInt = LocalServices.getService(PackageManagerInternal.class); if (packageName != null) { @@ -440,7 +438,8 @@ public class LauncherAppsService extends SystemService { ApplicationInfo appInfo = pmInt.getApplicationInfo(packageName, /*flags*/ 0, callingUid, user.getIdentifier()); if (shouldShowSyntheticActivity(user, appInfo)) { - ResolveInfo info = getHiddenAppActivityInfo(packageName, callingUid, user); + LauncherActivityInfoInternal info = getHiddenAppActivityInfo(packageName, + callingUid, user); if (info != null) { result.add(info); } @@ -448,8 +447,8 @@ public class LauncherAppsService extends SystemService { return new ParceledListSlice<>(result); } final HashSet<String> visiblePackages = new HashSet<>(); - for (ResolveInfo info : result) { - visiblePackages.add(info.activityInfo.packageName); + for (LauncherActivityInfoInternal info : result) { + visiblePackages.add(info.getActivityInfo().packageName); } List<ApplicationInfo> installedPackages = pmInt.getInstalledApplications(0, user.getIdentifier(), callingUid); @@ -458,8 +457,8 @@ public class LauncherAppsService extends SystemService { if (!shouldShowSyntheticActivity(user, applicationInfo)) { continue; } - ResolveInfo info = getHiddenAppActivityInfo(applicationInfo.packageName, - callingUid, user); + LauncherActivityInfoInternal info = getHiddenAppActivityInfo( + applicationInfo.packageName, callingUid, user); if (info != null) { result.add(info); } @@ -533,7 +532,7 @@ public class LauncherAppsService extends SystemService { } @Override - public ActivityInfo resolveActivity( + public LauncherActivityInfoInternal resolveLauncherActivityInternal( String callingPackage, ComponentName component, UserHandle user) throws RemoteException { if (!canAccessProfile(user.getIdentifier(), "Cannot resolve activity")) { @@ -545,10 +544,13 @@ public class LauncherAppsService extends SystemService { try { final PackageManagerInternal pmInt = LocalServices.getService(PackageManagerInternal.class); - return pmInt.getActivityInfo(component, + final ActivityInfo activityInfo = pmInt.getActivityInfo(component, PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, callingUid, user.getIdentifier()); + final IncrementalStatesInfo incrementalStatesInfo = pmInt.getIncrementalStatesInfo( + component.getPackageName(), callingUid, user.getIdentifier()); + return new LauncherActivityInfoInternal(activityInfo, incrementalStatesInfo); } finally { Binder.restoreCallingIdentity(ident); } @@ -562,28 +564,46 @@ public class LauncherAppsService extends SystemService { new Intent(Intent.ACTION_CREATE_SHORTCUT).setPackage(packageName), user); } - private ParceledListSlice<ResolveInfo> queryActivitiesForUser(String callingPackage, - Intent intent, UserHandle user) { + private ParceledListSlice<LauncherActivityInfoInternal> queryActivitiesForUser( + String callingPackage, Intent intent, UserHandle user) { if (!canAccessProfile(user.getIdentifier(), "Cannot retrieve activities")) { return null; } - final int callingUid = injectBinderCallingUid(); long ident = injectClearCallingIdentity(); try { - final PackageManagerInternal pmInt = - LocalServices.getService(PackageManagerInternal.class); - List<ResolveInfo> apps = pmInt.queryIntentActivities(intent, - intent.resolveTypeIfNeeded(mContext.getContentResolver()), - PackageManager.MATCH_DIRECT_BOOT_AWARE - | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, - callingUid, user.getIdentifier()); - return new ParceledListSlice<>(apps); + return new ParceledListSlice<>(queryIntentLauncherActivities(intent, callingUid, + user)); } finally { injectRestoreCallingIdentity(ident); } } + private List<LauncherActivityInfoInternal> queryIntentLauncherActivities( + Intent intent, int callingUid, UserHandle user) { + final PackageManagerInternal pmInt = + LocalServices.getService(PackageManagerInternal.class); + List<ResolveInfo> apps = pmInt.queryIntentActivities(intent, + intent.resolveTypeIfNeeded(mContext.getContentResolver()), + PackageManager.MATCH_DIRECT_BOOT_AWARE + | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, + callingUid, user.getIdentifier()); + final int numResolveInfos = apps.size(); + List<LauncherActivityInfoInternal> results = new ArrayList<>(); + for (int i = 0; i < numResolveInfos; i++) { + final ResolveInfo ri = apps.get(i); + final IncrementalStatesInfo incrementalStatesInfo = + pmInt.getIncrementalStatesInfo(ri.resolvePackageName, callingUid, + user.getIdentifier()); + if (incrementalStatesInfo == null) { + continue; + } + results.add(new LauncherActivityInfoInternal(ri.activityInfo, + incrementalStatesInfo)); + } + return results; + } + @Override public IntentSender getShortcutConfigActivityIntent(String callingPackage, ComponentName component, UserHandle user) throws RemoteException { @@ -1238,7 +1258,10 @@ public class LauncherAppsService extends SystemService { } finally { mListeners.finishBroadcast(); } - + PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class); + pmi.registerInstalledLoadingProgressCallback(packageName, + new PackageLoadingProgressCallback(packageName, user), + user.getIdentifier()); super.onPackageAdded(packageName, uid); } @@ -1266,6 +1289,11 @@ public class LauncherAppsService extends SystemService { @Override public void onPackageModified(String packageName) { + onPackageChanged(packageName); + super.onPackageModified(packageName); + } + + private void onPackageChanged(String packageName) { UserHandle user = new UserHandle(getChangingUserId()); final int n = mListeners.beginBroadcast(); try { @@ -1282,8 +1310,6 @@ public class LauncherAppsService extends SystemService { } finally { mListeners.finishBroadcast(); } - - super.onPackageModified(packageName); } @Override @@ -1435,6 +1461,7 @@ public class LauncherAppsService extends SystemService { } catch (RemoteException re) { Slog.d(TAG, "Callback failed ", re); } + } } catch (RuntimeException e) { // When the user is locked we get IllegalState, so just catch all. @@ -1443,6 +1470,12 @@ public class LauncherAppsService extends SystemService { mListeners.finishBroadcast(); } } + + @Override + public void onPackageStateChanged(String packageName, int uid) { + onPackageChanged(packageName); + super.onPackageStateChanged(packageName, uid); + } } class PackageCallbackList<T extends IInterface> extends RemoteCallbackList<T> { @@ -1451,5 +1484,38 @@ public class LauncherAppsService extends SystemService { checkCallbackCount(); } } + + class PackageLoadingProgressCallback extends + PackageManagerInternal.InstalledLoadingProgressCallback { + private String mPackageName; + private UserHandle mUser; + + PackageLoadingProgressCallback(String packageName, UserHandle user) { + super(mCallbackHandler); + mPackageName = packageName; + mUser = user; + } + + @Override + public void onLoadingProgressChanged(float progress) { + final int n = mListeners.beginBroadcast(); + try { + for (int i = 0; i < n; i++) { + IOnAppsChangedListener listener = mListeners.getBroadcastItem(i); + BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i); + if (!isEnabledProfileOf(cookie.user, mUser, "onLoadingProgressChanged")) { + continue; + } + try { + listener.onPackageProgressChanged(mUser, mPackageName, progress); + } catch (RemoteException re) { + Slog.d(TAG, "Callback failed ", re); + } + } + } finally { + mListeners.finishBroadcast(); + } + } + } } } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 805fbbc75a87..d30f866cd79a 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -180,6 +180,7 @@ import android.content.pm.IPackageManager; import android.content.pm.IPackageManagerNative; import android.content.pm.IPackageMoveObserver; import android.content.pm.IPackageStatsObserver; +import android.content.pm.IncrementalStatesInfo; import android.content.pm.InstallSourceInfo; import android.content.pm.InstantAppInfo; import android.content.pm.InstantAppRequest; @@ -17333,7 +17334,7 @@ public class PackageManagerService extends IPackageManager.Stub Bundle extras = new Bundle(); extras.putInt(Intent.EXTRA_UID, mUid); extras.putString(Intent.EXTRA_PACKAGE_NAME, mPackageName); - extras.putInt(Intent.EXTRA_REASON, reason); + extras.putInt(Intent.EXTRA_UNSTARTABLE_REASON, reason); // send broadcast to users with this app installed sendPackageBroadcast(Intent.ACTION_PACKAGE_UNSTARTABLE, mPackageName, extras, 0 /*flags*/, @@ -17756,7 +17757,7 @@ public class PackageManagerService extends IPackageManager.Stub // also includes the "updating the same package" case, of course. // "updating same package" could also involve key-rotation. final boolean sigsOk; - final String sourcePackageName = bp.getSourcePackageName(); + final String sourcePackageName = bp.getPackageName(); final PackageSetting sourcePackageSetting; synchronized (mLock) { sourcePackageSetting = mSettings.getPackageLPr(sourcePackageName); @@ -25658,8 +25659,22 @@ public class PackageManagerService extends IPackageManager.Stub return mIncrementalManager.unregisterCallback(ps.getPathString(), (IPackageLoadingProgressCallback) callback.getBinder()); } + + @Override + public IncrementalStatesInfo getIncrementalStatesInfo( + String packageName, int filterCallingUid, int userId) { + final PackageSetting ps = getPackageSettingForUser(packageName, filterCallingUid, + userId); + if (ps == null) { + Slog.w(TAG, "Failed getting incremental state. Package " + packageName + + " is not available"); + return null; + } + return ps.getIncrementalStates(); + } } + @GuardedBy("mLock") private SparseArray<String> getAppsWithSharedUserIdsLocked() { final SparseArray<String> sharedUserIds = new SparseArray<>(); diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index c356fc72379f..c46a7efaa704 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -24,6 +24,7 @@ import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATIO import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; import android.accounts.IAccountManager; +import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.role.IRoleManager; @@ -2686,9 +2687,18 @@ class PackageManagerShellCommand extends ShellCommand { } } + // pm remove-user [--set-ephemeral-if-in-use] USER_ID public int runRemoveUser() throws RemoteException { int userId; - String arg = getNextArg(); + String arg; + boolean setEphemeralIfInUse = false; + while ((arg = getNextOption()) != null) { + if (arg.equals("--set-ephemeral-if-in-use")) { + setEphemeralIfInUse = true; + } + } + + arg = getNextArg(); if (arg == null) { getErrPrintWriter().println("Error: no user id specified."); return 1; @@ -2696,6 +2706,15 @@ class PackageManagerShellCommand extends ShellCommand { userId = UserHandle.parseUserArg(arg); IUserManager um = IUserManager.Stub.asInterface( ServiceManager.getService(Context.USER_SERVICE)); + if (setEphemeralIfInUse) { + return removeUserOrSetEphemeral(um, userId); + } else { + return removeUser(um, userId); + } + } + + private int removeUser(IUserManager um, @UserIdInt int userId) throws RemoteException { + Slog.i(TAG, "Removing user " + userId); if (um.removeUser(userId)) { getOutPrintWriter().println("Success: removed user"); return 0; @@ -2705,6 +2724,27 @@ class PackageManagerShellCommand extends ShellCommand { } } + private int removeUserOrSetEphemeral(IUserManager um, @UserIdInt int userId) + throws RemoteException { + Slog.i(TAG, "Removing " + userId + " or set as ephemeral if in use."); + int result = um.removeUserOrSetEphemeral(userId); + switch (result) { + case UserManagerService.REMOVE_RESULT_REMOVED: + getOutPrintWriter().printf("Success: user %d removed\n", userId); + return 0; + case UserManagerService.REMOVE_RESULT_SET_EPHEMERAL: + getOutPrintWriter().printf("Success: user %d set as ephemeral\n", userId); + return 0; + case UserManagerService.REMOVE_RESULT_ALREADY_BEING_REMOVED: + getOutPrintWriter().printf("Success: user %d is already being removed\n", userId); + return 0; + default: + getErrPrintWriter().printf("Error: couldn't remove or mark ephemeral user id %d\n", + userId); + return 1; + } + } + public int runSetUserRestriction() throws RemoteException { int userId = UserHandle.USER_SYSTEM; String opt = getNextOption(); @@ -3769,9 +3809,13 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(" --restricted is shorthand for '--user-type android.os.usertype.full.RESTRICTED'."); pw.println(" --guest is shorthand for '--user-type android.os.usertype.full.GUEST'."); pw.println(""); - pw.println(" remove-user USER_ID"); + pw.println(" remove-user [--set-ephemeral-if-in-use] USER_ID"); pw.println(" Remove the user with the given USER_IDENTIFIER, deleting all data"); - pw.println(" associated with that user"); + pw.println(" associated with that user."); + pw.println(" --set-ephemeral-if-in-use: If the user is currently running and"); + pw.println(" therefore cannot be removed immediately, mark the user as ephemeral"); + pw.println(" so that it will be automatically removed when possible (after user"); + pw.println(" switch or reboot)"); pw.println(""); pw.println(" set-user-restriction [--user USER_ID] RESTRICTION VALUE"); pw.println(""); diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 3ec156f6a3a1..766b30f1dc21 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -22,6 +22,7 @@ import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import android.Manifest; import android.annotation.ColorRes; import android.annotation.DrawableRes; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.StringRes; @@ -110,7 +111,6 @@ import com.android.internal.widget.LockPatternUtils; import com.android.server.LocalServices; import com.android.server.LockGuard; import com.android.server.SystemService; -import com.android.server.SystemService.TargetUser; import com.android.server.am.UserState; import com.android.server.storage.DeviceStorageMonitorInternal; import com.android.server.utils.TimingsTraceAndSlog; @@ -132,6 +132,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; @@ -246,6 +248,43 @@ public class UserManagerService extends IUserManager.Stub { static final int WRITE_USER_MSG = 1; static final int WRITE_USER_DELAY = 2*1000; // 2 seconds + /** + * A response code from {@link #removeUserOrSetEphemeral(int)} indicating that the specified + * user has been successfully removed. + */ + public static final int REMOVE_RESULT_REMOVED = 0; + + /** + * A response code from {@link #removeUserOrSetEphemeral(int)} indicating that the specified + * user has had its {@link UserInfo#FLAG_EPHEMERAL} flag set to {@code true}, so that it will be + * removed when the user is stopped or on boot. + */ + public static final int REMOVE_RESULT_SET_EPHEMERAL = 1; + + /** + * A response code from {@link #removeUserOrSetEphemeral(int)} indicating that the specified + * user is already in the process of being removed. + */ + public static final int REMOVE_RESULT_ALREADY_BEING_REMOVED = 2; + + /** + * A response code from {@link #removeUserOrSetEphemeral(int)} indicating that an error occurred + * that prevented the user from being removed or set as ephemeral. + */ + public static final int REMOVE_RESULT_ERROR = 3; + + /** + * Possible response codes from {@link #removeUserOrSetEphemeral(int)}. + */ + @IntDef(prefix = { "REMOVE_RESULT_" }, value = { + REMOVE_RESULT_REMOVED, + REMOVE_RESULT_SET_EPHEMERAL, + REMOVE_RESULT_ALREADY_BEING_REMOVED, + REMOVE_RESULT_ERROR, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface RemoveResult {} + // Tron counters private static final String TRON_GUEST_CREATED = "users_guest_created"; private static final String TRON_USER_CREATED = "users_user_created"; @@ -253,9 +292,17 @@ public class UserManagerService extends IUserManager.Stub { private final Context mContext; private final PackageManagerService mPm; + + /** + * Lock for packages. If using with {@link #mUsersLock}, {@link #mPackagesLock} should be + * acquired first. + */ private final Object mPackagesLock; private final UserDataPreparer mUserDataPreparer; - // Short-term lock for internal state, when interaction/sync with PM is not required + /** + * Short-term lock for internal state, when interaction/sync with PM is not required. If using + * with {@link #mPackagesLock}, {@link #mPackagesLock} should be acquired first. + */ private final Object mUsersLock = LockGuard.installNewLock(LockGuard.INDEX_USER); private final Object mRestrictionsLock = new Object(); // Used for serializing access to app restriction files @@ -3862,13 +3909,7 @@ public class UserManagerService extends IUserManager.Stub { Slog.i(LOG_TAG, "removeUser u" + userId); checkManageOrCreateUsersPermission("Only the system can remove users"); - final boolean isManagedProfile; - synchronized (mUsersLock) { - UserInfo userInfo = getUserInfoLU(userId); - isManagedProfile = userInfo != null && userInfo.isManagedProfile(); - } - String restriction = isManagedProfile - ? UserManager.DISALLOW_REMOVE_MANAGED_PROFILE : UserManager.DISALLOW_REMOVE_USER; + final String restriction = getUserRemovalRestriction(userId); if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean(restriction, false)) { Slog.w(LOG_TAG, "Cannot remove user. " + restriction + " is enabled."); return false; @@ -3882,6 +3923,21 @@ public class UserManagerService extends IUserManager.Stub { return removeUserUnchecked(userId); } + /** + * Returns the string name of the restriction to check for user removal. The restriction name + * varies depending on whether the user is a managed profile. + */ + private String getUserRemovalRestriction(@UserIdInt int userId) { + final boolean isManagedProfile; + final UserInfo userInfo; + synchronized (mUsersLock) { + userInfo = getUserInfoLU(userId); + } + isManagedProfile = userInfo != null && userInfo.isManagedProfile(); + return isManagedProfile + ? UserManager.DISALLOW_REMOVE_MANAGED_PROFILE : UserManager.DISALLOW_REMOVE_USER; + } + private boolean removeUserUnchecked(@UserIdInt int userId) { final long ident = Binder.clearCallingIdentity(); try { @@ -3974,6 +4030,64 @@ public class UserManagerService extends IUserManager.Stub { } } + @Override + public @RemoveResult int removeUserOrSetEphemeral(@UserIdInt int userId) { + Slog.i(LOG_TAG, "removeUserOrSetEphemeral u" + userId); + checkManageUsersPermission("Only the system can remove users"); + final String restriction = getUserRemovalRestriction(userId); + if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean(restriction, false)) { + Slog.w(LOG_TAG, "Cannot remove user. " + restriction + " is enabled."); + return REMOVE_RESULT_ERROR; + } + if (userId == UserHandle.USER_SYSTEM) { + Slog.e(LOG_TAG, "System user cannot be removed."); + return REMOVE_RESULT_ERROR; + } + + final long ident = Binder.clearCallingIdentity(); + try { + final UserData userData; + synchronized (mPackagesLock) { + synchronized (mUsersLock) { + userData = mUsers.get(userId); + if (userData == null) { + Slog.e(LOG_TAG, + "Cannot remove user " + userId + ", invalid user id provided."); + return REMOVE_RESULT_ERROR; + } + + if (mRemovingUserIds.get(userId)) { + Slog.e(LOG_TAG, "User " + userId + " is already scheduled for removal."); + return REMOVE_RESULT_ALREADY_BEING_REMOVED; + } + } + + // Attempt to immediately remove a non-current user + final int currentUser = ActivityManager.getCurrentUser(); + if (currentUser != userId) { + // Attempt to remove the user. This will fail if the user is the current user + if (removeUser(userId)) { + return REMOVE_RESULT_REMOVED; + } + + Slog.w(LOG_TAG, "Unable to immediately remove non-current user: " + userId + + ". User is still set as ephemeral and will be removed on user " + + "switch or reboot."); + } + + // If the user was not immediately removed, make sure it is marked as ephemeral. + // Don't mark as disabled since, per UserInfo.FLAG_DISABLED documentation, an + // ephemeral user should only be marked as disabled when its removal is in progress. + userData.info.flags |= UserInfo.FLAG_EPHEMERAL; + writeUserLP(userData); + + return REMOVE_RESULT_SET_EPHEMERAL; + } + } finally { + Binder.restoreCallingIdentity(ident); + } + } + void finishRemoveUser(final @UserIdInt int userId) { if (DBG) Slog.i(LOG_TAG, "finishRemoveUser " + userId); diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java index c08601740158..bebb67686696 100644 --- a/services/core/java/com/android/server/pm/permission/BasePermission.java +++ b/services/core/java/com/android/server/pm/permission/BasePermission.java @@ -29,17 +29,17 @@ import static com.android.server.pm.Settings.TAG_ITEM; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.PermissionInfo; import android.content.pm.parsing.component.ParsedPermission; +import android.os.Build; import android.os.UserHandle; import android.util.Log; import android.util.Slog; import com.android.server.pm.DumpState; import com.android.server.pm.PackageManagerService; -import com.android.server.pm.PackageSettingBase; -import com.android.server.pm.parsing.PackageInfoUtils; import com.android.server.pm.parsing.pkg.AndroidPackage; import libcore.util.EmptyArray; @@ -80,269 +80,282 @@ public final class BasePermission { @Retention(RetentionPolicy.SOURCE) public @interface ProtectionLevel {} - final String name; + @NonNull + private final String mName; - final @PermissionType int type; + private final @PermissionType int mType; - String sourcePackageName; + private String mPackageName; - int protectionLevel; + private int mProtectionLevel; - ParsedPermission perm; + @Nullable + private PermissionInfo mPermissionInfo; - PermissionInfo pendingPermissionInfo; + @Nullable + private PermissionInfo mPendingPermissionInfo; /** UID that owns the definition of this permission */ - int uid; + private int mUid; /** Additional GIDs given to apps granted this permission */ @NonNull - private int[] gids = EmptyArray.INT; + private int[] mGids = EmptyArray.INT; /** - * Flag indicating that {@link #gids} should be adjusted based on the + * Flag indicating that {@link #mGids} should be adjusted based on the * {@link UserHandle} the granted app is running as. */ - private boolean perUser; + private boolean mGidsPerUser; - public BasePermission(String _name, String _sourcePackageName, @PermissionType int _type) { - name = _name; - sourcePackageName = _sourcePackageName; - type = _type; + public BasePermission(@NonNull String name, String packageName, @PermissionType int type) { + mName = name; + mPackageName = packageName; + mType = type; // Default to most conservative protection level. - protectionLevel = PermissionInfo.PROTECTION_SIGNATURE; + mProtectionLevel = PermissionInfo.PROTECTION_SIGNATURE; } @Override public String toString() { - return "BasePermission{" + Integer.toHexString(System.identityHashCode(this)) + " " + name + return "BasePermission{" + Integer.toHexString(System.identityHashCode(this)) + " " + mName + "}"; } + @NonNull public String getName() { - return name; + return mName; } + public int getProtectionLevel() { - return protectionLevel; + return mProtectionLevel; } - public String getSourcePackageName() { - return sourcePackageName; + + public String getPackageName() { + return mPackageName; } + public int getType() { - return type; + return mType; } + public int getUid() { - return uid; + return mUid; } - public void setGids(@NonNull int[] gids, boolean perUser) { - this.gids = gids; - this.perUser = perUser; + + public void setGids(@NonNull int[] gids, boolean gidsPerUser) { + mGids = gids; + mGidsPerUser = gidsPerUser; } - public void setPermission(@Nullable ParsedPermission perm) { - this.perm = perm; + + public void setPermissionInfo(@Nullable PermissionInfo permissionInfo) { + mPermissionInfo = permissionInfo; } public boolean hasGids() { - return gids.length != 0; + return mGids.length != 0; } @NonNull public int[] computeGids(int userId) { - if (perUser) { - final int[] userGids = new int[gids.length]; - for (int i = 0; i < gids.length; i++) { - final int gid = gids[i]; + if (mGidsPerUser) { + final int[] userGids = new int[mGids.length]; + for (int i = 0; i < mGids.length; i++) { + final int gid = mGids[i]; userGids[i] = UserHandle.getUid(userId, gid); } return userGids; } else { - return gids.length != 0 ? gids.clone() : gids; + return mGids.length != 0 ? mGids.clone() : mGids; } } public int calculateFootprint(BasePermission perm) { - if (uid == perm.uid) { - return perm.name.length() + perm.perm.calculateFootprint(); + if (mUid == perm.mUid) { + return perm.mName.length() + perm.mPermissionInfo.calculateFootprint(); } return 0; } public boolean isPermission(ParsedPermission perm) { - if (this.perm == null) { + if (mPermissionInfo == null) { return false; } - return Objects.equals(this.perm.getPackageName(), perm.getPackageName()) - && Objects.equals(this.perm.getName(), perm.getName()); + return Objects.equals(mPermissionInfo.packageName, perm.getPackageName()) + && Objects.equals(mPermissionInfo.name, perm.getName()); } public boolean isDynamic() { - return type == TYPE_DYNAMIC; + return mType == TYPE_DYNAMIC; } - public boolean isNormal() { - return (protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) + return (mProtectionLevel & PermissionInfo.PROTECTION_MASK_BASE) == PermissionInfo.PROTECTION_NORMAL; } public boolean isRuntime() { - return (protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) + return (mProtectionLevel & PermissionInfo.PROTECTION_MASK_BASE) == PermissionInfo.PROTECTION_DANGEROUS; } public boolean isRemoved() { - return perm != null && (perm.getFlags() & PermissionInfo.FLAG_REMOVED) != 0; + return mPermissionInfo != null + && (mPermissionInfo.flags & PermissionInfo.FLAG_REMOVED) != 0; } public boolean isSoftRestricted() { - return perm != null && (perm.getFlags() & PermissionInfo.FLAG_SOFT_RESTRICTED) != 0; + return mPermissionInfo != null + && (mPermissionInfo.flags & PermissionInfo.FLAG_SOFT_RESTRICTED) != 0; } public boolean isHardRestricted() { - return perm != null && (perm.getFlags() & PermissionInfo.FLAG_HARD_RESTRICTED) != 0; + return mPermissionInfo != null + && (mPermissionInfo.flags & PermissionInfo.FLAG_HARD_RESTRICTED) != 0; } public boolean isHardOrSoftRestricted() { - return perm != null && (perm.getFlags() & (PermissionInfo.FLAG_HARD_RESTRICTED - | PermissionInfo.FLAG_SOFT_RESTRICTED)) != 0; + return mPermissionInfo != null && (mPermissionInfo.flags + & (PermissionInfo.FLAG_HARD_RESTRICTED | PermissionInfo.FLAG_SOFT_RESTRICTED)) != 0; } public boolean isImmutablyRestricted() { - return perm != null && (perm.getFlags() & PermissionInfo.FLAG_IMMUTABLY_RESTRICTED) != 0; + return mPermissionInfo != null + && (mPermissionInfo.flags & PermissionInfo.FLAG_IMMUTABLY_RESTRICTED) != 0; } public boolean isInstallerExemptIgnored() { - return perm != null - && (perm.getFlags() & PermissionInfo.FLAG_INSTALLER_EXEMPT_IGNORED) != 0; + return mPermissionInfo != null + && (mPermissionInfo.flags & PermissionInfo.FLAG_INSTALLER_EXEMPT_IGNORED) != 0; } public boolean isSignature() { - return (protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) == - PermissionInfo.PROTECTION_SIGNATURE; + return (mProtectionLevel & PermissionInfo.PROTECTION_MASK_BASE) + == PermissionInfo.PROTECTION_SIGNATURE; } public boolean isAppOp() { - return (protectionLevel & PermissionInfo.PROTECTION_FLAG_APPOP) != 0; + return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_APPOP) != 0; } public boolean isDevelopment() { return isSignature() - && (protectionLevel & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0; + && (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0; } public boolean isInstaller() { - return (protectionLevel & PermissionInfo.PROTECTION_FLAG_INSTALLER) != 0; + return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_INSTALLER) != 0; } public boolean isInstant() { - return (protectionLevel & PermissionInfo.PROTECTION_FLAG_INSTANT) != 0; + return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_INSTANT) != 0; } public boolean isOEM() { - return (protectionLevel & PermissionInfo.PROTECTION_FLAG_OEM) != 0; + return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_OEM) != 0; } public boolean isPre23() { - return (protectionLevel & PermissionInfo.PROTECTION_FLAG_PRE23) != 0; + return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_PRE23) != 0; } public boolean isPreInstalled() { - return (protectionLevel & PermissionInfo.PROTECTION_FLAG_PREINSTALLED) != 0; + return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_PREINSTALLED) != 0; } public boolean isPrivileged() { - return (protectionLevel & PermissionInfo.PROTECTION_FLAG_PRIVILEGED) != 0; + return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_PRIVILEGED) != 0; } public boolean isRuntimeOnly() { - return (protectionLevel & PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) != 0; + return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) != 0; } public boolean isSetup() { - return (protectionLevel & PermissionInfo.PROTECTION_FLAG_SETUP) != 0; + return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_SETUP) != 0; } public boolean isVerifier() { - return (protectionLevel & PermissionInfo.PROTECTION_FLAG_VERIFIER) != 0; + return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_VERIFIER) != 0; } public boolean isVendorPrivileged() { - return (protectionLevel & PermissionInfo.PROTECTION_FLAG_VENDOR_PRIVILEGED) != 0; + return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_VENDOR_PRIVILEGED) != 0; } public boolean isSystemTextClassifier() { - return (protectionLevel & PermissionInfo.PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER) + return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER) != 0; } public boolean isWellbeing() { - return (protectionLevel & PermissionInfo.PROTECTION_FLAG_WELLBEING) != 0; + return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_WELLBEING) != 0; } public boolean isDocumenter() { - return (protectionLevel & PermissionInfo.PROTECTION_FLAG_DOCUMENTER) != 0; + return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_DOCUMENTER) != 0; } public boolean isConfigurator() { - return (protectionLevel & PermissionInfo.PROTECTION_FLAG_CONFIGURATOR) + return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_CONFIGURATOR) != 0; } public boolean isIncidentReportApprover() { - return (protectionLevel & PermissionInfo.PROTECTION_FLAG_INCIDENT_REPORT_APPROVER) != 0; + return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_INCIDENT_REPORT_APPROVER) != 0; } public boolean isAppPredictor() { - return (protectionLevel & PermissionInfo.PROTECTION_FLAG_APP_PREDICTOR) != 0; + return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_APP_PREDICTOR) != 0; } public boolean isCompanion() { - return (protectionLevel & PermissionInfo.PROTECTION_FLAG_COMPANION) != 0; + return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_COMPANION) != 0; } public boolean isRetailDemo() { - return (protectionLevel & PermissionInfo.PROTECTION_FLAG_RETAIL_DEMO) != 0; + return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_RETAIL_DEMO) != 0; } public void transfer(@NonNull String origPackageName, @NonNull String newPackageName) { - if (!origPackageName.equals(sourcePackageName)) { + if (!origPackageName.equals(mPackageName)) { return; } - sourcePackageName = newPackageName; - perm = null; - if (pendingPermissionInfo != null) { - pendingPermissionInfo.packageName = newPackageName; + mPackageName = newPackageName; + mPermissionInfo = null; + if (mPendingPermissionInfo != null) { + mPendingPermissionInfo.packageName = newPackageName; } - uid = 0; - gids = EmptyArray.INT; - perUser = false; + mUid = 0; + mGids = EmptyArray.INT; + mGidsPerUser = false; } public boolean addToTree(@ProtectionLevel int protectionLevel, - @NonNull PermissionInfo info, @NonNull BasePermission tree) { + @NonNull PermissionInfo permissionInfo, @NonNull BasePermission tree) { final boolean changed = - (this.protectionLevel != protectionLevel - || perm == null - || uid != tree.uid - || !Objects.equals(perm.getPackageName(), tree.perm.getPackageName()) - || !comparePermissionInfos(perm, info)); - this.protectionLevel = protectionLevel; - info = new PermissionInfo(info); - info.protectionLevel = protectionLevel; - perm = new ParsedPermission(tree.perm); - uid = tree.uid; + (mProtectionLevel != protectionLevel + || mPermissionInfo == null + || mUid != tree.mUid + || !Objects.equals(mPermissionInfo.packageName, + tree.mPermissionInfo.packageName) + || !comparePermissionInfos(mPermissionInfo, permissionInfo)); + mProtectionLevel = protectionLevel; + mPermissionInfo = new PermissionInfo(permissionInfo); + mPermissionInfo.protectionLevel = protectionLevel; + mPermissionInfo.packageName = tree.mPermissionInfo.packageName; + mUid = tree.mUid; return changed; } public void updateDynamicPermission(Collection<BasePermission> permissionTrees) { if (PackageManagerService.DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name=" - + getName() + " pkg=" + getSourcePackageName() - + " info=" + pendingPermissionInfo); - if (pendingPermissionInfo != null) { - final BasePermission tree = findPermissionTree(permissionTrees, name); - if (tree != null && tree.perm != null) { - perm = new ParsedPermission(tree.perm, pendingPermissionInfo, - tree.perm.getPackageName(), name); - uid = tree.uid; + + getName() + " pkg=" + getPackageName() + + " info=" + mPendingPermissionInfo); + if (mPendingPermissionInfo != null) { + final BasePermission tree = findPermissionTree(permissionTrees, mName); + if (tree != null && tree.mPermissionInfo != null) { + mPermissionInfo = new PermissionInfo(mPendingPermissionInfo); + mPermissionInfo.packageName = tree.mPermissionInfo.packageName; + mPermissionInfo.name = mName; + mUid = tree.mUid; } } } static BasePermission createOrUpdate(PackageManagerInternal packageManagerInternal, - @Nullable BasePermission bp, @NonNull ParsedPermission p, + @Nullable BasePermission bp, @NonNull PermissionInfo p, @NonNull AndroidPackage pkg, Collection<BasePermission> permissionTrees, boolean chatty) { - final PackageSettingBase pkgSetting = - (PackageSettingBase) packageManagerInternal.getPackageSetting(pkg.getPackageName()); // Allow system apps to redefine non-system permissions - if (bp != null && !Objects.equals(bp.sourcePackageName, p.getPackageName())) { + if (bp != null && !Objects.equals(bp.mPackageName, p.packageName)) { final boolean currentOwnerIsSystem; - if (bp.perm == null) { + if (bp.mPermissionInfo == null) { currentOwnerIsSystem = false; } else { AndroidPackage currentPackage = packageManagerInternal.getPackage( - bp.perm.getPackageName()); + bp.mPermissionInfo.packageName); if (currentPackage == null) { currentOwnerIsSystem = false; } else { @@ -351,52 +364,52 @@ public final class BasePermission { } if (pkg.isSystem()) { - if (bp.type == BasePermission.TYPE_BUILTIN && bp.perm == null) { + if (bp.mType == BasePermission.TYPE_BUILTIN && bp.mPermissionInfo == null) { // It's a built-in permission and no owner, take ownership now - p.setFlags(p.getFlags() | PermissionInfo.FLAG_INSTALLED); - bp.perm = p; - bp.uid = pkg.getUid(); - bp.sourcePackageName = p.getPackageName(); + p.flags |= PermissionInfo.FLAG_INSTALLED; + bp.mPermissionInfo = p; + bp.mUid = pkg.getUid(); + bp.mPackageName = p.packageName; } else if (!currentOwnerIsSystem) { String msg = "New decl " + pkg + " of permission " - + p.getName() + " is system; overriding " + bp.sourcePackageName; + + p.name + " is system; overriding " + bp.mPackageName; PackageManagerService.reportSettingsProblem(Log.WARN, msg); bp = null; } } } if (bp == null) { - bp = new BasePermission(p.getName(), p.getPackageName(), TYPE_NORMAL); + bp = new BasePermission(p.name, p.packageName, TYPE_NORMAL); } StringBuilder r = null; - if (bp.perm == null) { - if (bp.sourcePackageName == null - || bp.sourcePackageName.equals(p.getPackageName())) { - final BasePermission tree = findPermissionTree(permissionTrees, p.getName()); + if (bp.mPermissionInfo == null) { + if (bp.mPackageName == null + || bp.mPackageName.equals(p.packageName)) { + final BasePermission tree = findPermissionTree(permissionTrees, p.name); if (tree == null - || tree.sourcePackageName.equals(p.getPackageName())) { - p.setFlags(p.getFlags() | PermissionInfo.FLAG_INSTALLED); - bp.perm = p; - bp.uid = pkg.getUid(); - bp.sourcePackageName = p.getPackageName(); + || tree.mPackageName.equals(p.packageName)) { + p.flags |= PermissionInfo.FLAG_INSTALLED; + bp.mPermissionInfo = p; + bp.mUid = pkg.getUid(); + bp.mPackageName = p.packageName; if (chatty) { if (r == null) { r = new StringBuilder(256); } else { r.append(' '); } - r.append(p.getName()); + r.append(p.name); } } else { - Slog.w(TAG, "Permission " + p.getName() + " from package " - + p.getPackageName() + " ignored: base tree " - + tree.name + " is from package " - + tree.sourcePackageName); + Slog.w(TAG, "Permission " + p.name + " from package " + + p.packageName + " ignored: base tree " + + tree.mName + " is from package " + + tree.mPackageName); } } else { - Slog.w(TAG, "Permission " + p.getName() + " from package " - + p.getPackageName() + " ignored: original from " - + bp.sourcePackageName); + Slog.w(TAG, "Permission " + p.name + " from package " + + p.packageName + " ignored: original from " + + bp.mPackageName); } } else if (chatty) { if (r == null) { @@ -405,11 +418,10 @@ public final class BasePermission { r.append(' '); } r.append("DUP:"); - r.append(p.getName()); + r.append(p.name); } - if (bp.perm != null && Objects.equals(bp.perm.getPackageName(), p.getPackageName()) - && Objects.equals(bp.perm.getName(), p.getName())) { - bp.protectionLevel = p.getProtectionLevel(); + if (bp.mPermissionInfo == p) { + bp.mProtectionLevel = p.protectionLevel; } if (PackageManagerService.DEBUG_PACKAGE_SCANNING && r != null) { Log.d(TAG, " Permissions: " + r); @@ -422,12 +434,12 @@ public final class BasePermission { if (permName != null) { BasePermission bp = findPermissionTree(permissionTrees, permName); if (bp != null) { - if (bp.uid == UserHandle.getAppId(callingUid)) { + if (bp.mUid == UserHandle.getAppId(callingUid)) { return bp; } throw new SecurityException("Calling uid " + callingUid + " is not allowed to add to permission tree " - + bp.name + " owned by uid " + bp.uid); + + bp.mName + " owned by uid " + bp.mUid); } } throw new SecurityException("No permission tree found for " + permName); @@ -436,45 +448,63 @@ public final class BasePermission { private static BasePermission findPermissionTree( Collection<BasePermission> permissionTrees, String permName) { for (BasePermission bp : permissionTrees) { - if (permName.startsWith(bp.name) && - permName.length() > bp.name.length() && - permName.charAt(bp.name.length()) == '.') { + if (permName.startsWith(bp.mName) + && permName.length() > bp.mName.length() + && permName.charAt(bp.mName.length()) == '.') { return bp; } } return null; } - public @Nullable PermissionInfo generatePermissionInfo(@NonNull String groupName, int flags) { - if (groupName == null) { - if (perm == null || perm.getGroup() == null) { - return generatePermissionInfo(protectionLevel, flags); - } - } else { - if (perm != null && groupName.equals(perm.getGroup())) { - return PackageInfoUtils.generatePermissionInfo(perm, flags); - } - } - return null; + @Nullable + public String getBackgroundPermission() { + return mPermissionInfo != null ? mPermissionInfo.backgroundPermission : null; + } + + @Nullable + public String getGroup() { + return mPermissionInfo != null ? mPermissionInfo.group : null; + } + + public int getProtection() { + return mProtectionLevel & PermissionInfo.PROTECTION_MASK_BASE; } - public @NonNull PermissionInfo generatePermissionInfo(int adjustedProtectionLevel, int flags) { + public int getProtectionFlags() { + return mProtectionLevel & PermissionInfo.PROTECTION_MASK_FLAGS; + } + + @NonNull + public PermissionInfo generatePermissionInfo(int flags) { + return generatePermissionInfo(flags, Build.VERSION_CODES.CUR_DEVELOPMENT); + } + + @NonNull + public PermissionInfo generatePermissionInfo(int flags, int targetSdkVersion) { PermissionInfo permissionInfo; - if (perm != null) { - final boolean protectionLevelChanged = protectionLevel != adjustedProtectionLevel; - permissionInfo = PackageInfoUtils.generatePermissionInfo(perm, flags); - if (protectionLevelChanged) { - // if we return different protection level, don't use the cached info - permissionInfo = new PermissionInfo(permissionInfo); - permissionInfo.protectionLevel = adjustedProtectionLevel; + if (mPermissionInfo != null) { + permissionInfo = new PermissionInfo(mPermissionInfo); + if ((flags & PackageManager.GET_META_DATA) != PackageManager.GET_META_DATA) { + permissionInfo.metaData = null; + } + } else { + permissionInfo = new PermissionInfo(); + permissionInfo.name = mName; + permissionInfo.packageName = mPackageName; + permissionInfo.nonLocalizedLabel = mName; + } + if (targetSdkVersion >= Build.VERSION_CODES.O) { + permissionInfo.protectionLevel = mProtectionLevel; + } else { + final int protection = mProtectionLevel & PermissionInfo.PROTECTION_MASK_BASE; + if (protection == PermissionInfo.PROTECTION_SIGNATURE) { + // Signature permission's protection flags are always reported. + permissionInfo.protectionLevel = mProtectionLevel; + } else { + permissionInfo.protectionLevel = protection; } - return permissionInfo; } - permissionInfo = new PermissionInfo(); - permissionInfo.name = name; - permissionInfo.packageName = sourcePackageName; - permissionInfo.nonLocalizedLabel = name; - permissionInfo.protectionLevel = protectionLevel; return permissionInfo; } @@ -496,23 +526,23 @@ public final class BasePermission { final boolean dynamic = "dynamic".equals(ptype); BasePermission bp = out.get(name); // If the permission is builtin, do not clobber it. - if (bp == null || bp.type != TYPE_BUILTIN) { + if (bp == null || bp.mType != TYPE_BUILTIN) { bp = new BasePermission(name.intern(), sourcePackage, dynamic ? TYPE_DYNAMIC : TYPE_NORMAL); } - bp.protectionLevel = readInt(parser, null, "protection", + bp.mProtectionLevel = readInt(parser, null, "protection", PermissionInfo.PROTECTION_NORMAL); - bp.protectionLevel = PermissionInfo.fixProtectionLevel(bp.protectionLevel); + bp.mProtectionLevel = PermissionInfo.fixProtectionLevel(bp.mProtectionLevel); if (dynamic) { final PermissionInfo pi = new PermissionInfo(); pi.packageName = sourcePackage.intern(); pi.name = name.intern(); pi.icon = readInt(parser, null, "icon", 0); pi.nonLocalizedLabel = parser.getAttributeValue(null, "label"); - pi.protectionLevel = bp.protectionLevel; - bp.pendingPermissionInfo = pi; + pi.protectionLevel = bp.mProtectionLevel; + bp.mPendingPermissionInfo = pi; } - out.put(bp.name, bp); + out.put(bp.mName, bp); return true; } @@ -533,22 +563,23 @@ public final class BasePermission { } public void writeLPr(@NonNull XmlSerializer serializer) throws IOException { - if (sourcePackageName == null) { + if (mPackageName == null) { return; } serializer.startTag(null, TAG_ITEM); - serializer.attribute(null, ATTR_NAME, name); - serializer.attribute(null, ATTR_PACKAGE, sourcePackageName); - if (protectionLevel != PermissionInfo.PROTECTION_NORMAL) { - serializer.attribute(null, "protection", Integer.toString(protectionLevel)); + serializer.attribute(null, ATTR_NAME, mName); + serializer.attribute(null, ATTR_PACKAGE, mPackageName); + if (mProtectionLevel != PermissionInfo.PROTECTION_NORMAL) { + serializer.attribute(null, "protection", Integer.toString(mProtectionLevel)); } - if (type == BasePermission.TYPE_DYNAMIC) { - if (perm != null || pendingPermissionInfo != null) { + if (mType == BasePermission.TYPE_DYNAMIC) { + if (mPermissionInfo != null || mPendingPermissionInfo != null) { serializer.attribute(null, "type", "dynamic"); - int icon = perm != null ? perm.getIcon() : pendingPermissionInfo.icon; - CharSequence nonLocalizedLabel = perm != null - ? perm.getNonLocalizedLabel() - : pendingPermissionInfo.nonLocalizedLabel; + int icon = mPermissionInfo != null ? mPermissionInfo.icon + : mPendingPermissionInfo.icon; + CharSequence nonLocalizedLabel = mPermissionInfo != null + ? mPermissionInfo.nonLocalizedLabel + : mPendingPermissionInfo.nonLocalizedLabel; if (icon != 0) { serializer.attribute(null, "icon", Integer.toString(icon)); @@ -561,27 +592,14 @@ public final class BasePermission { serializer.endTag(null, TAG_ITEM); } - private static boolean compareStrings(CharSequence s1, CharSequence s2) { - if (s1 == null) { - return s2 == null; - } - if (s2 == null) { - return false; - } - if (s1.getClass() != s2.getClass()) { - return false; - } - return s1.equals(s2); - } - - private static boolean comparePermissionInfos(ParsedPermission pi1, PermissionInfo pi2) { - if (pi1.getIcon() != pi2.icon) return false; - if (pi1.getLogo() != pi2.logo) return false; - if (pi1.getProtectionLevel() != pi2.protectionLevel) return false; - if (!compareStrings(pi1.getName(), pi2.name)) return false; - if (!compareStrings(pi1.getNonLocalizedLabel(), pi2.nonLocalizedLabel)) return false; + private static boolean comparePermissionInfos(PermissionInfo pi1, PermissionInfo pi2) { + if (pi1.icon != pi2.icon) return false; + if (pi1.logo != pi2.logo) return false; + if (pi1.protectionLevel != pi2.protectionLevel) return false; + if (!Objects.equals(pi1.name, pi2.name)) return false; + if (!Objects.equals(pi1.nonLocalizedLabel, pi2.nonLocalizedLabel)) return false; // We'll take care of setting this one. - if (!compareStrings(pi1.getPackageName(), pi2.packageName)) return false; + if (!Objects.equals(pi1.packageName, pi2.packageName)) return false; // These are not currently stored in settings. //if (!compareStrings(pi1.group, pi2.group)) return false; //if (!compareStrings(pi1.nonLocalizedDescription, pi2.nonLocalizedDescription)) return false; @@ -593,36 +611,34 @@ public final class BasePermission { public boolean dumpPermissionsLPr(@NonNull PrintWriter pw, @NonNull String packageName, @NonNull Set<String> permissionNames, boolean readEnforced, boolean printedSomething, @NonNull DumpState dumpState) { - if (packageName != null && !packageName.equals(sourcePackageName)) { + if (packageName != null && !packageName.equals(mPackageName)) { return false; } - if (permissionNames != null && !permissionNames.contains(name)) { + if (permissionNames != null && !permissionNames.contains(mName)) { return false; } if (!printedSomething) { if (dumpState.onTitlePrinted()) pw.println(); pw.println("Permissions:"); - printedSomething = true; } - pw.print(" Permission ["); pw.print(name); pw.print("] ("); + pw.print(" Permission ["); pw.print(mName); pw.print("] ("); pw.print(Integer.toHexString(System.identityHashCode(this))); pw.println("):"); - pw.print(" sourcePackage="); pw.println(sourcePackageName); - pw.print(" uid="); pw.print(uid); - pw.print(" gids="); pw.print(Arrays.toString( - computeGids(UserHandle.USER_SYSTEM))); - pw.print(" type="); pw.print(type); - pw.print(" prot="); - pw.println(PermissionInfo.protectionToString(protectionLevel)); - if (perm != null) { - pw.print(" perm="); pw.println(perm); - if ((perm.getFlags() & PermissionInfo.FLAG_INSTALLED) == 0 - || (perm.getFlags() & PermissionInfo.FLAG_REMOVED) != 0) { - pw.print(" flags=0x"); pw.println(Integer.toHexString(perm.getFlags())); + pw.print(" sourcePackage="); pw.println(mPackageName); + pw.print(" uid="); pw.print(mUid); + pw.print(" gids="); pw.print(Arrays.toString(computeGids(UserHandle.USER_SYSTEM))); + pw.print(" type="); pw.print(mType); + pw.print(" prot="); + pw.println(PermissionInfo.protectionToString(mProtectionLevel)); + if (mPermissionInfo != null) { + pw.print(" perm="); pw.println(mPermissionInfo); + if ((mPermissionInfo.flags & PermissionInfo.FLAG_INSTALLED) == 0 + || (mPermissionInfo.flags & PermissionInfo.FLAG_REMOVED) != 0) { + pw.print(" flags=0x"); pw.println(Integer.toHexString(mPermissionInfo.flags)); } } - if (READ_EXTERNAL_STORAGE.equals(name)) { + if (READ_EXTERNAL_STORAGE.equals(mName)) { pw.print(" enforced="); pw.println(readEnforced); } diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 25e1848816d1..19a56505416d 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -378,8 +378,9 @@ public class PermissionManagerService extends IPermissionManager.Stub { @NonNull Injector injector) { mInjector = injector; // The package info cache is the cache for package and permission information. + // Disable the package info and package permission caches locally but leave the + // checkPermission cache active. mInjector.invalidatePackageInfoCache(); - mInjector.disablePermissionCache(); mInjector.disablePackageNamePermissionCache(); mContext = context; @@ -544,24 +545,37 @@ public class PermissionManagerService extends IPermissionManager.Stub { @Override @Nullable - public PermissionInfo getPermissionInfo(String permName, String packageName, + public PermissionInfo getPermissionInfo(@NonNull String permName, @NonNull String opPackageName, @PermissionInfoFlags int flags) { final int callingUid = getCallingUid(); if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) { return null; } - final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName); + final AndroidPackage opPackage = mPackageManagerInt.getPackage(opPackageName); + final int targetSdkVersion = getPermissionInfoCallingTargetSdkVersion(opPackage, + callingUid); synchronized (mLock) { final BasePermission bp = mSettings.getPermissionLocked(permName); if (bp == null) { return null; } - final int adjustedProtectionLevel = adjustPermissionProtectionFlagsLocked( - bp.getProtectionLevel(), pkg, callingUid); - return bp.generatePermissionInfo(adjustedProtectionLevel, flags); + return bp.generatePermissionInfo(flags, targetSdkVersion); } } + private int getPermissionInfoCallingTargetSdkVersion(@Nullable AndroidPackage pkg, int uid) { + final int appId = UserHandle.getAppId(uid); + if (appId == Process.ROOT_UID || appId == Process.SYSTEM_UID + || appId == Process.SHELL_UID) { + // System sees all flags. + return Build.VERSION_CODES.CUR_DEVELOPMENT; + } + if (pkg == null) { + return Build.VERSION_CODES.CUR_DEVELOPMENT; + } + return pkg.getTargetSdkVersion(); + } + @Override @Nullable public ParceledListSlice<PermissionInfo> queryPermissionsByGroup(String groupName, @@ -576,9 +590,8 @@ public class PermissionManagerService extends IPermissionManager.Stub { } final ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10); for (BasePermission bp : mSettings.mPermissions.values()) { - final PermissionInfo pi = bp.generatePermissionInfo(groupName, flags); - if (pi != null) { - out.add(pi); + if (Objects.equals(bp.getGroup(), groupName)) { + out.add(bp.generatePermissionInfo(flags)); } } return new ParceledListSlice<>(out); @@ -603,7 +616,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { int fixedLevel = PermissionInfo.fixProtectionLevel(info.protectionLevel); if (added) { enforcePermissionCapLocked(info, tree); - bp = new BasePermission(info.name, tree.getSourcePackageName(), + bp = new BasePermission(info.name, tree.getPackageName(), BasePermission.TYPE_DYNAMIC); } else if (!bp.isDynamic()) { throw new SecurityException("Not allowed to modify non-dynamic permission " @@ -2235,32 +2248,6 @@ public class PermissionManagerService extends IPermissionManager.Stub { } } - private int adjustPermissionProtectionFlagsLocked(int protectionLevel, - @Nullable AndroidPackage pkg, int uid) { - // Signature permission flags area always reported - final int protectionLevelMasked = protectionLevel - & (PermissionInfo.PROTECTION_NORMAL - | PermissionInfo.PROTECTION_DANGEROUS - | PermissionInfo.PROTECTION_SIGNATURE); - if (protectionLevelMasked == PermissionInfo.PROTECTION_SIGNATURE) { - return protectionLevel; - } - // System sees all flags. - final int appId = UserHandle.getAppId(uid); - if (appId == Process.SYSTEM_UID || appId == Process.ROOT_UID - || appId == Process.SHELL_UID) { - return protectionLevel; - } - if (pkg == null) { - return protectionLevel; - } - if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.O) { - return protectionLevelMasked; - } - // Apps that target O see flags for all protection levels. - return protectionLevel; - } - /** * We might auto-grant permissions if any permission of the group is already granted. Hence if * the group of a granted permission changes we need to revoke it to avoid having permissions of @@ -2363,17 +2350,19 @@ public class PermissionManagerService extends IPermissionManager.Stub { } } + final PermissionInfo permissionInfo = PackageInfoUtils.generatePermissionInfo(p, + PackageManager.GET_META_DATA); if (p.isTree()) { final BasePermission bp = BasePermission.createOrUpdate( mPackageManagerInt, - mSettings.getPermissionTreeLocked(p.getName()), p, pkg, + mSettings.getPermissionTreeLocked(p.getName()), permissionInfo, pkg, mSettings.getAllPermissionTreesLocked(), chatty); mSettings.putPermissionTreeLocked(p.getName(), bp); } else { final BasePermission bp = BasePermission.createOrUpdate( mPackageManagerInt, mSettings.getPermissionLocked(p.getName()), - p, pkg, mSettings.getAllPermissionTreesLocked(), chatty); + permissionInfo, pkg, mSettings.getAllPermissionTreesLocked(), chatty); mSettings.putPermissionLocked(p.getName(), bp); } } @@ -2433,7 +2422,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { bp = mSettings.mPermissionTrees.get(p.getName()); } if (bp != null && bp.isPermission(p)) { - bp.setPermission(null); + bp.setPermissionInfo(null); if (DEBUG_REMOVE && chatty) { if (r == null) { r = new StringBuilder(256); @@ -2624,7 +2613,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { if (permission == null) { continue; } - if (Objects.equals(permission.getSourcePackageName(), PLATFORM_PACKAGE_NAME) + if (Objects.equals(permission.getPackageName(), PLATFORM_PACKAGE_NAME) && permission.isRuntime() && !permission.isRemoved()) { if (permission.isHardOrSoftRestricted() || permission.isImmutablyRestricted()) { @@ -2817,10 +2806,10 @@ public class PermissionManagerService extends IPermissionManager.Stub { boolean wasChanged = false; boolean restrictionExempt = - (origState.getPermissionFlags(bp.name) + (origState.getPermissionFlags(bp.getName()) & FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) != 0; boolean restrictionApplied = (origState.getPermissionFlags( - bp.name) & FLAG_PERMISSION_APPLY_RESTRICTION) != 0; + bp.getName()) & FLAG_PERMISSION_APPLY_RESTRICTION) != 0; if (appSupportsRuntimePermissions) { // If hard restricted we don't allow holding it @@ -2868,7 +2857,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { if (origPermState == null) { // New permission if (PLATFORM_PACKAGE_NAME.equals( - bp.getSourcePackageName())) { + bp.getPackageName())) { if (!bp.isRemoved()) { flags |= FLAG_PERMISSION_REVIEW_REQUIRED | FLAG_PERMISSION_REVOKED_COMPAT; @@ -2877,7 +2866,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { } } - if (!uidState.isPermissionGranted(bp.name) + if (!uidState.isPermissionGranted(bp.getName()) && uidState.grantPermission(bp)) { wasChanged = true; } @@ -2914,7 +2903,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { flags); } else { if (DEBUG_PERMISSIONS) { - boolean wasGranted = uidState.isPermissionGranted(bp.name); + boolean wasGranted = uidState.isPermissionGranted(bp.getName()); if (wasGranted || bp.isAppOp()) { Slog.i(TAG, (wasGranted ? "Un-granting" : "Not granting") + " permission " + perm @@ -2926,7 +2915,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { + ")"); } } - if (uidState.removePermissionState(bp.name)) { + if (uidState.removePermissionState(bp.getName())) { changedInstallPermission = true; } } @@ -3309,7 +3298,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { final boolean isPrivilegedPermission = bp.isPrivileged() || isVendorPrivilegedPermission; final boolean isOemPermission = bp.isOEM(); if (!allowed && (isPrivilegedPermission || isOemPermission) && pkg.isSystem()) { - final String permissionName = bp.name; + final String permissionName = bp.getName(); // For updated system applications, a privileged/oem permission // is granted only if it had been defined by the original application. if (pkgSetting.getPkgState().isUpdatedSystemApp()) { @@ -3457,7 +3446,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { @Nullable private PackageSetting getSourcePackageSetting(@NonNull BasePermission bp) { - final String sourcePackageName = bp.getSourcePackageName(); + final String sourcePackageName = bp.getPackageName(); return mPackageManagerInt.getPackageSetting(sourcePackageName); } @@ -3467,14 +3456,14 @@ public class PermissionManagerService extends IPermissionManager.Stub { return false; } final boolean isPlatformPermission = PLATFORM_PACKAGE_NAME.equals( - permission.getSourcePackageName()); + permission.getPackageName()); if (!isPlatformPermission) { return true; } if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_DISABLE) { return true; } - final String permissionName = permission.name; + final String permissionName = permission.getName(); if (isInSystemConfigPrivAppPermissions(pkg, permissionName)) { return true; } @@ -3861,7 +3850,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { // TODO(zhanghai): Why are we only killing the UID when GIDs changed, instead of any // permission change? - if (uidState.removePermissionState(bp.name) && bp.hasGids()) { + if (uidState.removePermissionState(bp.getName()) && bp.hasGids()) { affectedUserId = userId; } } @@ -3902,7 +3891,8 @@ public class PermissionManagerService extends IPermissionManager.Stub { if (!usedPermissions.contains(permissionState.getName())) { BasePermission bp = mSettings.getPermissionLocked(permissionState.getName()); if (bp != null) { - if (uidState.removePermissionState(bp.name) && permissionState.isRuntime()) { + if (uidState.removePermissionState(bp.getName()) + && permissionState.isRuntime()) { runtimePermissionChanged = true; } } @@ -3973,9 +3963,9 @@ public class PermissionManagerService extends IPermissionManager.Stub { // Only system declares background permissions, hence mapping does never change. mBackgroundPermissions = new ArrayMap<>(); for (BasePermission bp : mSettings.getAllPermissionsLocked()) { - if (bp.perm != null && bp.perm.getBackgroundPermission() != null) { - String fgPerm = bp.name; - String bgPerm = bp.perm.getBackgroundPermission(); + if (bp.getBackgroundPermission() != null) { + String fgPerm = bp.getName(); + String bgPerm = bp.getBackgroundPermission(); List<String> fgPerms = mBackgroundPermissions.get(bgPerm); if (fgPerms == null) { @@ -4124,7 +4114,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { if (bp.isDynamic()) { bp.updateDynamicPermission(mSettings.mPermissionTrees.values()); } - if (!packageName.equals(bp.getSourcePackageName())) { + if (!packageName.equals(bp.getPackageName())) { // Not checking sourcePackageSetting because it can be null when // the permission source package is the target package and the target package is // being uninstalled, @@ -4145,7 +4135,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { // From all other packages if (pkg == null || !hasPermission(pkg, bp.getName())) { Slog.i(TAG, "Removing permission " + bp.getName() - + " that used to be declared by " + bp.getSourcePackageName()); + + " that used to be declared by " + bp.getPackageName()); if (bp.isRuntime()) { final int[] userIds = mUserManagerInt.getUserIds(); final int numUserIds = userIds.length; @@ -4167,7 +4157,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { + p.getPackageName() + " and user " + userId); continue; } - uidState.removePermissionState(bp.name); + uidState.removePermissionState(bp.getName()); } } }); @@ -4176,16 +4166,16 @@ public class PermissionManagerService extends IPermissionManager.Stub { continue; } final AndroidPackage sourcePkg = - mPackageManagerInt.getPackage(bp.getSourcePackageName()); + mPackageManagerInt.getPackage(bp.getPackageName()); final PackageSetting sourcePs = (PackageSetting) mPackageManagerInt.getPackageSetting( - bp.getSourcePackageName()); + bp.getPackageName()); synchronized (mLock) { if (sourcePkg != null && sourcePs != null) { continue; } Slog.w(TAG, "Removing dangling permission: " + bp.getName() - + " from package " + bp.getSourcePackageName()); + + " from package " + bp.getPackageName()); mSettings.removePermissionLocked(bp.getName()); } } @@ -4257,7 +4247,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { final Iterator<BasePermission> it = mSettings.mPermissionTrees.values().iterator(); while (it.hasNext()) { final BasePermission bp = it.next(); - if (!packageName.equals(bp.getSourcePackageName())) { + if (!packageName.equals(bp.getPackageName())) { // Not checking sourcePackageSetting because it can be null when // the permission source package is the target package and the target package is // being uninstalled, @@ -4268,7 +4258,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { changed = true; if (pkg == null || !hasPermission(pkg, bp.getName())) { Slog.i(TAG, "Removing permission tree " + bp.getName() - + " that used to be declared by " + bp.getSourcePackageName()); + + " that used to be declared by " + bp.getPackageName()); it.remove(); } if (needsUpdate == null) { @@ -4280,16 +4270,16 @@ public class PermissionManagerService extends IPermissionManager.Stub { if (needsUpdate != null) { for (final BasePermission bp : needsUpdate) { final AndroidPackage sourcePkg = - mPackageManagerInt.getPackage(bp.getSourcePackageName()); + mPackageManagerInt.getPackage(bp.getPackageName()); final PackageSetting sourcePs = (PackageSetting) mPackageManagerInt.getPackageSetting( - bp.getSourcePackageName()); + bp.getPackageName()); synchronized (mLock) { if (sourcePkg != null && sourcePs != null) { continue; } Slog.w(TAG, "Removing dangling permission tree: " + bp.getName() - + " from package " + bp.getSourcePackageName()); + + " from package " + bp.getPackageName()); mSettings.removePermissionLocked(bp.getName()); } } @@ -4902,9 +4892,8 @@ public class PermissionManagerService extends IPermissionManager.Stub { for (int i = 0; i < numTotalPermissions; i++) { BasePermission bp = mSettings.mPermissions.valueAt(i); - if (bp.perm != null && bp.perm.getProtection() == protection) { - matchingPermissions.add( - PackageInfoUtils.generatePermissionInfo(bp.perm, 0)); + if (bp.getProtection() == protection) { + matchingPermissions.add(bp.generatePermissionInfo(0)); } } } @@ -4923,10 +4912,8 @@ public class PermissionManagerService extends IPermissionManager.Stub { for (int i = 0; i < numTotalPermissions; i++) { BasePermission bp = mSettings.mPermissions.valueAt(i); - if (bp.perm != null && (bp.perm.getProtectionFlags() & protectionFlags) - == protectionFlags) { - matchingPermissions.add( - PackageInfoUtils.generatePermissionInfo(bp.perm, 0)); + if ((bp.getProtectionFlags() & protectionFlags) == protectionFlags) { + matchingPermissions.add(bp.generatePermissionInfo(0)); } } } diff --git a/services/core/java/com/android/server/pm/permission/UidPermissionState.java b/services/core/java/com/android/server/pm/permission/UidPermissionState.java index 38e8955e8cdb..9727a5452440 100644 --- a/services/core/java/com/android/server/pm/permission/UidPermissionState.java +++ b/services/core/java/com/android/server/pm/permission/UidPermissionState.java @@ -284,7 +284,7 @@ public final class UidPermissionState { final PermissionState permissionState = getOrCreatePermissionState(permission); final boolean changed = permissionState.updateFlags(flagMask, flagValues); if (changed && permissionState.isDefault()) { - removePermissionState(permission.name); + removePermissionState(permission.getName()); } return changed; } diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java index e0b671f38426..f43a4cec6080 100644 --- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java @@ -1630,13 +1630,14 @@ public class StatsPullAtomService extends SystemService { if (modemInfo == null) { return StatsManager.PULL_SKIP; } - pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, modemInfo.getTimestamp(), + pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, + modemInfo.getTimestampMillis(), modemInfo.getSleepTimeMillis(), modemInfo.getIdleTimeMillis(), - modemInfo.getTransmitPowerInfo().get(0).getTimeInMillis(), - modemInfo.getTransmitPowerInfo().get(1).getTimeInMillis(), - modemInfo.getTransmitPowerInfo().get(2).getTimeInMillis(), - modemInfo.getTransmitPowerInfo().get(3).getTimeInMillis(), - modemInfo.getTransmitPowerInfo().get(4).getTimeInMillis(), + modemInfo.getTransmitDurationMillisAtPowerLevel(0), + modemInfo.getTransmitDurationMillisAtPowerLevel(1), + modemInfo.getTransmitDurationMillisAtPowerLevel(2), + modemInfo.getTransmitDurationMillisAtPowerLevel(3), + modemInfo.getTransmitDurationMillisAtPowerLevel(4), modemInfo.getReceiveTimeMillis(), -1 /*`energy_used` field name deprecated, use -1 to indicate as unused.*/)); } finally { diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java index e9215f9793d2..ebfffec1774e 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java @@ -86,6 +86,13 @@ public interface StatusBarManagerInternal { void toggleSplitScreen(); void appTransitionFinished(int displayId); + /** + * Notifies the status bar that a Emergency Action launch gesture has been detected. + * + * TODO (b/169175022) Update method name and docs when feature name is locked. + */ + void onEmergencyActionLaunchGestureDetected(); + void toggleRecentApps(); void setCurrentUser(int newUserId); diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index 6a68dc1fb2a2..55cb7f32e1b7 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -264,6 +264,23 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D } } + /** + * Notifies the status bar that a Emergency Action launch gesture has been detected. + * + * TODO (b/169175022) Update method name and docs when feature name is locked. + */ + @Override + public void onEmergencyActionLaunchGestureDetected() { + if (SPEW) Slog.d(TAG, "Launching emergency action"); + if (mBar != null) { + try { + mBar.onEmergencyActionLaunchGestureDetected(); + } catch (RemoteException e) { + if (SPEW) Slog.d(TAG, "Failed to launch emergency action"); + } + } + } + @Override public void topAppWindowChanged(int displayId, boolean isFullscreen, boolean isImmersive) { StatusBarManagerService.this.topAppWindowChanged(displayId, isFullscreen, isImmersive); diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 8f2e60ec1f08..746bc0eaff3c 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -4761,14 +4761,15 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A supportsEnterPipOnTaskSwitch = false; break; case RESUMED: - // If the app is capable of entering PIP, we should try pausing it now - // so it can PIP correctly. - if (deferHidingClient) { - getRootTask().startPausingLocked( - mStackSupervisor.mUserLeaving /* userLeaving */, - false /* uiSleeping */, null /* resuming */, "makeInvisible"); + // Do nothing if currently in the process of resuming the activity. Otherwise, + // starting to pause it since it is not visible. + if (task.mInResumeTopActivity + && task.topRunningActivity(true /* focusableOnly */) == this) { break; } + getRootTask().startPausingLocked(mStackSupervisor.mUserLeaving, + false /* uiSleeping */, null /* resuming */, "makeInvisible"); + // fall through case INITIALIZING: case PAUSING: case PAUSED: diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java index e4f8d8ba6399..94b3d8d6c546 100644 --- a/services/core/java/com/android/server/wm/DisplayArea.java +++ b/services/core/java/com/android/server/wm/DisplayArea.java @@ -181,6 +181,10 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> { return false; } + boolean getIgnoreOrientationRequest() { + return mIgnoreOrientationRequest; + } + /** * When a {@link DisplayArea} is repositioned, it should only be moved among its siblings of the * same {@link Type}. diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 0bade7db911f..be03e91ac84d 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -5356,8 +5356,13 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp return mDisplayPolicy.getSystemUiContext(); } - Point getDisplayPosition() { - return mWmService.mDisplayManagerInternal.getDisplayPosition(getDisplayId()); + @Override + boolean setIgnoreOrientationRequest(boolean ignoreOrientationRequest) { + if (mIgnoreOrientationRequest == ignoreOrientationRequest) return false; + final boolean rotationChanged = super.setIgnoreOrientationRequest(ignoreOrientationRequest); + mWmService.mDisplayWindowSettings.setIgnoreOrientationRequest( + this, mIgnoreOrientationRequest); + return rotationChanged; } /** diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java index 04e37faf0ee4..f647bea950f2 100644 --- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java +++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java @@ -112,6 +112,7 @@ class DisplayWindowSettings { private boolean mShouldShowSystemDecors = false; private boolean mShouldShowIme = false; private int mFixedToUserRotation = IWindowManager.FIXED_TO_USER_ROTATION_DEFAULT; + private boolean mIgnoreOrientationRequest = false; private Entry(String name) { mName = name; @@ -131,6 +132,7 @@ class DisplayWindowSettings { mShouldShowSystemDecors = copyFrom.mShouldShowSystemDecors; mShouldShowIme = copyFrom.mShouldShowIme; mFixedToUserRotation = copyFrom.mFixedToUserRotation; + mIgnoreOrientationRequest = copyFrom.mIgnoreOrientationRequest; } /** @return {@code true} if all values are default. */ @@ -144,7 +146,8 @@ class DisplayWindowSettings { && !mShouldShowWithInsecureKeyguard && !mShouldShowSystemDecors && !mShouldShowIme - && mFixedToUserRotation == IWindowManager.FIXED_TO_USER_ROTATION_DEFAULT; + && mFixedToUserRotation == IWindowManager.FIXED_TO_USER_ROTATION_DEFAULT + && !mIgnoreOrientationRequest; } } @@ -248,6 +251,15 @@ class DisplayWindowSettings { writeSettingsIfNeeded(entry, displayInfo); } + void setIgnoreOrientationRequest( + DisplayContent displayContent, boolean ignoreOrientationRequest) { + final DisplayInfo displayInfo = displayContent.getDisplayInfo(); + final Entry entry = getOrCreateEntry(displayInfo); + if (entry.mIgnoreOrientationRequest == ignoreOrientationRequest) return; + entry.mIgnoreOrientationRequest = ignoreOrientationRequest; + writeSettingsIfNeeded(entry, displayInfo); + } + private int getWindowingModeLocked(Entry entry, DisplayContent dc) { int windowingMode = entry != null ? entry.mWindowingMode : WindowConfiguration.WINDOWING_MODE_UNDEFINED; @@ -389,6 +401,7 @@ class DisplayWindowSettings { final boolean hasSizeOverride = entry.mForcedWidth != 0 && entry.mForcedHeight != 0; dc.mIsDensityForced = hasDensityOverride; dc.mIsSizeForced = hasSizeOverride; + dc.setIgnoreOrientationRequest(entry.mIgnoreOrientationRequest); final int width = hasSizeOverride ? entry.mForcedWidth : dc.mBaseDisplayWidth; final int height = hasSizeOverride ? entry.mForcedHeight : dc.mBaseDisplayHeight; @@ -529,6 +542,8 @@ class DisplayWindowSettings { entry.mShouldShowSystemDecors = getBooleanAttribute(parser, "shouldShowSystemDecors"); entry.mShouldShowIme = getBooleanAttribute(parser, "shouldShowIme"); entry.mFixedToUserRotation = getIntAttribute(parser, "fixedToUserRotation"); + entry.mIgnoreOrientationRequest + = getBooleanAttribute(parser, "ignoreOrientationRequest"); mEntries.put(name, entry); } XmlUtils.skipCurrentTag(parser); @@ -613,6 +628,10 @@ class DisplayWindowSettings { out.attribute(null, "fixedToUserRotation", Integer.toString(entry.mFixedToUserRotation)); } + if (entry.mIgnoreOrientationRequest) { + out.attribute(null, "ignoreOrientationRequest", + Boolean.toString(entry.mIgnoreOrientationRequest)); + } out.endTag(null, "display"); } diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index 143b657b0437..470c2b1581d0 100644 --- a/services/core/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java @@ -531,7 +531,7 @@ final class InputMonitor { // event. This is used to omit Surfaces from occlusion detection. populateOverlayInputInfo(mInvalidInputWindow, w.getName(), type, isVisible); mInputTransaction.setInputWindowInfo( - w.mWinAnimator.mSurfaceController.getClientViewRootSurface(), + w.mWinAnimator.mSurfaceController.mSurfaceControl, mInvalidInputWindow); return; } @@ -600,8 +600,7 @@ final class InputMonitor { if (w.mWinAnimator.hasSurface()) { mInputTransaction.setInputWindowInfo( - w.mWinAnimator.mSurfaceController.getClientViewRootSurface(), - inputWindowHandle); + w.mWinAnimator.mSurfaceController.mSurfaceControl, inputWindowHandle); } } } diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index 1fdb49f38cf5..02230d6ae2a6 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -204,15 +204,14 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { int requestedWidth, int requestedHeight, int viewFlags, int flags, long frameNumber, ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration, SurfaceControl outSurfaceControl, InsetsState outInsetsState, - InsetsSourceControl[] outActiveControls, Point outSurfaceSize, - SurfaceControl outBLASTSurfaceControl) { + InsetsSourceControl[] outActiveControls, Point outSurfaceSize) { if (false) Slog.d(TAG_WM, ">>>>>> ENTERED relayout from " + Binder.getCallingPid()); Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mRelayoutTag); int res = mService.relayoutWindow(this, window, attrs, requestedWidth, requestedHeight, viewFlags, flags, frameNumber, outFrames, mergedConfiguration, outSurfaceControl, outInsetsState, - outActiveControls, outSurfaceSize, outBLASTSurfaceControl); + outActiveControls, outSurfaceSize); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); if (false) Slog.d(TAG_WM, "<<<<<< EXITING relayout to " + Binder.getCallingPid()); diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java index 6904740343a6..efa05255a415 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java @@ -122,7 +122,6 @@ class TaskSnapshotSurface implements StartingSurface { //tmp vars for unused relayout params private static final Point sTmpSurfaceSize = new Point(); - private static final SurfaceControl sTmpSurfaceControl = new SurfaceControl(); private final Window mWindow; private final Surface mSurface; @@ -260,7 +259,7 @@ class TaskSnapshotSurface implements StartingSurface { try { session.relayout(window, layoutParams, -1, -1, View.VISIBLE, 0, -1, tmpFrames, tmpMergedConfiguration, surfaceControl, mTmpInsetsState, - mTempControls, sTmpSurfaceSize, sTmpSurfaceControl); + mTempControls, sTmpSurfaceSize); } catch (RemoteException e) { // Local call. } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 223aa1e9be39..4be118ec97fa 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2104,8 +2104,7 @@ public class WindowManagerService extends IWindowManager.Stub int requestedWidth, int requestedHeight, int viewVisibility, int flags, long frameNumber, ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration, SurfaceControl outSurfaceControl, InsetsState outInsetsState, - InsetsSourceControl[] outActiveControls, Point outSurfaceSize, - SurfaceControl outBLASTSurfaceControl) { + InsetsSourceControl[] outActiveControls, Point outSurfaceSize) { Arrays.fill(outActiveControls, null); int result = 0; boolean configChanged; @@ -2280,8 +2279,7 @@ public class WindowManagerService extends IWindowManager.Stub result = win.relayoutVisibleWindow(result, attrChanges); try { - result = createSurfaceControl(outSurfaceControl, outBLASTSurfaceControl, - result, win, winAnimator); + result = createSurfaceControl(outSurfaceControl, result, win, winAnimator); } catch (Exception e) { displayContent.getInputMonitor().updateInputWindowsLw(true /*force*/); @@ -2313,7 +2311,6 @@ public class WindowManagerService extends IWindowManager.Stub // surface, let the client use that, but don't create new surface at this point. Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "relayoutWindow: getSurface"); winAnimator.mSurfaceController.getSurfaceControl(outSurfaceControl); - winAnimator.mSurfaceController.getBLASTSurfaceControl(outBLASTSurfaceControl); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } else { if (DEBUG_VISIBILITY) Slog.i(TAG_WM, "Releasing surface in: " + win); @@ -2501,8 +2498,7 @@ public class WindowManagerService extends IWindowManager.Stub return focusMayChange; } - private int createSurfaceControl(SurfaceControl outSurfaceControl, - SurfaceControl outBLASTSurfaceControl, int result, + private int createSurfaceControl(SurfaceControl outSurfaceControl, int result, WindowState win, WindowStateAnimator winAnimator) { if (!win.mHasSurface) { result |= RELAYOUT_RES_SURFACE_CHANGED; @@ -2517,7 +2513,6 @@ public class WindowManagerService extends IWindowManager.Stub } if (surfaceController != null) { surfaceController.getSurfaceControl(outSurfaceControl); - surfaceController.getBLASTSurfaceControl(outBLASTSurfaceControl); ProtoLog.i(WM_SHOW_TRANSACTIONS, "OUT SURFACE %s: copied", outSurfaceControl); } else { @@ -3714,16 +3709,52 @@ public class WindowManagerService extends IWindowManager.Stub @Override public void setFixedToUserRotation(int displayId, int fixedToUserRotation) { if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION, - "freezeRotation()")) { + "setFixedToUserRotation()")) { throw new SecurityException("Requires SET_ORIENTATION permission"); } + final long origId = Binder.clearCallingIdentity(); + try { + synchronized (mGlobalLock) { + final DisplayContent display = mRoot.getDisplayContent(displayId); + if (display == null) { + Slog.w(TAG, "Trying to set rotate for app for a missing display."); + return; + } + display.getDisplayRotation().setFixedToUserRotation(fixedToUserRotation); + } + } finally { + Binder.restoreCallingIdentity(origId); + } + } + + @Override + public void setIgnoreOrientationRequest(int displayId, boolean ignoreOrientationRequest) { + mAtmInternal.enforceCallerIsRecentsOrHasPermission( + android.Manifest.permission.SET_ORIENTATION, "setIgnoreOrientationRequest()"); + + final long origId = Binder.clearCallingIdentity(); + try { + synchronized (mGlobalLock) { + final DisplayContent display = mRoot.getDisplayContent(displayId); + if (display == null) { + Slog.w(TAG, "Trying to setIgnoreOrientationRequest() for a missing display."); + return; + } + display.setIgnoreOrientationRequest(ignoreOrientationRequest); + } + } finally { + Binder.restoreCallingIdentity(origId); + } + } + + boolean getIgnoreOrientationRequest(int displayId) { synchronized (mGlobalLock) { final DisplayContent display = mRoot.getDisplayContent(displayId); if (display == null) { - Slog.w(TAG, "Trying to set rotate for app for a missing display."); - return; + Slog.w(TAG, "Trying to getIgnoreOrientationRequest() for a missing display."); + return false; } - display.getDisplayRotation().setFixedToUserRotation(fixedToUserRotation); + return display.getIgnoreOrientationRequest(); } } diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java index 506e0dd508fb..fa1c50f9aed7 100644 --- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java +++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java @@ -106,6 +106,10 @@ public class WindowManagerShellCommand extends ShellCommand { return runSetDisplayUserRotation(pw); case "set-fix-to-user-rotation": return runSetFixToUserRotation(pw); + case "set-ignore-orientation-request": + return runSetIgnoreOrientationRequest(pw); + case "get-ignore-orientation-request": + return runGetIgnoreOrientationRequest(pw); case "dump-visible-window-views": return runDumpVisibleWindowViews(pw); default: @@ -368,6 +372,47 @@ public class WindowManagerShellCommand extends ShellCommand { return 0; } + private int runSetIgnoreOrientationRequest(PrintWriter pw) throws RemoteException { + int displayId = Display.DEFAULT_DISPLAY; + String arg = getNextArgRequired(); + if ("-d".equals(arg)) { + displayId = Integer.parseInt(getNextArgRequired()); + arg = getNextArgRequired(); + } + + final boolean ignoreOrientationRequest; + switch (arg) { + case "true": + case "1": + ignoreOrientationRequest = true; + break; + case "false": + case "0": + ignoreOrientationRequest = false; + break; + default: + getErrPrintWriter().println("Error: expecting true, 1, false, 0, but we " + + "get " + arg); + return -1; + } + + mInterface.setIgnoreOrientationRequest(displayId, ignoreOrientationRequest); + return 0; + } + + private int runGetIgnoreOrientationRequest(PrintWriter pw) throws RemoteException { + int displayId = Display.DEFAULT_DISPLAY; + String arg = getNextArg(); + if ("-d".equals(arg)) { + displayId = Integer.parseInt(getNextArgRequired()); + } + + final boolean ignoreOrientationRequest = mInternal.getIgnoreOrientationRequest(displayId); + pw.println("ignoreOrientationRequest " + ignoreOrientationRequest + + " for displayId=" + displayId); + return 0; + } + private int runDumpVisibleWindowViews(PrintWriter pw) { if (!mInternal.checkCallingPermission(android.Manifest.permission.DUMP, "runDumpVisibleWindowViews()")) { @@ -433,8 +478,11 @@ public class WindowManagerShellCommand extends ShellCommand { pw.println(" Set user rotation mode and user rotation."); pw.println(" dump-visible-window-views"); pw.println(" Dumps the encoded view hierarchies of visible windows"); - pw.println(" set-fix-to-user-rotation [-d DISPLAY_ID] [enabled|disabled]"); + pw.println(" set-fix-to-user-rotation [-d DISPLAY_ID] [enabled|disabled|default]"); pw.println(" Enable or disable rotating display for app requested orientation."); + pw.println(" set-ignore-orientation-request [-d DISPLAY_ID] [true|1|false|0]"); + pw.println(" get-ignore-orientation-request [-d DISPLAY_ID] "); + pw.println(" If app requested orientation should be ignored."); if (!IS_USER) { pw.println(" tracing (start | stop)"); pw.println(" Start or stop window tracing."); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 3b79241a3c3e..25b48281db8e 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -5770,7 +5770,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } SurfaceControl getClientViewRootSurface() { - return mWinAnimator.getClientViewRootSurface(); + return mWinAnimator.getSurfaceControl(); } @Override diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 6349e6d36ae1..972d0d46cec0 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -359,8 +359,8 @@ class WindowStateAnimator { // surface before destroying it. if (mSurfaceController != null && mPendingDestroySurface != null) { mPostDrawTransaction.reparentChildren( - mSurfaceController.getClientViewRootSurface(), - mPendingDestroySurface.getClientViewRootSurface()).apply(); + mSurfaceController.mSurfaceControl, + mPendingDestroySurface.mSurfaceControl).apply(); } destroySurfaceLocked(); mSurfaceDestroyDeferred = true; @@ -371,7 +371,7 @@ class WindowStateAnimator { // Our SurfaceControl is always at layer 0 within the parent Surface managed by // window-state. We want this old Surface to stay on top of the new one // until we do the swap, so we place it at a positive layer. - t.setLayer(mSurfaceController.getClientViewRootSurface(), PRESERVED_SURFACE_LAYER); + t.setLayer(mSurfaceController.mSurfaceControl, PRESERVED_SURFACE_LAYER); } mDestroyPreservedSurfaceUponRedraw = true; mSurfaceDestroyDeferred = true; @@ -393,8 +393,8 @@ class WindowStateAnimator { && !mPendingDestroySurface.mChildrenDetached && (mWin.mActivityRecord == null || !mWin.mActivityRecord.isRelaunching())) { mPostDrawTransaction.reparentChildren( - mPendingDestroySurface.getClientViewRootSurface(), - mSurfaceController.getClientViewRootSurface()).apply(); + mPendingDestroySurface.mSurfaceControl, + mSurfaceController.mSurfaceControl).apply(); } destroyDeferredSurfaceLocked(); @@ -984,8 +984,8 @@ class WindowStateAnimator { // Instead let the children get removed when the old surface is deleted. if (!mPendingDestroySurface.mChildrenDetached) { mPostDrawTransaction.reparentChildren( - mPendingDestroySurface.getClientViewRootSurface(), - mSurfaceController.getClientViewRootSurface()); + mPendingDestroySurface.mSurfaceControl, + mSurfaceController.mSurfaceControl); } } @@ -1201,10 +1201,10 @@ class WindowStateAnimator { mOffsetPositionForStackResize = offsetPositionForStackResize; } - SurfaceControl getClientViewRootSurface() { + SurfaceControl getSurfaceControl() { if (!hasSurface()) { return null; } - return mSurfaceController.getClientViewRootSurface(); + return mSurfaceController.mSurfaceControl; } } diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java index d2c36e2bf347..feecda79b6d7 100644 --- a/services/core/java/com/android/server/wm/WindowSurfaceController.java +++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java @@ -50,11 +50,6 @@ class WindowSurfaceController { SurfaceControl mSurfaceControl; - /** - * WM only uses for deferred transactions. - */ - SurfaceControl mBLASTSurfaceControl; - // Should only be set from within setShown(). private boolean mSurfaceShown = false; private float mSurfaceX = 0; @@ -112,22 +107,13 @@ class WindowSurfaceController { final boolean useBLAST = mService.mUseBLAST && ((win.getAttrs().privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST) != 0); + if (useBLAST) { - b.setContainerLayer(); + b.setBLASTLayer(); } mSurfaceControl = b.build(); - if (useBLAST) { - mBLASTSurfaceControl = win.makeSurface() - .setParent(mSurfaceControl) - .setName(name + "(BLAST)") - .setHidden(false) - .setBLASTLayer() - .setCallsite("WindowSurfaceController") - .build(); - } - Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } @@ -172,9 +158,6 @@ class WindowSurfaceController { } finally { setShown(false); mSurfaceControl = null; - if (mBLASTSurfaceControl != null) { - mBLASTSurfaceControl.release(); - } } } @@ -369,12 +352,6 @@ class WindowSurfaceController { outSurfaceControl.copyFrom(mSurfaceControl, "WindowSurfaceController.getSurfaceControl"); } - void getBLASTSurfaceControl(SurfaceControl outSurfaceControl) { - if (mBLASTSurfaceControl != null) { - outSurfaceControl.copyFrom(mBLASTSurfaceControl, "WindowSurfaceController.getBLASTSurfaceControl"); - } - } - boolean getShown() { return mSurfaceShown; } @@ -399,21 +376,6 @@ class WindowSurfaceController { return mSurfaceH; } - /** - * Returns the Surface which the client-framework ViewRootImpl will be using. - * This is either the WSA SurfaceControl or it's BLAST child surface. - * This has too main uses: - * 1. This is the Surface the client will add children to, we use this to make - * sure we don't reparent the BLAST surface itself when calling reparentChildren - * 2. We use this as the barrier Surface for some deferTransaction operations. - */ - SurfaceControl getClientViewRootSurface() { - if (mBLASTSurfaceControl != null) { - return mBLASTSurfaceControl; - } - return mSurfaceControl; - } - void dumpDebug(ProtoOutputStream proto, long fieldId) { final long token = proto.start(fieldId); proto.write(SHOWN, mSurfaceShown); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 36ff97446349..177b7b46bb24 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -1569,10 +1569,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } /** - * Creates a new {@link CallerIdentity} object to represent the caller's identity. If no - * component name is provided, look up the component name and fill it in for the caller. + * Creates a new {@link CallerIdentity} object to represent the caller's identity, which should + * be an admin of a profile on the device. If no component name is provided, look up the + * component name and fill it in for the caller. + * + * Note: this method should only be called when the expected caller is an admin. + * + * @throws SecurityException if the caller is not an active admin. */ - private CallerIdentity getCallerIdentityOptionalAdmin(@Nullable ComponentName adminComponent) { + private CallerIdentity getAdminCallerIdentity(@Nullable ComponentName adminComponent) { if (adminComponent == null) { ActiveAdmin admin = getActiveAdminOfCaller(); if (admin != null) { @@ -1586,24 +1591,66 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { /** * Creates a new {@link CallerIdentity} object to represent the caller's identity. If no + * component name is provided, look up the component name and fill it in for the caller. + * + * Note: this method should only be called when the caller may not be an admin. If the caller + * is not an admin, the ComponentName in the returned identity will be null. + */ + private CallerIdentity getNonPrivilegedOrAdminCallerIdentity( + @Nullable ComponentName adminComponent) { + if (adminComponent == null) { + ActiveAdmin admin = getActiveAdminOfCaller(); + if (admin != null) { + adminComponent = admin.info.getComponent(); + } else { + return getCallerIdentity(); + } + } + return getCallerIdentity(adminComponent); + + } + + /** + * Creates a new {@link CallerIdentity} object to represent the caller's identity. If no * package name is provided, look up the package name and fill it in for the caller. + * + * Note: this method should only be called when the expected caller is an admin. + * + * @throws SecurityException if the caller is not an active admin. */ - private CallerIdentity getCallerIdentityOptionalPackage(@Nullable String callerPackage) { + private CallerIdentity getAdminCallerIdentityUsingPackage(@Nullable String callerPackage) { if (callerPackage == null) { ActiveAdmin admin = getActiveAdminOfCaller(); if (admin != null) { return getCallerIdentity(admin.info.getPackageName()); } throw new SecurityException("Caller is not an active admin"); - } else { - return getCallerIdentity(callerPackage); } + return getCallerIdentity(callerPackage); + } + + /** + * Creates a new {@link CallerIdentity} object to represent the caller's identity. If no + * package name is provided, look up the package name and fill it in for the caller. + */ + private CallerIdentity getNonPrivilegedOrAdminCallerIdentityUsingPackage( + @Nullable String callerPackage) { + if (callerPackage == null) { + ActiveAdmin admin = getActiveAdminOfCaller(); + if (admin != null) { + callerPackage = admin.info.getPackageName(); + } else { + return getCallerIdentity(); + } + } + return getCallerIdentity(callerPackage); } /** * Retrieves the active admin of the caller. This method should not be called directly and - * should only be called by {@link #getCallerIdentityOptionalAdmin} or - * {@link #getCallerIdentityOptionalPackage}. + * should only be called by {@link #getAdminCallerIdentity}, + * {@link #getNonPrivilegedOrAdminCallerIdentity}, {@link #getAdminCallerIdentityUsingPackage} + * or {@link #getNonPrivilegedOrAdminCallerIdentityUsingPackage}. */ private ActiveAdmin getActiveAdminOfCaller() { final int callerUid = mInjector.binderGetCallingUid(); @@ -6023,7 +6070,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); - final CallerIdentity caller = getCallerIdentityOptionalAdmin(comp); + final CallerIdentity caller = getAdminCallerIdentity(comp); Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userHandle)); Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(BIND_DEVICE_ADMIN)); @@ -6463,12 +6510,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); - final CallerIdentity caller = getCallerIdentityOptionalAdmin(who); + final CallerIdentity caller = getAdminCallerIdentity(who); Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userHandle)); synchronized (getLockObject()) { // Check for permissions if a particular caller is specified - if (who != null) { + if (caller.hasAdminComponent()) { // When checking for a single caller, status is based on caller's request ActiveAdmin ap = getActiveAdminUncheckedLocked(who, userHandle); return ap != null ? ap.encryptionRequested : false; @@ -6497,7 +6544,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); - final CallerIdentity caller = getCallerIdentityOptionalPackage(callerPackage); + final CallerIdentity caller = getAdminCallerIdentityUsingPackage(callerPackage); Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userHandle)); // It's not critical here, but let's make sure the package name is correct, in case @@ -8614,12 +8661,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Objects.requireNonNull(agent, "agent null"); Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId"); - final CallerIdentity caller = getCallerIdentityOptionalAdmin(admin); + final CallerIdentity caller = getAdminCallerIdentity(admin); Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userHandle)); synchronized (getLockObject()) { final String componentName = agent.flattenToString(); - if (admin != null) { + if (caller.hasAdminComponent()) { final ActiveAdmin ap = getActiveAdminUncheckedLocked(admin, userHandle, parent); if (ap == null) return null; TrustAgentInfo trustAgentInfo = ap.trustAgentInfos.get(componentName); diff --git a/services/net/TEST_MAPPING b/services/net/TEST_MAPPING new file mode 100644 index 000000000000..7025dd178e0f --- /dev/null +++ b/services/net/TEST_MAPPING @@ -0,0 +1,7 @@ +{ + "imports": [ + { + "path": "frameworks/base/core/java/android/net" + } + ] +}
\ No newline at end of file diff --git a/services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java index 31ec4a53908c..3aedd3c7d753 100644 --- a/services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java @@ -710,7 +710,6 @@ public class LocationProviderManagerTest { @Test public void testProviderRequest() { assertThat(mProvider.getRequest().isActive()).isFalse(); - assertThat(mProvider.getRequest().getLocationRequests()).isEmpty(); ILocationListener listener1 = createMockLocationListener(); LocationRequest request1 = new LocationRequest.Builder(5).setWorkSource( @@ -718,7 +717,6 @@ public class LocationProviderManagerTest { mManager.registerLocationRequest(request1, IDENTITY, PERMISSION_FINE, listener1); assertThat(mProvider.getRequest().isActive()).isTrue(); - assertThat(mProvider.getRequest().getLocationRequests()).containsExactly(request1); assertThat(mProvider.getRequest().isLocationSettingsIgnored()).isFalse(); assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(5); assertThat(mProvider.getRequest().isLowPower()).isFalse(); @@ -732,8 +730,6 @@ public class LocationProviderManagerTest { mManager.registerLocationRequest(request2, IDENTITY, PERMISSION_FINE, listener2); assertThat(mProvider.getRequest().isActive()).isTrue(); - assertThat(mProvider.getRequest().getLocationRequests()).containsExactly(request1, - request2); assertThat(mProvider.getRequest().isLocationSettingsIgnored()).isFalse(); assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(1); assertThat(mProvider.getRequest().isLowPower()).isFalse(); @@ -742,7 +738,6 @@ public class LocationProviderManagerTest { mManager.unregisterLocationRequest(listener1); assertThat(mProvider.getRequest().isActive()).isTrue(); - assertThat(mProvider.getRequest().getLocationRequests()).containsExactly(request2); assertThat(mProvider.getRequest().isLocationSettingsIgnored()).isFalse(); assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(1); assertThat(mProvider.getRequest().isLowPower()).isTrue(); @@ -751,7 +746,6 @@ public class LocationProviderManagerTest { mManager.unregisterLocationRequest(listener2); assertThat(mProvider.getRequest().isActive()).isFalse(); - assertThat(mProvider.getRequest().getLocationRequests()).isEmpty(); } @Test @@ -855,7 +849,6 @@ public class LocationProviderManagerTest { mInjector.getSettingsHelper().setLocationEnabled(false, IDENTITY.getUserId()); assertThat(mProvider.getRequest().isActive()).isTrue(); - assertThat(mProvider.getRequest().getLocationRequests()).containsExactly(request2); assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(5); assertThat(mProvider.getRequest().isLocationSettingsIgnored()).isTrue(); } diff --git a/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java b/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java index c91bb93fc559..9a2ce3c598a4 100644 --- a/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java @@ -223,6 +223,25 @@ public class GestureLauncherServiceTest { } @Test + public void testInterceptPowerKeyDown_firstPowerDown_panicGestureNotLaunched() { + withPanicGestureEnabledSettingValue(true); + mGestureLauncherService.updatePanicButtonGestureEnabled(); + + long eventTime = INITIAL_EVENT_TIME_MILLIS + + GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS - 1; + KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, + IGNORED_REPEAT); + boolean interactive = true; + MutableBoolean outLaunched = new MutableBoolean(true); + boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, + outLaunched); + + assertFalse(intercepted); + assertFalse(outLaunched.value); + verify(mMetricsLogger).histogram("power_double_tap_interval", (int) eventTime); + } + + @Test public void testInterceptPowerKeyDown_intervalInBoundsCameraPowerGestureOffInteractive() { withCameraDoubleTapPowerEnableConfigValue(false); withCameraDoubleTapPowerDisableSettingValue(1); @@ -405,6 +424,146 @@ public class GestureLauncherServiceTest { } @Test + public void + testInterceptPowerKeyDown_fiveInboundPresses_cameraAndPanicEnabled_bothLaunch() { + withCameraDoubleTapPowerEnableConfigValue(true); + withCameraDoubleTapPowerDisableSettingValue(0); + withPanicGestureEnabledSettingValue(true); + mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); + mGestureLauncherService.updatePanicButtonGestureEnabled(); + withUserSetupCompleteValue(true); + + // First button press does nothing + long eventTime = INITIAL_EVENT_TIME_MILLIS; + KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, + IGNORED_REPEAT); + boolean interactive = true; + MutableBoolean outLaunched = new MutableBoolean(true); + boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, + outLaunched); + assertFalse(intercepted); + assertFalse(outLaunched.value); + + final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; + + // 2nd button triggers camera + eventTime += interval; + keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, + IGNORED_REPEAT); + outLaunched.value = false; + intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, + outLaunched); + assertTrue(intercepted); + assertTrue(outLaunched.value); + + // Camera checks + verify(mStatusBarManagerInternal).onCameraLaunchGestureDetected( + StatusBarManager.CAMERA_LAUNCH_SOURCE_POWER_DOUBLE_TAP); + verify(mMetricsLogger) + .action(MetricsEvent.ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE, (int) interval); + + final ArgumentCaptor<Integer> cameraIntervalCaptor = ArgumentCaptor.forClass(Integer.class); + verify(mMetricsLogger, times(2)).histogram( + eq("power_double_tap_interval"), cameraIntervalCaptor.capture()); + List<Integer> cameraIntervals = cameraIntervalCaptor.getAllValues(); + assertEquals((int) INITIAL_EVENT_TIME_MILLIS, cameraIntervals.get(0).intValue()); + assertEquals((int) interval, cameraIntervals.get(1).intValue()); + + final ArgumentCaptor<Integer> tapCountCaptor = ArgumentCaptor.forClass(Integer.class); + verify(mMetricsLogger, times(2)).histogram( + eq("power_consecutive_short_tap_count"), tapCountCaptor.capture()); + List<Integer> tapCounts = tapCountCaptor.getAllValues(); + assertEquals(1, tapCounts.get(0).intValue()); + assertEquals(2, tapCounts.get(1).intValue()); + + // Continue the button presses for the panic gesture. + + // Presses 3 and 4 should not trigger any gesture + for (int i = 0; i < 2; i++) { + eventTime += interval; + keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, + IGNORED_REPEAT); + outLaunched.value = false; + intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, + outLaunched); + assertFalse(intercepted); + assertFalse(outLaunched.value); + } + + // Fifth button press should trigger the panic flow + eventTime += interval; + keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, + IGNORED_REPEAT); + outLaunched.value = false; + intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, + outLaunched); + assertTrue(intercepted); + assertTrue(outLaunched.value); + + // TODO (b/169960245) Verify metric event equiv. to ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE + verify(mStatusBarManagerInternal).onEmergencyActionLaunchGestureDetected(); + + final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); + verify(mMetricsLogger, times(5)).histogram( + eq("power_double_tap_interval"), intervalCaptor.capture()); + List<Integer> intervals = intervalCaptor.getAllValues(); + assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); + assertEquals((int) interval, intervals.get(1).intValue()); + } + + @Test + public void + testInterceptPowerKeyDown_fiveInboundPresses_panicGestureEnabled_launchesPanicFlow() { + withPanicGestureEnabledSettingValue(true); + mGestureLauncherService.updatePanicButtonGestureEnabled(); + withUserSetupCompleteValue(true); + + // First button press does nothing + long eventTime = INITIAL_EVENT_TIME_MILLIS; + KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, + IGNORED_REPEAT); + boolean interactive = true; + MutableBoolean outLaunched = new MutableBoolean(true); + boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, + outLaunched); + assertFalse(intercepted); + assertFalse(outLaunched.value); + + final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; + // 3 more button presses which should not trigger any gesture (camera gesture disabled) + for (int i = 0; i < 3; i++) { + eventTime += interval; + keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, + IGNORED_REPEAT); + outLaunched.value = false; + intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, + outLaunched); + assertFalse(intercepted); + assertFalse(outLaunched.value); + } + + // Fifth button press should trigger the panic flow + eventTime += interval; + keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, + IGNORED_REPEAT); + outLaunched.value = false; + intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, + outLaunched); + assertTrue(outLaunched.value); + assertTrue(intercepted); + + // TODO (b/169960245) Verify metric event equiv. to ACTION_DOUBLE_TAP_POWER_CAMERA_GESTURE + verify(mStatusBarManagerInternal).onEmergencyActionLaunchGestureDetected(); + + final ArgumentCaptor<Integer> intervalCaptor = ArgumentCaptor.forClass(Integer.class); + verify(mMetricsLogger, times(5)).histogram( + eq("power_double_tap_interval"), intervalCaptor.capture()); + List<Integer> intervals = intervalCaptor.getAllValues(); + assertEquals((int) INITIAL_EVENT_TIME_MILLIS, intervals.get(0).intValue()); + assertEquals((int) interval, intervals.get(1).intValue()); + } + + @Test public void testInterceptPowerKeyDown_longpress() { withCameraDoubleTapPowerEnableConfigValue(true); withCameraDoubleTapPowerDisableSettingValue(0); diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java index 03dce4c62fe8..faf7169a68c7 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java @@ -68,6 +68,7 @@ import android.os.Message; import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; +import android.util.SparseArray; import androidx.test.filters.FlakyTest; import androidx.test.filters.MediumTest; @@ -76,6 +77,7 @@ import androidx.test.filters.SmallTest; import com.android.server.LocalServices; import com.android.server.am.ProcessList.IsolatedUidRange; import com.android.server.am.ProcessList.IsolatedUidRangeAllocator; +import com.android.server.am.UidObserverController.ChangeRecord; import com.android.server.appop.AppOpsService; import com.android.server.wm.ActivityTaskManagerService; @@ -539,15 +541,15 @@ public class ActivityManagerServiceTest { ActivityManager.PROCESS_STATE_CACHED_ACTIVITY, ActivityManager.PROCESS_STATE_TOP }; - final Map<Integer, UidRecord.ChangeItem> changeItems = new HashMap<>(); + final Map<Integer, ChangeRecord> changeItems = new HashMap<>(); for (int i = 0; i < changesForPendingUidRecords.length; ++i) { - final UidRecord.ChangeItem pendingChange = new UidRecord.ChangeItem(); + final ChangeRecord pendingChange = new ChangeRecord(); pendingChange.change = changesForPendingUidRecords[i]; pendingChange.uid = i; - pendingChange.processState = procStatesForPendingUidRecords[i]; + pendingChange.procState = procStatesForPendingUidRecords[i]; pendingChange.procStateSeq = i; changeItems.put(changesForPendingUidRecords[i], pendingChange); - mAms.mUidObserverController.mPendingUidChanges.add(pendingChange); + addPendingUidChange(pendingChange); } mAms.mUidObserverController.dispatchUidsChanged(); @@ -602,7 +604,7 @@ public class ActivityManagerServiceTest { verifyObserverReceivedChanges(observerToTest, changesToVerify, changeItems, (observer, changeItem) -> { verify(observer).onUidStateChanged(changeItem.uid, - changeItem.processState, changeItem.procStateSeq, + changeItem.procState, changeItem.procStateSeq, ActivityManager.PROCESS_CAPABILITY_NONE); }); } @@ -612,14 +614,14 @@ public class ActivityManagerServiceTest { } private interface ObserverChangesVerifier { - void verify(IUidObserver observer, UidRecord.ChangeItem changeItem) throws RemoteException; + void verify(IUidObserver observer, ChangeRecord changeItem) throws RemoteException; } private void verifyObserverReceivedChanges(IUidObserver observer, int[] changesToVerify, - Map<Integer, UidRecord.ChangeItem> changeItems, ObserverChangesVerifier verifier) + Map<Integer, ChangeRecord> changeItems, ObserverChangesVerifier verifier) throws RemoteException { for (int change : changesToVerify) { - final UidRecord.ChangeItem changeItem = changeItems.get(change); + final ChangeRecord changeItem = changeItems.get(change); verifier.verify(observer, changeItem); } } @@ -641,59 +643,59 @@ public class ActivityManagerServiceTest { // So, resetting the mock here. Mockito.reset(observer); - final UidRecord.ChangeItem changeItem = new UidRecord.ChangeItem(); + final ChangeRecord changeItem = new ChangeRecord(); changeItem.uid = TEST_UID; changeItem.change = UidRecord.CHANGE_PROCSTATE; - changeItem.processState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY; + changeItem.procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY; changeItem.procStateSeq = 111; - mAms.mUidObserverController.mPendingUidChanges.add(changeItem); + addPendingUidChange(changeItem); mAms.mUidObserverController.dispatchUidsChanged(); // First process state message is always delivered regardless of whether the process state // change is above or below the cutpoint (PROCESS_STATE_SERVICE). verify(observer).onUidStateChanged(TEST_UID, - changeItem.processState, changeItem.procStateSeq, + changeItem.procState, changeItem.procStateSeq, ActivityManager.PROCESS_CAPABILITY_NONE); verifyNoMoreInteractions(observer); - changeItem.processState = ActivityManager.PROCESS_STATE_RECEIVER; - mAms.mUidObserverController.mPendingUidChanges.add(changeItem); + changeItem.procState = ActivityManager.PROCESS_STATE_RECEIVER; + addPendingUidChange(changeItem); mAms.mUidObserverController.dispatchUidsChanged(); // Previous process state change is below cutpoint (PROCESS_STATE_SERVICE) and // the current process state change is also below cutpoint, so no callback will be invoked. verifyNoMoreInteractions(observer); - changeItem.processState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE; - mAms.mUidObserverController.mPendingUidChanges.add(changeItem); + changeItem.procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE; + addPendingUidChange(changeItem); mAms.mUidObserverController.dispatchUidsChanged(); // Previous process state change is below cutpoint (PROCESS_STATE_SERVICE) and // the current process state change is above cutpoint, so callback will be invoked with the // current process state change. verify(observer).onUidStateChanged(TEST_UID, - changeItem.processState, changeItem.procStateSeq, + changeItem.procState, changeItem.procStateSeq, ActivityManager.PROCESS_CAPABILITY_NONE); verifyNoMoreInteractions(observer); - changeItem.processState = ActivityManager.PROCESS_STATE_TOP; - mAms.mUidObserverController.mPendingUidChanges.add(changeItem); + changeItem.procState = ActivityManager.PROCESS_STATE_TOP; + addPendingUidChange(changeItem); mAms.mUidObserverController.dispatchUidsChanged(); // Previous process state change is above cutpoint (PROCESS_STATE_SERVICE) and // the current process state change is also above cutpoint, so no callback will be invoked. verifyNoMoreInteractions(observer); - changeItem.processState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; - mAms.mUidObserverController.mPendingUidChanges.add(changeItem); + changeItem.procState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; + addPendingUidChange(changeItem); mAms.mUidObserverController.dispatchUidsChanged(); // Previous process state change is above cutpoint (PROCESS_STATE_SERVICE) and // the current process state change is below cutpoint, so callback will be invoked with the // current process state change. verify(observer).onUidStateChanged(TEST_UID, - changeItem.processState, changeItem.procStateSeq, + changeItem.procState, changeItem.procStateSeq, ActivityManager.PROCESS_CAPABILITY_NONE); verifyNoMoreInteractions(observer); } /** - * This test verifies that {@link ActivityManagerService#mValidateUids} which is a + * This test verifies that {@link UidObserverController#getValidateUidsForTest()} which is a * part of dumpsys is correctly updated. */ @Test @@ -707,45 +709,45 @@ public class ActivityManagerServiceTest { ActivityManager.PROCESS_STATE_SERVICE, ActivityManager.PROCESS_STATE_RECEIVER }; - final ArrayList<UidRecord.ChangeItem> pendingItemsForUids = + final ArrayList<ChangeRecord> pendingItemsForUids = new ArrayList<>(changesForPendingItems.length); for (int i = 0; i < changesForPendingItems.length; ++i) { - final UidRecord.ChangeItem item = new UidRecord.ChangeItem(); + final ChangeRecord item = new ChangeRecord(); item.uid = i; item.change = changesForPendingItems[i]; - item.processState = procStatesForPendingItems[i]; + item.procState = procStatesForPendingItems[i]; pendingItemsForUids.add(i, item); } // Verify that when there no observers listening to uid state changes, then there will // be no changes to validateUids. - mAms.mUidObserverController.mPendingUidChanges.addAll(pendingItemsForUids); + addPendingUidChanges(pendingItemsForUids); mAms.mUidObserverController.dispatchUidsChanged(); assertEquals("No observers registered, so validateUids should be empty", - 0, mAms.mUidObserverController.mValidateUids.size()); + 0, mAms.mUidObserverController.getValidateUidsForTest().size()); final IUidObserver observer = mock(IUidObserver.Stub.class); when(observer.asBinder()).thenReturn((IBinder) observer); mAms.registerUidObserver(observer, 0, 0, null); // Verify that when observers are registered, then validateUids is correctly updated. - mAms.mUidObserverController.mPendingUidChanges.addAll(pendingItemsForUids); + addPendingUidChanges(pendingItemsForUids); mAms.mUidObserverController.dispatchUidsChanged(); for (int i = 0; i < pendingItemsForUids.size(); ++i) { - final UidRecord.ChangeItem item = pendingItemsForUids.get(i); + final ChangeRecord item = pendingItemsForUids.get(i); final UidRecord validateUidRecord = - mAms.mUidObserverController.mValidateUids.get(item.uid); + mAms.mUidObserverController.getValidateUidsForTest().get(item.uid); if ((item.change & UidRecord.CHANGE_GONE) != 0) { assertNull("validateUidRecord should be null since the change is either " + "CHANGE_GONE or CHANGE_GONE_IDLE", validateUidRecord); } else { assertNotNull("validateUidRecord should not be null since the change is neither " + "CHANGE_GONE nor CHANGE_GONE_IDLE", validateUidRecord); - assertEquals("processState: " + item.processState + " curProcState: " + assertEquals("processState: " + item.procState + " curProcState: " + validateUidRecord.getCurProcState() + " should have been equal", - item.processState, validateUidRecord.getCurProcState()); - assertEquals("processState: " + item.processState + " setProcState: " + item.procState, validateUidRecord.getCurProcState()); + assertEquals("processState: " + item.procState + " setProcState: " + validateUidRecord.getCurProcState() + " should have been equal", - item.processState, validateUidRecord.setProcState); + item.procState, validateUidRecord.setProcState); if (item.change == UidRecord.CHANGE_IDLE) { assertTrue("UidRecord.idle should be updated to true for CHANGE_IDLE", validateUidRecord.idle); @@ -759,19 +761,19 @@ public class ActivityManagerServiceTest { // Verify that when uid state changes to CHANGE_GONE or CHANGE_GONE_IDLE, then it // will be removed from validateUids. assertNotEquals("validateUids should not be empty", 0, - mAms.mUidObserverController.mValidateUids.size()); + mAms.mUidObserverController.getValidateUidsForTest().size()); for (int i = 0; i < pendingItemsForUids.size(); ++i) { - final UidRecord.ChangeItem item = pendingItemsForUids.get(i); + final ChangeRecord item = pendingItemsForUids.get(i); // Assign CHANGE_GONE_IDLE to some items and CHANGE_GONE to the others, using even/odd // distribution for this assignment. item.change = (i % 2) == 0 ? (UidRecord.CHANGE_GONE | UidRecord.CHANGE_IDLE) : UidRecord.CHANGE_GONE; } - mAms.mUidObserverController.mPendingUidChanges.addAll(pendingItemsForUids); + addPendingUidChanges(pendingItemsForUids); mAms.mUidObserverController.dispatchUidsChanged(); assertEquals("validateUids should be empty, size=" - + mAms.mUidObserverController.mValidateUids.size(), - 0, mAms.mUidObserverController.mValidateUids.size()); + + mAms.mUidObserverController.getValidateUidsForTest().size(), + 0, mAms.mUidObserverController.getValidateUidsForTest().size()); } @Test @@ -784,8 +786,6 @@ public class ActivityManagerServiceTest { // Add a pending change for TEST_UID and verify enqueueUidChangeLocked still works as // expected. - final UidRecord.ChangeItem changeItem = new UidRecord.ChangeItem(); - uidRecord.pendingChange = changeItem; uidRecord.curProcStateSeq = TEST_PROC_STATE_SEQ2; verifyLastProcStateSeqUpdated(uidRecord, -1, TEST_PROC_STATE_SEQ2); } @@ -793,7 +793,7 @@ public class ActivityManagerServiceTest { @Test public void testEnqueueUidChangeLocked_nullUidRecord() { // Use "null" uidRecord to make sure there is no crash. - mAms.mUidObserverController.enqueueUidChangeLocked(null, TEST_UID, UidRecord.CHANGE_ACTIVE); + mAms.enqueueUidChangeLocked(null, TEST_UID, UidRecord.CHANGE_ACTIVE); } private void verifyLastProcStateSeqUpdated(UidRecord uidRecord, int uid, long curProcstateSeq) { @@ -802,7 +802,7 @@ public class ActivityManagerServiceTest { final int changeToDispatch = UID_RECORD_CHANGES[i]; // Reset lastProcStateSeqDispatchToObservers after every test. uidRecord.lastDispatchedProcStateSeq = 0; - mAms.mUidObserverController.enqueueUidChangeLocked(uidRecord, uid, changeToDispatch); + mAms.enqueueUidChangeLocked(uidRecord, uid, changeToDispatch); // Verify there is no effect on curProcStateSeq. assertEquals(curProcstateSeq, uidRecord.curProcStateSeq); if ((changeToDispatch & UidRecord.CHANGE_GONE) != 0) { @@ -833,16 +833,16 @@ public class ActivityManagerServiceTest { // Reset the current state mHandler.reset(); - uidRecord.pendingChange = null; - mAms.mUidObserverController.mPendingUidChanges.clear(); + clearPendingUidChanges(); - mAms.mUidObserverController.enqueueUidChangeLocked(uidRecord, -1, changeToDispatch); + mAms.enqueueUidChangeLocked(uidRecord, -1, changeToDispatch); - // Verify that UidRecord.pendingChange is updated correctly. - assertNotNull(uidRecord.pendingChange); - assertEquals(TEST_UID, uidRecord.pendingChange.uid); - assertEquals(expectedProcState, uidRecord.pendingChange.processState); - assertEquals(TEST_PROC_STATE_SEQ1, uidRecord.pendingChange.procStateSeq); + // Verify that pendingChange is updated correctly. + final ChangeRecord pendingChange = getPendingChange(uidRecord.uid); + assertNotNull(pendingChange); + assertEquals(TEST_UID, pendingChange.uid); + assertEquals(expectedProcState, pendingChange.procState); + assertEquals(TEST_PROC_STATE_SEQ1, pendingChange.procStateSeq); // TODO: Verify that DISPATCH_UIDS_CHANGED_UI_MSG is posted to handler. } @@ -923,6 +923,29 @@ public class ActivityManagerServiceTest { mAms.mProcessList.mActiveUids.clear(); } + private ChangeRecord getPendingChange(int uid) { + final SparseArray<ChangeRecord> pendingChanges = + mAms.mUidObserverController.getPendingUidChangesForTest(); + return pendingChanges.get(uid); + } + + private void addPendingUidChange(ChangeRecord record) { + mAms.mUidObserverController.getPendingUidChangesForTest().put(record.uid, record); + } + + private void addPendingUidChanges(ArrayList<ChangeRecord> changes) { + final SparseArray<ChangeRecord> pendingChanges = + mAms.mUidObserverController.getPendingUidChangesForTest(); + for (int i = 0; i < changes.size(); ++i) { + final ChangeRecord record = changes.get(i); + pendingChanges.put(record.uid, record); + } + } + + private void clearPendingUidChanges() { + mAms.mUidObserverController.getPendingUidChangesForTest().clear(); + } + private static class TestHandler extends Handler { private static final long WAIT_FOR_MSG_TIMEOUT_MS = 4000; // 4 sec private static final long WAIT_FOR_MSG_INTERVAL_MS = 400; // 0.4 sec diff --git a/services/tests/servicestests/src/com/android/server/am/UidObserverControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UidObserverControllerTest.java new file mode 100644 index 000000000000..57c581ea132f --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/am/UidObserverControllerTest.java @@ -0,0 +1,233 @@ +/* + * Copyright (C) 2020 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.am; + +import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL; +import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION; +import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE; +import static android.app.ActivityManager.PROCESS_STATE_CACHED_RECENT; +import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE; +import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND; +import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; +import static android.app.ActivityManager.PROCESS_STATE_RECEIVER; +import static android.app.ActivityManager.PROCESS_STATE_SERVICE; +import static android.app.ActivityManager.PROCESS_STATE_TOP; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertNull; + +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +import android.app.ActivityManager; +import android.app.IUidObserver; +import android.os.Handler; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.DebugUtils; +import android.util.Pair; +import android.util.SparseArray; + +import androidx.test.filters.SmallTest; + +import com.android.server.am.UidObserverController.ChangeRecord; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; + +@SmallTest +public class UidObserverControllerTest { + private static final int TEST_UID1 = 1111; + private static final int TEST_UID2 = 2222; + private static final int TEST_UID3 = 3333; + + private static final String TEST_PKG1 = "com.example1"; + private static final String TEST_PKG2 = "com.example2"; + private static final String TEST_PKG3 = "com.example3"; + + private UidObserverController mUidObserverController; + + @Before + public void setUp() { + mUidObserverController = new UidObserverController(Mockito.mock(Handler.class)); + } + + @Test + public void testEnqueueUidChange() { + int change = mUidObserverController.enqueueUidChange(TEST_UID1, UidRecord.CHANGE_ACTIVE, + PROCESS_STATE_FOREGROUND_SERVICE, PROCESS_CAPABILITY_ALL, 0, false); + assertEquals("expected=ACTIVE,actual=" + changeToStr(change), + UidRecord.CHANGE_ACTIVE, change); + assertPendingChange(TEST_UID1, UidRecord.CHANGE_ACTIVE, PROCESS_STATE_FOREGROUND_SERVICE, + PROCESS_CAPABILITY_ALL, 0, false); + assertNull(getPendingChange(TEST_UID2)); + + change = mUidObserverController.enqueueUidChange(TEST_UID2, UidRecord.CHANGE_CACHED, + PROCESS_STATE_CACHED_RECENT, PROCESS_CAPABILITY_NONE, 99, true); + assertEquals("expected=ACTIVE,actual=" + changeToStr(change), + UidRecord.CHANGE_CACHED, change); + assertPendingChange(TEST_UID1, UidRecord.CHANGE_ACTIVE, PROCESS_STATE_FOREGROUND_SERVICE, + PROCESS_CAPABILITY_ALL, 0, false); + assertPendingChange(TEST_UID2, UidRecord.CHANGE_CACHED, PROCESS_STATE_CACHED_RECENT, + PROCESS_CAPABILITY_NONE, 99, true); + + change = mUidObserverController.enqueueUidChange(TEST_UID1, UidRecord.CHANGE_UNCACHED, + PROCESS_STATE_TOP, PROCESS_CAPABILITY_ALL, 0, false); + assertEquals("expected=ACTIVE|UNCACHED,actual=" + changeToStr(change), + UidRecord.CHANGE_ACTIVE | UidRecord.CHANGE_UNCACHED, change); + assertPendingChange(TEST_UID1, UidRecord.CHANGE_ACTIVE | UidRecord.CHANGE_UNCACHED, + PROCESS_STATE_TOP, PROCESS_CAPABILITY_ALL, 0, false); + assertPendingChange(TEST_UID2, UidRecord.CHANGE_CACHED, PROCESS_STATE_CACHED_RECENT, + PROCESS_CAPABILITY_NONE, 99, true); + } + + @Test + public void testMergeWithPendingChange() { + final SparseArray<Pair<Integer, Integer>> changesToVerify = new SparseArray<>(); + + changesToVerify.put(UidRecord.CHANGE_ACTIVE, + Pair.create(UidRecord.CHANGE_ACTIVE, UidRecord.CHANGE_IDLE)); + changesToVerify.put(UidRecord.CHANGE_IDLE, + Pair.create(UidRecord.CHANGE_IDLE, UidRecord.CHANGE_ACTIVE)); + changesToVerify.put(UidRecord.CHANGE_CACHED, + Pair.create(UidRecord.CHANGE_CACHED, UidRecord.CHANGE_UNCACHED)); + changesToVerify.put(UidRecord.CHANGE_UNCACHED, + Pair.create(UidRecord.CHANGE_UNCACHED, UidRecord.CHANGE_CACHED)); + changesToVerify.put(UidRecord.CHANGE_ACTIVE | UidRecord.CHANGE_UNCACHED, + Pair.create(UidRecord.CHANGE_ACTIVE, UidRecord.CHANGE_UNCACHED)); + changesToVerify.put(UidRecord.CHANGE_IDLE | UidRecord.CHANGE_CACHED, + Pair.create(UidRecord.CHANGE_IDLE, UidRecord.CHANGE_CACHED)); + changesToVerify.put(UidRecord.CHANGE_GONE, + Pair.create(UidRecord.CHANGE_GONE, UidRecord.CHANGE_ACTIVE)); + changesToVerify.put(UidRecord.CHANGE_GONE, + Pair.create(UidRecord.CHANGE_GONE, UidRecord.CHANGE_CACHED)); + + for (int i = 0; i < changesToVerify.size(); ++i) { + final int expectedChange = changesToVerify.keyAt(i); + final int currentChange = changesToVerify.valueAt(i).first; + final int pendingChange = changesToVerify.valueAt(i).second; + assertEquals("current=" + changeToStr(currentChange) + ", pending=" + + changeToStr(pendingChange) + "exp=" + changeToStr(expectedChange), + expectedChange, UidObserverController.mergeWithPendingChange( + currentChange, pendingChange)); + } + } + + @Test + public void testDispatchUidsChanged() throws RemoteException { + addPendingChange(TEST_UID1, UidRecord.CHANGE_ACTIVE | UidRecord.CHANGE_PROCSTATE, + PROCESS_STATE_TOP, 0, PROCESS_CAPABILITY_ALL, false); + + final IUidObserver observer1 = Mockito.mock(IUidObserver.Stub.class); + registerObserver(observer1, + ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_ACTIVE, + PROCESS_STATE_IMPORTANT_FOREGROUND, TEST_PKG2, TEST_UID2); + final IUidObserver observer2 = Mockito.mock(IUidObserver.Stub.class); + registerObserver(observer2, ActivityManager.UID_OBSERVER_PROCSTATE, + PROCESS_STATE_SERVICE, TEST_PKG3, TEST_UID3); + + mUidObserverController.dispatchUidsChanged(); + verify(observer1).onUidStateChanged(TEST_UID1, PROCESS_STATE_TOP, + 0, PROCESS_CAPABILITY_ALL); + verify(observer1).onUidActive(TEST_UID1); + verifyNoMoreInteractions(observer1); + verify(observer2).onUidStateChanged(TEST_UID1, PROCESS_STATE_TOP, + 0, PROCESS_CAPABILITY_ALL); + verifyNoMoreInteractions(observer2); + + addPendingChange(TEST_UID1, UidRecord.CHANGE_PROCSTATE, PROCESS_STATE_IMPORTANT_BACKGROUND, + 99, PROCESS_CAPABILITY_FOREGROUND_LOCATION, false); + mUidObserverController.dispatchUidsChanged(); + verify(observer1).onUidStateChanged(TEST_UID1, PROCESS_STATE_IMPORTANT_BACKGROUND, + 99, PROCESS_CAPABILITY_FOREGROUND_LOCATION); + verifyNoMoreInteractions(observer1); + verifyNoMoreInteractions(observer2); + + addPendingChange(TEST_UID1, UidRecord.CHANGE_PROCSTATE, PROCESS_STATE_RECEIVER, + 111, PROCESS_CAPABILITY_NONE, false); + mUidObserverController.dispatchUidsChanged(); + verify(observer2).onUidStateChanged(TEST_UID1, PROCESS_STATE_RECEIVER, + 111, PROCESS_CAPABILITY_NONE); + verifyNoMoreInteractions(observer1); + verifyNoMoreInteractions(observer2); + + unregisterObserver(observer1); + + addPendingChange(TEST_UID1, UidRecord.CHANGE_PROCSTATE, PROCESS_STATE_TOP, + 112, PROCESS_CAPABILITY_ALL, false); + mUidObserverController.dispatchUidsChanged(); + verify(observer2).onUidStateChanged(TEST_UID1, PROCESS_STATE_TOP, + 112, PROCESS_CAPABILITY_ALL); + verifyNoMoreInteractions(observer1); + verifyNoMoreInteractions(observer2); + + unregisterObserver(observer2); + + addPendingChange(TEST_UID1, UidRecord.CHANGE_PROCSTATE, PROCESS_STATE_CACHED_RECENT, + 112, PROCESS_CAPABILITY_NONE, false); + mUidObserverController.dispatchUidsChanged(); + verifyNoMoreInteractions(observer1); + verifyNoMoreInteractions(observer2); + } + + private void registerObserver(IUidObserver observer, int which, int cutpoint, + String callingPackage, int callingUid) { + when(observer.asBinder()).thenReturn((IBinder) observer); + mUidObserverController.register(observer, which, cutpoint, callingPackage, callingUid); + Mockito.reset(observer); + } + + private void unregisterObserver(IUidObserver observer) { + when(observer.asBinder()).thenReturn((IBinder) observer); + mUidObserverController.unregister(observer); + Mockito.reset(observer); + } + + private void addPendingChange(int uid, int change, int procState, long procStateSeq, + int capability, boolean ephemeral) { + final ChangeRecord record = new ChangeRecord(); + record.uid = uid; + record.change = change; + record.procState = procState; + record.procStateSeq = procStateSeq; + record.capability = capability; + record.ephemeral = ephemeral; + mUidObserverController.getPendingUidChangesForTest().put(uid, record); + } + + private void assertPendingChange(int uid, int change, int procState, long procStateSeq, + int capability, boolean ephemeral) { + final ChangeRecord record = getPendingChange(uid); + assertNotNull(record); + assertEquals(change, record.change); + assertEquals(procState, record.procState); + assertEquals(procStateSeq, record.procStateSeq); + assertEquals(capability, record.capability); + assertEquals(ephemeral, record.ephemeral); + } + + private ChangeRecord getPendingChange(int uid) { + return mUidObserverController.getPendingUidChangesForTest().get(uid); + } + + private static String changeToStr(int change) { + return DebugUtils.flagsToString(UidRecord.class, "CHANGE_", change); + } +} diff --git a/services/tests/servicestests/src/com/android/server/pm/IncrementalStatesTest.java b/services/tests/servicestests/src/com/android/server/pm/IncrementalStatesTest.java index 62e135b09593..c4c2f68e8219 100644 --- a/services/tests/servicestests/src/com/android/server/pm/IncrementalStatesTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/IncrementalStatesTest.java @@ -146,7 +146,7 @@ public class IncrementalStatesTest { // Test that package is now unstartable assertTrue(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS)); assertFalse(mIncrementalStates.isStartable()); - assertEquals(PackageManager.UNSTARTABLE_REASON_DATALOADER_TRANSPORT, + assertEquals(PackageManager.UNSTARTABLE_REASON_CONNECTION_ERROR, mUnstartableReason.get()); } @@ -160,7 +160,7 @@ public class IncrementalStatesTest { // Test that package is now unstartable assertTrue(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS)); assertFalse(mIncrementalStates.isStartable()); - assertEquals(PackageManager.UNSTARTABLE_REASON_DATALOADER_TRANSPORT, + assertEquals(PackageManager.UNSTARTABLE_REASON_CONNECTION_ERROR, mUnstartableReason.get()); } @@ -181,7 +181,7 @@ public class IncrementalStatesTest { // Test that package is now unstartable assertTrue(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS)); assertFalse(mIncrementalStates.isStartable()); - assertEquals(PackageManager.UNSTARTABLE_REASON_DATALOADER_STORAGE, + assertEquals(PackageManager.UNSTARTABLE_REASON_INSUFFICIENT_STORAGE, mUnstartableReason.get()); } @@ -202,7 +202,7 @@ public class IncrementalStatesTest { // Test that package is now unstartable assertTrue(mUnstartableCalled.block(WAIT_TIMEOUT_MILLIS)); assertFalse(mIncrementalStates.isStartable()); - assertEquals(PackageManager.UNSTARTABLE_REASON_DATALOADER_STORAGE, + assertEquals(PackageManager.UNSTARTABLE_REASON_INSUFFICIENT_STORAGE, mUnstartableReason.get()); } diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java index 22b07157e94e..75799562abfa 100644 --- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java @@ -41,6 +41,7 @@ import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.SmallTest; import android.util.Slog; +import androidx.annotation.Nullable; import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; @@ -58,6 +59,8 @@ import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import javax.annotation.concurrent.GuardedBy; + /** Test {@link UserManager} functionality. */ @RunWith(AndroidJUnit4.class) public final class UserManagerTest { @@ -134,7 +137,7 @@ public final class UserManagerTest { @SmallTest @Test public void testHasSystemUser() throws Exception { - assertThat(findUser(UserHandle.USER_SYSTEM)).isTrue(); + assertThat(hasUser(UserHandle.USER_SYSTEM)).isTrue(); } @MediumTest @@ -164,9 +167,9 @@ public final class UserManagerTest { assertThat(user1).isNotNull(); assertThat(user2).isNotNull(); - assertThat(findUser(UserHandle.USER_SYSTEM)).isTrue(); - assertThat(findUser(user1.id)).isTrue(); - assertThat(findUser(user2.id)).isTrue(); + assertThat(hasUser(UserHandle.USER_SYSTEM)).isTrue(); + assertThat(hasUser(user1.id)).isTrue(); + assertThat(hasUser(user2.id)).isTrue(); } @MediumTest @@ -175,7 +178,7 @@ public final class UserManagerTest { UserInfo userInfo = createUser("Guest 1", UserInfo.FLAG_GUEST); removeUser(userInfo.id); - assertThat(findUser(userInfo.id)).isFalse(); + assertThat(hasUser(userInfo.id)).isFalse(); } @MediumTest @@ -199,7 +202,7 @@ public final class UserManagerTest { } } - assertThat(findUser(userInfo.id)).isFalse(); + assertThat(hasUser(userInfo.id)).isFalse(); } @MediumTest @@ -208,6 +211,79 @@ public final class UserManagerTest { assertThrows(IllegalArgumentException.class, () -> mUserManager.removeUser(null)); } + @MediumTest + @Test + public void testRemoveUserOrSetEphemeral_restrictedReturnsError() throws Exception { + final int currentUser = ActivityManager.getCurrentUser(); + final UserInfo user1 = createUser("User 1", /* flags= */ 0); + mUserManager.setUserRestriction(UserManager.DISALLOW_REMOVE_USER, /* value= */ true, + asHandle(currentUser)); + try { + assertThat(mUserManager.removeUserOrSetEphemeral(user1.id)).isEqualTo( + UserManagerService.REMOVE_RESULT_ERROR); + } finally { + mUserManager.setUserRestriction(UserManager.DISALLOW_REMOVE_USER, /* value= */ false, + asHandle(currentUser)); + } + + assertThat(hasUser(user1.id)).isTrue(); + assertThat(getUser(user1.id).isEphemeral()).isFalse(); + } + + @MediumTest + @Test + public void testRemoveUserOrSetEphemeral_systemUserReturnsError() throws Exception { + assertThat(mUserManager.removeUserOrSetEphemeral(UserHandle.USER_SYSTEM)).isEqualTo( + UserManagerService.REMOVE_RESULT_ERROR); + + assertThat(hasUser(UserHandle.USER_SYSTEM)).isTrue(); + } + + @MediumTest + @Test + public void testRemoveUserOrSetEphemeral_invalidUserReturnsError() throws Exception { + assertThat(hasUser(Integer.MAX_VALUE)).isFalse(); + assertThat(mUserManager.removeUserOrSetEphemeral(Integer.MAX_VALUE)).isEqualTo( + UserManagerService.REMOVE_RESULT_ERROR); + } + + @MediumTest + @Test + public void testRemoveUserOrSetEphemeral_currentUserSetEphemeral() throws Exception { + final int startUser = ActivityManager.getCurrentUser(); + final UserInfo user1 = createUser("User 1", /* flags= */ 0); + // Switch to the user just created. + switchUser(user1.id, null, /* ignoreHandle= */ true); + + assertThat(mUserManager.removeUserOrSetEphemeral(user1.id)).isEqualTo( + UserManagerService.REMOVE_RESULT_SET_EPHEMERAL); + + assertThat(hasUser(user1.id)).isTrue(); + assertThat(getUser(user1.id).isEphemeral()).isTrue(); + + // Switch back to the starting user. + switchUser(startUser, null, /* ignoreHandle= */ true); + + // User is removed once switch is complete + synchronized (mUserRemoveLock) { + waitForUserRemovalLocked(user1.id); + } + assertThat(hasUser(user1.id)).isFalse(); + } + + @MediumTest + @Test + public void testRemoveUserOrSetEphemeral_nonCurrentUserRemoved() throws Exception { + final UserInfo user1 = createUser("User 1", /* flags= */ 0); + synchronized (mUserRemoveLock) { + assertThat(mUserManager.removeUserOrSetEphemeral(user1.id)).isEqualTo( + UserManagerService.REMOVE_RESULT_REMOVED); + waitForUserRemovalLocked(user1.id); + } + + assertThat(hasUser(user1.id)).isFalse(); + } + /** Tests creating a FULL user via specifying userType. */ @MediumTest @Test @@ -608,15 +684,20 @@ public final class UserManagerTest { () -> mUserManager.getUserCreationTime(asHandle(user.id))); } - private boolean findUser(int id) { + @Nullable + private UserInfo getUser(int id) { List<UserInfo> list = mUserManager.getUsers(); for (UserInfo user : list) { if (user.id == id) { - return true; + return user; } } - return false; + return null; + } + + private boolean hasUser(int id) { + return getUser(id) != null; } @MediumTest @@ -918,17 +999,22 @@ public final class UserManagerTest { private void removeUser(int userId) { synchronized (mUserRemoveLock) { mUserManager.removeUser(userId); - long time = System.currentTimeMillis(); - while (mUserManager.getUserInfo(userId) != null) { - try { - mUserRemoveLock.wait(REMOVE_CHECK_INTERVAL_MILLIS); - } catch (InterruptedException ie) { - Thread.currentThread().interrupt(); - return; - } - if (System.currentTimeMillis() - time > REMOVE_TIMEOUT_MILLIS) { - fail("Timeout waiting for removeUser. userId = " + userId); - } + waitForUserRemovalLocked(userId); + } + } + + @GuardedBy("mUserRemoveLock") + private void waitForUserRemovalLocked(int userId) { + long time = System.currentTimeMillis(); + while (mUserManager.getUserInfo(userId) != null) { + try { + mUserRemoveLock.wait(REMOVE_CHECK_INTERVAL_MILLIS); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + return; + } + if (System.currentTimeMillis() - time > REMOVE_TIMEOUT_MILLIS) { + fail("Timeout waiting for removeUser. userId = " + userId); } } } diff --git a/services/usb/java/com/android/server/usb/MtpNotificationManager.java b/services/usb/java/com/android/server/usb/MtpNotificationManager.java index 462ee19124ff..39f2f296a305 100644 --- a/services/usb/java/com/android/server/usb/MtpNotificationManager.java +++ b/services/usb/java/com/android/server/usb/MtpNotificationManager.java @@ -64,12 +64,13 @@ class MtpNotificationManager { private final Context mContext; private final OnOpenInAppListener mListener; + private final Receiver mReceiver; MtpNotificationManager(Context context, OnOpenInAppListener listener) { mContext = context; mListener = listener; - final Receiver receiver = new Receiver(); - context.registerReceiver(receiver, new IntentFilter(ACTION_OPEN_IN_APPS)); + mReceiver = new Receiver(); + context.registerReceiver(mReceiver, new IntentFilter(ACTION_OPEN_IN_APPS)); } void showNotification(UsbDevice device) { @@ -154,4 +155,8 @@ class MtpNotificationManager { static interface OnOpenInAppListener { void onOpenInApp(UsbDevice device); } + + public void unregister() { + mContext.unregisterReceiver(mReceiver); + } } diff --git a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java index d7b6b5d0d36a..26ee03c25013 100644 --- a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java +++ b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java @@ -261,6 +261,15 @@ class UsbProfileGroupSettingsManager { } /** + * Unregister all broadcast receivers. Must be called explicitly before + * object deletion. + */ + public void unregisterReceivers() { + mPackageMonitor.unregister(); + mMtpNotificationManager.unregister(); + } + + /** * Remove all defaults and denied packages for a user. * * @param userToRemove The user diff --git a/services/usb/java/com/android/server/usb/UsbSettingsManager.java b/services/usb/java/com/android/server/usb/UsbSettingsManager.java index 7b677eea6b8f..8e53ff412f0a 100644 --- a/services/usb/java/com/android/server/usb/UsbSettingsManager.java +++ b/services/usb/java/com/android/server/usb/UsbSettingsManager.java @@ -124,6 +124,7 @@ class UsbSettingsManager { if (mSettingsByProfileGroup.indexOfKey(userToRemove.getIdentifier()) >= 0) { // The user to remove is the parent user of the group. The parent is the last user // that gets removed. All state will be removed with the user + mSettingsByProfileGroup.get(userToRemove.getIdentifier()).unregisterReceivers(); mSettingsByProfileGroup.remove(userToRemove.getIdentifier()); } else { // We cannot find the parent user of the user that is removed, hence try to remove diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java index 917f65ab7c01..547d253501e8 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java @@ -1048,9 +1048,9 @@ public class VoiceInteractionManagerService extends SystemService { if (unloadStatus != SoundTriggerInternal.STATUS_OK) { Slog.w(TAG, "Unable to unload keyphrase sound model:" + unloadStatus); } - deleted = mDbHelper.deleteKeyphraseSoundModel(keyphraseId, callingUserId, - bcp47Locale); } + deleted = mDbHelper.deleteKeyphraseSoundModel(keyphraseId, callingUserId, + bcp47Locale); return deleted ? SoundTriggerInternal.STATUS_OK : SoundTriggerInternal.STATUS_ERROR; } finally { if (deleted) { diff --git a/telephony/api/system-current.txt b/telephony/api/system-current.txt index 4fb7302a5c5f..a67273cfc908 100644 --- a/telephony/api/system-current.txt +++ b/telephony/api/system-current.txt @@ -227,6 +227,25 @@ package android.telephony { field public static final String MBMS_STREAMING_SERVICE_ACTION = "android.telephony.action.EmbmsStreaming"; } + public final class ModemActivityInfo implements android.os.Parcelable { + method public int describeContents(); + method @NonNull public android.telephony.ModemActivityInfo getDelta(@NonNull android.telephony.ModemActivityInfo); + method public long getIdleTimeMillis(); + method public static int getNumTxPowerLevels(); + method public long getReceiveTimeMillis(); + method public long getSleepTimeMillis(); + method public long getTimestampMillis(); + method public long getTransmitDurationMillisAtPowerLevel(int); + method @NonNull public android.util.Range<java.lang.Integer> getTransmitPowerRange(int); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ModemActivityInfo> CREATOR; + field public static final int TX_POWER_LEVEL_0 = 0; // 0x0 + field public static final int TX_POWER_LEVEL_1 = 1; // 0x1 + field public static final int TX_POWER_LEVEL_2 = 2; // 0x2 + field public static final int TX_POWER_LEVEL_3 = 3; // 0x3 + field public static final int TX_POWER_LEVEL_4 = 4; // 0x4 + } + public final class NetworkRegistrationInfo implements android.os.Parcelable { method @Nullable public android.telephony.DataSpecificRegistrationInfo getDataSpecificInfo(); method public int getRegistrationState(); diff --git a/telephony/java/android/telephony/CellSignalStrength.java b/telephony/java/android/telephony/CellSignalStrength.java index 2e7bde3b3d89..e0896570d3ed 100644 --- a/telephony/java/android/telephony/CellSignalStrength.java +++ b/telephony/java/android/telephony/CellSignalStrength.java @@ -17,6 +17,7 @@ package android.telephony; import android.annotation.IntRange; +import android.annotation.SystemApi; import android.os.PersistableBundle; /** @@ -155,11 +156,12 @@ public abstract class CellSignalStrength { /** * Returns the number of signal strength levels. - * @return Number of signal strength levels, enforced to be 5 + * @return Number of signal strength levels, currently defined in the HAL as 5. * * @hide */ - public static final int getNumSignalStrengthLevels() { + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static int getNumSignalStrengthLevels() { return NUM_SIGNAL_STRENGTH_BINS; } } diff --git a/telephony/java/android/telephony/ModemActivityInfo.java b/telephony/java/android/telephony/ModemActivityInfo.java index debb119c94bc..881d85c73b5d 100644 --- a/telephony/java/android/telephony/ModemActivityInfo.java +++ b/telephony/java/android/telephony/ModemActivityInfo.java @@ -16,8 +16,12 @@ package android.telephony; +import android.annotation.DurationMillisLong; +import android.annotation.ElapsedRealtimeLong; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; import android.os.SystemClock; @@ -25,46 +29,50 @@ import android.util.Range; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import java.util.ArrayList; -import java.util.List; +import java.util.Arrays; +import java.util.Objects; /** - * Reports modem activity information. + * Contains information about the modem's activity. May be useful for power stats reporting. * @hide */ +@SystemApi +@TestApi public final class ModemActivityInfo implements Parcelable { + private static final int TX_POWER_LEVELS = 5; + /** - * Tx(transmit) power level. see power index below - * <ul> - * <li> index 0 = tx_power < 0dBm. </li> - * <li> index 1 = 0dBm < tx_power < 5dBm. </li> - * <li> index 2 = 5dBm < tx_power < 15dBm. </li> - * <li> index 3 = 15dBm < tx_power < 20dBm. </li> - * <li> index 4 = tx_power > 20dBm. </li> - * </ul> - */ - public static final int TX_POWER_LEVELS = 5; - /** - * Tx(transmit) power level 0: tx_power < 0dBm + * Corresponds to transmit power of less than 0dBm. */ public static final int TX_POWER_LEVEL_0 = 0; + /** - * Tx(transmit) power level 1: 0dBm < tx_power < 5dBm + * Corresponds to transmit power between 0dBm and 5dBm. */ public static final int TX_POWER_LEVEL_1 = 1; + /** - * Tx(transmit) power level 2: 5dBm < tx_power < 15dBm + * Corresponds to transmit power between 5dBm and 15dBm. */ public static final int TX_POWER_LEVEL_2 = 2; + /** - * Tx(transmit) power level 3: 15dBm < tx_power < 20dBm. + * Corresponds to transmit power between 15dBm and 20dBm. */ public static final int TX_POWER_LEVEL_3 = 3; + /** - * Tx(transmit) power level 4: tx_power > 20dBm + * Corresponds to transmit power above 20dBm. */ public static final int TX_POWER_LEVEL_4 = 4; + /** + * The number of transmit power levels. Fixed by HAL definition. + */ + public static int getNumTxPowerLevels() { + return TX_POWER_LEVELS; + } + /** @hide */ @IntDef(prefix = {"TX_POWER_LEVEL_"}, value = { TX_POWER_LEVEL_0, @@ -82,34 +90,39 @@ public final class ModemActivityInfo implements Parcelable { new Range<>(5, 15), new Range<>(15, 20), new Range<>(20, Integer.MAX_VALUE) - }; private long mTimestamp; private int mSleepTimeMs; private int mIdleTimeMs; - private List<TransmitPower> mTransmitPowerInfo = new ArrayList<>(TX_POWER_LEVELS); + private int[] mTxTimeMs; private int mRxTimeMs; + /** + * @hide + */ + @TestApi public ModemActivityInfo(long timestamp, int sleepTimeMs, int idleTimeMs, @NonNull int[] txTimeMs, int rxTimeMs) { + Objects.requireNonNull(txTimeMs); + if (txTimeMs.length != TX_POWER_LEVELS) { + throw new IllegalArgumentException("txTimeMs must have length == TX_POWER_LEVELS"); + } mTimestamp = timestamp; mSleepTimeMs = sleepTimeMs; mIdleTimeMs = idleTimeMs; - populateTransmitPowerRange(txTimeMs); + mTxTimeMs = txTimeMs; mRxTimeMs = rxTimeMs; } - /** helper API to populate tx power range for each bucket **/ - private void populateTransmitPowerRange(@NonNull int[] transmitPowerMs) { - int i = 0; - for ( ; i < Math.min(transmitPowerMs.length, TX_POWER_LEVELS); i++) { - mTransmitPowerInfo.add(i, new TransmitPower(TX_POWER_RANGES[i], transmitPowerMs[i])); - } - // Make sure that mTransmitPowerInfo is fully initialized. - for ( ; i < TX_POWER_LEVELS; i++) { - mTransmitPowerInfo.add(i, new TransmitPower(TX_POWER_RANGES[i], 0)); - } + /** + * Provided for convenience in manipulation since the API exposes long values but internal + * representations are ints. + * @hide + */ + public ModemActivityInfo(long timestamp, long sleepTimeMs, long idleTimeMs, + @NonNull int[] txTimeMs, long rxTimeMs) { + this(timestamp, (int) sleepTimeMs, (int) idleTimeMs, txTimeMs, (int) rxTimeMs); } @Override @@ -118,7 +131,7 @@ public final class ModemActivityInfo implements Parcelable { + " mTimestamp=" + mTimestamp + " mSleepTimeMs=" + mSleepTimeMs + " mIdleTimeMs=" + mIdleTimeMs - + " mTransmitPowerInfo[]=" + mTransmitPowerInfo.toString() + + " mTxTimeMs[]=" + mTxTimeMs + " mRxTimeMs=" + mRxTimeMs + "}"; } @@ -129,14 +142,12 @@ public final class ModemActivityInfo implements Parcelable { public static final @android.annotation.NonNull Parcelable.Creator<ModemActivityInfo> CREATOR = new Parcelable.Creator<ModemActivityInfo>() { - public ModemActivityInfo createFromParcel(Parcel in) { + public ModemActivityInfo createFromParcel(@NonNull Parcel in) { long timestamp = in.readLong(); int sleepTimeMs = in.readInt(); int idleTimeMs = in.readInt(); int[] txTimeMs = new int[TX_POWER_LEVELS]; - for (int i = 0; i < TX_POWER_LEVELS; i++) { - txTimeMs[i] = in.readInt(); - } + in.readIntArray(txTimeMs); int rxTimeMs = in.readInt(); return new ModemActivityInfo(timestamp, sleepTimeMs, idleTimeMs, txTimeMs, rxTimeMs); @@ -147,21 +158,25 @@ public final class ModemActivityInfo implements Parcelable { } }; - public void writeToParcel(Parcel dest, int flags) { + /** + * @param dest The Parcel in which the object should be written. + * @param flags Additional flags about how the object should be written. + */ + public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeLong(mTimestamp); dest.writeInt(mSleepTimeMs); dest.writeInt(mIdleTimeMs); - for (int i = 0; i < TX_POWER_LEVELS; i++) { - dest.writeInt(mTransmitPowerInfo.get(i).getTimeInMillis()); - } + dest.writeIntArray(mTxTimeMs); dest.writeInt(mRxTimeMs); } /** - * @return milliseconds since boot, including mTimeInMillis spent in sleep. - * @see SystemClock#elapsedRealtime() + * Gets the timestamp at which this modem activity info was recorded. + * + * @return The timestamp, as returned by {@link SystemClock#elapsedRealtime()}, when this + * {@link ModemActivityInfo} was recorded. */ - public long getTimestamp() { + public @ElapsedRealtimeLong long getTimestampMillis() { return mTimestamp; } @@ -171,35 +186,48 @@ public final class ModemActivityInfo implements Parcelable { } /** - * @return an arrayList of {@link TransmitPower} with each element representing the total time where - * transmitter is awake time (in ms) for a given power range (in dbm). + * Gets the amount of time the modem spent transmitting at a certain power level. * - * @see #TX_POWER_LEVELS + * @param powerLevel The power level to query. + * @return The amount of time, in milliseconds, that the modem spent transmitting at the + * given power level. */ - @NonNull - public List<TransmitPower> getTransmitPowerInfo() { - return mTransmitPowerInfo; + public @DurationMillisLong long getTransmitDurationMillisAtPowerLevel( + @TxPowerLevel int powerLevel) { + return mTxTimeMs[powerLevel]; + } + + /** + * Gets the range of transmit powers corresponding to a certain power level. + * + * @param powerLevel The power level to query + * @return A {@link Range} object representing the range of intensities (in dBm) to which this + * power level corresponds. + */ + public @NonNull Range<Integer> getTransmitPowerRange(@TxPowerLevel int powerLevel) { + return TX_POWER_RANGES[powerLevel]; } /** @hide */ public void setTransmitTimeMillis(int[] txTimeMs) { - populateTransmitPowerRange(txTimeMs); + mTxTimeMs = Arrays.copyOf(txTimeMs, TX_POWER_LEVELS); } - /** @hide */ + /** + * @return The raw array of transmit power durations + * @hide + */ @NonNull public int[] getTransmitTimeMillis() { - int[] transmitTimeMillis = new int[TX_POWER_LEVELS]; - for (int i = 0; i < transmitTimeMillis.length; i++) { - transmitTimeMillis[i] = mTransmitPowerInfo.get(i).getTimeInMillis(); - } - return transmitTimeMillis; + return mTxTimeMs; } /** - * @return total mTimeInMillis (in ms) when modem is in a low power or sleep state. + * Gets the amount of time (in milliseconds) when the modem is in a low power or sleep state. + * + * @return Time in milliseconds. */ - public int getSleepTimeMillis() { + public @DurationMillisLong long getSleepTimeMillis() { return mSleepTimeMs; } @@ -209,10 +237,44 @@ public final class ModemActivityInfo implements Parcelable { } /** - * @return total mTimeInMillis (in ms) when modem is awake but neither the transmitter nor receiver are - * active. + * Provided for convenience, since the API surface needs to return longs but internal + * representations are ints. + * @hide */ - public int getIdleTimeMillis() { + public void setSleepTimeMillis(long sleepTimeMillis) { + mSleepTimeMs = (int) sleepTimeMillis; + } + + /** + * Computes the difference between this instance of {@link ModemActivityInfo} and another + * instance. + * + * This method should be used to compute the amount of activity that has happened between two + * samples of modem activity taken at separate times. The sample passed in as an argument to + * this method should be the one that's taken later in time (and therefore has more activity). + * @param other The other instance of {@link ModemActivityInfo} to diff against. + * @return An instance of {@link ModemActivityInfo} representing the difference in modem + * activity. + */ + public @NonNull ModemActivityInfo getDelta(@NonNull ModemActivityInfo other) { + int[] txTimeMs = new int[ModemActivityInfo.TX_POWER_LEVELS]; + for (int i = 0; i < ModemActivityInfo.TX_POWER_LEVELS; i++) { + txTimeMs[i] = other.mTxTimeMs[i] - mTxTimeMs[i]; + } + return new ModemActivityInfo(other.getTimestampMillis(), + other.getSleepTimeMillis() - getSleepTimeMillis(), + other.getIdleTimeMillis() - getIdleTimeMillis(), + txTimeMs, + other.getReceiveTimeMillis() - getReceiveTimeMillis()); + } + + /** + * Gets the amount of time (in milliseconds) when the modem is awake but neither transmitting + * nor receiving. + * + * @return Time in milliseconds. + */ + public @DurationMillisLong long getIdleTimeMillis() { return mIdleTimeMs; } @@ -222,9 +284,20 @@ public final class ModemActivityInfo implements Parcelable { } /** - * @return rx(receive) mTimeInMillis in ms. + * Provided for convenience, since the API surface needs to return longs but internal + * representations are ints. + * @hide + */ + public void setIdleTimeMillis(long idleTimeMillis) { + mIdleTimeMs = (int) idleTimeMillis; + } + + /** + * Gets the amount of time (in milliseconds) when the modem is awake and receiving data. + * + * @return Time in milliseconds. */ - public int getReceiveTimeMillis() { + public @DurationMillisLong long getReceiveTimeMillis() { return mRxTimeMs; } @@ -234,71 +307,56 @@ public final class ModemActivityInfo implements Parcelable { } /** + * Provided for convenience, since the API surface needs to return longs but internal + * representations are ints. + * @hide + */ + public void setReceiveTimeMillis(long receiveTimeMillis) { + mRxTimeMs = (int) receiveTimeMillis; + } + + /** * Indicates if the modem has reported valid {@link ModemActivityInfo}. * * @return {@code true} if this {@link ModemActivityInfo} record is valid, * {@code false} otherwise. + * TODO: remove usages of this outside Telephony by always returning a valid (or null) result + * from telephony. + * @hide */ + @TestApi public boolean isValid() { - for (TransmitPower powerInfo : getTransmitPowerInfo()) { - if(powerInfo.getTimeInMillis() < 0) { - return false; - } - } + boolean isTxPowerValid = Arrays.stream(mTxTimeMs).allMatch((i) -> i >= 0); - return ((getIdleTimeMillis() >= 0) && (getSleepTimeMillis() >= 0) + return isTxPowerValid && ((getIdleTimeMillis() >= 0) && (getSleepTimeMillis() >= 0) && (getReceiveTimeMillis() >= 0) && !isEmpty()); } private boolean isEmpty() { - for (TransmitPower txVal : getTransmitPowerInfo()) { - if(txVal.getTimeInMillis() != 0) { - return false; - } - } + boolean isTxPowerEmpty = mTxTimeMs == null || mTxTimeMs.length == 0 + || Arrays.stream(mTxTimeMs).allMatch((i) -> i == 0); - return ((getIdleTimeMillis() == 0) && (getSleepTimeMillis() == 0) + return isTxPowerEmpty && ((getIdleTimeMillis() == 0) && (getSleepTimeMillis() == 0) && (getReceiveTimeMillis() == 0)); } - /** - * Transmit power Information, including the power range in dbm and the total time (in ms) where - * the transmitter is active/awake for this power range. - * e.g, range: 0dbm(lower) ~ 5dbm(upper) - * time: 5ms - */ - public class TransmitPower { - private int mTimeInMillis; - private Range<Integer> mPowerRangeInDbm; - /** @hide */ - public TransmitPower(@NonNull Range<Integer> range, int time) { - this.mTimeInMillis = time; - this.mPowerRangeInDbm = range; - } - - /** - * @return the total time in ms where the transmitter is active/wake for this power range - * {@link #getPowerRangeInDbm()}. - */ - public int getTimeInMillis() { - return mTimeInMillis; - } - /** - * @return the power range in dbm. e.g, range: 0dbm(lower) ~ 5dbm(upper) - */ - @NonNull - public Range<Integer> getPowerRangeInDbm() { - return mPowerRangeInDbm; - } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ModemActivityInfo that = (ModemActivityInfo) o; + return mTimestamp == that.mTimestamp + && mSleepTimeMs == that.mSleepTimeMs + && mIdleTimeMs == that.mIdleTimeMs + && mRxTimeMs == that.mRxTimeMs + && Arrays.equals(mTxTimeMs, that.mTxTimeMs); + } - @Override - public String toString() { - return "TransmitPower{" - + " mTimeInMillis=" + mTimeInMillis - + " mPowerRangeInDbm={" + mPowerRangeInDbm.getLower() - + "," + mPowerRangeInDbm.getUpper() - + "}}"; - } + @Override + public int hashCode() { + int result = Objects.hash(mTimestamp, mSleepTimeMs, mIdleTimeMs, mRxTimeMs); + result = 31 * result + Arrays.hashCode(mTxTimeMs); + return result; } } diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java index cab62098f08e..d3fca3ec78df 100644 --- a/telephony/java/android/telephony/SmsManager.java +++ b/telephony/java/android/telephony/SmsManager.java @@ -2604,13 +2604,12 @@ public final class SmsManager { /** * Send an MMS message * - * <p class="note"><strong>Note:</strong> This method will never trigger an SMS disambiguation - * dialog. If this method is called on a device that has multiple active subscriptions, this - * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined - * default subscription is defined, the subscription ID associated with this message will be - * INVALID, which will result in the operation being completed on the subscription associated - * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the - * operation is performed on the correct subscription. + * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this + * manager on a multi-SIM device, this operation may fail sending the MMS message because no + * suitable default subscription could be found. In this case, if {@code sentIntent} is + * non-null, then the {@link PendingIntent} will be sent with an error code + * {@code RESULT_NO_DEFAULT_SMS_APP}. See {@link #getDefault()} for more information on the + * conditions where this operation may fail. * </p> * * @param context application context @@ -2629,21 +2628,30 @@ public final class SmsManager { } MmsManager m = (MmsManager) context.getSystemService(Context.MMS_SERVICE); if (m != null) { - m.sendMultimediaMessage(getSubscriptionId(), contentUri, locationUrl, configOverrides, - sentIntent, 0L /* messageId */); + resolveSubscriptionForOperation(new SubscriptionResolverResult() { + @Override + public void onSuccess(int subId) { + m.sendMultimediaMessage(subId, contentUri, locationUrl, configOverrides, + sentIntent, 0L /* messageId */); + } + + @Override + public void onFailure() { + notifySmsError(sentIntent, RESULT_NO_DEFAULT_SMS_APP); + } + }); } } /** * Download an MMS message from carrier by a given location URL * - * <p class="note"><strong>Note:</strong> This method will never trigger an SMS disambiguation - * dialog. If this method is called on a device that has multiple active subscriptions, this - * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined - * default subscription is defined, the subscription ID associated with this message will be - * INVALID, which will result in the operation being completed on the subscription associated - * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the - * operation is performed on the correct subscription. + * <p class="note"><strong>Note:</strong> If {@link #getDefault()} is used to instantiate this + * manager on a multi-SIM device, this operation may fail downloading the MMS message because no + * suitable default subscription could be found. In this case, if {@code downloadedIntent} is + * non-null, then the {@link PendingIntent} will be sent with an error code + * {@code RESULT_NO_DEFAULT_SMS_APP}. See {@link #getDefault()} for more information on the + * conditions where this operation may fail. * </p> * * @param context application context @@ -2666,8 +2674,18 @@ public final class SmsManager { } MmsManager m = (MmsManager) context.getSystemService(Context.MMS_SERVICE); if (m != null) { - m.downloadMultimediaMessage(getSubscriptionId(), locationUrl, contentUri, - configOverrides, downloadedIntent, 0L /* messageId */); + resolveSubscriptionForOperation(new SubscriptionResolverResult() { + @Override + public void onSuccess(int subId) { + m.downloadMultimediaMessage(subId, locationUrl, contentUri, configOverrides, + downloadedIntent, 0L /* messageId */); + } + + @Override + public void onFailure() { + notifySmsError(downloadedIntent, RESULT_NO_DEFAULT_SMS_APP); + } + }); } } diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 4f4a133f08ac..a202644dfafe 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -2835,11 +2835,13 @@ public class TelephonyManager { }; /** - * Return a collection of all network types - * @return network types + * Returns an array of all valid network types. + * + * @return An integer array containing all valid network types in no particular order. * * @hide */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public static @NonNull @NetworkType int[] getAllNetworkTypes() { return NETWORK_TYPES; } diff --git a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java index 6662b0e199fb..bf7a6ff3ca77 100644 --- a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java +++ b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java @@ -128,12 +128,14 @@ public class StagedRollbackTest extends BaseHostJUnit4Test { } if (found) { - if (!getDevice().isAdbRoot()) { + try { getDevice().enableAdbRoot(); - } - getDevice().remountSystemWritable(); - for (String file : files) { - getDevice().executeShellCommand("rm -rf " + file); + getDevice().remountSystemWritable(); + for (String file : files) { + getDevice().executeShellCommand("rm -rf " + file); + } + } finally { + getDevice().disableAdbRoot(); } getDevice().reboot(); } @@ -334,8 +336,8 @@ public class StagedRollbackTest extends BaseHostJUnit4Test { String oldFilePath1 = apexDataDirDeSys(APK_IN_APEX_TESTAPEX_NAME) + "/" + TEST_FILENAME_1; String oldFilePath2 = apexDataDirDeSys(APK_IN_APEX_TESTAPEX_NAME) + TEST_SUBDIR + TEST_FILENAME_2; - assertTrue(getDevice().pushString(TEST_STRING_1, oldFilePath1)); - assertTrue(getDevice().pushString(TEST_STRING_2, oldFilePath2)); + pushString(TEST_STRING_1, oldFilePath1); + pushString(TEST_STRING_2, oldFilePath2); // Install new version of the APEX with rollback enabled runPhase("testRollbackApexDataDirectories_Phase1"); @@ -347,8 +349,8 @@ public class StagedRollbackTest extends BaseHostJUnit4Test { String newFilePath3 = apexDataDirDeSys(APK_IN_APEX_TESTAPEX_NAME) + "/" + TEST_FILENAME_3; String newFilePath4 = apexDataDirDeSys(APK_IN_APEX_TESTAPEX_NAME) + TEST_SUBDIR + TEST_FILENAME_4; - assertTrue(getDevice().pushString(TEST_STRING_3, newFilePath3)); - assertTrue(getDevice().pushString(TEST_STRING_4, newFilePath4)); + pushString(TEST_STRING_3, newFilePath3); + pushString(TEST_STRING_4, newFilePath4); // Roll back the APEX runPhase("testRollbackApexDataDirectories_Phase2"); @@ -382,8 +384,8 @@ public class StagedRollbackTest extends BaseHostJUnit4Test { APK_IN_APEX_TESTAPEX_NAME, 0) + "/" + TEST_FILENAME_1; String oldFilePath2 = apexDataDirDeUser(APK_IN_APEX_TESTAPEX_NAME, 0) + TEST_SUBDIR + TEST_FILENAME_2; - assertTrue(getDevice().pushString(TEST_STRING_1, oldFilePath1)); - assertTrue(getDevice().pushString(TEST_STRING_2, oldFilePath2)); + pushString(TEST_STRING_1, oldFilePath1); + pushString(TEST_STRING_2, oldFilePath2); // Install new version of the APEX with rollback enabled runPhase("testRollbackApexDataDirectories_Phase1"); @@ -396,8 +398,8 @@ public class StagedRollbackTest extends BaseHostJUnit4Test { apexDataDirDeUser(APK_IN_APEX_TESTAPEX_NAME, 0) + "/" + TEST_FILENAME_3; String newFilePath4 = apexDataDirDeUser(APK_IN_APEX_TESTAPEX_NAME, 0) + TEST_SUBDIR + TEST_FILENAME_4; - assertTrue(getDevice().pushString(TEST_STRING_3, newFilePath3)); - assertTrue(getDevice().pushString(TEST_STRING_4, newFilePath4)); + pushString(TEST_STRING_3, newFilePath3); + pushString(TEST_STRING_4, newFilePath4); // Roll back the APEX runPhase("testRollbackApexDataDirectories_Phase2"); @@ -430,8 +432,8 @@ public class StagedRollbackTest extends BaseHostJUnit4Test { String oldFilePath1 = apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + "/" + TEST_FILENAME_1; String oldFilePath2 = apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + TEST_SUBDIR + TEST_FILENAME_2; - assertTrue(getDevice().pushString(TEST_STRING_1, oldFilePath1)); - assertTrue(getDevice().pushString(TEST_STRING_2, oldFilePath2)); + pushString(TEST_STRING_1, oldFilePath1); + pushString(TEST_STRING_2, oldFilePath2); // Install new version of the APEX with rollback enabled runPhase("testRollbackApexDataDirectories_Phase1"); @@ -443,8 +445,8 @@ public class StagedRollbackTest extends BaseHostJUnit4Test { String newFilePath3 = apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + "/" + TEST_FILENAME_3; String newFilePath4 = apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + TEST_SUBDIR + TEST_FILENAME_4; - assertTrue(getDevice().pushString(TEST_STRING_3, newFilePath3)); - assertTrue(getDevice().pushString(TEST_STRING_4, newFilePath4)); + pushString(TEST_STRING_3, newFilePath3); + pushString(TEST_STRING_4, newFilePath4); // Roll back the APEX runPhase("testRollbackApexDataDirectories_Phase2"); @@ -476,8 +478,8 @@ public class StagedRollbackTest extends BaseHostJUnit4Test { // Push files to apk data directory String oldFilePath1 = apkDataDirDe(TESTAPP_A, 0) + "/" + TEST_FILENAME_1; String oldFilePath2 = apkDataDirDe(TESTAPP_A, 0) + TEST_SUBDIR + TEST_FILENAME_2; - assertTrue(getDevice().pushString(TEST_STRING_1, oldFilePath1)); - assertTrue(getDevice().pushString(TEST_STRING_2, oldFilePath2)); + pushString(TEST_STRING_1, oldFilePath1); + pushString(TEST_STRING_2, oldFilePath2); // Install version 2 of TESTAPP_A with rollback enabled runPhase("testRollbackApkDataDirectories_Phase2"); @@ -488,8 +490,8 @@ public class StagedRollbackTest extends BaseHostJUnit4Test { getDevice().deleteFile(oldFilePath2); String newFilePath3 = apkDataDirDe(TESTAPP_A, 0) + "/" + TEST_FILENAME_3; String newFilePath4 = apkDataDirDe(TESTAPP_A, 0) + TEST_SUBDIR + TEST_FILENAME_4; - assertTrue(getDevice().pushString(TEST_STRING_3, newFilePath3)); - assertTrue(getDevice().pushString(TEST_STRING_4, newFilePath4)); + pushString(TEST_STRING_3, newFilePath3); + pushString(TEST_STRING_4, newFilePath4); // Roll back the APK runPhase("testRollbackApkDataDirectories_Phase3"); @@ -511,8 +513,8 @@ public class StagedRollbackTest extends BaseHostJUnit4Test { String oldFilePath1 = apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + "/" + TEST_FILENAME_1; String oldFilePath2 = apexDataDirCe(APK_IN_APEX_TESTAPEX_NAME, 0) + TEST_SUBDIR + TEST_FILENAME_2; - assertTrue(getDevice().pushString(TEST_STRING_1, oldFilePath1)); - assertTrue(getDevice().pushString(TEST_STRING_2, oldFilePath2)); + pushString(TEST_STRING_1, oldFilePath1); + pushString(TEST_STRING_2, oldFilePath2); // Install new version of the APEX with rollback enabled runPhase("testRollbackApexDataDirectories_Phase1"); @@ -534,11 +536,13 @@ public class StagedRollbackTest extends BaseHostJUnit4Test { CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(getBuild()); final String fileName = APK_IN_APEX_TESTAPEX_NAME + "_v1.apex"; final File apex = buildHelper.getTestFile(fileName); - if (!getDevice().isAdbRoot()) { + try { getDevice().enableAdbRoot(); + getDevice().remountSystemWritable(); + assertTrue(getDevice().pushFile(apex, "/system/apex/" + fileName)); + } finally { + getDevice().disableAdbRoot(); } - getDevice().remountSystemWritable(); - assertTrue(getDevice().pushFile(apex, "/system/apex/" + fileName)); getDevice().reboot(); } @@ -616,4 +620,13 @@ public class StagedRollbackTest extends BaseHostJUnit4Test { return false; } } + + private void pushString(String contents, String deviceFilePath) throws Exception { + try { + getDevice().enableAdbRoot(); + assertThat(getDevice().pushString(contents, deviceFilePath)).isTrue(); + } finally { + getDevice().disableAdbRoot(); + } + } } diff --git a/tests/net/TEST_MAPPING b/tests/net/TEST_MAPPING index 005cbe9ffdc4..89fc6ea2c47b 100644 --- a/tests/net/TEST_MAPPING +++ b/tests/net/TEST_MAPPING @@ -8,5 +8,10 @@ { "name": "FrameworksNetDeflakeTest" } + ], + "imports": [ + { + "path": "cts/tests/tests/net" + } ] }
\ No newline at end of file diff --git a/wifi/api/current.txt b/wifi/api/current.txt index 2d48a8325d6e..f7061181b72b 100644 --- a/wifi/api/current.txt +++ b/wifi/api/current.txt @@ -803,13 +803,13 @@ package android.net.wifi.hotspot2.pps { method public String getFriendlyName(); method @Nullable public long[] getMatchAllOis(); method @Nullable public long[] getMatchAnyOis(); - method @Nullable public String[] getOtherHomePartners(); + method @NonNull public java.util.Collection<java.lang.String> getOtherHomePartnersList(); method public long[] getRoamingConsortiumOis(); method public void setFqdn(String); method public void setFriendlyName(String); method public void setMatchAllOis(@Nullable long[]); method public void setMatchAnyOis(@Nullable long[]); - method public void setOtherHomePartners(@Nullable String[]); + method public void setOtherHomePartnersList(@NonNull java.util.Collection<java.lang.String>); method public void setRoamingConsortiumOis(long[]); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.HomeSp> CREATOR; diff --git a/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java b/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java index 35a8ff6095e0..64aad613c8b2 100644 --- a/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java +++ b/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java @@ -16,6 +16,7 @@ package android.net.wifi.hotspot2.pps; +import android.annotation.NonNull; import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; @@ -24,6 +25,7 @@ import android.util.Log; import java.nio.charset.StandardCharsets; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -214,23 +216,52 @@ public final class HomeSp implements Parcelable { * * @param otherHomePartners Array of Strings containing the FQDNs of other Home partner * providers + * @hide */ public void setOtherHomePartners(@Nullable String[] otherHomePartners) { mOtherHomePartners = otherHomePartners; } /** + * Set the list of FQDN (Fully Qualified Domain Name) of other Home partner providers. + * + * @param otherHomePartners Collection of Strings containing the FQDNs of other Home partner + * providers + */ + public void setOtherHomePartnersList(@NonNull Collection<String> otherHomePartners) { + if (otherHomePartners == null) { + return; + } + mOtherHomePartners = otherHomePartners.toArray(new String[otherHomePartners.size()]); + } + + /** * Get the list of FQDN (Fully Qualified Domain Name) of other Home partner providers set in * the profile. * * @return Array of Strings containing the FQDNs of other Home partner providers set in the * profile + * @hide */ public @Nullable String[] getOtherHomePartners() { return mOtherHomePartners; } /** + * Get the list of FQDN (Fully Qualified Domain Name) of other Home partner providers set in + * the profile. + * + * @return Collection of Strings containing the FQDNs of other Home partner providers set in the + * profile + */ + public @NonNull Collection<String> getOtherHomePartnersList() { + if (mOtherHomePartners == null) { + return Collections.emptyList(); + } + return Arrays.asList(mOtherHomePartners); + } + + /** * List of Organization Identifiers (OIs) identifying a roaming consortium of * which this provider is a member. */ diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSpTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSpTest.java index 93d471ab6b81..fe889fc31ed4 100644 --- a/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSpTest.java +++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/HomeSpTest.java @@ -16,6 +16,7 @@ package android.net.wifi.hotspot2.pps; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -26,7 +27,9 @@ import androidx.test.filters.SmallTest; import org.junit.Test; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; import java.util.Map; @@ -35,6 +38,7 @@ import java.util.Map; */ @SmallTest public class HomeSpTest { + private static final String[] OTHER_HOME_PARTNER_LIST = new String[]{"partner1", "partner2"}; /** * Helper function for creating a map of home network IDs for testing. @@ -62,7 +66,7 @@ public class HomeSpTest { homeSp.setHomeNetworkIds(homeNetworkIds); homeSp.setMatchAllOis(new long[] {0x11L, 0x22L}); homeSp.setMatchAnyOis(new long[] {0x33L, 0x44L}); - homeSp.setOtherHomePartners(new String[] {"partner1", "partner2"}); + homeSp.setOtherHomePartners(OTHER_HOME_PARTNER_LIST); homeSp.setRoamingConsortiumOis(new long[] {0x55, 0x66}); return homeSp; } @@ -218,4 +222,34 @@ public class HomeSpTest { HomeSp copySp = new HomeSp(sourceSp); assertTrue(copySp.equals(sourceSp)); } + + /** + * Verify that the getOtherHomePartnersList gets the list of partners as expected. + * + * @throws Exception + */ + @Test + public void validateGetOtherHomePartnersList() throws Exception { + HomeSp homeSp = createHomeSpWithoutHomeNetworkIds(); + + Collection<String> otherHomePartnersList = homeSp.getOtherHomePartnersList(); + assertEquals(2, otherHomePartnersList.size()); + assertTrue(Arrays.equals(OTHER_HOME_PARTNER_LIST, otherHomePartnersList.toArray())); + } + + /** + * Verify that the setOtherHomePartnersList sets the list of partners as expected. + * + * @throws Exception + */ + @Test + public void validateSetOtherHomePartnersList() throws Exception { + HomeSp homeSp = createHomeSpWithoutHomeNetworkIds(); + + final Collection<String> homePartners = + new ArrayList<>(Arrays.asList(OTHER_HOME_PARTNER_LIST)); + + homeSp.setOtherHomePartnersList(homePartners); + assertTrue(Arrays.equals(homeSp.getOtherHomePartners(), OTHER_HOME_PARTNER_LIST)); + } } |